Wie führe ich einen Befehl aus, bevor ein Bash-Skript beendet wird?

119

Wenn ein Bash-Skript vorhanden ist set -eund ein Befehl im Skript einen Fehler zurückgibt, wie kann ich vor dem Beenden des Skripts eine Bereinigung durchführen?

Beispielsweise:

#!/bin/bash
set -e
mkdir /tmp/foo
# ... do stuff ...
rm -r /tmp/foo

Wie kann ich sicherstellen, dass /tmp/foodas entfernt wird, auch wenn einer der Befehle in ... do stuff ...fehlschlägt?

David Wolever
quelle

Antworten:

193

Hier ist ein Beispiel für die Verwendung von Trap:

#!/bin/bash -e

function cleanup {
  echo "Removing /tmp/foo"
  rm  -r /tmp/foo
}

trap cleanup EXIT
mkdir /tmp/foo
asdffdsa #Fails

Ausgabe:

dbrown@luxury:~ $ sh traptest
t: line 9: asdffdsa: command not found
Removing /tmp/foo
dbrown@luxury:~ $

Beachten Sie, dass die Bereinigung ausgeführt wurde, obwohl die Zeile asdffdsa fehlgeschlagen ist.

devguydavid
quelle
11

Aus der bashManpage (bezüglich Builtins):

trap [-lp] [[arg] sigspec ...]
Der Befehl arg muss gelesen und ausgeführt werden, wenn die Shell die Signale sigspec empfängt.

Rufen Sie also, wie in der Antwort von Anon angegeben , trapfrüh im Skript auf, um den gewünschten Handler für ERR einzurichten.

dmckee --- Ex-Moderator Kätzchen
quelle
Führen Sie die Funktion aus help trap, um Hilfe zum integrierten Gerät zu erhalten.
Flimm
8

Aus der Referenz für set:

-e

Beenden Sie das Programm sofort, wenn ein einfacher Befehl (siehe Abschnitt 3.2.1 Einfache Befehle) mit einem Status ungleich Null beendet wird, es sei denn, der fehlgeschlagene Befehl ist Teil einer till- oder while-Schleife, Teil einer if-Anweisung, Teil eines && oder || Liste, oder wenn der Rückgabestatus des Befehls mit! invertiert wird. Ein Trap auf ERR wird, falls gesetzt, ausgeführt, bevor die Shell beendet wird.

(Hervorhebung von mir).

Anon.
quelle
Es könnte sich lohnen, "-E" hinzuzufügen, wenn "-e" verwendet wird, siehe vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail
Max Barraclough
3

shVersion von Devguydavids Antwort .

#!/bin/sh
set -e
cleanup() {
  echo "Removing /tmp/foo"
  rm  -r /tmp/foo
}
trap cleanup EXIT
mkdir /tmp/foo
asdffdsa #Fails

ref: shellscript.sh

Saftever
quelle
POSIXbringt mich zum Lächeln. :) Tolle Lehrseite, auf die du auch verlinkt hast.
Kometengesang