Beenden Sie jeden Hintergrundprozess

10

Ich habe einige StoppedHintergrundprozesse.

kill $(jobs -p)und kill `jobs -p`haben keine Wirkung

kill %1, kill %2etc. einzelne Prozesse erfolgreich beenden

Wie kann ich jeden Hintergrundprozess mit einem Befehl beenden?

Warum funktionieren die ersten beiden Befehle bei mir nicht?

Ich verwende Linux Mint 15, 64 Bit

user49888
quelle

Antworten:

10

Wenn sie rennen

Scheint, als könnten Sie dies einfach mit killund der Ausgabe von tun jobs -p.

Beispiel

$ sleep 1000 &
[1] 21952
$ sleep 1000 &
[2] 21956
$ sleep 1000 &
[3] 21960

Jetzt laufen 3 falsche Jobs.

$ jobs
[1]   Running                 sleep 1000 &
[2]-  Running                 sleep 1000 &
[3]+  Running                 sleep 1000 &

Töte sie alle so:

$ kill $(jobs -p)
[1]   Terminated              sleep 1000
[2]-  Terminated              sleep 1000
[3]+  Terminated              sleep 1000

Bestätigen, dass sie alle weg sind.

$ jobs
$

Wenn sie gestoppt sind

Wenn Sie Jobs haben, die gestoppt sind und nicht ausgeführt werden, tun Sie dies stattdessen.

Beispiel

$ kill $(jobs -p)

$ jobs
[1]+  Stopped                 sleep 1000
[2]-  Stopped                 sleep 1000
[3]   Stopped                 sleep 1000

OK, das hat sie nicht getötet, aber das liegt daran, dass das Kill-Signal nicht vom Prozess selbst verarbeitet werden kann, sondern gestoppt wird. Sagen Sie dem Betriebssystem also, dass es stattdessen töten soll. Dafür -9ist a da.

$ kill -9 $(jobs -p)
[1]+  Killed                  sleep 1000
[2]-  Killed                  sleep 1000
[3]   Killed                  sleep 1000

Das ist besser.

$ jobs
$ 

Wenn einige laufen und andere gestoppt werden

Wenn Sie eine gemischte Sammlung von Prozessen haben, bei denen einige gestoppt sind und andere ausgeführt werden, können Sie eine killerste gefolgt von a ausführen kill -9.

$ kill $(jobs -p); sleep <time>; \
    kill -18 $(jobs -p); sleep <time>; kill -9 $(jobs -p)

Verlängern Sie die Zeit geringfügig, wenn Sie mehr benötigen, damit sich Prozesse zuerst selbst stoppen können.

Signale

Weder ein HUP (-1) noch ein SIGTERM (-15) zum Töten werden erfolgreich sein. Aber wieso? Das liegt daran, dass diese Signale in dem Sinne freundlicher sind, dass sie der Anwendung sagen, dass sie sich selbst beenden soll. Da sich die Anwendung jedoch in einem gestoppten Zustand befindet, kann sie diese Signale nicht verarbeiten. Sie müssen also nur ein SIGKILL (-9) verwenden.

Sie können alle Signale sehen, killdie mit liefern kill -l.

$ kill -l | column -t
1)   SIGHUP       2)   SIGINT       3)   SIGQUIT      4)   SIGILL       5)   SIGTRAP
6)   SIGABRT      7)   SIGBUS       8)   SIGFPE       9)   SIGKILL      10)  SIGUSR1
11)  SIGSEGV      12)  SIGUSR2      13)  SIGPIPE      14)  SIGALRM      15)  SIGTERM
16)  SIGSTKFLT    17)  SIGCHLD      18)  SIGCONT      19)  SIGSTOP      20)  SIGTSTP
21)  SIGTTIN      22)  SIGTTOU      23)  SIGURG       24)  SIGXCPU      25)  SIGXFSZ
26)  SIGVTALRM    27)  SIGPROF      28)  SIGWINCH     29)  SIGIO        30)  SIGPWR
31)  SIGSYS       34)  SIGRTMIN     35)  SIGRTMIN+1   36)  SIGRTMIN+2   37)  SIGRTMIN+3
38)  SIGRTMIN+4   39)  SIGRTMIN+5   40)  SIGRTMIN+6   41)  SIGRTMIN+7   42)  SIGRTMIN+8
43)  SIGRTMIN+9   44)  SIGRTMIN+10  45)  SIGRTMIN+11  46)  SIGRTMIN+12  47)  SIGRTMIN+13
48)  SIGRTMIN+14  49)  SIGRTMIN+15  50)  SIGRTMAX-14  51)  SIGRTMAX-13  52)  SIGRTMAX-12
53)  SIGRTMAX-11  54)  SIGRTMAX-10  55)  SIGRTMAX-9   56)  SIGRTMAX-8   57)  SIGRTMAX-7
58)  SIGRTMAX-6   59)  SIGRTMAX-5   60)  SIGRTMAX-4   61)  SIGRTMAX-3   62)  SIGRTMAX-2
63)  SIGRTMAX-1   64)  SIGRTMAX

