Debian 服務在啟動時沒有正確啟動文件
我有一個包含以下內容
botstart.service
的文件/etc/systemd/system
:[Unit] Description=Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper) and the lavalink server. [Service] ExecStart=/bin/bash /home/scripts/start.sh [Install] WantedBy=multi-user.target
我開始使用
systemctl enable botstart
它,它說它已啟用。我重新啟動了我的 VPS,但腳本沒有執行。我做到了systemctl status botstart
,它顯示了這一點:root@Hetzner-01:~# systemctl status botstart ● botstart.service - Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper) Loaded: loaded (/etc/systemd/system/botstart.service; enabled; vendor preset: Active: inactive (dead) since Wed 2021-10-27 01:37:10 CEST; 50s ago Process: 481 ExecStart=/bin/bash /home/scripts/start.sh (code=eited, status=0 Main PID: 481 (code=existed, status=0/SUCCESS) Oct 27 01:37:07 Hetzner-01 systemd[1]: STarted Start all discord bots (antiSpam, Oct 27 01:37:10 Hetzner-01 bash[481]: Started all bots Oct 27 01:37:10 Hetzner-01 systemd[1]: botstart.service: Succeeded. lines 1-9/9 (END)...skipping... ● botstart.service - Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper) and the lavalink server. Loaded: loaded (/etc/systemd/system/botstart.service; enabled; vendor preset: enabled) Active: inactive (dead) since Wed 2021-10-27 01:37:10 CEST; 50s ago Process: 481 ExecStart=/bin/bash /home/scripts/start.sh (code=eited, status=0/SUCCESS) Main PID: 481 (code=existed, status=0/SUCCESS)
如果我手動執行腳本,它可以工作,但不知何故不是作為服務,但服務被執行並且腳本執行(這就是服務狀態告訴我的內容。)有人知道為什麼嗎?這是腳本程式碼:
screen -dmS antispam bash -c "cd /home/AntiSpam; python3.8 main.py" screen -dmS autochat bash -c "cd /home/AutoChat; python3.8 main.py" screen -dmS helper bash -c "cd /home/Helper; python3.8 main.py" screen -dmS lavalink bash -c "cd /home/Lavalink; python3.8 main.py" sleep 3 screen -dmS nyoko bash -c "cd /home/Nyoko; python3.8 main.py" echo "Started all bots"
在您的
[Service]
部分中,您沒有明確定義Type=
. 這意味著它將預設為Type=simple
.手冊頁說:
如果設置為簡單,服務管理器將考慮在主服務程序被分叉後立即啟動該單元。預計ExecStart=配置的程序是服務的主程序….
簡而言之,您的腳本是主要過程。它啟動一堆程序,然後退出。
systemd
看到您的主程序退出,然後繼續清理不再有父程序的子程序。相反,你想要
Type=forking
.如果設置為分叉,則預計使用 ExecStart= 配置的程序將呼叫 fork() 作為其啟動的一部分。當啟動完成並設置所有通信通道時,父程序將退出。子程序作為主服務程序繼續執行,當父程序退出時服務管理器會認為該單元啟動。這是傳統 UNIX 服務的行為。如果使用此設置,建議同時使用 PIDFile= 選項,以便 systemd 可以可靠地辨識服務的主程序。
在這種情況下,即使腳本結束,您的子程序也將被允許繼續存在。如果您添加
Type=forking
,事情應該對您更好。請注意,您的設計還有一些其他問題。如果您所做的唯一更改是
Type=forking
,那麼您仍然有一些問題:
- 如果其中一個程序結束,systemd 可能會或可能不會決定這是 MainPID 並考慮您的整個服務
inactive (dead)
。寫入 aPIDFile=
可能對此有所幫助,但我懷疑您不打算將這些程序中的任何一個作為 MainPID。- 如果程序失敗,
systemd
可能不會報告失敗狀態。目前還不清楚其他程序應該發生什麼。建議1:將每個程序拆分為自己的服務。然後
Type=simple
會工作。這樣,如果一項服務發生故障,您可以檢測到它並可靠地對其進行操作,而不會影響其他機器人。建議 2:添加
Restart=on-failure
. 這將允許失敗的服務自動重啟(無需人工干預)。建議 3:不要呼叫
bash
which callsscreen
which callspython3
。直接呼叫python就行了。screen
是一種在環境中不需要的systemd
解決方法。建議 4:要實現它
sleep 3
,您可以使用ExecStartPre=
按照這些建議,
nyoko.service
將如下所示:[Unit] Description=Nyoko discord bot [Service] WorkingDirectory=/home/Nyoko ExecStartPre=/usr/bin/sleep 3 ExecStart=/usr/bin/python3 /home/Nyoko/main.py Restart=on-failure [Install] WantedBy=multi-user.target
建議5:
sleep
不太可靠。在美好的一天,它浪費了 3 秒。在糟糕的一天,這還不夠,您的服務將失敗。考慮添加After=lavalink.service
到您的[Unit]
部分以確保lavalink.service
在依賴它的內容之前開始。如果lavalink
有某種信號表明它已啟動(文件已創建或套接字已打開),那麼您可以觸發它。