Debian 服務在啟動時無法正確啟動文件

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"

答案1

在您的[Service]部分中,您沒有明確定義Type=.這意味著它將預設為Type=simple.

手冊頁說:

如果設定為 simple,服務管理員將認為該單元在主服務程序被分叉後立即啟動。預計ExecStart=配置的程序是服務的主程序....

簡而言之,你的腳本就是主行程。它啟動一堆進程,然後退出。 systemd看到主進程退出,然後繼續清理不再有父進程的子進程。

相反,你想要Type=forking

如果設定為 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哪個呼叫screen哪個呼叫python3。直接呼叫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有某種訊號表示它已啟動(檔案已建立或套接字已開啟),那麼您可以觸發它。

相關內容