Wenn Sie noch mehr über die verschiedenen Signale erfahren möchten, empfehle ich Ihnen dringend, einen Blick auf die Signal-Manpage zu werfen man 7 signal.

slm
quelle
Warum haben wir ein +Symbol für den ersten Prozess und ein -Symbol für den zweiten Prozess und kein Symbol für den dritten?
Ramesh
Ich habe die gleichen Ergebnisse wie Sie. Allerdings möchte ich terminatestattdessen kill, da ich gelesen habe, dass das sicherer ist. Ich habe es versucht kill -15 $(jobs -p), aber das hatte keine Wirkung. Ich vermutete, dass gestoppte Prozesse nur beendet werden können, aber dann kill %number(einzelne) gestoppte Prozesse beenden.
user49888
@Ramesh Die +und -sind nur die letzten Prozesse, die ich beim Einrichten der Beispiele berührt habe. Dies +bedeutet, dass alle Befehle, die nicht explizit ein enthalten %#, auf diesen Befehl einwirken. Der Bindestrich ( -) ist der vorletzte Befehl, den ich berührt habe.
slm
@ user49888 - das kill -9 .. hätte funktionieren sollen. Was sind die Prozesse? Sind sie nicht mehr existierende oder verwaiste Prozesse?
slm
1
@ user49888 - Ja, wenn sich der Prozess mitten in etwas befand, hat er nicht die Möglichkeit, vor dem Beenden eine Bereinigung durchzuführen.
slm
2

Sie können dies versuchen.

for x in `jobs -p`; do kill -9 $x; done

Wenn Sie den Prozess jedoch beenden möchten, können Sie den Befehl wie folgt ausgeben:

for x in `jobs -p`; do kill -15 $x; done

Aus der Wiki - Seite des KillBefehls,

Ein Prozess kann auf vier Arten ein SIGTERM- Signal senden (die Prozess-ID lautet in diesem Fall '1234'):

kill 1234
kill -s TERM 1234
kill -TERM 1234
kill -15 1234

Dem Prozess kann auf drei Arten ein SIGKILL- Signal gesendet werden:

kill -s KILL 1234
kill -KILL 1234
kill -9 1234

Wie in dieser Antwort erläutert , ist dies der Unterschied zwischen Beenden und Töten .

Das Abschlusssignal SIGTERM ist ein Signal, das in einem Programm abgefangen werden kann. Oft fangen Prozesse, die im Hintergrund ausgeführt werden sollen, dieses Signal ab und starten einen Shutdown-Prozess, was zu einem sauberen Exit führt. Das Kill-Signal SIGKILL kann nicht abgefangen werden. Wenn dies an einen Prozess gesendet wird, wird dieses Programm abrupt beendet.

Wenn Sie beispielsweise Ihren Computer herunterfahren oder neu starten, wird normalerweise zuerst ein SIGTERM an die ausgeführten Prozesse gesendet, damit diese auf saubere Weise beendet werden können, wenn sie dies unterstützen. Nach einigen Sekunden wird dann ein SIGKILL an die noch laufenden Prozesse gesendet, damit die verwendeten Ressourcen zwangsweise freigegeben werden (z. B. verwendete Dateien) und die Sequenz zum Herunterfahren fortgesetzt werden kann (z. B. Aufheben der Bereitstellung von Dateisystemen).

Ramesh
quelle
Dies macht killjeden Hintergrundprozess. Gibt es terminatestattdessen einen Weg zu ihnen, da ich glaube, dass dies sicherer ist?
user49888
Wenn Sie beenden möchten, können Sie -15den Befehl kill verwenden.
Ramesh
-15wird auch hier nicht funktionieren. Siehe meine A.
slm
@Ramesh - die letzten 2 Absätze sind nicht richtig. Ein SIGTERM wird nicht gesendet (zunächst nicht). Es wird versucht, Prozesse zuerst über ihre Service-Stop / Start-Skripte anzuhalten. Wenn dies der Fall wäre, dass eine 9 an den Prozess gesendet wurde, hätten die Prozesse gestoppt, wie im Beispiel des OP, was kill -9in meinem Beispiel nicht funktioniert hätte.
slm
1

Ok, wenn ich damit herumspiele, sehe ich, dass wenn Sie einen Job beenden, der gestoppt ist (wo die Ausführung angehalten, aber nicht beendet wurde), er erst beendet wird, wenn er in den Vordergrund gerückt wird. Programme werden normalerweise durch Drücken von Ctrl- Zauf dem Terminal gestoppt . Die meisten Terminals senden das SIGSTOPin diesem Fall, aber es gibt natürlich auch andere Möglichkeiten, es zu senden, z. B. mit kill -STOPoder kill -19.

Es ist normal, dass das Programm nicht sofort beendet wird, da das Programm ausgeführt werden muss, um das von SIGTERMgesendete Standardsignal zu verarbeiten kill. Darüber hinaus wird es manchmal nach dem bashSenden SIGTERMan einen Hintergrundprozess irgendwie gestoppt (obwohl das SIGTERMnoch aussteht).

