timeout: Befehle, die sich festfahren, nach N Sekunden abbrechen
Ein Skript, das jede Nacht läuft, hängt irgendwann an einem Server, der nicht mehr antwortet – und dann läuft es eben nicht mehr zu Ende. timeout ist ein einziges Wort vor dem Befehl und macht aus dem Hänger einen sauberen Fehler.
Der unangenehmste Fehler in einem Automatisierungsskript ist nicht der Absturz. Es ist der Stillstand: curl wartet auf einen Server, der die Verbindung offen hält und nichts sendet. Das Skript wartet mit. Am nächsten Morgen ist die Sicherung nicht gelaufen, es gibt keine Fehlermeldung, und im Prozessbaum steht ein Aufruf von vor zehn Stunden.
Dagegen gibt es ein Wort, das man einfach davorschreibt.
Der Normalfall
timeout 30 curl -fsSL https://api.example.com/statusLäuft der Befehl länger als 30 Sekunden, bekommt er SIGTERM und timeout beendet sich mit Status 124. Genau darauf kannst du reagieren:
#!/usr/bin/env bash
set -euo pipefail
if timeout 30 curl -fsSL -o /tmp/status.json https://api.example.com/status; then
echo "Status geholt."
elif [ $? -eq 124 ]; then
echo "API antwortet nicht – nach 30 s abgebrochen." >&2
exit 1
else
echo "API hat einen Fehler gemeldet." >&2
exit 1
fiDie Dauer nimmt Einheiten: timeout 90s, timeout 5m, timeout 2h, timeout 1d. Ohne Einheit sind es Sekunden.
Wenn der Befehl sich nicht beenden lässt
SIGTERM ist eine Bitte, kein Befehl. Manche Programme fangen das Signal ab und räumen erst auf – oder ignorieren es. Dafür gibt es -k:
timeout -k 10 60 ./import.shNach 60 Sekunden kommt SIGTERM. Ist der Prozess 10 Sekunden später immer noch da, folgt SIGKILL, und das kann niemand ignorieren. Ich setze -k bei allem, was auf fremdem Code aufsetzt.
Braucht dein Programm ein anderes Signal, sag es dazu:
timeout --signal=INT 30 python3 lange_rechnung.pyIm Cron ist es Pflicht
0 3 * * * timeout -k 30 20m /usr/local/bin/backup.shOhne Grenze bleibt ein hängender nächtlicher Lauf einfach stehen – und der Lauf am Tag darauf startet daneben. Nach einer Woche hast du sieben blockierte Prozesse und immer noch keine Sicherung. Mit timeout bricht der Lauf ab, der nächste beginnt sauber, und im Log steht eine Zeile, die man lesen kann.
Drei Dinge, die du wissen solltest
Status 124 heißt „Zeit abgelaufen", 125 heißt „timeout selbst hat versagt", 126 „Befehl nicht ausführbar", 127 „Befehl nicht gefunden". Wurde der Befehl durch ein Signal beendet, ist es 128 + Signalnummer. Diese Zahlen zu kennen ist der halbe Wert des Werkzeugs – nur so kannst du „hing" von „ist fehlgeschlagen" unterscheiden.
Es wirkt auf den gestarteten Prozess, nicht automatisch auf dessen Kinder. Startet dein Skript selbst weitere Programme, können die weiterlaufen. timeout --foreground und in hartnäckigen Fällen eine eigene Prozessgruppe helfen; im Alltag reicht meistens, timeout direkt vor den wirklich langsamen Befehl zu setzen statt vor das ganze Skript.
Es ersetzt keine Timeouts des Werkzeugs selbst. curl --max-time 30 ist präziser als timeout 30 curl, weil curl weiß, ob gerade Daten fließen. timeout ist das Netz darunter für alles, was so etwas nicht anbietet – und das sind die meisten Programme.
timeout gehört zu den GNU coreutils und ist auf jedem Linux dabei. Auf macOS heißt es gtimeout (aus coreutils via Homebrew).
Seit ich das konsequent vor jeden Netzaufruf in meinen Deploy- und Sicherungsskripten setze, gibt es keine stehengebliebenen Läufe mehr – nur noch Fehlermeldungen, und die kann man beheben. Wenn du solche Skripte für dein Projekt gebrauchen kannst, meld dich gern über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Warum deine Zählvariable nach der Schleife wieder 0 ist – Prozess-Substitution in Bash
Ein Klassiker, der jeden einmal erwischt: Du zählst in einer while-Schleife hoch, und hinterher steht die Variable trotzdem auf 0. Schuld ist eine Subshell hinter der Pipe. Mit Prozess-Substitution behältst du das Ergebnis – und kannst nebenbei zwei Befehle direkt vergleichen.
cron – Aufgaben, die von selbst laufen (und warum sie es oft nicht tun)
Nächtliches Backup, wöchentlicher Bericht, stündliche Bereinigung: Fünf Zahlen und ein Befehl reichen. Der häufigste Fehler ist dabei nicht die Zeitangabe, sondern eine Umgebung, die ganz anders aussieht als dein Terminal.
Zwei Listen vergleichen mit comm – wer fehlt, wer ist neu, wer ist in beiden
Welche Dateien fehlen im Backup? Welche Kunden aus der alten Liste stehen nicht in der neuen? Für genau diese Fragen gibt es seit Unix-Urzeiten ein Werkzeug, das kaum jemand kennt – comm vergleicht zwei sortierte Listen und sagt dir in einer Zeile, was nur links, nur rechts oder in beiden steht.