timeout-Befehl in Bash

Faaiq Bilal 15 Februar 2024
  1. der timeout-Befehl in Bash
  2. Verwenden Sie timeout mit SIGKILL Signal in Bash
timeout-Befehl in Bash

Dieser Artikel ist eine einfache Anleitung zum Einrichten eines Timeouts für bestimmte Programme mit dem Befehl timeout des GNU-Pakets coreutils in Bash.

der timeout-Befehl in Bash

In vielen Situationen, z. B. beim Abrufen von Daten von einem Server oder beim Ausführen einer Funktion oder eines Programms mit zufälligen Eingaben, kann das Programm oder die Funktion sehr lange oder unbegrenzt ausgeführt werden.

In solchen Fällen ist es wichtig, das Programm zu stoppen und zu verhindern, dass mehr Zeit und Ressourcen verschwendet werden.

Hier kommt eine Timeout-Funktionalität ins Spiel. Der Benutzer definiert ein Zeitlimit, und dann darf das Programm bis zum erfolgreichen Abschluss ausgeführt werden, und wenn es bis zum benutzerdefinierten Zeitlimit zu lange dauert, wird es beendet.

Die Timeout-Funktionalität ist normalerweise für die meisten Programmiersprachen integriert. Für Bash ist es jedoch nicht integriert und Teil eines externen Pakets namens coreutils.

Dieses Paket wird von GNU entwickelt und gepflegt und enthält Implementierungen vieler grundlegender Dienstprogramme.

Das Paket coreutils kann einfach durch Ausführen des Befehls sudo apt-get install -y coreutils in LINUX-Systemen installiert werden.

Um die coreutils auf macOS-Systemen zu erhalten, müssen Sie zuerst Homebrew installiert haben. Um Homebrew zu erhalten, führen Sie den folgenden Befehl im Befehlsterminal aus.

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Führen Sie nach der vollständigen Installation von Homebrew den folgenden Befehl aus.

brew install coreutils
Note
Für coreutils-Befehle auf macOS haben alle Befehle ein g vor dem Namen (z. B. gdir oder gtimeout).

Wenn Sie das Paket coreutils installiert haben, können Sie einfach die Funktion timeout verwenden, zum Beispiel:

timeout 10 ping google.com

Der obige Befehl gibt aus:

Timeout-Befehl verwenden

Das Dienstprogramm ping in Bash ist integriert und läuft weiter, bis es manuell unterbrochen wird. Standardmäßig sendet ping alle 1 Sekunde ein Paket.

Wie oben zu sehen, beendet der Befehl timeout ping nach 10 Sekunden, da die Zahl direkt nach dem Befehl timeout das Zeitlimit ist.

Daher bedeutet der Befehl timeout 10 cmd1, dass cmd1 bis zum erfolgreichen Abschluss oder 10 Sekunden ausgeführt wird, je nachdem, was früher eintritt. Die Zeiteinheit für den timeout-Befehl ist in Sekunden.

Um einen in Minuten, Stunden oder Tagen gemessenen Zeitwert zu verwenden, fügen Sie jeweils ein m, ein h oder ein d hinzu.

So stellen Sie beispielsweise ein Timeout von 2 Minuten ein:

timeout 2m programToRun

Es ist zu beachten, dass der Exit-Status für ein Timeout 124 ist, wenn der Prozess abläuft. Im folgenden Beispiel verwenden wir dies, um zu überprüfen, ob der Prozess abgelaufen ist oder nicht.

timeout 1 ping 8.8.8.8 -w3
EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 124 ]
then
echo 'Process timed out!'
else
echo 'Process did not timeout.'
fi
exit $EXIT_STATUS

Wenn der Vorgang im oben dargestellten Beispiel nicht innerhalb von 1 Sekunde abgeschlossen ist, wird der Vorgang abgebrochen. Die Erweiterung -w3 zeigt an, dass die Adresse dreimal angepingt wird.

Daher läuft dieser Prozess immer ab und gibt die folgende Ausgabe aus.

PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=40.4 ms
Process timed out!

Es ist wichtig zu beachten, dass ein interner Timeout auch zum gleichen Exit-Status (124) führt. Daher zeigt diese Ausgabe an, dass entweder der Prozess mit unserem angegebenen Timeout abgelaufen ist oder ein interner Timeout ihn beendet hat.

Verwenden Sie timeout mit SIGKILL Signal in Bash

Typischerweise sendet die timeout-Funktion ein SIGTERM-Signal, um die Ausführung eines Programms zu stoppen, wenn das Zeitlimit erreicht ist. Das Problem ist, dass manche Programme das SIGTERM-Signal ignorieren und weiterlaufen.

Hier kommt das SIGKILL-Signal ins Spiel; Es stoppt sofort die Ausführung eines Prozesses und aller seiner untergeordneten Prozesse und kann nicht blockiert oder ignoriert werden. Um ein Timeout mit SIGKILL zu verwenden, müssen wir das Flag -s hinzufügen.

Zum Beispiel:

timeout -s SIGKILL 10 programToRun

Wenn timeout nicht direkt von der Shell ausgeführt wird, wie beim Ausführen von einem Skript, ist es wichtig, --foreground zum timeout-Befehl hinzuzufügen.

Es können viele Alternativen zum timeout-Befehl verwendet werden, die alle hauptsächlich auf der gleichen Logik basieren, ein Kill-Signal mit sleep zu verwenden und dann den erforderlichen Befehl oder das Programm auszuführen, das gestoppt wird, sobald sleep endet.

Beispiel:

(sleep 2 && killall prog) & ./prog

Der obige Code beendet alle Prozesse von prog nach 2 Sekunden, wenn prog seine Ausführung nicht abgeschlossen hat. Solche Lösungen können funktionieren, sind aber nicht so sicher und zuverlässig wie der Befehl timeout, daher ist es immer besser, stattdessen timeout zu verwenden.