Systemd
systemd 在啟動服務時忽略返回碼
我在為一個簡單的守護程序編寫單元文件時遇到了這個問題。當守護程序在啟動時返回“1”時,systemd 會忽略它,看起來守護程序已成功啟動,但實際上它已經死了。
例如,我有非常簡單的 shell 腳本:
#!/bin/bash exit 1
所以單元文件看起來像這樣:
[Unit] Description=test service After=syslog.target [Service] User=testuser Group=testuser ExecStart=/usr/local/bin/return1 [Install] WantedBy=multi-user.target
嘗試開始,似乎沒問題:
# service testservice start # echo $? 0
但實際上它已經死了:
# service testservice status ● testservice.service - test service Loaded: loaded (/etc/systemd/system/testservice.service; enabled) Active: failed (Result: exit-code) since Fri 2016-01-22 14:51:45 MSK; 1min 13s ago Process: 16416 ExecStart=/usr/local/bin/return1 (code=exited, status=1/FAILURE) Main PID: 16416 (code=exited, status=1/FAILURE) Jan 22 14:51:45 servername systemd[1]: Started test service. Jan 22 14:51:45 servername systemd[1]: testservice.service: main process exited, code=exited, status=1/FAILURE Jan 22 14:51:45 servername systemd[1]: Unit testservice.service entered failed state.
看起來 systemd 認為守護程序已成功啟動,但後來崩潰了。
我試圖通過將服務類型更改為“分叉”等來解決這個問題 - 這在非零程式碼的情況下工作正常,但服務實際上是“簡單的”,所以在成功啟動的情況下,它只會保持並保持終端忙。
如何管理此類服務?或者可能有必要修復守護程式碼中的某些內容?
作業系統 debian 8 x64,systemd 215
要
systemd
檢測程序是否成功啟動,您必須使用Type=forking
,然後在幫助腳本中分叉您的程序,並在程序啟動成功時簽入該腳本。使用分叉systemd
將等待ExecStart
命令完成並檢查其退出狀態。您應該像這樣更改您的單元文件:
[Unit] Description=test service After=syslog.target [Service] Type=forking User=testuser Group=testuser ExecStart=/usr/local/bin/fork_service [Install] WantedBy=multi-user.target
/usr/local/bin/fork_service
你應該有這樣的東西:#!/bin/bash # Run your process in background /path/to/your_service & # Check if the services started successfully if ! kill -0 $! 2>/dev/null; then # Return 1 so that systemd knows the service failed to start exit 1 fi
我在這裡只是檢查後台程序 PID 是否仍處於活動狀態,但您可以進行任何您想要的檢查。唯一重要的是,如果程序成功啟動,則此腳本以 0 退出,如果失敗,則以正的非零值退出。
此外,您不必使用 Bash 來分叉程序,您可以使用任何您想要的語言。