[Bearbeiten: Dies sieht ähnlich aus wie einige andere Fragen, bei denen gefragt wird, wie alle erzeugten Prozesse beendet werden sollen. Die Antworten scheinen alle darin zu bestehen, pkill zu verwenden. Der Kern meiner Frage könnte also sein: Gibt es eine Möglichkeit, Strg-C / Z auf alle Prozesse zu übertragen, die von einem Skript erzeugt werden?]
Wenn Sie ein SoX rec
mit dem timeout
Befehl von coreutils ( hier beschrieben ) aufrufen , scheint es keine Möglichkeit zu geben, es mit einem Tastendruck zu beenden, sobald es aus einem Bash-Skript heraus aufgerufen wurde.
Beispiele:
timeout 10 rec test.wav
... kann mit Ctrl+ Coder Ctrl+ Zvon bash getötet werden, aber nicht, wenn es aus einem Skript heraus aufgerufen wurde.
timeout 10 ping nowhere
... kann mit Ctrl+ Coder Ctrl+ Zvon bash und mit Ctrl+ getötet werden, Zwenn es aus einem Skript heraus ausgeführt wird.
Ich kann die Prozess-ID finden und auf diese Weise beenden, aber warum kann ich keinen Standard-Unterbrechungstastenanschlag verwenden? Und gibt es eine Möglichkeit, mein Skript so zu strukturieren, dass ich es kann?
quelle
bg
offg
eingeben. Gibt es einen Unterschied zwischen Ihrem 1. und 3. Beispiel?timeout
auf meinem System, aber das Tötensleep
funktioniert, unabhängig davon, ob es direkt in der Befehlszeile eingegeben, bezogen, ausgeführt oder explizit durch den Interpreter geleitet wirdAntworten:
Signaltasten wie Ctrl+ Csenden ein Signal an alle Prozesse im Vordergrund Prozessgruppe .
Im typischen Fall ist eine Prozessgruppe eine Pipeline. In befinden sich beispielsweise
head <somefile | sort
der laufende Prozesshead
und der laufende Prozesssort
in derselben Prozessgruppe wie die Shell, sodass alle das Signal empfangen. Wenn Sie einen Job im Hintergrund (somecommand &
) ausführen , befindet sich dieser Job in einer eigenen Prozessgruppe, sodass das Drücken von Ctrl+ Ckeinen Einfluss darauf hat.Das
timeout
Programm stellt sich in eine eigene Prozessgruppe. Aus dem Quellcode:Wenn eine Zeitüberschreitung auftritt,
timeout
wird das einfache Mittel durchlaufen, um die Prozessgruppe zu beenden, zu der sie gehört. Da es sich in eine separate Prozessgruppe gestellt hat, befindet sich sein übergeordneter Prozess nicht in der Gruppe. Durch die Verwendung einer Prozessgruppe wird hier sichergestellt, dass alle Prozesse das Signal empfangen, wenn sich die untergeordnete Anwendung in mehrere Prozesse aufteilt.Wenn Sie
timeout
direkt in der Befehlszeile ausführen und Ctrl+ drücken C, wird das resultierende SIGINT sowohl vomtimeout
als auch vom untergeordneten Prozess empfangen , jedoch nicht von der interaktiven Shell, dietimeout
der übergeordnete Prozess ist. Wenntimeout
es von einem Skript aufgerufen wird, empfängt nur die Shell, die das Skript ausführt, das Signal: Estimeout
wird nicht empfangen , da es sich in einer anderen Prozessgruppe befindet.Sie können einen Signalhandler in einem Shell-Skript mit dem
trap
eingebauten festlegen. Leider ist es nicht so einfach. Bedenken Sie:Wenn Sie nach 2 Sekunden Ctrl+ drücken C, wartet dies noch die vollen 5 Sekunden und druckt dann die Meldung „Unterbrochen“. Dies liegt daran, dass die Shell den Trap-Code nicht ausführt, während ein Vordergrundjob aktiv ist.
Um dies zu beheben, führen Sie den Job im Hintergrund aus. Rufen Sie
kill
im Signalhandler auf , um das Signal an dietimeout
Prozessgruppe weiterzuleiten.quelle
Aufbauend auf der hervorragenden Antwort von Gilles. Der Timeout-Befehl verfügt über eine Vordergrundoption. Wenn er verwendet wird, beendet STRG + C den Timeout-Befehl.
quelle
timeout
GNU-Coreutils gut funktioniert .Grundsätzlich sendet Ctrl+ Cein
SIGINT
Signal, während Ctrl+ Z einSIGTSTP
Signal sendet .SIGTSTP
stoppt einfach den Prozess, aSIGCONT
wird ihn fortsetzen.Dies funktioniert mit dem Vordergrundprozess, der in der Befehlszeile gegabelt wurde.
Wenn Ihr Prozess ein Hintergrundprozess ist, müssen Sie dieses Signal auf andere Weise an die Prozesse senden.
kill
wird das machen. Theoretisch sollte ein "-" - Operator für diesen Kill auch untergeordnete Prozesse signalisieren, aber dies funktioniert selten wie erwartet.Zur weiteren Lektüre: Unix-Signale
quelle
Verbesserung der Antwort von @Gilles durch Bereitstellung eines "Find and Replace " -Ansatzes für vorhandene Skripte:
INT
Handler den folgenden Code hinzu (oder führen Sie ihn zusammen) :timeout
Befehle durchmy_timeout
Funktionen in Ihrem Skript.Beispiel
Hier ist ein Beispielskript:
quelle