Der sicherste Weg, um alle Jobs zu beenden ( ohne darauf zurückzugreifen kill -9), besteht darin, zuerst SIGTERMmit einem normalen Job killzu senden und dann SIGCONTan alle verbleibenden Jobs zu senden , z.

kill $(jobs -p)
kill -18 $(jobs -p)

Das SIGCONT( 18ist die Signalnummer) bringt alle gestoppten Jobs in den Vordergrund, damit sie SIGTERMsie wie gewohnt verarbeiten können.

Wenn nicht alle Programme damit fertig sind, können Sie einige andere Signale ausprobieren, die den Prozess normalerweise zum Abschluss bringen, bevor Sie darauf zurückgreifen kill -9. Das erste, das ich empfehle, ist SIGHUP, dass viele Programme, die normalerweise die anderen Abschlusssignale blockieren, darauf reagieren SIGHUP. Dies wird normalerweise gesendet, wenn ein steuerndes Terminal geschlossen wird, insbesondere wenn eine sshSitzung mit einem ttybeendet wird. Viele interaktive Programme, wie z. B. Shells, reagieren nicht auf andere Beendigungssignale, sondern darauf, da es für sie ein Problem wäre, nach sshBeendigung einer Sitzung (oder nach dem Schließen eines steuernden Terminals) weiter zu laufen . Um dies zu versuchen, können Sie dies tun

kill -1 $(jobs -p)
kill -18 $(jobs -p)

Auch hier müssen Sie natürlich sicherstellen, dass das Programm nicht gestoppt wird, damit es das Signal verarbeiten kann. Andere Abschlusssignale, die Sie ausprobieren können, sind SIGINT( kill -2) und SIGQUIT( kill -3). Aber natürlich lassen die Vorteile des Versuchs mit der vollen Reichweite nach und können zu einem unvermeidlichen SIGKILL(auch bekannt als kill -9) führen.

Graeme
quelle
Wenn Sie dies tun man signal, können Sie das Referenzmaterial erhalten, um dies zu sichern.
slm
Dies ist eine weichere Form dessen, was mein A vorschlägt. Es gibt Fälle, in denen ich in der Vergangenheit darauf gestoßen bin, dass dies die Dinge immer noch nicht vollständig bereinigt. Wenn Sie dies über ein Skript tun, kill -9 ..funktioniert die Methode in den meisten Fällen. Dies führt manchmal dazu, dass Prozesse hängen bleiben und daher häufiger fehlschlagen. Es ist ein Kompromiss, den Sie entscheiden müssen. Es ist besser, hartnäckig zu sein und alles zu töten, Daten / Bereinigungen zu riskieren oder eine sanftere Bereinigung durchzuführen, aber mehr Analysen durchzuführen, wenn Ihre Kills zunehmend härter werden.
slm
@slm, sollten Sie nach Möglichkeit vermeiden kill -9, da dies nur den Stecker zieht, ohne dem Programm die Möglichkeit zu geben, ordnungsgemäß zu bereinigen. Ich werde mit einigen Alternativen aktualisieren.
Graeme
Wie ich bereits sagte, ist Ihr Geschmack weicher als von mir vorgeschlagen. Es kommt darauf an, was Sie versuchen und was Sie aus Risikogesichtspunkten tolerieren wollen. Ich habe deine und meine Methode angewendet. Sie sind beide richtig IMO. Auch a kill ..; sleep <time>; kill -18 ..; Schlaf <Zeit>; töte -9 ... . Basically working up to the -9`.
slm
@slm, das kill -18ist definitiv etwas, das verwendet werden sollte , da es üblich ist, Jobs gestoppt zu haben (und in einigen Fällen scheint es, dass bashJobs vor dem Senden irgendwie nicht mehr ausgeführt werden SIGTERM). Wie oben hinzugefügt, SIGHUPlohnt es sich auch, es zu versuchen, da viele Programme, die nicht auf die anderen reagieren, darauf reagieren (versuchen Sie es mit einer Shell). Darüber hinaus lohnt es sich jedoch nicht so sehr, wie SIGKILLes wahrscheinlich unvermeidlich ist.
Graeme
0

Dadurch werden alle Jobs in Ihrer aktuellen Shell einzeln beendet:

while kill %; do :; done

Erläuterung: %Bezieht sich auf den letzten Job in der Liste, sodass eine Schleife ausgeführt wird, bis ein killWert ungleich Null zurückgegeben wird. Dies würde bedeuten, dass keine Jobs mehr beendet werden müssen.

Ein anderer Ansatz könnte darin bestehen, zuerst zu senden SIGTERM, SIGCONTdamit Ihre Jobs fortgesetzt werden können, und als Erstes erhalten Sie Ihre SIGTERM.

/bin/kill $(jobs -p) && /bin/kill -CONT $(jobs -p)

(Aus irgendeinem Grund ist das eingebaute killseltsam, deshalb habe ich hier ein externes verwendet).

dnt
quelle