如何使用 screen 控制 systemd 服务?

如何使用 screen 控制 systemd 服务?

我已经设置了一个 systemd 服务来运行我的 Minecraft 服务器。现在,我需要它在服务器崩溃时重复启动脚本。到目前为止,这是我的代码:

#!/bin/bash

while true; do
    cd /home/mcserver/Spigot
    echo Starting Spigot...
    echo 600 > ./restart-info
    java -jar spigot.jar
    echo Server has stopped or crashed, starting again in 5 minutes...
    sleep 300
done

spigot.jar我实际上可以使用查看输出systemctl status spigot,但我还想控制服务器控制台,也许使用screen

当我尝试这样做时:

screen -S "Spigot" java -jar spigot.jar

我会得到Must be connected to a terminal错误。该命令仅适用于终端(不适用于脚本),我可以使用 附加它screen -r

有什么办法可以“绕过”这个屏幕错误吗?我已经尝试放置script /dev/null在屏幕命令之前。我不想将 screen 与 -d 和 -m 一起使用,因为它将在后台运行,并且脚本将不断重新启动我的服务器。

答案1

我怀疑你偶然发现了这篇博文它用于解决当您关闭 ssh 或 putty 会话screen时您的 Minecraft 服务器停止的问题。$ java -jar spigot.jar该方法似乎已成为如何运行 Minecraft 服务器的规范答案,尽管它不是必需的。

systemd 是解决这个问题的一个完全不同(也是更好)的解决方案,避免了对screen.您可以使用 systemd 服务选项来实现您在脚本中所做的一切。


要运行普通的Minecraft服务器,请/etc/systemd/system/minecraft.service使用以下内容创建:

[Unit]
Description=Minecraft Server

[Service]
Type=simple
WorkingDirectory=/home/minecraft
ExecStart=java -Xmx1024M -Xms1024M -jar /home/minecraft/server.jar nogui
User=minecraft
Restart=on-failure

[Install]
WantedBy=multi-user.target

将其设置为启动后自动启动systemctl enable minecraft

您问的是如何控制它:

$ sudo systemctl start minecraft   # Starts the service if it wasn't running
$ sudo systemctl stop minecraft    # Stops the service
$ sudo systemctl restart minecraft # Restarts the service
$ sudo systemctl status minecraft  # Find out how the service is doing
$ sudo journalctl -u minecraft -f  # Monitor the logs

除了为您提供一种向控制台发送命令的方法之外,它可以完成所有操作。为此,我们将设置一个文件,服务器将侦听该文件,您可以通过创建以下 systemd 单元在其中编写命令:

/etc/systemd/system/minecraft.socket

[Unit]
PartOf=minecraft.service

[Socket]
ListenFIFO=%t/minecraft.stdin

/etc/systemd/system/minecraft.service

[Unit]
Description=Minecraft Server

[Service]
Type=simple
WorkingDirectory=/home/minecraft
ExecStart=java -Xmx1024M -Xms1024M -jar /home/minecraft/server.jar nogui
User=minecraft
Restart=on-failure
Sockets=minecraft.socket
StandardInput=socket
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

现在您可以通过将内容回显到该文件来发送控制台命令:

echo "help" > /run/minecraft.stdin
echo "/stop" > /run/minecraft.stdin

同样很酷的是,您可以将自己的自定义命令序列和cat整个文件放入控制台中。例如,如果你玩全民健康覆盖,你可以开始一个新的世界,让人们登录,然后cat uhc.commands > /run/minecraft.stdin设置游戏规则,分散玩家,并开始活动。

答案2

我不想将 screen 与 -d 和 -m 一起使用,因为它将在后台运行,并且脚本将不断重新启动我的服务器。

所以使用-D而不是-d(注意大写!)

-D -m 这也会以“分离”模式启动屏幕,但不会分叉新进程。如果会话终止,该命令将退出。

由于screen不会派生新进程,因此它将在java运行时阻塞,并在服务器停止时退出。

作为奖励,如果您添加,-S spigot您可以通过连接到该屏幕来监控任何终端的输出(甚至发送命令!)

而且...既然您无论如何都在使用 systemd 服务(而且您确实应该),为什么要在脚本中执行此重新启动循环?让 systemd 为您处理这个问题,使用Restart=alwaysRestartSec=5min

答案3

我已经找到了解决方案,但我无法使用systemctl status spigot.

#!/bin/bash

while true; do
    cd /home/mcserver/Spigot
    echo Starting Spigot...
    screen -d -m -S Spigot java -jar spigot.jar
    SCREEN_NAME="Spigot"
    while screen -list | grep -q $SCREEN_NAME
    do
        sleep 1
    done
    echo Server has stopped, starting again in 5 minutes...
    sleep 300
done

该脚本将等待,直到屏幕会话终止。我现在可以使用查看输出或与控制台交互screen -r,或者如果我正在运行多个屏幕会话,我可以使用附加screen -D -R "Spigot"

相关内容