Python

讓 systemd 服務稍後停止,而不會阻塞 systemctl stop

  • March 2, 2022

我有一堆服務負責執行隊列中消耗的操作。

我希望能夠輕輕地重新啟動服務(不中斷已經執行的操作)

可以通過處理 systemd 發送的 SIGTERM 並保存程序在目前操作處理後應該退出的資訊來解決。

還有一個小問題是,在服務配置文件中定義的一段時間後,TimeoutStopSecsystemd 將發送額外的 SIGKILL 以殘酷地終止我的程序。

我可以通過設置輕鬆避免它TimeoutStopSec=infinity。然後systemctl stop‘將等到腳本自行終止,這可能會持續一個多小時,並導致我遇到主要問題。

我不希望systemctl命令等到腳本結束

看起來SendSIGKILL=no配置完成了這項工作。SIGTERM這導致在之後重試TimeoutStopSec,然後創建新的工作人員,並讓舊的工作人員繼續執行。

journalctl 日誌

May 06 14:14:43 jaku systemd[1]: Stopping Jaku test worker...
May 06 14:14:43 jaku python3[31597]: * 15 <frame object at 0x14d8108>
May 06 14:14:53 jaku systemd[1]: jaku-test-worker.service: State 'stop-sigterm' timed out. Skipping SIGKILL.
May 06 14:14:53 jaku python3[31597]: * 15 <frame object at 0x14d8108>
May 06 14:15:03 jaku systemd[1]: jaku-test-worker.service: State 'stop-final-sigterm' timed out. Skipping SIGKILL. Entering failed mode.
May 06 14:15:03 jaku systemd[1]: jaku-test-worker.service: Failed with result 'timeout'.
May 06 14:15:03 jaku systemd[1]: Stopped Jaku test worker.
May 06 14:15:03 jaku systemd[1]: jaku-test-worker.service: Found left-over process 31597 (python3) in control group while starting unit. Ignoring.
May 06 14:15:03 jaku systemd[1]: This usually indicates unclean termination of a previous run, or service implementation deficiencies.
May 06 14:15:03 jaku systemd[1]: Started Jaku test worker.
jaku@jaku:/nfs/home/jaku/tmp$ ps aux | grep "sig.py"
jaku     31597 99.9  0.0  31884  9916 ?        Rs   14:00  15:10 /usr/bin/python3 /home/jaku/tmp/sig.py
jaku     32359  100  0.0  31884 10032 ?        Rs   14:15   0:43 /usr/bin/python3 /home/jaku/tmp/sig.py
jaku     32483  0.0  0.0  15968  1040 pts/7    S+   14:15   0:00 grep --color=auto sig.py

解決方案看起來像是在做它的工作,但我很擔心這句話:

這通常表示先前執行的不干淨終止,或服務實現缺陷。

我錯過了什麼或者它真的是最好的解決方案嗎?

參考:

看起來沒有辦法解決它,這裡有一些 相關的執行緒。但是……我不希望**命令等到腳本結束

的假設是錯誤的。systemctl

我希望這個命令簡短,因為它必須是 jenkins 部署的一部分,而且我不希望部署過程花費超過幾分鐘。

我不知道的是,中斷systemctl命令不會停止關閉服務的過程,所以可能的解決方案是:

systemctl有時間限制的執行命令,例如timeout 60 systemctl restart services-preifx-* || echo "processes will be restart in background"

現在TimeoutStopSec可以設置為某個較高的值(如 10h)以防止服務永遠重啟。

另外KillMode=process必須設置,不要中斷任何子程序。

systemd 停止服務的想法是終止與該單元的 cgroup 關聯的所有程序。執行ExecStop=之後再發送KillSignal=,最後如果有必要FinalKillSignal=。對我來說似乎很合理。

您的軟體正在處理 SIGTERM,使程序保持活動狀態,然後將該單元配置為不發送 SIGKILL。systemd 認為這是損壞的,警告意味著“服務實現缺陷”。它沒有停止。

我不希望 systemctl 命令等到腳本結束

然後在一分鐘左右關閉。服務的使用者不想等待它關閉;DefaultTimeoutStopSec=大概是90年代。雖然您的服務單位可以增加TimeoutStopSec=,但我認為一個小時是不合理的時間來等待初始化腳本中停止的事情。

如果您有(同步)停止腳本,請將其實現為ExecStop=. 如果不是,請立即將 SIGTERM 處理為正常關閉。啟用 SIGKILL 作為停止它的最後手段。


除了殺死它的程序之外,還有其他方法可以阻止服務開始工作。例如,將其從負載均衡器中移除並耗盡負載。

引用自:https://serverfault.com/questions/1015930