我应该如何设置 systemd 服务来自动启动服务器并让我向其传递命令?

Ril*_*ley 5 fedora systemd fifo minecraft

目标:

\n

我正在尝试让 Minecraft 服务器在 Fedora 上使用 systemd 在计算机启动时运行。我有一些自我强加的标准,我需要满足这些标准才能正确管理我的服务器:

\n
    \n
  1. 它必须以minecraft我使用主目录创建的系统用户身份运行/opt/minecraft。我尝试通过addusering 然后添加行User=minecraftWorkingDirectory=/opt/minecraft/
  2. \n
  3. 它必须是可扩展的并且可以与任意数量的服务器一起工作。我尝试使用模板服务,然后将行更改WorkingDirectoryWorkingDirectory=/opt/minecraft/%i让我传入目录。
  4. \n
  5. 我必须能够以某种方式将命令传递给它。这就是我所坚持的。我尝试过使用插座单元,然后将其连接到/run/minecraft%I,但我无法让它工作。如果您不熟悉 Minecraft 服务器,他们有一个交互式控制台,您可以将命令传递到其中。过去,我使用过在会话tmux send中运行的服务器tmux,但问题是它不会自动启动并且感觉不优雅。
  6. \n
\n

尝试的解决方案:

\n

/usr/local/lib/systemd/system/minecraft@.service:

\n
[Unit]\nDescription=Minecraft server: %i\n\n# only run after networking is ready\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\n\n# restart if the server crashes\nRestart=on-failure\nRestartSec=5s\n\n# set the input and outputs to a socket unit and the journal resp.\nSockets=minecraft@%i.socket\nStandardInput=socket                     \nStandardOutput=journal\nStandardError=journal\n\n# set the user and directory to the correct values\nUser=minecraft\nWorkingDirectory=/opt/minecraft/%i/\n\n# run the start script for the specified server\nExecStart=/bin/bash /opt/minecraft/%i/start.sh\n\n[Install]\nWantedBy=default.target\n
Run Code Online (Sandbox Code Playgroud)\n

/usr/local/lib/systemd/system/minecraft@.socket:

\n
[Unit]\nDescription=Socket for Minecraft server: %i\n\n[Socket]\n# listen to a pipe for input\nListenFIFO=%t/minecraft%I.stdin\n\nService=minecraft@%i.service\n
Run Code Online (Sandbox Code Playgroud)\n

问题:

\n

sudo systemctl start minecraft@1_17_1.service当我尝试使用(我已安装服务器/opt/minecraft/1_17_1/)启动服务器时,它失败:

\n
Job for minecraft@1_17_1.service failed because of unavailable resources or another system error.\nSee "systemctl status minecraft@1_17_1.service" and "journalctl -xeu minecraft@1_17_1.service" for details.\n
Run Code Online (Sandbox Code Playgroud)\n

这促使我运行systemctl status minecraft@1_17_1.service

\n
\xe2\x97\x8f minecraft@1_17_1.service - Minecraft server: 1_17_1\n     Loaded: loaded (/usr/local/lib/systemd/system/minecraft@.service; enabled; vendor preset: disabled)\n     Active: activating (auto-restart) (Result: resources) since Thu 2021-11-04 14:37:27 EDT; 163ms ago\nTriggeredBy: \xc3\x97 minecraft@1_17_1.socket\n        CPU: 0\n
Run Code Online (Sandbox Code Playgroud)\n

并且journalctl -xeu minecraft@1_17_1.service

