![背景](https://rvso.com/image/726372/%E8%83%8C%E6%99%AF.png)
背景
我被要求systemd
為新服務建立一個腳本,foo_daemon
有時會進入“不良狀態”,並且不會通過SIGTERM
(可能是由於自訂訊號處理程序)而死掉。這對開發人員來說是個問題,因為他們被指示透過以下方式啟動/停止/重新啟動服務:
systemctl start foo_daemon.service
systemctl stop foo_daemon.service
systemctl restart foo_daemon.service
問題
有時,由於foo_daemon
進入了糟糕的狀態,我們不得不透過以下方式強行殺死它:
systemctl kill -s KILL foo_daemon.service
問題
如何設定我的systemd
腳本foo_daemon
,以便每當使用者嘗試停止/重新啟動服務時,systemd
將:
- 嘗試正常關閉
foo_daemon
viaSIGTERM
。 foo_daemon
最多需要 2 秒的時間來完成關閉/終止。- 如果進程仍然存在,請嘗試強制關閉
foo_daemon
viaSIGKILL
(這樣我們就不會有 PID 被回收的風險以及針對錯誤 PID 的systemd
問題)。SIGKILL
我們正在測試的設備快速產生/分叉大量進程,因此,很少有人擔心 PID 回收會導致問題。 - 在實踐中,如果我只是對 PID 回收抱持偏執,那麼我可以接受只針對進程 PID 發出的腳本,
SIGKILL
而不用擔心殺死回收的 PID。
答案1
systemd 已經開箱即用地支援這一點,而且它是預設啟用。
您可能想要自訂的唯一事情是超時,您可以使用TimeoutStopSec=
.例如:
[Service]
TimeoutStopSec=2
現在,systemd 將發送一個 SIGTERM,等待兩秒鐘讓服務退出,如果沒有退出,它將發送一個 SIGKILL。
如果您的服務不支援 systemd,您可能需要提供其 PID 檔案的路徑PIDFile=
。
最後,您提到您的守護程式會產生許多進程。在這種情況下,您可能想要進行設置KillMode=control-group
,systemd 將向 cgroup 中的所有進程發送訊號。
答案2
由於沒有人提到需要Type=oneshot
,這裡有一個完整的範例,該範例因超時失敗而退出。
[Unit]
Description=timeout test
[Service]
Type=oneshot
TimeoutStartSec=2
ExecStart=/bin/sleep 10