Der GNU- timeout
Befehl coreutils ist für bestimmte Skriptsituationen äußerst praktisch. Er ermöglicht es, die Ausgabe eines Befehls zu verwenden, wenn er schnell ausgeführt werden kann, und zu überspringen, wenn er zu lange dauern würde.
Wie kann ich das grundlegende Verhalten der timeout
Verwendung nur von POSIX angegebenen Dienstprogrammen approximieren ?
(Ich denke , es eine Kombination von umfassen kann wait
, sleep
, kill
und wer weiß , was sonst noch, aber vielleicht einen einfacheren Ansatz fehlt mir.)
shell-script
posix
timeout
Platzhalter
quelle
quelle
command & pid=$! ; sleep 5 && kill $pid
command
schnellem Ende die Wahrscheinlichkeit gering ist, dass das System vor der Ausführungpid
deskill
Befehls von einem anderen Prozess erneut verwendet wird . Ich würde nicht wollen, dass in Produktionscode ....timeout
Programm kompilieren und verwenden?Antworten:
Mein Ansatz wäre dieser:
Befehl als Hintergrundprozess ausführen 1
"Watchdog Timer" als Hintergrundprozess ausführen 2
Richten Sie einen Handler ein, um ein Beendigungssignal in der übergeordneten Shell abzufangen
Warten Sie, bis beide Prozesse abgeschlossen sind. Der Prozess, der zuerst beendet wird, sendet das Beendigungssignal an das übergeordnete Element.
Der Trap-Handler des Elternteils bricht beide Hintergrundprozesse über die Jobsteuerung ab (einer von ihnen wurde bereits per Definition beendet, aber dieser Kill ist ein harmloser No-Op, da wir keine PIDs verwenden, siehe unten).
Ich habe versucht, die in den Kommentaren angesprochene mögliche Race-Bedingung zu umgehen, indem ich die Job-Control-IDs der Shell (die in dieser Shell-Instanz eindeutig wären) verwendete, um die abzubrechenden Hintergrundprozesse anstelle der System-PIDs zu identifizieren.
Ergebnis für
TIMEOUT=10
(Befehl wird vor Watchdog beendet):Ergebnis für
TIMEOUT=1
(Watchdog wird vor dem Befehl beendet):Ergebnis für
TIMEOUT=5
(Watchdog und Kommando enden "fast" gleichzeitig):quelle
cleanup() { ...; }
und (b) die Auftragssteuerung eine von POSIX nicht spezifizierte Bash-Funktion ist (obwohl ksh und andere dies auch haben). Nettes Drehbuch!timeout="$1"; shift
und kann man es auch besser machen(exec "$@"; echo "Command completed"; kill $$)
die Argumentliste nicht neu aufteilen.