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 einem ENOEXEC
( 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 normalerweise sh
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 auf vi
mit seinem !
Befehl oder xterm -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, #
als sh
Skript betrachtet. Was sh
es ist, wird jedoch variieren.
execlp()
/ execvp()
, bei der execve()
Rückkehr ENOEXEC
wird in der Regel darauf aufgerufen sh
. 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 Verwendung execvp()
/ execlp()
durch Verknüpfen eines anderen Code-Blocks, der auf einen anderen Pfad verweist sh
). Unter Solaris ist dies beispielsweise entweder /usr/xpg4/bin/sh
(ein Standard, POSIX sh
) 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 & T ksh
, interpretiert die Bourne-Shell das Skript normalerweise selbst (in einem untergeordneten Prozess, sofern nicht anders angegeben exec
), nachdem Sie eine execve()
, dh alle nicht exportierten Variablen, zurückgesetzt, alle ausführbaren Dateien geschlossen und alle benutzerdefinierten Traps entfernt haben. Aliase, Funktionen ... ( bash
interpretiert das Skript im sh
Modus). yash
wird sich selbst ausführen (mit sh
as argv[0]
so in sh
mode) um es zu interpretieren.
zsh
, pdksh
, ash
Wird -basierte shells typischerweise aufrufen sh
(der Pfad , von denen bei der Kompilierung bestimmt).
Wenn für csh
und tcsh
(und sh
für einige frühe BSDs) das erste Zeichen der Datei ist #
, werden sie sich selbst ausführen, um sie zu interpretieren, und sh
ansonsten. Das geht auf eine Zeit vor Shebang zurück, in der die Bourne-Shell als Kommentar csh
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 dieser execve()
fehlschlägt (es wird nicht versucht, ihn als Skript zu behandeln).
Einige Shells (wie bash
oder AT & T ksh
) 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:
- Wann
$SHELL
ist /bin/bash
, xterm -e 'myscript with args'
wird myscript
von bash
im sh
Modus interpretiert . Während mit xterm -e myscript with args
, xterm
wird verwendet, execvp()
damit das Skript von interpretiert wird sh
.
su -c myscript
Unter Solaris 10, wo sich root
die Anmeldeshell befindet /bin/sh
und /bin/sh
befindet, wird die Bourne-Shell myscript
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 von execvp()
) 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
ist bash
-only die Syntax, daher sollten Sie sicherstellen, dass das Skript von interpretiert wird bash
(und diese irreführende .sh
Erweiterung vermeiden ). Entweder kennen Sie den Pfad der bash
ausführbaren Datei und verwenden:
#! /path/to/bash -
read -p ...
Oder Sie können versuchen, sich auf eine $PATH
Suche nach der bash
ausführbaren Datei zu verlassen (vorausgesetzt, sie bash
ist installiert), indem Sie Folgendes verwenden:
#! /usr/bin/env bash
read -p ...
( 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.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"