Wird bei der Ausführung von „exec echo some; echo test“ in Bash nie „some test“ ausgegeben?

Wird bei der Ausführung von „exec echo some; echo test“ in Bash nie „some test“ ausgegeben?

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 execAufruf 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,

  1. die Shell führt das Programm aus exec, das
  2. 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 execes 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 execfailShell-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 execFehler fortgesetzt wird.

Antwort2

Das execBuiltin (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 textein 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 .echosome textsomeechoecho

echoWenn im PATH keine ausführbare Datei vorhanden ist oder die Ausführung fehlschlägt, execwird 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

execbeendet immer das SkriptWennEs führt einen Befehl aus und tut dies erfolgreich (nicht bezogen auf den Exitcode des Befehls, sondern auf das Starten).

execkann 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. bashWird 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"

verwandte Informationen