
Ich bin auf dieses Problem gestoßen, als ich versuchte,Beantworten Sie eine Frage auf Stackoverflow.
Beim Herunterfahren sendet Ubuntu 12.04 SIGTERM
an alle Prozesse und wartet höchstens 10 Sekunden, bevor es sie mit beendet SIGKILL
(es sei denn, sie wurden vorher beendet). Meine Antwort auf SO enthält sogar ein Python-Skript, das dieses Verhalten überprüft. Das Skript wird in einem Terminal gestartet, in den Hintergrund gesendet und dann vom Terminal abgelehnt. Beim Empfang SIGTERM
läuft das Skript einfach weiter und druckt kontinuierlich in eine Datei, wie lange es ausgeführt wurdenachEmpfangen SIGTERM
.
Bei Ubuntu 16.04 wird das Skript jedoch beim Herunterfahren sofort beendet (es SIGTERM
wird nichts protokolliert).
Ich habe eine Weile gegoogelt, aber nichts Nützliches gefunden. Ist noch nie jemand auf diese entscheidende Änderung für die aktuelle LTS-Version gestoßen?
Hier ist das Skriptsignaltest.py
import signal
import time
stopped = False
out = open('log.txt', 'w')
def stop(sig, frame):
global stopped
stopped = True
out.write('caught SIGTERM\n')
out.flush()
signal.signal(signal.SIGTERM, stop)
while not stopped:
out.write('running\n')
out.flush()
time.sleep(1)
stop_time = time.time()
while True:
out.write('%.4fs after stop\n' % (time.time() - stop_time))
out.flush()
time.sleep(0.1)
Das Skript verwendet die Datei log.txt
im aktuellen Verzeichnis für alle Ausgaben. Es verfügt über eine Schleife, die jede Sekunde „running“ ausgibt. Der Empfang SIGTERM
unterbricht die Schleife und startet eine weitere Schleife, die die seit dem Empfang vergangenen Sekunden ausgibt SIGTERM
.
Das Skript wird von einem Terminal aus ausgeführt und zwar mit disown
:
python signaltest.py &
disown
Nur um das klar zu stellen:Dies ist kein Duplikat vonUbuntu sendet beim Herunterfahren kein SIGTERM. Die Frage bezieht sich auf Desktop-Anwendungen und die Antworten passen auch nicht.
Antwort1
systemd (im Gegensatz zu upstart in früheren Ubuntu-Versionen) sendet zusätzlich SIGHUP beim Herunterfahren (und wartet 90 s statt 10 s, bevor es sendet SIGKILL
). Ich schlage vor, es zu ignorieren oder auf die gleiche (idempotente) Weise SIGHUP
zu handhaben .SIGTERM
SIGHUP
Das modifizierte Testskript könnte wie folgt geändert werden:
import signal
import time
stopped = False
out = open('log.txt', 'w')
def stop(sig, frame):
global stopped
stopped = True
out.write('caught SIGTERM\n')
out.flush()
def ignore(sig, frsma):
out.write('ignoring signal %d\n' % sig)
out.flush()
signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGHUP, ignore)
while not stopped:
out.write('running\n')
out.flush()
time.sleep(1)
stop_time = time.time()
while True:
out.write('%.4fs after stop\n' % (time.time() - stop_time))
out.flush()
time.sleep(0.1)