Systemd 和程序生成:子程序在主程序退出時被殺死
通常不在這裡發帖,但我正在把頭髮扯掉。我有一個 Python 腳本,它在啟動時分叉,並負責啟動一堆其他程序。該腳本曾經在啟動時通過 via 啟動
sysvinit
,但最近我升級到 Debian Jessie,因此已將其調整為通過啟動啟動systemd
。不幸的是,我遇到了一個我無法解決的問題。當您直接在使用者 shell 中啟動腳本時,它會正確啟動它的子程序,並且當腳本退出時,子程序將成為孤立的並繼續執行。
當通過 systemd 啟動時,如果父程序退出,則子程序也都退出(嗯,
screen
他們啟動的 s 死亡並顯示為 Dead)。理想情況下,我需要能夠在不殺死所有子程序的情況下重新啟動父腳本,有什麼我遺漏的嗎?
謝謝!
[Unit] Description=Server commander After=network.target [Service] User=serveruser Type=forking PIDFile=/var/Server/Server.pid ExecStart=/var/Server/Server.py ExecStop=/bin/kill -s TERM $MAINPID [Install] WantedBy=multi-user.target
編輯:
我可能需要指出 Python 腳本本質上是其子程序的“控制器”。
screen
它根據中央伺服器的請求啟動和停止 GNU中的伺服器。它通常一直在執行,它不會產生服務並退出。然而,在某些情況下,我希望能夠在不殺死子程序的情況下重新載入腳本,即使這意味著程序被孤立到 pid 1。事實上,Python 腳本是否啟動程序也沒關係一個父程序,如果可能的話。
更好地解釋它是如何工作的:
systemd
產卵Server.py
Server.py
分叉並寫入 pid 文件systemd
Server.py
然後根據其指令在 gnu 螢幕中生成伺服器程序Server.py
繼續執行以執行從伺服器請求的任何重新啟動在沒有 , 的情況下啟動時
systemd
,Server.py
可以重新啟動並且screens
它啟動的 GNU 不受影響。當使用 啟動時systemd
,當Server.py
關閉時,這些螢幕程序不會被孤立到 pid 1,而是被殺死。
我設法通過設置而不是(預設)來解決
KillMode
這個process
問題control-group
。謝謝大家!
我有一個 Python 腳本,它在啟動時分叉,並負責啟動一堆其他程序。
這表明你做錯了。稍後再介紹。
當腳本退出時,子程序被孤立並繼續執行。
這不是正確的守護程序行為。如果“主”程序(在這種情況下是您指定的分叉子程序)
Type=forking
退出,systemd 會認為該服務已停用並終止任何其他仍在執行的程序(在控制組中)以進行整理.有時從 System 5
rc
腳本到 systemd 的轉換並不簡單,因為在 systemd 下做事的正確方法是完全不同的。在 systemd 中執行(例如)OpenVPN、OpenStack 或 OSSEC HIDS 的正確方法與使用rc
腳本執行的方法不同。您有一個正在分叉的腳本,然後產生一大堆孫子程序,然後期望這些孫子程序繼續執行,這表明您正在犯下與ossec-control
. 如果您發現自己編寫了一個“主”腳本來檢查“啟用”標誌並為系統的“啟用”部分執行子程序,那麼您犯的錯誤與可怕的ossec-control
.systemd 不需要這種本土機制。它已經是服務經理了。根據https://unix.stackexchange.com/a/200365/5132,在 systemd 中解決此問題的正確方法不是讓一項服務產生一些古怪和困惑的“子服務”嘗試。它將每個子程序本身作為一個成熟的 systemd 服務。然後使用正常的 systemd 控制項啟用和禁用以及啟動和停止系統的各個部分。正如您在 OSSEC HIDS 案例中看到的那樣,一個簡單的模板服務單元幾乎涵蓋了所有(一個例外是 https://askubuntu.com/a/624871/43344)服務,允許執行諸如
systemctl enable ossec@agentlessd.service
啟用可選agentlessd
服務,根本不需要 System 5 所需的可怕的“主腳本”機制rc
。有很多案例,可能不像 OSSEC HIDS 那樣極端,需要重新思考。像 exim 和 sendmail 這樣的 MTS 就是這樣的兩個。一個人可能有一個
rc
腳本,它產生一個隊列執行器、一個 SMTP 送出守護程序和一個 SMTP 中繼守護程序,並在一個配置文件中使用一堆即席 shell 變數來精確控制哪些是執行的。但是使用 systemd 的正確方法是擁有三個適當的服務單元(其中兩個具有關聯的套接字單元)並且根本沒有臨時的東西,只是服務管理器的正常機制。