Wird beim Ausführen exec echo "some "; echo "test"
in Bash nie „some test“ ausgegeben?
Ich hätte gern eine Bestätigung dieser Frage, da ich ein kleines Shell-Skript schreibe und möchte, dass es nach dem exec
Aufruf des Befehls nicht weiter ausgeführt wird.
Ich glaube, dass ich mir keine Sorgen machen muss, denn nach Rücksprache mit Ihnen verstehe ich Folgendes:
man 3 exec
man 1p exec
Die Shell-Skripte werden, wenn sie von der Shell ausgeführt werden,
- die Shell führt das Programm aus
exec
, das - verwendet die
exec***
Systemaufrufe der Familie, die die Shell/Bash ersetzen, die das Skript ausgeführt hat, dadurchbehinderndweitere Aktionen der Shell (die "ersetzt" wurde)
Wie bereits zuvor dargelegt, besteht das Hauptziel dieser Frage darin, eine Bestätigung meiner Argumentation zu erhalten, um zu verhindern, dass im Skript irgendetwas ausgeführt wird, das nach der Ausführung geschieht (wie z. B. echo test
).
Ich würde mich über eine möglichst allgemeine Antwort (POSIX) freuen, aber falls es Besonderheiten gibt, bin ich am meisten an GNU/Linux und GNU/Bash interessiert.
Antwort1
Richtig, wenn exec
es erfolgreich ist, ersetzt es die aktuelle Shell, sodass die folgenden Befehle nicht, ähm... ausgeführt werden.
Jedoch,zumindest in Bashwird die Shell auch beendet, wenn derexec
schlägt fehl:
exec [-cl] [-a name] [command [arguments]]
WennBefehlangegeben ist, ersetzt es die Shell, ohne einen neuen Prozess zu erstellen. [...] WennBefehlkann aus irgendeinem Grund nicht ausgeführt werden, es sei denn, die
execfail
Shell-Option ist aktiviert. In diesem Fall wird ein Fehler zurückgegeben.
Selbst etwas wie bash -c 'exec /bin/nosuchfile; echo foo'
gibt nur eine Fehlermeldung über die fehlende Programmdatei aus. Um den Fehler im Skript zu behandeln, benötigen Sie etwas wie
#!/bin/bash
shopt -s execfail
exec /someprogram
echo whoops, it failed
Sie erhalten jedoch immer noch die Fehlermeldung von exec
. Wenn Sie eine Umleitung auf die exec
,es bleibt in Kraftwenn das Skript nach dem exec
Fehler fortgesetzt wird.
Antwort2
Das exec
Builtin (mit einem Befehlsargument¹) ersetzt den Shell-Prozess². Es wird kein nachfolgender Code im Shell-Prozess ausgeführt.
Daher würde nur exec echo "some "; echo "test"
gedruckt , wenn im PATH some text
ein ausführbarer Befehl aufgerufen würde und dieser ausführbare Befehl statt gedruckt würde . Dies kann unter normalen Umständen nicht passieren, wenn sich der ausführbare Befehl so verhält, wie man es von einem aufgerufenen Befehl erwarten würde .echo
some text
some
echo
echo
echo
Wenn im PATH keine ausführbare Datei vorhanden ist oder die Ausführung fehlschlägt, exec
wird eine Fehlermeldung angezeigt und die Shell beendet. Auch in diesem Fall echo "test"
wird nicht ausgeführt.
¹ ohne Befehlsargument ist etwas ganz anderes. Es ersetzt nicht den Shell-Prozess, sondern wendet nur Umleitungen an.
² In einer Subshell ist nur die Subshell betroffen, die übergeordnete Shell läuft normal weiter. exec
Antwort3
exec
beendet immer das SkriptWennEs führt einen Befehl aus und tut dies erfolgreich (nicht bezogen auf den Exitcode des Befehls, sondern auf das Starten).
exec
kann auf sehr nützliche Weise ohne Befehl ausgeführt werden: So leiten Sie Datei-Deskriptoren dauerhaft um:
exec 3>/path/to/file
Wenn der Befehl nicht gestartet werden kann, hängt das Verhalten der Shell von der Konfiguration ab. bash
Wird standardmäßig beendet.
Möglicherweise ist es für Sie am besten, stattdessen eine Funktion zu verwenden:
safe_exec () {
cmd="$1"
if test -z "$cmd" || ! test -f "$cmd" || ! test -x "$cmd"; then
exit 1
else
exec "$@"
fi
}
safe_exec echo "some "; echo "test"