Fedora

我應該如何設置 systemd 服務來自動啟動伺服器並讓我將命令傳遞給它?

  • November 11, 2021

目標:

我正在嘗試讓 Minecraft 伺服器在 Fedora 上使用 systemd 在電腦啟動時執行。我需要滿足一些自我強加的標準才能正確管理我的伺服器:

  1. 它必須以minecraft我使用 home dir 創建的系統使用者身份執行/opt/minecraft。我通過 ing 嘗試了這個adduser,然後添加了行User=minecraftWorkingDirectory=/opt/minecraft/
  2. 它必須是可擴展的並且可以與任意數量的伺服器一起工作。我通過使用模板服務嘗試了此操作,然後將WorkingDirectory行更改WorkingDirectory=/opt/minecraft/%i為讓我傳入一個目錄。
  3. 我必須能夠以某種方式將命令傳遞給它。這是我堅持的那個。我曾嘗試使用插座單元,然後將其連接到/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.

您可能會在這裡遇到一些技巧:

  1. 如果你systemctl stop minecraft@1_17_1.service,那麼這不會停止並行套接字。這意味著/run/minecraft1_17_1.stdin將繼續執行。事實上,如果你echo "hello" > /run/minecraft1_17_1.stdin,它會啟動你的服務。我可以想像,如果您正在對服務進行故障排除,舊的套接字可能會影響您的測試。我建議以下兩種選擇之一:

  2. systemctl stop minecrat@1_17_1.{service,socket}它來阻止它,

  3. 添加PartOf=minecraft@%i.service[Unit]套接字的部分。這將導致它在服務停止時自動停止。

  4. 您正在使用Restart=on-failure. 這對您的最終結果非常有用,但它可能會隱藏您最初的失敗。在進行故障排除時,請考慮暫時刪除它。然後當它失敗時,你會看到它失敗的最初原因。我的猜測是您在伺服器啟動時遇到了合法問題,但是您的套接字綁定到了第一個實例。然後每次重新啟動都無法在嘗試 ExecStart= 之前綁定到舊套接字,因此您永遠不會發現它最初失敗的原因。一定要停止服務和套接字,然後啟動它並立即檢查輸出。如果您的錯誤資訊不同,我不會感到驚訝。

  5. 您將 minecraft 伺服器描述為具有 gui。這是可選的,並且突然取決於您的設置DISPLAYXAUTHORITY設置。這引入了很多可以破壞的東西。考慮使用noguiin 選項呼叫您的服務,start.sh以消除導致初始失敗的可能原因。如果你真的很想要那個 gui,那麼你需要在你的腳本中設置DISPLAYXAUTHORITY環境變數(但這不一定是最簡單的事情)。我建議至少在沒有 GUI 的情況下嘗試它,看看是否可以讓您的服務執行。

  6. 您可能sudo systemctl daemon-reload在編輯文件時忘記執行。提醒一下,請務必執行此命令,以便 systemd 讀取每個單元的最新版本。

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