it-swarm.com.de

Wie kann ich ein Skript beenden, das im Terminal ausgeführt wird, ohne das Terminal zu schließen (Strg + C funktioniert nicht)?

Ich habe ein Bash-Skript geschrieben, das mehrere andere Programme aufruft und eine Reihe von Befehlen ausführt. Ich führe dieses Skript vom Terminal aus. Jetzt möchte ich das Drehbuch töten.

Das Drücken von Ctrl + C schneidet manchmal nicht ab, weil das Skript manchmal ein anderes Programm ausführt und aus irgendeinem Grund das Kill-Signal nicht funktioniert.

Wenn ich jedoch das Terminalfenster schließe, wird das Skript beendet.

Kann ich (eine Tastenkombination) etwas tun, das dem Schließen des Terminalfensters entspricht, ohne das Terminalfenster tatsächlich zu schließen (ich möchte den Befehlsverlauf, das aktuelle Verzeichnis, den Ausgabeverlauf usw. nicht verlieren)?

35
becko

Sie haben nur wenige Möglichkeiten. Eine ist, das Skript zu stoppen (CtrlZ), ermitteln Sie die PID des Skripts und senden Sie SIGKILL an die Prozessgruppe.

Wenn ein Befehl in einer Shell ausgeführt wird, wird der Prozess gestartet, und alle untergeordneten Befehle gehören zur selben Prozessgruppe ( in diesem Fall die Vordergrundprozessgruppe). Um ein Signal an alle Prozesse in dieser Gruppe zu senden, senden Sie es an den Prozessleiter. Für den Befehl kill wird der Prozessleiter folgendermaßen bezeichnet:

kill -PID

Dabei ist PID die Prozess-ID des Skripts.

Beispiel:

Betrachten Sie ein Skript test.sh, das einige Prozesse startet. Angenommen, Sie haben es in einer Shell ausgeführt:

$ ./test.sh

In einem anderen Terminal,

$ pgrep test.sh
17802
$ pstree -ps `!!`
pstree -ps `pgrep test.sh`
init(1)───sshd(1211)───sshd(17312)───sshd(17372)───zsh(17788)───test.sh(17802)─┬─dd(17804)
                                                                               ├─sleep(17805)
                                                                               └─yes(17803)

Um in diesem Fall ein Signal an die von test.sh erstellte Prozessgruppe zu senden, gehen Sie wie folgt vor:

kill -INT -17802

-INT wird verwendet, um SIGINT zu senden, und daher entspricht dieser Befehl dem Drücken von CtrlC auf dem terminal. So senden Sie SIGKILL:

kill -KILL -17802

Sie müssen das Skript nur anhalten, wenn Sie kein anderes Terminal öffnen können. Wenn möglich, verwenden Sie pgrep, um die PID zu ermitteln.

Einer der Befehle, die das Skript startet, ist möglicherweise das Überfüllen von SIGINT, was wahrscheinlich der Grund ist CtrlC ist unwirksam. SIGKILL kann jedoch nicht abgefangen werden, und es ist normalerweise eine Option der letzten Instanz . Möglicherweise möchten Sie SIGTERM (-TERM) ausprobieren, bevor Sie den Kill ausführen. Weder SIGKILL noch SIGTERM können als Tastaturkürzel wie SIGINT eingerichtet werden.

All dies ist umstritten, wenn Ihr Skript keine Shebang-Zeile enthält. Von diese SO Antwort :

Normalerweise vermutet die übergeordnete Shell, dass das Skript für dieselbe Shell geschrieben wurde (minimale Bourne-ähnliche Shells führen das Skript mit/bin/sh aus, bash führt es als bash-Unterprozess aus) ...

Aus diesem Grund wird bei der Ausführung des Skripts kein nach dem Skript benannter Prozess (oder ein Prozess mit dem Namen des Skripts in der Befehlszeile) gefunden, und pgrep schlägt fehl.

Verwenden Sie immer eine Shebang-Linie.

38
muru

Wenn Sie die mit dem Skript verbundenen Prozesse kennen, können Sie deren PID mithilfe von ermitteln

 ps -A

und verwenden Sie dann die PID-Nummer, um die entsprechenden Prozesse mit abzubrechen

 kill -9 PID_Number
6
Harris

Wie Harris sagte, können Sie Kill -9 PID_Number ausführen, aber Sie können auch das Paket htop installieren, um einen interaktiven Prozessbrowser zu erhalten, der das Auffinden bestimmter Prozesse erheblich erleichtert. htop unterstützt auch Tötungsprozesse.