\n
Nov 04 14:51:01 riley-fedora systemd[1]: minecraft@1_17_1.service: Got no socket.\nNov 04 14:51:01 riley-fedora systemd[1]: minecraft@1_17_1.service: Failed to run 'start' task: Invalid argument\nNov 04 14:51:01 riley-fedora systemd[1]: minecraft@1_17_1.service: Failed with result 'resources'.\n\xe2\x96\x91\xe2\x96\x91 Subject: Unit failed\n\xe2\x96\x91\xe2\x96\x91 Defined-By: systemd\n\xe2\x96\x91\xe2\x96\x91 Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel\n\xe2\x96\x91\xe2\x96\x91 \n\xe2\x96\x91\xe2\x96\x91 The unit minecraft@1_17_1.service has entered the 'failed' state with result 'resources'.\nNov 04 14:51:01 riley-fedora systemd[1]: Failed to start Minecraft server: 1_17_1.\n\xe2\x96\x91\xe2\x96\x91 Subject: A start job for unit minecraft@1_17_1.service has failed\n\xe2\x96\x91\xe2\x96\x91 Defined-By: systemd\n\xe2\x96\x91\xe2\x96\x91 Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel\n\xe2\x96\x91\xe2\x96\x91 \n\xe2\x96\x91\xe2\x96\x91 A start job for unit minecraft@1_17_1.service has finished with a failure.\n\xe2\x96\x91\xe2\x96\x91 \n\xe2\x96\x91\xe2\x96\x91 The job identifier is 55890 and the job result is failed.\n
Run Code Online (Sandbox Code Playgroud)\n

我看到它似乎对我的minecraft@.socket文件生气,所以我跑了systemctl status minecraft@1_17_1.socket

\n
\xc3\x97 minecraft@1_17_1.socket - Socket for Minecraft server: 1_17_1\n     Loaded: loaded (/usr/local/lib/systemd/system/minecraft@.socket; static)\n     Active: failed (Result: resources)\n   Triggers: \xe2\x97\x8f minecraft@1_17_1.service\n     Listen: /run/minecraft1_17_1.stdin (FIFO)\n\nNov 04 14:52:35 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed with result 'resources'.\nNov 04 14:52:35 riley-fedora systemd[1]: Failed to listen on Socket for Minecraft server: 1_17_1.\nNov 04 14:52:41 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to open FIFO /run/minecraft1_17_1.stdin: Permission denied\nNov 04 14:52:41 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to listen on sockets: Permission denied\nNov 04 14:52:41 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed with result 'resources'.\nNov 04 14:52:41 riley-fedora systemd[1]: Failed to listen on Socket for Minecraft server: 1_17_1.\nNov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to open FIFO /run/minecraft1_17_1.stdin: Permission denied\nNov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to listen on sockets: Permission denied\nNov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed with result 'resources'.\nNov 04 14:52:46 riley-fedora systemd[1]: Failed to listen on Socket for Minecraft server: 1_17_1.\n
Run Code Online (Sandbox Code Playgroud)\n

所以看来这个问题与我使用的管道的权限有关。

\n

为了更好地衡量,我跑了journalctl -xeu minecraft@1_17_1.socket

\n
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\nNov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed to listen on sockets: Permission denied\nNov 04 14:52:46 riley-fedora systemd[1]: minecraft@1_17_1.socket: Failed with result 'resources'.\n\xe2\x96\x91\xe2\x96\x91 Subject: Unit failed\n\xe2\x96\x91\xe2\x96\x91 Defined-By: systemd\n\xe2\x96\x91\xe2\x96\x91 Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel\n\xe2\x96\x91\xe2\x96\x91 \n\xe2\x96\x91\xe2\x96\x91 The unit minecraft@1_17_1.socket has entered the 'failed' state with result 'resources'.\nNov 04 14:52:46 riley-fedora systemd[1]: Failed to listen on Socket for Minecraft server: 1_17_1.\n\xe2\x96\x91\xe2\x96\x91 Subject: A start job for unit minecraft@1_17_1.socket has failed\n\xe2\x96\x91\xe2\x96\x91 Defined-By: systemd\n\xe2\x96\x91\xe2\x96\x91 Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel\n\xe2\x96\x91\xe2\x96\x91 \n\xe2\x96\x91\xe2\x96\x91 A start job for unit minecraft@1_17_1.socket has finished with a failure.\n\xe2\x96\x91\xe2\x96\x91 \n\xe2\x96\x91\xe2\x96\x91 The job identifier is 58598 and the job result is failed.\n
Run Code Online (Sandbox Code Playgroud)\n

问题:

\n

我究竟做错了什么?我在 Google 的第二页、第三页甚至第四页上花了 4 个多小时,但没有找到解决方案。我在这里不知所措,所以非常感谢任何和所有的帮助。

