Shell-Skripte funktionieren immer noch ohne #! (Sha-Bang-Linie)

10

Ich bin neu in Shell-Skripten und viele Bücher haben geschrieben, die die Zeile #! (Sha-bang) am Anfang des Skripts verwenden, um den Interpreter aufzurufen. Und dies ruft eine neue Shell für Skripte auf und führt die Interpretation Zeile für Zeile durch. Aber eine meines Basisskripts läuft immer noch ohne die magische Linie.

Meine Fragen sind also:

  • Woher hat mein Basisskript den Interpreter?
  • Wie hat das Skript den Interpreter gefunden?

Lassen Sie mich Ihnen jetzt etwas über mein Basisskript erzählen, das nur die folgende Zeile enthält:

Echo "Basisskript ohne die magischen Linien"

user1678213
quelle

Antworten:

3

Wenn die magische Linie nicht angegeben ist, wird eine Standard-Shell zum Ausführen des Skripts verwendet. Diese Standard-Shell kann entweder eine Bourne-Shell (sh) sein, was in einigen Varianten der Fall ist. In einigen anderen Varianten entspricht die verwendete Standard-Shell jedoch der Anmeldeschale, um sie auszuführen. Die Sache ist: Überlassen Sie es nicht dem System, die Shell zu bestimmen, sondern geben Sie immer die gewünschte Shell in der ersten Zeile an.

Guru
quelle
1
yup..may meine aktuelle Shell ruft eine Standard-Shell für Shell-Skript ohne magische Zahlen auf.
user1678213
1
@ user1678213 Ja, es ist Ihre Shell (und nicht der Kernel), die dies tut.
Gilles 'SO - hör auf böse zu sein'
1
Ich glaube, POSIX schreibt vor, dass in diesem Fall / bin / sh verwendet wird.
vonbrand
2
@vonbrand Dies ist ein häufiges Missverständnis. POSIX schreibt nicht vor, dass die POSIX-Shell /bin/shdie erste shausführbare Datei ist, die beim Erkunden eines konformen Pfads gefunden wird.
Jlliagre
3
Das ist falsch, es ist nie die "Login-Shell" , die verwendet wird, um es auszuführen. Was jedoch passieren kann, ist, dass die aufrufende Shell (wenn das Skript von einer Shell aufgerufen wird) möglicherweise von einem untergeordneten Element interpretiert wird.
Stéphane Chazelas
8

Wenn Sie ein Programm ausführen, prüft der Kernel, ob es mit einer magischen Bytesequenz startet . Wenn die ausführbare Datei mit beginnt #!, interpretiert der Kernel den Rest der Zeile als Interpreternamen. Wenn die ausführbare Datei mit beginnt \177ELF(wobei \177Byte 127 ist), wird die Datei als ausführbare ELF- Datei geladen. Das ist heutzutage die normale Art auf den meisten Unix-Systemen.

Wenn der Kernel das Dateiformat nicht erkennt, weigert er sich, die Datei auszuführen, und gibt den Fehler ENOEXEC (Exec format error) zurück. Wenn die Shell dies bemerkt, muss sie das Programm als Shell-Skript ausführen.

Fügen Sie Ihrem Skript einige Befehle hinzu, um dies in Aktion zu beobachten:

ps l $$
ls -l /proc/$$/exe
echo hello

(Dies ist für Linux, passen Sie es an andere Unices an.) Versuchen Sie dann, dieses Skript von verschiedenen Shells aus auszuführen. Sie werden sehen, dass einige Shells neue Instanzen von sich selbst /bin/sherzeugen, um das Skript auszuführen (bash, ksh93), während andere erscheinen (dash, pdksh, zsh).

Gilles 'SO - hör auf böse zu sein'
quelle
Was suche ich mit Ihrem ls -lBefehl? Dies: lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash-? Wenn ja, was steht darin? Auch bemerkte ich SHELL=/bin/bashauf env, aber ändert es nicht zu ändern Verhalten schien. Vielleicht hat es nichts damit zu tun?
Emanuel Berg
Es scheint, als würden Sie die Shell-Variable "SHELL" ändern. Wenn ja, ändern Sie nur den Wert der Shell-Variablen SHELL. Sie ändern Ihre Shell nicht. Um Ihre Shell zu ändern, bearbeiten Sie die Datei / etc / passwd.
user1678213
2
@EmanuelBerg Ja (ich hätte eigentlich schreiben ls -l /proc/$$/exesollen). Die exeLinks verweisen auf die Shell, die Ihr Skript ausführt. Wenn Sie Ihr Skript ausführen, werden Sie feststellen, dass es Bash ist, das das Skript interpretiert. Wenn Sie es beispielsweise von pdksh aus ausführen, wird es ausgeführt /bin/sh. Ich kenne keine Shell, die unter SHELLdiesen Umständen die Umgebungsvariable oder die Login-Shell verwendet.
Gilles 'SO - hör auf böse zu sein'
2
@ user1678213 Durch Ändern der Shell wird /etc/passwdgeändert, welche Shell ausgeführt wird, wenn Sie sich über SSH oder an einer Textkonsole anmelden. Es ändert nichts daran, welche Shell Skripte ausführen kann.
Gilles 'SO - hör auf böse zu sein'
2
@ user1678213 Ich habe überprüft, was ich hier geschrieben habe, indem ich Tests ausgeführt habe. Keine der von mir getesteten Shells hat nachgesehen, um /etc/passwdzu entscheiden, welche Shell verwendet werden soll. Sie haben entweder eine Instanz von sich selbst gegabelt oder ausgeführt /bin/sh.
Gilles 'SO - hör auf böse zu sein'
-2

Es ist wahrscheinlich eine der folgenden 3 Möglichkeiten:

  1. Sie rufen das Skript direkt mit dem Interpreter IE: bash script.sh auf

  2. Der Name der Skriptdatei hat die Erweiterung .sh, mit der das System nach dem Standardprogramm für diesen Dateityp sucht

  3. Die Shell-Umgebung, die Sie verwenden, führt das 'Echo' selbst aus, da ich nur vermuten kann, dass die Skriptdatei ausführbar ist. Wenn Sie beispielsweise eine Bash-Shell verwenden und einen Befehl in Ihrer Datei haben, der nur von ksh verwendet wird, werden Sie feststellen, dass dies nicht funktioniert.

Viel Glück!

bizna
quelle
3
Weder habe ich es mit Bash noch mit einer Erweiterung genannt.
user1678213
1
und die Shell-Umgebung führt es nicht aus, weil beim Aufrufen des Befehls ps nach dem Aufrufen meines Skripts. Der Befehl ps zeigt zwei Bash-Prozesse an. Dies bedeutet, dass zwei Bash ausgeführt werden. Eine ist meine Login-Bash-Shell und die andere ist Bash für mein basic_script
user1678213
1
2: Der Kernel macht so etwas nicht. Zsh kann es tun, und Bash kann dazu verdreht werden. 3: Ja, aber es variiert ein bisschen zwischen den Muscheln, siehe meine Antwort.
Gilles 'SO - hör auf böse zu sein'