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 shzum Analysieren dieser Befehlszeile (deren Pfad zur Kompilierungszeit festgelegt werden kann (wie bei Solaris im /bin/shVergleich /usr/xpg4/bin/shzu Solaris)) oder zum Aufrufen der $SHELLvon ihnen selbst gespeicherten Shell auf vimit seinem !Befehl oder xterm -e 'command line'vielen anderen Befehlen ( su user -cruft stattdessen die Anmeldeshell des Benutzers auf $SHELL).
Im Allgemeinen wird eine shebang-less-Textdatei, die nicht mit beginnt, #als shSkript betrachtet. Was shes ist, wird jedoch variieren.
execlp()/ execvp(), bei der execve()Rückkehr ENOEXECwird in der Regel darauf aufgerufen sh. Bei Systemen, die mehrere haben, shweil sie mehreren Standards entsprechen können, shwird 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 ... ( bashinterpretiert das Skript im shModus). yashwird sich selbst ausführen (mit shas argv[0]so in shmode) um es zu interpretieren.
zsh, pdksh, ashWird -basierte shells typischerweise aufrufen sh(der Pfad , von denen bei der Kompilierung bestimmt).
Wenn für cshund tcsh(und shfür einige frühe BSDs) das erste Zeichen der Datei ist #, werden sie sich selbst ausführen, um sie zu interpretieren, und shansonsten. Das geht auf eine Zeit vor Shebang zurück, in der die Bourne-Shell als Kommentar csherkannt 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 bashoder 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
$SHELList /bin/bash, xterm -e 'myscript with args'wird myscriptvon bashim shModus interpretiert . Während mit xterm -e myscript with args, xtermwird verwendet, execvp()damit das Skript von interpretiert wird sh.
su -c myscriptUnter Solaris 10, wo sich rootdie Anmeldeshell befindet /bin/shund /bin/shbefindet, wird die Bourne-Shell myscriptvon 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/sheven with interpretiert /usr/xpg4/bin/find.
csh -c myscriptwird interpretiert, cshwenn es mit beginnt #, shsonst 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 -pist bash-only die Syntax, daher sollten Sie sicherstellen, dass das Skript von interpretiert wird bash(und diese irreführende .shErweiterung vermeiden ). Entweder kennen Sie den Pfad der bashausführbaren Datei und verwenden:
#! /path/to/bash -
read -p ...
Oder Sie können versuchen, sich auf eine $PATHSuche nach der bashausführbaren Datei zu verlassen (vorausgesetzt, sie bashist installiert), indem Sie Folgendes verwenden:
#! /usr/bin/env bash
read -p ...
( envist 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"