Die #!
Linie verwendet wird , bevor das Skript ausgeführt wird, dann ignoriert , wenn das Skript ausgeführt wird .
Sie fragen, was der Unterschied zwischen einer Shebang-Zeile und einem normalen Kommentar ist.
Eine Zeile, die mit beginnt, #!
ist genauso ein Kommentar wie jede andere Zeile, die mit beginnt #
. Dies ist der Fall, wenn dies die #!
erste Zeile der Datei ist oder an einer anderen Stelle. #!/bin/sh
hat einen Effekt , wird aber nicht vom Interpreter selbst gelesen .
#
ist kein Kommentar in allen Programmiersprachen, aber, wie Sie wissen, ein Kommentar in Shells im Bourne-Stil, einschließlich sh
und bash
(sowie in den meisten Shells im Nicht-Bourne-Stil, wie csh
). Es ist auch ein Kommentar in Python . Und es ist ein Kommentar in einer Vielzahl von Konfigurationsdateien, die überhaupt keine Skripte sind (wie /etc/fstab
).
Angenommen, ein Shell-Skript beginnt mit #!/bin/sh
. Das ist ein Kommentar, und der Interpreter (die Shell) ignoriert alles in der Zeile nach dem #
Zeichen.
Der Zweck einer #!
Zeile besteht nicht darin, dem Dolmetscher Informationen zu geben. Der Zweck dieser #!
Zeile besteht darin, dem Betriebssystem (oder dem Prozess, durch den der Interpreter gestartet wird) mitzuteilen, was als Interpreter verwendet werden soll .
Wenn Sie das Skript beispielsweise durch Ausführen als ausführbare Datei aufrufen ./script.sh
, überprüft das System in der ersten Zeile, ob mit #!
, gefolgt von null oder mehr Leerzeichen, gefolgt von einem Befehl, begonnen wird. In diesem Fall wird dieser Befehl mit dem Namen des Skripts als Argument ausgeführt. In diesem Beispiel wird es ausgeführt /bin/sh script.sh
(oder technisch /bin/sh ./script.sh
).
Wenn Sie das Skript aufrufen, indem Sie den Interpreter explizit aufrufen, wird die #!
Zeile nie konsultiert. Wenn Sie also ausführen sh script.sh
, hat die erste Zeile keine Auswirkung. Wenn script2.sh
's erste Zeile ist #!/usr/games/nibbles
, wird beim Ausführen sh script2.sh
nicht versucht, das Skript in nibbles
(aber ./script2.sh
wird) zu öffnen .
Sie werden feststellen, dass in keinem Fall die Erweiterung ( .sh
) des Skripts , sofern vorhanden, die Ausführung beeinflusst. In einem Unix-ähnlichen System wirkt sich dies normalerweise nicht auf die Ausführung des Skripts aus. Auf einigen anderen Systemen wie Windows wird die #!
Shebang-Zeile möglicherweise vollständig vom System ignoriert, und die Erweiterung bestimmt möglicherweise, wie die Skripte ausgeführt werden. (Dies bedeutet nicht, dass Sie Ihre Skripterweiterungen angeben müssen, aber dies ist einer der Gründe, warum sie korrekt sein sollten, wenn Sie dies tun.)
#!
wurde ausgewählt, um genau diesem Zweck zu dienen, da #
ein Kommentar beginnt. Die #!
Zeile ist für das System, nicht für den Interpreter, und sollte vom Interpreter ignoriert werden.
Shebang Line für Bash-Skripte
Sie sagten (ursprünglich), Sie verwenden #!/bin/sh
für bash
Skripte. Sie sollten dies nur tun, wenn für das Skript keine der bash
Erweiterungen sh
erforderlich sind - es muss in der Lage sein, das Skript auszuführen. sh
ist nicht immer ein symlink zu bash
. Oft, auch auf allen neueren Debian- und Ubuntu-Systemen , sh
besteht ein Symlink zu dash
.
Shebang Line für Python-Skripte
Sie sagten auch (in der ersten Version Ihrer Frage vor der Bearbeitung), dass Sie Ihre Python-Skripte mit starten #!/bin/sh read by the interpretor
. Wenn du das wörtlich meinst, dann solltest du definitiv damit aufhören. Wenn hello.py
mit dieser Zeile begonnen wird, wird Folgendes ./hello.py
ausgeführt:
/bin/sh read by the interpretor hello.py
/bin/sh
wird versuchen, ein Skript auszuführen, das read
(mit by the interpretor hello.py
seinen Argumenten) aufgerufen read
wird, (hoffentlich) nicht gefunden wird, und Ihr Python-Skript wird von einem Python-Interpreter niemals gesehen.
Wenn Sie diesen Fehler machen, aber das von mir beschriebene Problem nicht haben, rufen Sie wahrscheinlich Ihre Python-Skripte auf, indem Sie explizit den Interpreter angeben (z. B. python hello.py
), wodurch die erste Zeile ignoriert wird. Wenn Sie Ihre Skripte an andere verteilen oder später verwenden, ist es möglicherweise nicht klar, dass dies erforderlich ist, damit sie funktionieren. Es ist am besten, sie jetzt zu beheben. Oder entfernen Sie zumindest die erste Zeile vollständig, damit sie ./
sinnvoll ist , wenn sie nicht mit der Fehlermeldung ausgeführt werden.
Wenn Sie für Python-Skripte wissen, wo sich der Python-Interpreter befindet (oder befinden wird), können Sie die #!
Zeile auf dieselbe Weise schreiben :
#!/usr/bin/python
Wenn es sich um ein Python 3-Skript handelt, sollten Sie Folgendes angeben python3
, da python
es sich fast immer um Python 2 handelt :
#!/usr/bin/python3
Allerdings ist das Problem , dass während /bin/sh
sollte immer vorhanden, und /bin/bash
fast immer auf Systeme liegt vor , wenn bash
mit dem O kommt, Python kann in einer Vielzahl von Orten existiert.
Daher verwenden viele Python-Programmierer stattdessen Folgendes:
#!/usr/bin/env python
(Oder #!/usr/bin/env python3
für Python 3.)
Dies macht das Skript darauf angewiesen, am env
"richtigen Ort" zu sein, anstatt sich darauf zu verlassen, am python
richtigen Ort zu sein. Das ist gut so, denn:
env
befindet sich fast immer in /usr/bin
.
- Auf den meisten Systemen, je nachdem , was
python
sollte Ihr Skript ausgeführt ist derjenige, der zuerst in der erscheint PATH
. Beginnen Sie hello.py
mit #!/usr/bin/env python
make ./hello.py
run /usr/bin/env python hello.py
, was (praktisch) dem Ausführen entspricht python hello.py
.
Der Grund, den Sie nicht verwenden können, #!python
ist folgender:
- Sie möchten, dass der angegebene Interpreter durch einen absoluten Pfad angegeben wird (dh beginnend mit
/
).
- Der aufrufende Prozess würde
python
im aktuellen Verzeichnis ausgeführt . Das Durchsuchen des Pfads, wenn der Befehl keinen Schrägstrich enthält, ist ein spezifisches Shell-Verhalten.
Gelegentlich wird ein Python oder andere Skript , das nicht ein Shell - Skript ist eine Shebang - Zeile mit dem Starten haben , #!/bin/sh ...
wo ...
ein anderer Code. Dies ist manchmal richtig, da es einige Möglichkeiten gibt, die Bourne-kompatible shell ( sh
) mit Argumenten aufzurufen, damit sie einen Python-Interpreter aufruft. (Eines der Argumente wird wahrscheinlich enthalten python
.) Für die meisten Zwecke #!/usr/bin/env python
ist es jedoch einfacher, eleganter und es ist wahrscheinlicher, dass es so funktioniert, wie Sie es möchten.
Shebang Lines in anderen Sprachen
Viele Programmier- und Skriptsprachen sowie einige andere Dateiformate werden #
als Kommentar verwendet. Für jede von ihnen kann eine Datei in der Sprache von einem Programm ausgeführt werden, das sie als Argument verwendet, indem das Programm in der ersten Zeile danach angegeben wird #!
.
In einigen Programmiersprachen #
ist dies normalerweise kein Kommentar, aber als Sonderfall wird die erste Zeile ignoriert, wenn sie mit beginnt #!
. Dies erleichtert die Verwendung der #!
Syntax, obwohl #
eine Zeile sonst keinen Kommentar enthält.
Shebang Lines für Dateien, die nicht als Skripte ausgeführt werden
Während es weniger intuitiv ist, kann jede Datei, deren Dateiformat eine erste Zeile aufnehmen kann, die mit #!
dem vollständigen Pfad einer ausführbaren Datei beginnt , eine Shebang-Zeile haben. Wenn Sie dies tun und die Datei als ausführbar markiert ist, können Sie sie wie ein Programm ausführen, wodurch sie wie ein Dokument geöffnet wird.
Einige Anwendungen verwenden dieses Verhalten absichtlich. In VMware .vmx
definieren Dateien beispielsweise virtuelle Maschinen. Sie können eine virtuelle Maschine "ausführen", als wäre es ein Skript, da diese Dateien als ausführbar gekennzeichnet sind und eine Shebang-Zeile aufweisen, die bewirkt, dass sie in einem VMware-Dienstprogramm geöffnet werden.
Shebang Lines für Dateien, die nicht als Scripte ausgeführt werden, sondern sich trotzdem wie Scripte verhalten
rm
Entfernt Dateien. Es ist keine Skriptsprache. Eine Datei, die gestartet wird #!/bin/rm
und als ausführbar markiert ist, kann jedoch ausgeführt werden. Wenn Sie sie ausführen, rm
wird sie aufgerufen und gelöscht.
Dies wird oft als "die Datei löscht sich selbst" konzipiert. Aber die Datei läuft überhaupt nicht. Dies entspricht eher der oben für .vmx
Dateien beschriebenen Situation .
Da die #!
Zeile jedoch die Ausführung eines einfachen Befehls (einschließlich Befehlszeilenargumente) erleichtert, können Sie auf diese Weise einige Skripts ausführen. Als einfaches Beispiel für ein "Skript", das ausgefeilter #!/bin/rm
ist als:
#!/usr/bin/env tee -a
Dadurch werden Benutzereingaben interaktiv übernommen, zeilenweise an den Benutzer zurückgesendet und an das Ende der "Skript" -Datei angehängt.
Nützlich? Nicht sehr. Konzeptuell interessant? Total! Ja. (Etwas.)
Konzeptionell ähnliche Programmier- / Skripting-Konzepte (nur zum Spaß)
#include
. Auch hier ist das#
nicht als Kommentar gemeint.