TL; DR: sudo
keine Signale, die durch einen Prozess in der Prozessgruppe des Befehls gesendet weiterleiten since 28 May 2014 commit in sudo 1.8.11
freigegeben - der Python-Prozess (Sudo der Eltern) und den tcpdump Prozess (Enkel) ist in der gleichen Prozeßgruppe standardmäßig und daher sudo
nicht weiterleiten SIGTERM
Signal von .terminate()
an die tcpdump
Prozess gesendet.
Es zeigt das gleiche Verhalten, wenn dieser Code ausgeführt wird, während der Benutzer root und mehr, während ein normaler Benutzer + sudo sein
als normaler Benutzer laufen wirft OSError: [Errno 1] Operation not permitted
Ausnahme auf .terminate()
(wie erwartet).
als root
Lauf reproduziert das Problem: sudo
und tcpdump
Prozesse nicht getötet auf .terminate()
und der Code auf .communicate()
auf Ubuntu 15.10 steckt.
Der gleiche Code tötet beide Prozesse auf Ubuntu 12.04.
tcpdump_process
Name ist irreführend, weil die Variable auf den sudo
Prozess bezieht (das Kind Prozess), nicht tcpdump
(Enkel):
python
└─ sudo tcpdump -w example.pcap -i eth0 -n icmp
└─ tcpdump -w example.pcap -i eth0 -n icmp
Als @Mr.E pointed out in the comments, brauchen Sie nicht sudo
hier: Sie sind root schon (obwohl du nicht sein solltest - du kannst sniff the network without root). Wenn Sie sudo
löschen; .terminate()
funktioniert.
Im Allgemeinen führt .terminate()
nicht den gesamten Prozessbaum rekursiv ab und daher wird erwartet, dass ein Enkelprozess überlebt. Obwohl sudo
ein Sonderfall ist, from sudo(8) man page:
Wenn der Befehl als Kind des sudo
Prozess ausgeführt wird, sudo
wird Relais Signale es auf den Befehl empfängt. Schwerpunkt ist mein
heißt sudo
SIGTERM
-tcpdump
Relais sollte und tcpdump
should stop capturing packets on SIGTERM
, from tcpdump(8) man page:
Tcpdump wird, ..., weiterhin die Erfassung von Paketen, bis sie unterbrochen wird durch ein Signal SIGINT (generiert z. B. durch Eingabe Ihres Interrupt-Zeichens, typischerweise control-C) oder eines SIGTERM-Signals (normalerweise generiert mit dem Befehl kill (1));
heißt das erwartete Verhalten ist: tcpdump_process.terminate()
sendet SIGTERM an sudo
, die das Signal zu tcpdump
Relais, die die Erfassung stoppen sollten und beide Prozesse verlassen und .communicate()
kehrt tcpdump
‚s stderr Ausgabe an das Python-Skript.
Hinweis: Grundsätzlich kann der Befehl, ohne ein Kind-Prozess ausgeführt werden, from the same sudo(8) man page:
Als Sonderfall, wenn die Politik Plugin nicht eine enge Funktion definieren ist und keine pty erforderlich ist, sudo
den Befehl direkt anstelle Gabel des Aufrufs (2) erste
und daher .terminate()
kann SIGTERM an den tcpdump
Prozess direkt senden auszuführen - wenn es nicht die Erklärung ist: sudo tcpdump
erstellt zwei Prozesse auf beiden Ubuntu 12.04 und 15.10 in meinen Tests. Wenn ich sudo tcpdump -w example.pcap -i eth0 -n icmp
in der Shell ausführen, beendet kill -SIGTERM
beide Prozesse. Es sieht nicht wie Python aus (Python 2.7.3 (unter Ubuntu 12.04) verhält sich unter Ubuntu 15.10 genauso. Python 3 schlägt hier auch fehl).
Es wird in Verbindung stehende Gruppen zu verarbeiten (job control): passing preexec_fn=os.setpgrp
-subprocess.Popen()
so dass sudo
in einer neuen Prozessgruppe sein wird (Job), wo es der Führer ist wie in der Schale tcpdump_process.terminate()
Arbeit in diesem Fall macht.
Was ist passiert? Es funktioniert auf früheren Versionen.
Die Erklärung ist in the sudo's source code:
nicht vorwärts Signale Sie durch einen Prozess in dem Befehl des Prozesses gesendet Gruppe, leite es nicht, wie wir das Kind nicht wollen indirekt töten selbst. Dies kann zum Beispiel bei einigen Versionen von reboot auftreten, die kill (-1, SIGTERM) aufrufen, um alle anderen Prozesse zu beenden. Schwerpunkt ist mein
preexec_fn=os.setpgrp
ändert sudo
‚s Prozessgruppe. sudo
's Nachkommen wie tcpdump
Prozess erben die Gruppe. python
und tcpdump
sind nicht mehr in derselben Prozessgruppe und daher wird das von .terminate()
gesendete Signal von sudo
an tcpdump
weitergeleitet und es wird beendet.
Ubuntu 15.04 verwendet Sudo version 1.8.9p5
wo der Code aus der Frage funktioniert, wie es ist.
Ubuntu 15.10 verwendet Sudo version 1.8.12
, das the commit enthält.
sudo(8) man page in wily (15.10) nur noch über das Kind Prozess spricht selbst - keinen Hinweis auf der Prozessgruppe:
Als Sonderfall, sudo wird keine Signale weiterleiten, die von dem Befehl gesendet wurde er ausgeführt wird.
Es sollte stattdessen sein:
Als Sonderfall, sudo werden keine Signale weiterleiten, die von einem Prozess in der Prozessgruppe des Befehls gesendet wurden er ausgeführt wird.
Sie könnten eine Dokumentation Ausgabe öffnen auf Ubuntu's bug tracker und/oder auf the upstream bug tracker.
Wenn Sie dies ausführen, während Sie root sind, warum müssen Sie Sudo aufrufen? Was versuchst du zu machen? –
Ok, guter Punkt. Ohne 'Sudo' scheint es zu funktionieren. Aber warum hat es bei allen früheren Versionen funktioniert? –
Ich weiß nicht, warum, das wahrscheinlichste Szenario ist, dass wenn Sie auf 15.10 aktualisiert einige Konfiguration über Ihre sudoer oder die damit verbundenen Privilegien oder ihre Gruppe geändert. Vielleicht hast du deinen Python ohne Root-Privilegien ausgeführt und kann keine erhöhte Shell töten (sudo) –