In bash
oder sh
, denke ich, ist alles, was mit beginnt, #
ein Kommentar .
Aber in bash
Skripten schreiben wir:
#!/bin/bash
Und in Python-Skripten gibt es:
#!/bin/python
Bedeutet dies, dass #
für sich genommen ein Kommentar ist, während dies #!
nicht der Fall ist?
#include
. Auch hier ist das#
nicht als Kommentar gemeint.Antworten:
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ßlichsh
undbash
(sowie in den meisten Shells im Nicht-Bourne-Stil, wiecsh
). 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ührensh script.sh
, hat die erste Zeile keine Auswirkung. Wennscript2.sh
's erste Zeile ist#!/usr/games/nibbles
, wird beim Ausführensh script2.sh
nicht versucht, das Skript innibbles
(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ürbash
Skripte. Sie sollten dies nur tun, wenn für das Skript keine derbash
Erweiterungensh
erforderlich sind - es muss in der Lage sein, das Skript auszuführen.sh
ist nicht immer ein symlink zubash
. Oft, auch auf allen neueren Debian- und Ubuntu-Systemen ,sh
besteht ein Symlink zudash
.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. Wennhello.py
mit dieser Zeile begonnen wird, wird Folgendes./hello.py
ausgeführt:/bin/sh
wird versuchen, ein Skript auszuführen, dasread
(mitby the interpretor hello.py
seinen Argumenten) aufgerufenread
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 :Wenn es sich um ein Python 3-Skript handelt, sollten Sie Folgendes angeben
python3
, dapython
es sich fast immer um Python 2 handelt :Allerdings ist das Problem , dass während
/bin/sh
sollte immer vorhanden, und/bin/bash
fast immer auf Systeme liegt vor , wennbash
mit dem O kommt, Python kann in einer Vielzahl von Orten existiert.Daher verwenden viele Python-Programmierer stattdessen Folgendes:
(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, ampython
richtigen Ort zu sein. Das ist gut so, denn:env
befindet sich fast immer in/usr/bin
.python
sollte Ihr Skript ausgeführt ist derjenige, der zuerst in der erscheintPATH
. Beginnen Siehello.py
mit#!/usr/bin/env python
make./hello.py
run/usr/bin/env python hello.py
, was (praktisch) dem Ausführen entsprichtpython hello.py
.Der Grund, den Sie nicht verwenden können,
#!python
ist folgender:/
).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 enthaltenpython
.) 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: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ß)
Skripte / Programme, die mehrere Sprachen gleichzeitig unterstützen , um beispielsweise die Hashbang-Funktionalität in Betriebssystemen zu simulieren, in denen dies nicht der Fall ist .
(Diese Programme heißen Polyglots , aber das ist nicht zu verwechseln mit dem anderen Sinn von Polyglot in der Softwareentwicklung , einem Programm / Projekt, bei dem verschiedene Teile in verschiedenen Sprachen geschrieben sind.)
Metabefehle in QBasic / QuickBASIC, die dem Compiler (für kompilierten Code) Optionen für die Codegenerierung signalisierten, jedoch Teil von Kommentaren waren und daher während der tatsächlichen Kompilierung / Interpretation ignoriert wurden.
quelle
-x
Flag?-x
"überspringe [s] die erste Zeile ..." Die 2. Zeile wird nummeriert1
anstatt2
, die 3. Zeile2
anstatt3
, usw. Deshalb solltest du dieses Flag nicht verwenden. ;)-x
ist für die Skripterstellung auf nicht-Unix-ähnlichen Betriebssystemen gedacht, deren shebang-ähnliche Syntax nicht mit#
(also nicht mit einem Python-Kommentar) beginnt .perl script.pl
vs../script.pl
) , liest der Interpreter die shebang-Zeile, um Flags wie z-w
. Es wird jedoch nicht empfohlen, sich auf diese Funktion zu verlassen.Ein Shebang ist die Zeichenfolge, die aus dem Nummernzeichen und dem Ausrufezeichen (z. B. "#!") Besteht, wenn sie als die ersten beiden Zeichen in der ersten Zeile eines Skripts vorkommt.
Wenn unter * nix-Betriebssystemen ein Skript ausgeführt wird, das mit shebang beginnt, analysiert der Programmlader den Rest der Anfangszeile des Skripts als Interpreter-Direktive. Stattdessen wird das angegebene Interpreterprogramm ausgeführt und als Argument der Pfad übergeben, der ursprünglich verwendet wurde, als versucht wurde, das Skript auszuführen. Zum Beispiel, wenn ein Skript mit dem Pfad "path / to / your-script" benannt ist und mit der folgenden Zeile beginnt:
dann wird der Programmlader angewiesen, das Programm "/ bin / sh" anstelle von zB der Bourne-Shell oder einer kompatiblen Shell auszuführen, wobei als erstes Argument "path / to / your-script" übergeben wird.
Dementsprechend heißt das Skript "path / to / python-script" und beginnt mit der folgenden Zeile:
dann wird das geladene Programm angewiesen, das Programm "/ bin / python" anstelle von zB Python-Interpreter auszuführen, wobei als erstes Argument "path / to / python-script" übergeben wird.
Kurz gesagt, "#" wird eine Zeile auskommentieren, während die Zeichenfolge "#!" Das Auftreten der ersten beiden Zeichen in der ersten Zeile eines Skripts hat die oben angegebene Bedeutung.
Einzelheiten finden Sie unter Warum beginnen einige Skripte mit #! ...?
Quelle: Einige Abschnitte dieser Antwort stammen (mit geringfügigen Änderungen) von Shebang (Unix) in der englischen Wikipedia (von Wikipedia-Mitwirkenden ). Dieser Artikel ist unter CC-BY-SA 3.0 lizensiert , ebenso wie der Benutzerinhalt hier auf AU, daher ist diese Ableitung mit Zuschreibung gestattet.
quelle
#!
wirdshebang
als die ersten zwei Zeichen in der ersten Zeile eines Skripts bezeichnet. Es wird in Skripten verwendet, um einen Interpreter für die Ausführung anzugeben. Dasshebang
ist für das Betriebssystem (Kernel), nicht für die Shell; es wird also nicht als Kommentar interpretiert.Mit freundlicher Genehmigung: http://en.wikipedia.org/wiki/Shebang_%28Unix%29
Detaillierte Informationen: http://wiki.bash-hackers.org/scripting/basics#the_shebang
quelle
Nein, es wird nur vom
exec
Systemaufruf des Linux-Kernels verwendet und vom Interpreter als Kommentar behandeltWenn Sie auf Bash machen:
Unter Linux ruft dies den
exec
Systemaufruf mit dem Pfad auf./something
.Diese Zeile des Kernels wird in der Datei aufgerufen, die an folgende Adresse übergeben wird
exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25Es liest die allerersten Bytes der Datei und vergleicht sie mit
#!
.Wenn der Vergleich wahr ist, wird der Rest der Zeile vom Linux-Kernel analysiert, der einen weiteren
exec
Aufruf mit Pfad/usr/bin/env python
und aktueller Datei als erstes Argument ausführt:Dies funktioniert für alle Skriptsprachen, die
#
als Kommentarzeichen verwendet werden.Und ja, Sie können eine Endlosschleife machen mit:
Bash erkennt den Fehler:
#!
Zufällig ist es für Menschen lesbar, aber das ist nicht erforderlich.Wenn die Datei mit unterschiedlichen Bytes gestartet
exec
würde, würde der Systemaufruf einen anderen Handler verwenden. Der andere wichtigste integrierte Handler ist für ausführbare ELF-Dateien: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305, der nach Bytes sucht7f 45 4c 46
(was zufällig auch menschlich ist) lesbar für.ELF
). Lassen Sie uns das bestätigen, indem wir die 4 ersten Bytes von lesen/bin/ls
, die eine ELF-ausführbare Datei sind:Ausgabe:
Wenn der Kernel diese Bytes sieht, nimmt er die ELF-Datei, speichert sie korrekt und startet damit einen neuen Prozess. Siehe auch: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861
Schließlich können Sie mit dem
binfmt_misc
Mechanismus Ihre eigenen Shebang-Handler hinzufügen . Beispielsweise können Sie einen benutzerdefinierten Handler für.jar
Dateien hinzufügen . Dieser Mechanismus unterstützt sogar Handler nach Dateierweiterung. Eine andere Anwendung besteht darin , ausführbare Dateien einer anderen Architektur transparent mit QEMU auszuführen .Ich glaube jedoch nicht, dass POSIX Shebangs spezifiziert: https://unix.stackexchange.com/a/346214/32558 , obwohl es in den Begründungsabschnitten und in der Form "Wenn ausführbare Skripte vom System unterstützt werden, kann etwas sein" erwähnt geschehen".
quelle