2017-12-28 6 views
1

Ich habe sehr einfach Haskell-Projekt mit nur ausführbar my-exec. Es druckt nur "Hallo, Welt!" zu trösten.Strange Stack Bash Fehler: -: Befehl nicht gefunden

Ich möchte bin/setup.sh die Skriptdatei erstellen, die meine ausführbare Datei ausgeführt wird und tun auch einige echo

#!/usr/bin/env stack 
-- stack exec bash 

echo Echo printing 
my-exec 

Als ich es betreibe ich

bekommen
$ ./bin/setup.sh 
./bin/setup.sh: line 2: --: command not found 
Echo printing 
Hello, world! 

Und ich verstehe nicht, was das Problem mit dieser Datei und warum es --: command not found sagt, aber immer noch wie erwartet funktioniert.

Ich verstehe, dass in diesem einfachen Beispiel könnte ich es in viel einfacherer Form schreiben, aber in meiner realen Situation muss ich wie 10 von nicht trivialen Exec Anrufe machen und nicht multiplizieren wollen stack exec.

Also was kann ich tun, um diesen Fehler loszuwerden?

+0

Entfernen Sie die Zeile '- stack exec bash' oder korrigieren Sie sie als gültigen Befehl. – jordanm

+2

@jordanm, es funktioniert nicht ohne diese Linie. Und meine Frage ist genau, wie man es beheben kann. – vrom911

+0

Nun, es funktioniert auch nicht * mit * der Linie. –

Antwort

6

Hier ist das Problem. Die erste Zeile:

#!/usr/bin/env stack 

vom Betriebssystem (zB der Linux-Kernel) wie das anzeigt, dass das Skript mit dem Äquivalent des Shell-Befehls aufgerufen werden interpretiert:

$ /usr/bin/env stack setup.sh 

oder, da env ist gerade dort den Weg für stack zu suchen, um das Äquivalent von:

$ stack setup.sh 

Wenn Sie dies manuell ausführen, werden Sie den gleichen Fehler. Das liegt daran, wenn stack auf diese Weise aufgerufen wird, es die angegebene Datei liest, für eine Zeile der Form der Suche:

-- stack blah blah whatever blah blah 

nach der ersten #! Linie. Normalerweise sieht diese Zeile so etwas wie:

-- stack --resolver lts-10.0 script 

, die das Skript auszuführen stapeln Tells als ob Sie den Shell-Befehl ausgeführt hatte:

$ stack --resolver lts-10.0 script hello.sh 

die hello.sh als Haskell Programm interpretiert, statt einer Schale Skript, aber läuft es mit dem LTS-10.0 Resolver, und alles ist gut.

Allerdings haben Sie stack sagte dem Befehl stack exec bash zu verwenden, so ruft stack Ihr Skript mit dem Äquivalent von:

$ stack exec bash hello.sh 

, die im Grunde die gleichen wie Laufen ist:

$ bash hello.sh 

nach Einrichten der stack Pfade und so weiter.

SCHLIESSLICH, dann wird in der Shell bash das Skript ausgeführt.Bash ignoriert die erste Zeile, da sie mit # Zeichen beginnt, das einen Shell-Kommentar angibt. Aber wenn Bash versucht, die zweite Zeile zu interpretieren, dann ist es, als ob Sie den folgenden Befehl an der Shell-Eingabeaufforderung eingegeben:

$ -- stack exec bash 

Bash für ein Programm sieht -- Namen mit Argumenten laufen stack exec bash, und Sie erhalten eine Fehlermeldung. Das Skript wird jedoch weiterhin ausgeführt, sodass die Zeilen echo und my-exec wie erwartet ausgeführt werden.

Wow.

Hier ist eine Möglichkeit, die für Sie arbeiten kann. Sie können:

#!/bin/bash 
exec stack exec bash <<EOF 

echo Echo printing 
./hello 

EOF 

Dieses Shell-Skript stack exec bash unter Verwendung eines so genannten „hier doc“ berufen wird, im Grunde alles vorbei bis zum EOF als Skriptdatei für stack exec bash auszuführen.

+0

"Wow." -- tatsächlich! Das war ein ziemlicher Hase, der das Loch hinunterjagte. – chi

+0

Könnten wir einfach '#!/Usr/bin/env stack exec bash'? edit: Scheint nicht. Alles nach dem Befehlsnamen in einer '#!' - Zeile wird als einzelnes erstes Argument angegeben. Bummel. –

+0

Danke! Dies ist eine wirklich detaillierte Erklärung! Leider funktioniert das für meinen komplizierten realen Fall nicht, da ich 'stack exec' innerhalb' $ (...) 'aufrufe. Also habe ich 'bin/setup.sh' shebang' #!/Usr/bin/env bash' gemacht und das Skript mit 'stack exec./Bin/setup.sh' aufgerufen. – vrom911