Fehlerbehandlung mit Trap

ShellBeginner
Jetzt üben

Einführung

Wenn ein Skript ausgeführt wird, erstellt es häufig temporäre Dateien oder startet Hintergrundprozesse. Unterbricht der Benutzer das Skript, zum Beispiel durch Drücken von Ctrl+C, bleiben diese temporären Dateien oft zurück und belasten das System.

Um das zu verhindern, benötigt ein Skript eine Möglichkeit zu erkennen, wann es beendet wird, und die erforderlichen Aufräumarbeiten auszuführen.

Unter Linux verwenden wir den Befehl trap, um Unterbrechungs-signale und Beendigungsereignisse abzufangen. Signale gehören zu den Möglichkeiten, mit denen das Betriebssystem mit Prozessen kommuniziert. Durch Drücken von Ctrl+C wird beispielsweise normalerweise SIGINT gesendet. Damit fordert das Betriebssystem den Prozess zum Beenden auf.

So können wir eine „Beim-Beenden“-Prozedur definieren, damit das Skript vor seiner Beendigung noch aufräumen kann.

In diesem Lab werden Sie:

  1. Ein Skript erstellen, das temporäre Dateien erzeugt.
  2. Das Skript unterbrechen, um die zurückgebliebenen Dateien zu sehen.
  3. Einen Trap einrichten, der die temporären Dateien beim Beenden automatisch löscht.

Einen lang laufenden Prozess erstellen

Erstellen Sie zunächst ein Skript, das eine lange laufende Aufgabe simuliert. Es erstellt eine temporäre Datei und wartet anschließend unbegrenzt.

Lang laufende Skripte kommen häufig bei Administrationsaufgaben zum Einsatz. Sie können beispielsweise ein Protokoll überwachen, auf Eingaben warten, einen Dienst regelmäßig abfragen oder über längere Zeit Aufträge verarbeiten. Je länger ein Skript läuft, desto wichtiger ist das Aufräumen, wenn es unterbrochen wird.

Erstellen und öffnen Sie long_process.sh im Projektverzeichnis:

cd ~/project
nano long_process.sh

Geben Sie diesen Code ein:

#!/bin/bash

## Create a temporary file
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."

## Fall asleep (Simulate a long job)
echo "Process is running. Press Ctrl+C to stop..."
while true; do
  sleep 1
done

Speichern Sie die Datei (Ctrl+O, Enter) und beenden Sie den Editor (Ctrl+X).

Machen Sie das Skript ausführbar:

chmod +x long_process.sh

Das Problem: Wenn Sie das Skript ausführen und anschließend mit Ctrl+C beenden, bleibt die Datei temp_data.txt auf der Festplatte erhalten. Das gilt als schlechte Praxis, da wiederholte Ausführungen den Speicherplatz mit nicht mehr benötigten Dateien füllen können.

Temporäre Dateien sind ein klassisches Beispiel. Dasselbe Problem kann jedoch auch bei Sperrdateien, Sockets, Mountpoints oder Prozessen von Hintergrund-Hilfsprogrammen auftreten. Beim Aufräumen geht es darum, das System in einem vorhersehbaren Zustand zu hinterlassen.

Eine Cleanup-Funktion definieren

Für ein zuverlässiges Aufräumen empfiehlt es sich, eine eigene Funktion zu definieren, die die gesamte Aufräumlogik enthält.

Wenn Sie das Aufräumen in eine separate Funktion auslagern, bleibt das Skript übersichtlich. Außerdem können Sie dieselbe Logik von verschiedenen Beendigungspfaden aus wiederverwenden, anstatt sie an mehreren Stellen zu kopieren.

Öffnen Sie das Skript erneut:

nano long_process.sh

Fügen Sie die Funktion cleanup am Anfang des Skripts ein:

#!/bin/bash

## Define the cleanup function
cleanup() {
  echo ""
  echo "Cleaning up temporary files..."
  rm -f temp_data.txt
  echo "Cleanup complete."
}

## Create a temporary file
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."

