Ich versuche einen Prozesscontainer zu bauen. Der Container löst andere Programme aus. Zum Beispiel - ein Bash-Skript, das ausgeführte Hintergrundaufgaben mit '&' startet.
Das wichtige Merkmal, nach dem ich mich sehne, ist folgendes: Wenn ich den Container töte, sollte alles, was unter ihm hervorgebracht wurde, getötet werden. Nicht nur direkte Kinder, sondern auch deren Nachkommen.
Als ich dieses Projekt gestartet habe, habe ich fälschlicherweise geglaubt, dass beim Töten eines Prozesses automatisch auch seine Kinder getötet wurden. Ich habe mich von Leuten beraten lassen, die die gleiche falsche Vorstellung hatten. Es ist zwar möglich, ein Signal zu empfangen und die Tötung an Kinder weiterzugeben, aber das ist nicht das, wonach ich hier suche.
Ich glaube, was ich erreichen möchte, denn wenn Sie ein xterm schließen, wird alles, was darin lief, getötet, es sei denn, es wurde nicht ausgeführt. Dies schließt verwaiste Prozesse ein. Das ist es, was ich neu erschaffen möchte.
Ich habe eine Idee, dass ich nach Unix-Sessions Ausschau halte.
Wenn es eine zuverlässige Möglichkeit gibt, alle Nachkommen eines Prozesses zu identifizieren, wäre es nützlich, ihnen auch beliebige Signale senden zu können. zB SIGUSR1.
SIGHUP
, werden die Prozesse direkt an die untergeordneten Prozesse gesendet . Der Standard-Handler für das Auflegen-Signal bricht die Prozessausführung ab. Die Standardroute besteht also darin, alle Nachkommen zu töten. Lesen Sie mehr über Prozesse und Prozessgruppen.Antworten:
Wenn Sie ein Signal an einen Prozess senden, wird dieser Prozess abgebrochen. Ich frage mich, wie das Gerücht entstanden ist, dass das Beenden eines Prozesses auch andere Prozesse tötet. Es scheint besonders kontraintuitiv zu sein.
Es gibt jedoch Möglichkeiten, mehr als einen Prozess zu beenden. Sie senden jedoch kein Signal an einen Prozess. Sie können eine ganze Prozessgruppe beenden, indem Sie ein Signal an -1234 senden, wobei 1234 die PGID (Prozessgruppen-ID) ist, die die PID des Prozessgruppenleiters ist. Wenn Sie eine Pipeline ausführen , beginnt die gesamte Pipeline als Prozessgruppe (die Anwendungen können dies durch Aufrufen von
setpgid
oder ändernsetpgrp
).Wenn Sie Prozesse im Hintergrund starten (
foo &
), befinden sie sich in einer eigenen Prozessgruppe. Prozessgruppen werden verwendet, um den Zugriff auf das Terminal zu verwalten. Normalerweise hat nur die Vordergrundprozessgruppe Zugriff auf das Terminal. Die Hintergrundjobs verbleiben in derselben Sitzung , aber es gibt keine Möglichkeit, eine ganze Sitzung abzubrechen oder die Prozessgruppen oder -prozesse in einer Sitzung aufzulisten, was nicht viel hilft.Wenn Sie ein Terminal schließen, sendet der Kernel das Signal
SIGHUP
an alle Prozesse, die es als steuerndes Terminal haben . Diese Prozesse bilden eine Sitzung , aber nicht alle Sitzungen verfügen über ein steuerndes Terminal. Für Ihr Projekt besteht daher eine Möglichkeit darin, alle Prozesse in einem eigenen Terminal zu starten, das durch ein Skript , einen Bildschirm usw. erstellt wurde. Beenden Sie den Terminal-Emulator-Prozess, um die enthaltenen Prozesse zu beenden (vorausgesetzt, sie wurden nicht getrenntsetsid
).Sie können für mehr Isolation sorgen, indem Sie die Prozesse als eigene Benutzer ausführen, die nichts anderes tun. Dann ist es einfach, alle Prozesse zu beenden: Führen Sie
kill
(den Systemaufruf oder das Dienstprogramm ) als diesen Benutzer aus und verwenden Sie -1 als das zu beendende PID-Argument, was "alle Prozesse dieses Benutzers" bedeutet.Sie können noch mehr Isolation, aber erheblich mehr Setup bereitstellen, indem Sie die enthaltenen Prozesse in einem tatsächlichen Container ausführen .
quelle
prctl(PR_SET_PDEATHSIG, SIGHUP);
Weitere Informationen: man7.org/linux/man-pages/man2/prctl.2.htmlIm übergeordneten Skript wird das Kill-Signal abgefangen und alle Kinder getötet. Beispielsweise,
quelle
Ein zuverlässiger Weg, um alle Nachfahren eines Prozesses zu identifizieren, ist die Verwendung des Befehls,
pstree <pid>
bei dem pid Ihre übergeordnete Prozess-ID ist.Lesen Sie die man - Seite auf
pstree
hier .So signalisieren Sie allen Mitgliedern einer Prozessgruppe:
killpg(<pgrp>, <sig>);
Dabei ist pgrp die Prozessgruppennummer und sig das Signal.
So warten Sie auf Kinder in einer bestimmten Prozessgruppe:
waitpid(-<pgrp>, &status, ...);
Alternativ dazu können Sie Ihren Prozesscontainer in einer neuen Bash-Shell ausführen. Erstellen Sie die neue Bash-Shell mit dem Befehl
bash
und führen Sie dann Ihre Prozesse aus. Wenn Sie möchten, dass alle Prozesse beendet werden, beenden Sie die Shell mit dem Befehlexit
.quelle
Verwenden
Wenn Sie beenden
unshare
, werden alle untergeordneten Prozesse (dieyourprogram
möglicherweise gestartet wurden) beendet.Dies ist jetzt mit util-linux möglich
2.32
; Ich habe das Upstream implementiert . Es erfordert entweder Benutzernamensräume (Kernel-KonfigurationsoptionCONFIG_USER_NS=y
) oder Root-Rechte. Siehe auch hier .quelle
Der Befehl rkill aus dem Paket pslist sendet ein bestimmtes Signal (oder
SIGTERM
standardmäßig) an den angegebenen Prozess und alle seine Nachkommen:quelle
Eine weitere Option zum Töten aller Nachkommen der Shell:
jobs -p | xargs -n 1 pkill -P
quelle