Auf der Seite Shell Command Language der POSIX-Spezifikation:
Wenn die erste Zeile einer Datei mit Shell-Befehlen mit den Zeichen "#!" Beginnt, werden die Ergebnisse nicht angegeben.
Warum ist das Verhalten #!
von POSIX nicht spezifiziert? Ich finde es verblüffend, dass etwas so tragbares und weit verbreitetes ein unspezifisches Verhalten haben würde.
exec()
Funktion implementiert . Wenn Sie also gegen mehrere Shells prüfen, wissen Sie nicht wirklich, wie portabel es ist.Antworten:
Ich denke vor allem, weil:
Das Verhalten ist von Implementierung zu Implementierung sehr unterschiedlich. Weitere Informationen finden Sie unter https://www.in-ulm.de/~mascheck/various/shebang/ .
Es könnte jedoch jetzt eine minimale Teilmenge der meisten Unix-ähnlichen Implementierungen spezifizieren: wie
#! *[^ ]+( +[^ ]+)?\n
(mit nur Zeichen aus dem Zeichensatz des portablen Dateinamens in diesen ein oder zwei Wörtern), wo das erste Wort ein absoluter Pfad zu einer nativen ausführbaren Datei ist, ist das Ding nicht zu lang und Verhalten nicht spezifiziert, wenn die ausführbare Datei setuid / setgid ist und die Implementierung definiert, ob der Interpreterpfad oder der Skriptpfadargv[0]
an den Interpreter übergeben wird.POSIX gibt den Pfad der ausführbaren Dateien sowieso nicht an. Einige Systeme haben Pre-POSIX-Dienstprogramme in
/bin
//usr/bin
und haben die POSIX-Dienstprogramme an einer anderen Stelle (wie in Solaris 10, wo/bin/sh
sich eine Bourne-Shell und die POSIX-Shell befindet/usr/xpg4/bin
; Solaris 11 hat sie durch ksh93 ersetzt, die mehr mit POSIX kompatibel ist, aber die meisten anderen Werkzeuge in/bin
sind immer noch alte Nicht-POSIX- Werkzeuge . Einige Systeme sind keine POSIX-Systeme, verfügen jedoch über einen POSIX-Modus / eine POSIX-Emulation. Für POSIX ist lediglich eine dokumentierte Umgebung erforderlich, in der sich ein System POSIX-gerecht verhält.Siehe zum Beispiel Windows + Cygwin. Tatsächlich wird bei Windows + Cygwin der Wahnsinn gewürdigt, wenn ein Skript von einer Cygwin-Anwendung aufgerufen wird, jedoch nicht von einer nativen Windows-Anwendung.
Selbst wenn POSIX den Shebang-Mechanismus spezifizierte, konnte er nicht zum Schreiben von POSIX
sh
/sed
/awk
...-Skripten verwendet werden (beachten Sie auch, dass der Shebang-Mechanismus nicht zum Schreiben von zuverlässigensed
/awk
Skripten verwendet werden kann, da das Übergeben eines End-of-Option nicht möglich ist Marker).Nun, die Tatsache, dass es nicht spezifiziert ist, bedeutet nicht, dass Sie es nicht verwenden können (nun, es heißt, Sie sollten nicht mit der ersten Zeile beginnen,
#!
wenn Sie erwarten, dass es sich nur um einen regulären Kommentar handelt und nicht um eine Pauke), aber dass POSIX Ihnen sonst keine Garantie gibt.Nach meiner Erfahrung Bauden gibt Ihnen mehr Garantie für Portabilität als Skripte zu schreiben Shell POSIX Weg mit: Abschied von dem sie Bang, schreiben Sie das Skript in POSIX -
sh
Syntax und die Hoffnung , dass was auch immer das Skript ruft eine POSIX - konform ruftsh
darauf, das ist Gut, wenn Sie wissen, dass das Skript in der richtigen Umgebung vom richtigen Tool aufgerufen wird, aber nicht anders.Möglicherweise müssen Sie folgende Aufgaben ausführen:
Wenn Sie auf Windows + Cygwin tragbar sein möchten, können Sie Ihre Datei mit einem Namen haben
.bat
oder.ps1
Erweiterung und verwenden einen ähnlichen Trickcmd.exe
oderpowershell.exe
zum Aufrufen der Cygwinsh
auf der gleichen Datei.quelle
sh
, keine Hashbang-Zeile benötigen, da es von POSIX ausgeführt würdesh
.execlp
oderexecvp
wurden verwendet, oder? Wenn ich verwenden würdeexecve
, würde es zu ENOEXEC führen?Du schaust nicht tief genug.
In den 1980er Jahren war dieser Mechanismus nicht de facto standardisiert. Obwohl Dennis Ritchie es implementiert hatte, hatte diese Implementierung die Öffentlichkeit auf der AT & T-Seite des Universums nicht erreicht. Es war praktisch nur öffentlich verfügbar und in BSD bekannt; mit ausführbaren Shell-Skripten, die unter AT & T Unix nicht verfügbar sind. Daher war es nicht sinnvoll, es zu standardisieren. Der Stand der Dinge wird durch dieses zeitgenössische Dokument veranschaulicht, eines von vielen solchen:
- Stephen Frede (1988). "Programmieren auf System X Release Y". Australischer Newsletter der Unix Systems User Group . Band 9. Nummer 4. p. 111.Ein wichtiger Punkt hierbei ist, dass Sie sich mit Shells befassen, wohingegen die Existenz von ausführbaren Shell-Skripten tatsächlich eine Frage der
exec…()
Funktionen ist. Was Shells tun, schließt die Vorläufer des ausführbaren Skriptmechanismus ein, der auch heute noch in einigen Shells zu finden ist (und auch heutzutage für dieexec…p()
Untermenge von Funktionen vorgeschrieben ist), und ist etwas irreführend. Was der Standard in dieser Hinsicht berücksichtigen muss, ist die Funktionsweiseexec…()
eines interpretierten Skripts, und zu der Zeit, als POSIX ursprünglich erstellt wurde , funktionierte es in einem Großteil des Spektrums der Zielbetriebssysteme überhaupt nicht .Eine untergeordnete Frage ist , warum ist dies , da nicht standardisiert worden, zumal der magische Zahl Mechanismus für die Skript - Interpreter hatte die Öffentlichkeit in der AT & T - Seite des Universums erreicht und hatte dokumentiert
-exec…()
in dem System 5 Interface Definition , durch die Wende der 1990er Jahre :exec
. System V-Schnittstellendefinition . Band 1. 1991.Leider ist das Verhalten heute fast so unterschiedlich wie in den 1980er Jahren, und es gibt kein wirklich verbreitetes Verhalten, das standardisiert werden könnte. Einige Unices (beispielsweise HP-UX und FreeBSD) unterstützen keine Skripte als Interpreter für Skripte. Ob es sich bei der ersten Zeile um ein, zwei oder viele durch Leerzeichen getrennte Elemente handelt, hängt von MacOS (und Versionen von FreeBSD vor 2005) und anderen ab. Die maximal unterstützte Pfadlänge variiert.
␀
und Zeichen außerhalb des POSIX-Zeichensatzes für portable Dateinamen sind ebenso schwierig wie führende und nachfolgende Leerzeichen. Was das 0., 1. und 2. Argument ist, ist ebenfalls schwierig, mit erheblichen Abweichungen zwischen den Systemen. Einige derzeit POSIX-konforme aber nicht-Unix-Systeme unterstützen solche Mechanismen immer noch nicht, und wenn dies vorgeschrieben ist, werden sie nicht mehr POSIX-konform.Weitere Lektüre
script
. NetBSD Miscellaneous Information Manual . 2005-05-06.quelle
Wie in einigen anderen Antworten erwähnt, variieren die Implementierungen. Dies erschwert die Standardisierung und Aufrechterhaltung der Abwärtskompatibilität mit vorhandenen Skripten. Dies gilt auch für moderne POSIX-Systeme. Zum Beispiel tokenisiert Linux die Shebang-Zeile nicht vollständig durch Leerzeichen. Unter macOS darf der Skriptinterpreter kein anderes Skript sein.
Siehe auch http://en.wikipedia.org/wiki/Shebang_(Unix)#Portability
quelle