我應該如何設置 systemd 服務來自動啟動伺服器並讓我將命令傳遞給它?
目標:
我正在嘗試讓 Minecraft 伺服器在 Fedora 上使用 systemd 在電腦啟動時執行。我需要滿足一些自我強加的標準才能正確管理我的伺服器:
- 它必須以
minecraft
我使用 home dir 創建的系統使用者身份執行/opt/minecraft
。我通過 ing 嘗試了這個adduser
,然後添加了行User=minecraft
和WorkingDirectory=/opt/minecraft/
- 它必須是可擴展的並且可以與任意數量的伺服器一起工作。我通過使用模板服務嘗試了此操作,然後將
WorkingDirectory
行更改WorkingDirectory=/opt/minecraft/%i
為讓我傳入一個目錄。- 我必須能夠以某種方式將命令傳遞給它。這是我堅持的那個。我曾嘗試使用插座單元,然後將其連接到
/run/minecraft%I
,但我無法讓它工作。如果您不熟悉 Minecraft 伺服器,他們有這個互動式控制台,您可以將命令傳遞到其中。過去,我使用tmux send
過在會話中執行的伺服器tmux
,但問題是它不會自動啟動並且感覺不優雅。嘗試的解決方案:
/usr/local/lib/systemd/system/minecraft@.service
:[Unit] Description=Minecraft server: %i # only run after networking is ready After=network-online.target Wants=network-online.target [Service] Type=simple # restart if the server crashes Restart=on-failure RestartSec=5s # set the input and outputs to a socket unit and the journal resp. Sockets=minecraft@%i.socket StandardInput=socket StandardOutput=journal StandardError=journal # set the user and directory to the correct values User=minecraft WorkingDirectory=/opt/minecraft/%i/ # run the start script for the specified server ExecStart=/bin/bash /opt/minecraft/%i/start.sh [Install] WantedBy=default.target
/usr/local/lib/systemd/system/minecraft@.socket
:[Unit] Description=Socket for Minecraft server: %i [Socket] # listen to a pipe for input ListenFIFO=%t/minecraft%I.stdin Service=minecraft@%i.service
問題:
當我嘗試使用
sudo systemctl start minecraft@1_17_1.service
(我已經安裝了伺服器/opt/minecraft/1_17_1/
)啟動伺服器時,它失敗了:Job for minecraft@1_17_1.service failed because of unavailable resources or another system error. See "systemctl status minecraft@1_17_1.service" and "journalctl -xeu minecraft@1_17_1.service" for details.
這促使我執行
systemctl status minecraft@1_17_1.service
:● minecraft@1_17_1.service - Minecraft server: 1_17_1 Loaded: loaded (/usr/local/lib/systemd/system/minecraft@.service; enabled; vendor preset: disabled) Active: activating (auto-restart) (Result: resources) since Thu 2021-11-04 14:37:27 EDT; 163ms ago TriggeredBy: × minecraft@1_17_1.socket CPU: 0
並且
journalctl -xeu minecraft@1_17_1.service
Nov 04 14:51:01 riley-fedora systemd[1]: minecraft@1_17_1.service: Got no socket. Nov 04 14:51:01 riley-fedora systemd[1]: minecraft@1_17_1.service: Failed to run 'start' task: Invalid argument Nov 04 14:51:01 riley-fedora systemd[1]: minecraft@1_17_1.service: Failed with result 'resources'. ░░ Subject: Unit failed ░░ Defined-By: systemd ░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel ░░ ░░ The unit minecraft@1_17_1.service has entered the 'failed' state with result 'resources'. Nov 04 14:51:01 riley-fedora systemd[1]: Failed to start Minecraft server: 1_17_1. ░░ Subject: A start job for unit minecraft@1_17_1.service has failed ░░ Defined-By: systemd ░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel ░░ ░░ A start job for unit minecraft@1_17_1.service has finished with a failure. ░░ ░░ The job identifier is 55890 and the job result is failed.
我看到它似乎對我的
minecraft@.socket
文件很生氣,所以我跑了systemctl status minecraft@1_17_1.socket
:× minecraft@1_17_1.socket - Socket for Minecraft server: 1_17_1 Loaded: loaded (/usr/local/lib/systemd/system/minecraft@.socket; static) Active: failed (Result: resources) Triggers: ● minecraft@1_17_1.service Listen: /run/minecraft1_17_1.stdin (FIFO) Nov 04 14:52:35 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed with result 'resources'. Nov 04 14:52:35 riley-fedora systemd[1]: Failed to listen on Socket for Minecraft server: 1_17_1. Nov 04 14:52:41 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to open FIFO /run/minecraft1_17_1.stdin: Permission denied Nov 04 14:52:41 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to listen on sockets: Permission denied Nov 04 14:52:41 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed with result 'resources'. Nov 04 14:52:41 riley-fedora systemd[1]: Failed to listen on Socket for Minecraft server: 1_17_1. Nov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to open FIFO /run/minecraft1_17_1.stdin: Permission denied Nov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to listen on sockets: Permission denied Nov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed with result 'resources'. Nov 04 14:52:46 riley-fedora systemd[1]: Failed to listen on Socket for Minecraft server: 1_17_1.
因此,問題似乎與我使用的管道的權限有關。
為了更好的衡量,我跑了
journalctl -xeu minecraft@1_17_1.socket
Nov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to open FIFO /run/minecraft1_17_1.stdin: Permission denied Nov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to listen on sockets: Permission denied Nov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed with result 'resources'. ░░ Subject: Unit failed ░░ Defined-By: systemd ░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel ░░ ░░ The unit minecraft@1_17_1.socket has entered the 'failed' state with result 'resources'. Nov 04 14:52:46 riley-fedora systemd[1]: Failed to listen on Socket for Minecraft server: 1_17_1. ░░ Subject: A start job for unit minecraft@1_17_1.socket has failed ░░ Defined-By: systemd ░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel ░░ ░░ A start job for unit minecraft@1_17_1.socket has finished with a failure. ░░ ░░ The job identifier is 58598 and the job result is failed.
問題:
我究竟做錯了什麼?我在Google的第二、第三甚至第四頁上花了 4 個小時,但沒有任何解決方案。我在這裡不知所措,因此非常感謝任何和所有幫助。
我無法為您提供完整的答案,因為我無法重現該問題。但我試圖把一個最小可驗證的例子放在一起,並對故障排除有一些想法:
# /etc/systemd/system/sockinst@.service [Service] ExecStart=cat - User=stew Sockets=sockinst@%i.socket StandardInput=socket StandardOutput=journal StandardError=journal
# /etc/systemd/system/sockinst@.socket [Socket] ListenFIFO=%t/sockinst%I.stdin Service=sockinst@%i.service
然後執行這個工作:
stew /etc/systemd/system $ systemctl start sockinst@1_1.service stew /etc/systemd/system $ echo "Hello" > /run/sockinst1_1.stdin stew /etc/systemd/system $ systemctl status sockinst@1_1.{service,socket} ● sockinst@1_1.service - Testing instanced sockets 1_1 Loaded: loaded (/etc/systemd/system/sockinst@.service; static) Active: active (running) since Fri 2021-11-05 10:35:41 CET; 37s ago TriggeredBy: ● sockinst@1_1.socket systemd[1]: Started Testing instanced sockets 1_1. cat[11623]: Hello ● sockinst@1_1.socket - Socket for instance 1_1 Loaded: loaded (/etc/systemd/system/sockinst@.socket; static) Active: active (running) since Fri 2021-11-05 10:35:41 CET; 37s ago Triggers: ● sockinst@1_1.service Listen: /run/sockinst1_1.stdin (FIFO) systemd[1]: Listening on Socket for instance 1_1.
您可能會在這裡遇到一些技巧:
如果你
systemctl stop minecraft@1_17_1.service
,那麼這不會停止並行套接字。這意味著/run/minecraft1_17_1.stdin
將繼續執行。事實上,如果你echo "hello" > /run/minecraft1_17_1.stdin
,它會啟動你的服務。我可以想像,如果您正在對服務進行故障排除,舊的套接字可能會影響您的測試。我建議以下兩種選擇之一:用
systemctl stop minecrat@1_17_1.{service,socket}
它來阻止它,添加
PartOf=minecraft@%i.service
到[Unit]
套接字的部分。這將導致它在服務停止時自動停止。您正在使用
Restart=on-failure
. 這對您的最終結果非常有用,但它可能會隱藏您最初的失敗。在進行故障排除時,請考慮暫時刪除它。然後當它失敗時,你會看到它失敗的最初原因。我的猜測是您在伺服器啟動時遇到了合法問題,但是您的套接字綁定到了第一個實例。然後每次重新啟動都無法在嘗試 ExecStart= 之前綁定到舊套接字,因此您永遠不會發現它最初失敗的原因。一定要停止服務和套接字,然後啟動它並立即檢查輸出。如果您的錯誤資訊不同,我不會感到驚訝。您將 minecraft 伺服器描述為具有 gui。這是可選的,並且突然取決於您的設置
DISPLAY
和XAUTHORITY
設置。這引入了很多可以破壞的東西。考慮使用nogui
in 選項呼叫您的服務,start.sh
以消除導致初始失敗的可能原因。如果你真的很想要那個 gui,那麼你需要在你的腳本中設置DISPLAY
和XAUTHORITY
環境變數(但這不一定是最簡單的事情)。我建議至少在沒有 GUI 的情況下嘗試它,看看是否可以讓您的服務執行。您可能
sudo systemctl daemon-reload
在編輯文件時忘記執行。提醒一下,請務必執行此命令,以便 systemd 讀取每個單元的最新版本。