Shell-Script

Debian 服務在啟動時沒有正確啟動文件

  • November 22, 2021

我有一個包含以下內容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:不要呼叫bashwhich calls screenwhich calls 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有某種信號表明它已啟動(文件已創建或套接字已打開),那麼您可以觸發它。

引用自:https://unix.stackexchange.com/questions/674917