Das mag eine dumme Frage sein, aber ich frage es immer noch. Wenn ich einen Shebang deklariert habe
#!/bin/bash
am anfang my_shell_script.sh
muss ich dieses script immer mit bash aufrufen
[my@comp]$bash my_shell_script.sh
oder kann ich zB benutzen
[my@comp]$sh my_shell_script.sh
und mein script ermittelt die laufende shell mit dem shebang? Ist es dasselbe, was mit ksh
Shell passiert ? Ich benutze AIX.
scripting
executable
shebang
jrara
quelle
quelle
chmod +x my_shell_script.sh ; /path/to/my_shell_script.sh # or ./my_shell_script.sh if you happen to be in its directory
Antworten:
Der Shebang
#!
ist eine für den Menschen lesbare Instanz einer magischen Zahl, die aus der Byte-Zeichenfolge0x23 0x21
besteht und von derexec()
Funktionsfamilie verwendet wird, um zu bestimmen, ob es sich bei der auszuführenden Datei um ein Skript oder eine Binärdatei handelt. Wenn der Shebang vorhanden ist,exec()
wird stattdessen die nach dem Shebang angegebene ausführbare Datei ausgeführt.Beachten Sie, dass dies bedeutet, dass beim Aufrufen eines Skripts durch Angabe des Interpreters in der Befehlszeile, wie in beiden in der Frage angegebenen Fällen, der in
exec()
der Befehlszeile angegebene Interpreter ausgeführt wird, das Skript nicht einmal angezeigt wird.Wenn Sie also, wie andere angemerkt haben,
exec()
den in der shebang-Zeile angegebenen Interpreter aufrufen möchten , muss für das Skript das ausführbare Bit gesetzt und aufgerufen werden als./my_shell_script.sh
.Das Verhalten lässt sich mit dem folgenden Skript leicht demonstrieren:
Erläuterung:
#!/bin/ksh
legt festksh
, der Dolmetscher zu sein.$$
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 des symbolischen Links aus.Beispiel:
Hinweis : Ich bin demonstriert dies auf Ubuntu, wo die Standard - Shell
/bin/sh
ein symbolischer Link zu schleudern also/bin/dash
und/bin/ksh
ist ein symbolischer Link auf/etc/alternatives/ksh
, was wiederum ein symbolischer Link zu/bin/pdksh
.quelle
exec()
dieser Antwort wird auf einen Systemaufruf verwiesen. Der Befehlexec
ist eine eingebaute Shell. Aus diesem Grund können Sie einexec
Programm nicht über Node.js oder Java aufrufen . Jeder Shell-Befehl, der beispielsweiseRuntime.exec()
in Java aufgerufen wird, wird schließlich vomexec()
Systemaufruf verarbeitet .child_process.{exec(),execFile(),spawn()
} alles würde mit dem Cexec()
(durchprocess
) implementiert werden .Ja tut es. Übrigens ist es keine dumme Frage. Eine Referenz für meine Antwort ist hier . Starten eines Skripts mit #!
Es wird ein Shebang oder eine "Bang" -Linie genannt.
Es ist nichts anderes als der absolute Weg zum Bash-Interpreter.
Es besteht aus einem Nummernzeichen 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 bei Bell Laboratories eingeführt. Es wurde dann auch der BSD-Linie in Berkeley hinzugefügt.
Ignorieren einer Dolmetscherzeile (shebang)
Wenn Sie keine Interpreterzeile angeben, ist die Standardeinstellung normalerweise / bin / sh. Es wird jedoch empfohlen, die Zeile #! / Bin / bash festzulegen.
quelle
#!/usr/bin/perl
#!/usr/local/bin/python
#!/usr/local/bin/ruby
Ein anderer allgemeiner shebang-Eintrag, der zur Unterstützung mehrerer Systeme verwendet wird, ist die Verwendung von env, um den Interpreter zu finden, den Sie verwenden möchten, beispielsweise#!/usr/bin/env perl
#!/usr/bin/env python
env
, was sollte eigentlich vorgezogen werden? Bei Python und Perlenv
wird dies häufig weggelassen, während bei Shellskripten shebang auf die betreffende Shell verweist.env
Ein Programm in $ PATH zu finden ist ein bisschen hacken. Es werden keine Umgebungsvariablen gesetzt, wie der Name impliziert. $ PATH kann für verschiedene Benutzer ein unterschiedliches Ergebnis sein. Aber es hilft Skripten, ohne Modifikation auf Systemen zu laufen, die einen vernünftigen Perl-Interpreter an einer merkwürdigen Stelle platzieren.Der
exec
Systemaufruf des Linux-Kernels versteht shebangs (#!
) nativWenn 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 weitergeleitet 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
, bei denen es sich um eine ELF-ausführbare Datei handelt: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 dies in Begründungsabschnitten und in der Form "Wenn ausführbare Skripte vom System unterstützt werden" erwähnt könnte passieren".
quelle
./something
von einer Shell wird nicht der vollständige Pfad an übergebenexec
, sondern genau der eingegebene Pfad. Können Sie dies in Ihrer Antwort korrigieren? Machen Sieecho "$0"
in Ihrem Skript und Sie werden sehen, dass dies der Fall ist.Wenn Sie es konsequent nehmen, ist die ausführbare Datei, die in der shebang-Zeile angegeben ist, 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:
Die Datei test.txt genannt und stellten Sie das ausführbare Bit
chmod u+x test.txt
„genannt , “ es dann:./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 Interpreter sollte daher in der Lage sein, diese Shebang-Linie zu ignorieren. Für Bash, Perl und PHP ist es einfach eine Kommentarzeile. Also ja, diese ignorieren die Shebang-Linie.quelle
Wenn für eine Datei ein ausführbares Bit gesetzt ist und aufgerufen wird, analysiert der Kernel den Dateiheader, um festzustellen, wie vorzugehen ist (meines Wissens können Sie benutzerdefinierte Handler für benutzerdefinierte Dateiformate über LKMs hinzufügen). Wenn die Datei eine Textdatei mit einem # zu sein scheint! Kombination zu Beginn wird seine Ausführung an eine andere ausführbare Datei (normalerweise eine Art Shell) gesendet, deren Pfad direkt nach dem besagten Shebang in derselben Zeile angegeben werden soll. Der Kernel führt dann die Shell aus und übergibt die Datei zur Bearbeitung.
Kurz gesagt, es spielt keine Rolle, mit welcher Shell Sie das Skript aufrufen - der Kernel leitet die Ausführung auf die entsprechende Weise weiter.
quelle
bash ./myscript.sh
und./myscript.sh
.