it-swarm.com.de

Bestimmt der Shebang die Shell, die das Skript ausführt?

Das mag eine dumme Frage sein, aber ich stelle sie trotzdem. Wenn ich einen Shebang deklariert habe

#!/bin/bash 

am Anfang von my_Shell_script.sh, also muss ich dieses Skript immer mit bash aufrufen

[[email protected]]$bash my_Shell_script.sh

oder kann ich z.B.

[[email protected]]$sh my_Shell_script.sh

und mein Skript bestimmt die laufende Shell mit dem Shebang? Ist es dasselbe mit ksh Shell? Ich benutze AIX.

90
jrara

Das Shebang#! Ist eine vom Menschen lesbare Instanz eines magische Zahl bestehend aus der Byte-Zeichenfolge 0x23 0x21, Die von der verwendet wird exec() Funktionsfamilie, um zu bestimmen, ob die auszuführende Datei ein Skript oder eine Binärdatei ist. Wenn der Shebang vorhanden ist, führt exec() stattdessen die nach dem Shebang angegebene ausführbare Datei aus.

Beachten Sie, dass dies bedeutet, dass exec(), wenn Sie ein Skript aufrufen, indem Sie den Interpreter in der Befehlszeile angeben, wie dies in beiden Fällen in der Frage der Fall ist Führen Sie den in der Befehlszeile angegebenen Interpreter aus. Das Skript wird nicht einmal angezeigt.

Wie andere angemerkt haben, muss für das Skript das ausführbare Bit gesetzt und als ./my_Shell_script.sh Aufgerufen werden, wenn exec() den in der Shebang-Zeile angegebenen Interpreter aufrufen soll.

Das Verhalten lässt sich mit dem folgenden Skript leicht demonstrieren:

#!/bin/ksh
readlink /proc/$$/exe

Erläuterung:

  • #!/bin/ksh Definiert ksh als Interpreter.

  • $$ Enthält die PID des aktuellen Prozesses.

  • /proc/pid/exe Ist ein Symlink zur ausführbaren Datei des Prozesses (zumindest unter Linux; unter AIX ist /proc/$$/object/a.out ein Link zur ausführbaren Datei).

  • readlink gibt den Wert der symbolischen Verknüpfung aus.

Beispiel:

Hinweis : Ich demonstriere dies unter Ubuntu, wo die Standard-Shell /bin/sh Ein Symlink zu dash ist, d. H. /bin/dash Und /bin/ksh Ist ein Symlink zu /etc/alternatives/ksh, Der wiederum ein Symlink zu /bin/pdksh Ist.

$ chmod +x getshell.sh
$ ./getshell.sh 
/bin/pdksh
$ bash getshell.sh 
/bin/bash
$ sh getshell.sh 
/bin/dash
123
Thomas Nyman

Ja tut es. Übrigens ist es keine dumme Frage. Eine Referenz für meine Antwort ist hier . Starten eines Skripts mit #!

  • Es wird eine Shebang- oder "Bang" -Linie genannt.

  • Es ist nichts anderes als der absolute Weg zum Bash-Interpreter.

  • Es besteht aus einem Zahlenzeichen und einem Ausrufezeichen (#!), Gefolgt vom vollständigen Pfad zum Interpreter wie/bin/bash.

    Alle Skripte unter Linux werden mit dem in der ersten Zeile angegebenen Interpreter ausgeführt. Fast alle Bash-Skripte beginnen häufig mit #!/Bin/bash (vorausgesetzt, Bash wurde in/bin installiert). Dadurch wird sichergestellt, dass Bash auch zur Interpretation des Skripts verwendet wird wenn es unter einer anderen Shell ausgeführt wird. Der Shebang wurde von Dennis Ritchie zwischen Version 7 Unix und 8 in den Bell Laboratories eingeführt. Es wurde dann auch in die BSD-Linie in Berkeley aufgenommen.

Ignorieren einer Dolmetscherzeile (Shebang)

Wenn Sie keine Interpreterzeile angeben, ist die Standardeinstellung normalerweise/bin/sh. Es wird jedoch empfohlen, die Zeile #!/Bin/bash festzulegen.

9
vfbsilva

Der Systemaufruf exec des Linux-Kernels versteht Shebangs (#!) Nativ

Wenn Sie auf Bash tun:

./something

unter Linux ruft dies den Systemaufruf exec mit dem Pfad ./something auf.

Diese Zeile des Kernels wird für die an exec übergebene Datei aufgerufen: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25 =

if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))

Es liest die ersten Bytes der Datei und vergleicht sie mit #!.

Wenn der Vergleich wahr ist, wird der Rest der Zeile vom Linux-Kernel analysiert, der einen weiteren Aufruf von exec mit dem Pfad /usr/bin/env python Und der aktuellen Datei als erstem Argument ausführt:

/usr/bin/env python /path/to/script.py

dies funktioniert für jede Skriptsprache, die # als Kommentarzeichen verwendet.

Und ja, Sie können eine Endlosschleife erstellen mit:

printf '#!/a\n' | Sudo tee /a
Sudo chmod +x /a
/a

Bash erkennt den Fehler:

-bash: /a: /a: bad interpreter: Too many levels of symbolic links

#! Ist zufällig für Menschen lesbar, aber das ist nicht erforderlich.

Wenn die Datei mit unterschiedlichen Bytes gestartet würde, würde der Systemaufruf exec 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 sucht 7f 45 4c 46 (Was auch für .ELF Vom Menschen lesbar ist). Lassen Sie uns dies bestätigen, indem Sie die 4 ersten Bytes von /bin/ls Lesen, einer ausführbaren ELF-Datei:

head -c 4 "$(which ls)" | hd 

ausgabe:

00000000  7f 45 4c 46                                       |.ELF|
00000004                                                                 

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 Mechanismus binfmt_misc Ihre eigenen Shebang-Handler hinzufügen. Sie können beispielsweise ein benutzerdefinierter Handler für .jar - Dateien hinzufügen. Dieser Mechanismus unterstützt sogar Handler nach Dateierweiterung. Eine andere Anwendung ist ausführbare Dateien einer anderen Architektur mit QEMU transparent ausführen .

Ich glaube nicht, dass POSIX Shebangs spezifiziert: https://unix.stackexchange.com/a/346214/32558 , obwohl es in Begründungsabschnitten und in der Form "falls ausführbar" erwähnt wird Skripte werden vom System unterstützt, es kann etwas passieren ".

Wenn Sie es konsequent nehmen, ist die in der Shebang-Zeile angegebene ausführbare Datei nur eine ausführbare Datei. Es ist sinnvoll, einen Textinterpreter als ausführbare Datei zu verwenden, dies ist jedoch nicht erforderlich. Nur zur Verdeutlichung und Demonstration habe ich einen ziemlich nutzlosen Test gemacht:

#!/bin/cat
useless text
more useless text
still more useless text

Benannte die Datei test.txt und setzte das ausführbare Bit chmod u+x test.txt, dann "nannte" es: ./test.txt. Wie erwartet wird der Inhalt der Datei ausgegeben. In diesem Fall ignoriert cat die Shebang-Linie nicht. Es werden einfach alle Zeilen ausgegeben. Jeder nützliche Dolmetscher sollte daher in der Lage sein, diese Shebang-Zeile zu ignorieren. Für Bash, Perl und PHP ist es einfach eine Kommentarzeile. Also ja, diese ignorieren die Shebang-Linie.

4
Siegfried