\n

Ste*_*art 4

我没有完整的答案给你,因为我无法重现这个问题。但我尝试整理一个最小的可验证示例,并提出了一些故障排除的想法:

\n
# /etc/systemd/system/sockinst@.service\n[Service]\nExecStart=cat -\nUser=stew\nSockets=sockinst@%i.socket\nStandardInput=socket\nStandardOutput=journal\nStandardError=journal\n
Run Code Online (Sandbox Code Playgroud)\n
# /etc/systemd/system/sockinst@.socket\n[Socket]\nListenFIFO=%t/sockinst%I.stdin\nService=sockinst@%i.service\n
Run Code Online (Sandbox Code Playgroud)\n

然后运行这个作品:

\n
stew /etc/systemd/system $ systemctl start sockinst@1_1.service\nstew /etc/systemd/system $ echo "Hello" > /run/sockinst1_1.stdin \nstew /etc/systemd/system $ systemctl status sockinst@1_1.{service,socket}\n\xe2\x97\x8f sockinst@1_1.service - Testing instanced sockets 1_1\n     Loaded: loaded (/etc/systemd/system/sockinst@.service; static)\n     Active: active (running) since Fri 2021-11-05 10:35:41 CET; 37s ago\nTriggeredBy: \xe2\x97\x8f sockinst@1_1.socket\n\nsystemd[1]: Started Testing instanced sockets 1_1.\ncat[11623]: Hello\n\n\xe2\x97\x8f sockinst@1_1.socket - Socket for instance 1_1\n     Loaded: loaded (/etc/systemd/system/sockinst@.socket; static)\n     Active: active (running) since Fri 2021-11-05 10:35:41 CET; 37s ago\n   Triggers: \xe2\x97\x8f sockinst@1_1.service\n     Listen: /run/sockinst1_1.stdin (FIFO)\n\nsystemd[1]: Listening on Socket for instance 1_1.\n
Run Code Online (Sandbox Code Playgroud)\n

您可能会在这里遇到一些技巧:

\n
    \n
  1. 如果您这样做systemctl stop minecraft@1_17_1.service,那么这不会停止并行套接字。这意味着/run/minecraft1_17_1.stdin将继续运行。事实上,如果您这样做echo "hello" > /run/minecraft1_17_1.stdin,它就会启动您的服务。我可以想象,如果您正在对服务进行故障排除,旧套接字可能会影响您的测试。我建议选择以下两个选项之一:

    \n
      \n
    1. systemctl stop minecrat@1_17_1.{service,socket}它来阻止它,
    2. \n
    3. 添加PartOf=minecraft@%i.service[Unit]套接字部分。这将导致它在服务停止时自动停止。
    4. \n
    \n
  2. \n
  3. 您正在使用Restart=on-failure。这对您的最终结果很有好处,但它可能会掩盖您最初的失败。在排除故障时,请考虑暂时删除它。然后当它失败时,您将看到失败的最初原因。我的猜测是,您在服务器启动时遇到了合法的问题,但是您的套接字绑定到了第一个实例。然后,每次重新启动都无法在尝试 ExecStart= 之前绑定到旧套接字,因此您永远不会发现它最初失败的原因。请务必停止服务和套接字,然后启动它并立即检查输出。如果您的错误消息有所不同,我不会感到惊讶。

    \n
  4. \n
  5. 您将我的世界服务器描述为具有图形用户界面。这是可选的,并且突然取决于您DISPLAYXAUTHORITY正在设置的事情。这引入了很多可能会破坏的东西。请考虑致电您的服务人员并选择nogui消除start.sh这种可能导致初始故障的原因。如果您真的非常想要那个 gui,那么您需要在脚本中设置DISPLAYXAUTHORITY环境变量(但这不一定是最简单的事情)。我建议至少在没有 GUI 的情况下尝试一下,看看是否能让您的服务运行。

    \n
  6. \n
  7. 您可能sudo systemctl daemon-reload在编辑文件时忘记运行。提醒一下,请务必运行此命令,以便 systemd 读取每个单元的最新版本。

    \n
  8. \n
\n