Ubuntu 16.04 の systemd で SIGKILL/シャットダウンの前に SIGTERM が発行されない

Ubuntu 16.04 の systemd で SIGKILL/シャットダウンの前に SIGTERM が発行されない

私はこの問題に遭遇しました。Stackoverflowで質問に答える

シャットダウン時に、Ubuntu 12.04 はSIGTERMすべてのプロセスに を送信し、最大 10 秒待ってからSIGKILL(プロセスがそれ以前に終了しない限り) でプロセスを停止します。SO での私の回答には、その動作を確認する Python スクリプトも含まれています。スクリプトはターミナルで開始され、バックグラウンドに送信され、ターミナルによって破棄されます。 を受信するとSIGTERM、スクリプトはそのまま実行を続け、実行時間をファイルに継続的に出力します。受信中SIGTERM

ただし、Ubuntu 16.04 では、シャットダウン時にスクリプトは直ちに終了されます (SIGTERMログに記録されません)。

しばらくグーグルで検索しましたが、役に立つものは何も見つかりませんでした。現在の LTS リリースのその重大な変更に遭遇した人はいないのでしょうか?

スクリプトはこちらsignaltest.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)

スクリプトは、log.txtすべての出力に現在のディレクトリ内のファイルを使用します。 1 秒ごとに 'running' を出力するループがあります。 受信するとSIGTERMループが中断され、受信してから経過した秒数を出力する別のループが開始されますSIGTERM

スクリプトは、次のコマンドを使用して、分離されたターミナルから実行されますdisown

python signaltest.py &
disown

ただ明確にします:これは重複ではありませんUbuntu はシャットダウン時に SIGTERM を送信しません質問はデスクトップ アプリケーションに関するもので、回答も適切ではありません。

答え1

systemd (以前の Ubuntu バージョンの upstart とは対照的に) はシャットダウン時に SIGHUP も送信します (送信前に 10 秒ではなく 90 秒待機します)。無視するか、同じ (べき等な) 方法で処理することをSIGKILLお勧めします。SIGHUPSIGTERMSIGHUP

変更されたテスト スクリプトは次のように変更できます。

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)

関連情報