Angenommen, die Standard-Shell für mein Konto ist zsh, aber ich habe das Terminal geöffnet und bash gestartet und ein Skript mit dem Namen ausgeführt prac002.sh
. Mit welchem Shell-Interpreter würde das Skript ausgeführt, zsh oder bash? Betrachten Sie das folgende Beispiel:
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % sudo cat /etc/passwd | grep papagolf
[sudo] password for papagolf:
papagolf:x:1000:1001:Rex,,,:/home/papagolf:/usr/bin/zsh
# papagolf's default shell is zsh
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % bash
# I fired up bash. (See that '%' prompt in zsh changes to '$' prompt, indicating bash.)
papagolf@Sierra:~/My Files/My Programs/Learning/Shell$ ./prac002.sh
Enter username : Rex
Rex
# Which interpreter did it just use?
** EDIT: ** Hier ist der Inhalt des Skripts
papagolf@Sierra ~/My Files/My Programs/Learning/Shell % cat ./prac002.sh
read -p "Enter username : " uname
echo $uname
. prac002.sh
Punktquelle ein, vorausgesetzt, Ihr Skript befindet sich im aktuellen Verzeichnis.. ./prac002.sh
und es wird mit der aktuellen Shell ausgeführt, d. H. Dot (.
), space () gefolgt vom Pfad Ihres Skripts. Es heißt Punkt-Sourcing Ihres Skripts. ;-)Antworten:
Da das Skript nicht mit einer
#!
Shebang-Zeile beginnt , die angibt, welcher Interpreter verwendet werden soll, sagt POSIX Folgendes :Diese Formulierung ist ein wenig mehrdeutig und verschiedene Muscheln haben unterschiedliche Interpretationen.
In diesem Fall führt Bash das Skript selbstständig aus . Wenn Sie es stattdessen von zsh aus ausführen, würde
sh
zsh stattdessen verwenden (was auch immer sich auf Ihrem System befindet).Sie können dieses Verhalten für diesen Fall überprüfen, indem Sie dem Skript die folgenden Zeilen hinzufügen:
Sie werden feststellen, dass in Bash die erste Zeile Ihre Version ausgibt, während die zweite nie etwas sagt, egal welche Shell Sie verwenden.
/bin/sh
sind, gibtdash
keine der Zeilen etwas aus, wenn das Skript von zsh oder dash ausgeführt wird./bin/sh
es sich um einen Link zu Bash handelt, wird in jedem Fall die Ausgabe der ersten Zeile angezeigt./bin/sh
es sich um eine andere Version von Bash handelt als die, die Sie direkt verwendet haben, wird eine andere Ausgabe angezeigt, wenn Sie das Skript von Bash direkt und von zsh aus ausführen.Der
ps -p $$
Befehl aus der Antwort von rools zeigt auch nützliche Informationen zu dem Befehl an, den die Shell zum Ausführen des Skripts verwendet hat.quelle
execl()
, wenn ein Shell-Skript keinen Shebang enthält und als ausgeführt wirdscriptname
? Kommt es nicht vor, wenn ein Shell-Skript wie folgt ausgeführt wirdbash scriptname
? Kommt es nicht vor, wenn ein Shell-Skript einen Shebang enthält und als ausgeführt wirdscriptname
?Da es sich bei der Datei nicht um eine vom System erkannte ausführbare Datei handelt und vorausgesetzt, Sie haben die Berechtigung, diese Datei auszuführen, schlägt der
execve()
Systemaufruf normalerweise mit einemENOEXEC
( nicht ausführbaren ) Fehler fehl .Was dann passiert, hängt von der Anwendung und / oder der Bibliotheksfunktion ab, mit der der Befehl ausgeführt wird.
Das kann zum Beispiel eine Shell sein, die
execlp()
/execvp()
libc Funktion.Die meisten anderen Anwendungen verwenden eine dieser Optionen, wenn sie einen Befehl ausführen. Sie rufen eine Shell zum Beispiel über die
system("command line")
libc-Funktion auf, die normalerweisesh
zum Analysieren dieser Befehlszeile (deren Pfad zur Kompilierungszeit festgelegt werden kann (wie bei Solaris im/bin/sh
Vergleich/usr/xpg4/bin/sh
zu Solaris)) oder zum Aufrufen der$SHELL
von ihnen selbst gespeicherten Shell aufvi
mit seinem!
Befehl oderxterm -e 'command line'
vielen anderen Befehlen (su user -c
ruft stattdessen die Anmeldeshell des Benutzers auf$SHELL
).Im Allgemeinen wird eine shebang-less-Textdatei, die nicht mit beginnt,
#
alssh
Skript betrachtet. Wassh
es ist, wird jedoch variieren.execlp()
/execvp()
, bei derexecve()
RückkehrENOEXEC
wird in der Regel darauf aufgerufensh
. Bei Systemen, die mehrere haben,sh
weil sie mehreren Standards entsprechen können,sh
wird dies in der Regel zum Zeitpunkt der Kompilierung ermittelt (von der Anwendung unter Verwendungexecvp()
/execlp()
durch Verknüpfen eines anderen Code-Blocks, der auf einen anderen Pfad verweistsh
). Unter Solaris ist dies beispielsweise entweder/usr/xpg4/bin/sh
(ein Standard, POSIXsh
) oder/bin/sh
(die Bourne-Shell (eine veraltete Shell) unter Solaris 10 und höher, ksh93 in Solaris 11).Wenn es um Muscheln geht, gibt es viele Variationen.
bash
, AT & Tksh
, interpretiert die Bourne-Shell das Skript normalerweise selbst (in einem untergeordneten Prozess, sofern nicht anders angegebenexec
), nachdem Sie eineexecve()
, dh alle nicht exportierten Variablen, zurückgesetzt, alle ausführbaren Dateien geschlossen und alle benutzerdefinierten Traps entfernt haben. Aliase, Funktionen ... (bash
interpretiert das Skript imsh
Modus).yash
wird sich selbst ausführen (mitsh
asargv[0]
so insh
mode) um es zu interpretieren.zsh
,pdksh
,ash
Wird -basierte shells typischerweise aufrufensh
(der Pfad , von denen bei der Kompilierung bestimmt).Wenn für
csh
undtcsh
(undsh
für einige frühe BSDs) das erste Zeichen der Datei ist#
, werden sie sich selbst ausführen, um sie zu interpretieren, undsh
ansonsten. Das geht auf eine Zeit vor Shebang zurück, in der die Bourne-Shell als Kommentarcsh
erkannt wurde,#
aber nicht. Das#
war ein Hinweis darauf, dass es sich um ein csh-Skript handelte.fish
(mindestens Version 2.4.0) gibt nur einen Fehler zurück, wenn dieserexecve()
fehlschlägt (es wird nicht versucht, ihn als Skript zu behandeln).Einige Shells (wie
bash
oder AT & Tksh
) versuchen zunächst heuristisch festzustellen, ob es sich bei der Datei wahrscheinlich um ein Skript handelt oder nicht. Es kann also vorkommen, dass einige Shells die Ausführung eines Skripts ablehnen, wenn es in den ersten Bytes ein NUL-Zeichen enthält.Beachten Sie auch, dass
execve()
einige Shells versuchen, die Shebang-Linie selbst zu interpretieren , wenn ENOEXEC fehlschlägt, die Datei jedoch eine Shebang-Linie enthält.Also ein paar Beispiele:
$SHELL
ist/bin/bash
,xterm -e 'myscript with args'
wirdmyscript
vonbash
imsh
Modus interpretiert . Während mitxterm -e myscript with args
,xterm
wird verwendet,execvp()
damit das Skript von interpretiert wirdsh
.su -c myscript
Unter Solaris 10, wo sichroot
die Anmeldeshell befindet/bin/sh
und/bin/sh
befindet, wird die Bourne-Shellmyscript
von der Bourne-Shell interpretiert./usr/xpg4/bin/awk 'BEGIN{system("myscript")'
unter Solaris 10 wird es von/usr/xpg4/bin/sh
(dasselbe für/usr/xpg4/bin/env myscript
) interpretiert .find . -prune -exec myscript {} \;
Unter Solaris 10 (unter Verwendung vonexecvp()
) wird es sogar in einer POSIX-Umgebung (ein Konformitätsfehler) von/bin/sh
even with interpretiert/usr/xpg4/bin/find
.csh -c myscript
wird interpretiert,csh
wenn es mit beginnt#
,sh
sonst mit.Alles in allem können Sie nicht sicher sein, welche Shell verwendet wird, um das Skript zu interpretieren, wenn Sie nicht wissen, wie und durch was es aufgerufen wird.
In jedem Fall
read -p
istbash
-only die Syntax, daher sollten Sie sicherstellen, dass das Skript von interpretiert wirdbash
(und diese irreführende.sh
Erweiterung vermeiden ). Entweder kennen Sie den Pfad derbash
ausführbaren Datei und verwenden:Oder Sie können versuchen, sich auf eine
$PATH
Suche nach derbash
ausführbaren Datei zu verlassen (vorausgesetzt, siebash
ist installiert), indem Sie Folgendes verwenden:(
env
ist fast allgegenwärtig in/usr/bin
). Alternativ können Sie es POSIX + Bourne-kompatibel machen. In diesem Fall können Sie es verwenden/bin/sh
. Alle Systeme haben eine/bin/sh
. Auf den meisten von ihnen wird es (größtenteils) POSIX-kompatibel sein, aber es kann auch vorkommen, dass Sie dort ab und zu eine Bourne-Shell finden.quelle
Wenn Sie keine
#!
(als shebang bezeichnete ) Leitung haben, wird sh verwendet. Um dies zu überprüfen, können Sie das folgende Skript ausführen.Auf meinem Computer bekomme ich
Auch wenn meine Standard-Shell zsh ist . Es benutzt bash, da auf meinem Rechner der Befehl sh von bash implementiert wird .
quelle