Ich habe in dieser Frage Folgendes gelesen :
bash unterstützt einen --posix-Schalter, wodurch es POSIX-kompatibler wird. Es wird auch versucht, POSIX nachzuahmen, wenn es als sh aufgerufen wird .
Das obige Zitat geht davon aus, dass /bin/sh
es sich um einen Link handelt, auf den verwiesen wird /bin/bash
.
Aber ich verstehe nicht ganz, was unter "als sh angerufen" zu verstehen ist .
Angenommen, ich habe das folgende Skript mit dem Namen "script.sh":
#!/bin/bash
echo "Hello World"
Bitte teilen Sie mir in jedem der folgenden Fälle mit, ob das Skript im normalen bash
Modus oder im POSIX-Modus ausgeführt wird (vorausgesetzt, ich habe die folgenden Befehle in einem Terminal ausgeführt, das ausgeführt wird bash
):
sh script.sh
bash script.sh
./script.sh
Sagen Sie jetzt, dass ich das folgende Skript habe, das "script.sh" heißt (das wie das obige Skript ist, aber ohne den Shebang):
echo "Hello World"
Bitte teilen Sie mir in jedem der folgenden Fälle mit, ob das Skript im normalen bash
Modus oder im POSIX-Modus ausgeführt wird (vorausgesetzt, ich habe die folgenden Befehle in einem Terminal ausgeführt, das ausgeführt wird bash
):
sh script2.sh
bash script2.sh
./script2.sh
Antworten:
Nur die Fälle 1 und 4 werden im POSIX-Modus ausgeführt (vorausgesetzt, dies
sh
ist Bash und keine andere Implementierung von sh). Jeder Fall, der explizitbash
ohne ruft,--posix
wird nicht, ob vom Schebang oder nicht. Jeder Fall, der explizit aufruft,sh
wird. Der Shebang wird nur verwendet, wenn noch keine Shell explizit für das Skript gestartet wurde.Fall 6, wenn Ihr Terminal ausgeführt wird
bash
, wird nicht im POSIX-Modus ausgeführt und Bash ruft es mit sich selbst auf. Wenn Ihr Terminal zsh ausgeführt wurde stattdessen Fall 6 würde auch im POSIX - Modus. POSIX ist sich nicht sicher, was genau in diesem Fall passieren soll , und Bash und zsh haben dort unterschiedliche Entscheidungen getroffen. Bash ruft das Skript mit sich selbst auf, während zsh es verwendetsh
(was auch immer das sein mag). In diesem Punkt variieren auch andere Schalen.Eine einfache Möglichkeit, um festzustellen, in welchem Modus Sie sich befinden, besteht darin, Ihren Skriptkörper zu erstellen:
Dies schlägt mit einem Fehler im POSIX-Modus fehl , gibt jedoch Anweisungen zur Verwendung
kill
außerhalb des POSIX-Modus . Dies ist eine einfache Unterscheidung und funktioniert durch eine Vielzahl von Bash-Versionen, die so weit zurückreichen, wie es wahrscheinlich ist.quelle
bash
die im POSIX-Modus ausgeführt werden müssen, z. B. diePOSIXLY_CORRECT
Umgebungsvariable oderSHELLOPTS=posix
.[ -o posix ]
Dies ist eine naheliegendere Methode, um zu überprüfen, ob Sie in Bash im Posix-Modus ausgeführt werden (nicht in anderen Shells (außer Yash), daher möchten Sie dies nicht in einemsh
Skript tun ).POSIXLY_CORRECT=1 bash -c '[ -o posix ] && echo yes'
Ausgabenyes
`Das "aufgerufen als" bezieht sich auf alles, was der Prozess, der Bash startet, in sein "nulltes" Befehlszeilenargument einfügt
argv[0]
.Wenn ein Programm mit den
exec*()
Syscalls gestartet wird, erfahren sie nicht wirklich den Namen der Binärdatei, die das Programm enthält, sondern der aufrufende Prozess kann dort beliebig viel ablegen . Normalerweise wird der Name natürlich aus dem Dateisystem übernommen. Wenn Sie also ausführen/bin/sh
, wird dieser dort abgelegt. Und wenn/bin/sh
es sich um Bash handelt, muss es sich nicht um einen Symlink handeln, sondern um einen Hardlink oder nur um eine weitere Kopie des Shell-Programms.Als Beispiel für das Setzen des "Programmnamens" kann der
exec
Befehl von Bash das nullte Argument mit der-a
Option setzen. (Wir könnten dasselbe mit Perl oder direkt mit C usw. machen.)Hier
myname
ist ein einfaches C-Programm, das nur sein nulltes Argument druckt, den Namen, den es selbst sieht:Quelle:
Aber um die nummerierten Fragen zu beantworten ...
(1 & 4) Laufen
sh somescript
wird laufen, was auchsh
immer auf Ihrem istPATH
, wahrscheinlich/bin/sh
aber möglicherweise so etwas/usr/xpg4/bin/sh
.sh
.sh
wird jedoch im "SH-kompatiblen" Modus ausgeführt, der darauf abzielt, mit der Bourne-Shell kompatibel zu sein, und sich in beiden Shells geringfügig vom vollständigen POSIX-konformen Modus unterscheidet .(2 & 5) Das Laufen
bash somescript
wird im regulären Bash-Modus ausgeführt (wieder hängt es natürlich davon ab, was sichbash
in IhremPATH
befindet.)(3) Hier wird der Name des Skripts anstelle der Programmdatei direkt dem Systemaufruf gegeben. Der Kernel liest die Hashbang-Zeile und verwendet sie zum Ausführen des Skripts.
(6) Dies ist die komplexe. Es ist ähnlich wie (3), aber der Systemaufruf zum Starten des Programms schlägt fehl (
ENOEXEC (Exec format error)
), da keine Hashbang-Zeile vorhanden ist. Was als nächstes passiert, hängt davon ab, ob sich die von Ihnen ausgeführte Shell selbst im POSIX-Modus befindet. POSIX erfordert, dass sich eine POSIX-konforme Shell als Reaktion auf eine bestimmte Art und Weise verhältENOEXEC
. Es gibt jedoch einen gewissen Spielraum in "einem Befehl, der dem Aufrufen einer Shell entspricht", was bedeutet, dass verschiedene Shells unterschiedliche Aufgaben ausführen./bin/sh
mit dem Namen des Skripts ausgeführt, das vor den anderen Argumenten als erstes Befehlszeilenargument eingefügt wurde. Die Z-Shell, die Almquist-Shell und die Korn-Shell versuchen, eine POSIX-konforme Shell aufzurufen, indem angenommen wird, dass es sich bei dem/bin/sh
Programm um eines handelt.quelle
int main(int argc, char *argv[]){printf("I am %s\n",argv[0]);}
Die ausgeführte Shell ist entweder die in der Befehlszeile aufgerufene oder die im Shebang aufgerufene (wenn die Befehlszeile dies nicht angibt).
Daher werden die Versionen 1 und 4 mit
sh
, 2 und 5 mit Bash und 6 möglicherweise nicht ausgeführt, wenn Sie sh (und einige andere) interaktiv verwenden. Bash startet das Skript. Ksh auch. Zsh startet es als sh.Nur diejenigen, die als gestartet wurden
sh
, verwenden die Option posix, wenn bash mit verknüpft ist/bin/sh
.Fügen Sie diese Zeile zu Ihrem Skript hinzu, um festzustellen, ob eine bash ksh- oder zsh-Version ausgeführt wird:
quelle