## Simulate a long-running process
echo "Process is running. Press Ctrl+C to stop..."
while true; do
  sleep 1
done

Speichern Sie die Datei und beenden Sie den Editor.

In diesem Stadium haben Sie die Funktion definiert, aber dem Skript noch nicht mitgeteilt, wann es sie aufrufen soll.

Einen Trap zum Abfangen von Signalen einrichten

Verwenden Sie jetzt den Befehl trap, um Bash mitzuteilen: „Wenn Sie ein Unterbrechungssignal wie Ctrl+C empfangen, führen Sie die Funktion cleanup aus.“

Dies ist eines der anschaulichsten Beispiele dafür, wie ein Shell-Skript auf Betriebssystemereignisse und nicht nur auf Texteingaben reagiert. Ein Signal ist eine asynchrone Nachricht des Systems oder des Benutzers an einen Prozess. Mit trap kann Ihr Skript gezielt darauf reagieren.

Öffnen Sie das Skript:

nano long_process.sh

Fügen Sie den Befehl trap unterhalb der Funktionsdefinition, aber vor dem Beginn der Hauptlogik ein.

#!/bin/bash

cleanup() {
  echo ""
  echo "Cleaning up temporary files..."
  rm -f temp_data.txt
  echo "Cleanup complete."
  exit
}

## Register the trap
## SIGINT = Ctrl+C
## EXIT = Any exit (success or failure)
trap cleanup SIGINT EXIT

## The rest of the script...
touch temp_data.txt
echo "Temporary file 'temp_data.txt' created."

echo "Process is running. Press Ctrl+C to stop..."
while true; do
  sleep 1
done

Die Argumente von trap verstehen:

  • cleanup: Der auszuführende Befehl oder die auszuführende Funktion.
  • SIGINT: Das Signal, das beim Drücken von Ctrl+C gesendet wird.
  • EXIT: Ein Pseudosignal, das immer dann ausgelöst wird, wenn das Skript aus irgendeinem Grund beendet wird.

Die Verwendung von SIGINT und EXIT macht das Aufräumen zuverlässiger. SIGINT deckt die übliche Unterbrechung über die Tastatur ab, während EXIT ein allgemeineres Sicherheitsnetz für die normale Beendigung und viele Fehlerfälle bietet.

Speichern Sie die Datei und beenden Sie den Editor.

Das Aufräumen überprüfen

Überprüfen Sie nun, ob der Mechanismus funktioniert.

Führen Sie das Skript aus:

./long_process.sh

Das Skript erstellt temp_data.txt und beginnt mit der Ausführung.

Unterbrechen Sie es nun, indem Sie Ctrl+C drücken.

Sie sollten folgende Ausgabe sehen:

^C
Cleaning up temporary files...
Cleanup complete.

Prüfen Sie abschließend, ob die Datei gelöscht wurde:

ls temp_data.txt

Der Befehl sollte einen Fehler wie diesen zurückgeben:

ls: cannot access 'temp_data.txt': No such file or directory

Der Befehl trap hat das Beendigungssignal erfolgreich abgefangen und Ihren Aufräumcode ausgeführt, bevor das Skript beendet wurde.

Das ist eine professionelle Gewohnheit beim Skripting: Wenn ein Skript einen temporären Zustand erzeugt, sollte es auch festlegen, wie dieser Zustand entfernt wird. trap ist eines der wichtigsten Werkzeuge, die Bash dafür bereitstellt.

Zusammenfassung

In diesem Lab haben Sie gelernt, wie Sie mit Trap robuste Skripte schreiben.

  1. Signale: Sie haben verstanden, dass Ctrl+C ein SIGINT-Signal an den Prozess sendet.
  2. Trap: Sie haben trap verwendet, um Signale abzufangen und bestimmten Code auszuführen.
  3. Aufräumen: Sie haben Wartungsaufgaben automatisiert, damit Ihr System sauber bleibt.

Professionelle Skripte behandeln Beendigungsszenarien immer angemessen, um beschädigte Daten und zurückgebliebene Dateien zu verhindern.