我正在通过为不同的游戏服务器设置服务来积累我的 Linux 知识(至少我正在尝试)。
目前我正在开发一个 Minecraft 服务器,该服务器将在服务器重启时自动启动。一切似乎都正常,但我认为我在停止命令上终止服务器的方式不是最好的。
这是当前的单元文件:
[Unit]
Description=Minecraft Dedicated Server
After=network.service
[Service]
User=user
Group=user_group
Type=simple
WorkingDirectory=/usr/local/bin/services/minecraft/
ExecStart=/usr/local/bin/services/minecraft/run.sh
ExecStop=/bin/kill -9 $MAINPID
RestartSec=15
Restart=on-failure
[Install]
WantedBy=multi-user.target
我读到过,仅仅使用 kill 命令无法正常终止服务器,而应该使用 minecraft-internal “stop” 命令。不幸的是,我无法弄清楚如何修改 ExecStop 命令以将内部命令发送到 minecraft 进程。
编辑:
已实施以下措施:
minecraft.service:
[Unit]
Description=Minecraft Dedicated Server
After=network.service
[Service]
User=user
Group=user_group
Type=simple
KillSignal=SIGCONT
Sockets=minecraft.socket
WorkingDirectory=/usr/local/bin/services/minecraft/
ExecStart=/bin/sh -c "java -Xms2G -Xmx4G -XX:+UseConcMarkSweepGC -jar spigot-1.14.4.jar < /run/minecraft.control"
ExecStop=/bin/sh -c "echo /stop > /run/minecraft.control"
RestartSec=15
Restart=on-failure
[Install]
WantedBy=multi-user.target
minecraft.socket:
[Unit]
BindsTo=minecraft.service
[Socket]
ListenFIFO=/run/minecraft.control
RemoveOnStop=true
sockeSocketMode=0664
SocketUser=user
SocketGroup=user_group
不幸的是,通过 minecraft.control fifo 传递的命令不起作用。
我观察到以下行为:使用
echo "/help" > /run/minecraft.control
有时在查看 minecraft.control fifo(使用 cat)时会给出输出,有时则不会。如果 fifo 中没有输出,则 minecraft.service 单元的日志会显示未知命令。输入“/help”获取帮助。尽管我已发送“/help”作为命令。此外,该设备的 ExecStop 命令
echo "/stop" > /run/minecraft.control
也不起作用,服务器会被 sigkill 信号杀死。
知道为什么这不起作用吗?
答案1
添加一个新的 minecraft.socket 文件(假设您的服务名为 minecraft.service)以将您的服务器的输入绑定到:
[单元] 绑定到=minecraft.service [插座] ListenFIFO=/run/minecraft.control FileDescriptorName=control RemoveOnStop=true 套接字模式=0660 SocketUser=用户 套接字组=用户组
然后修改 minecraft.service 文件以不发送 SIGTERM,通过使用 exec 包装器修改 ExecStart 将标准输入绑定到套接字。然后 ExecStop 将简单地写入新套接字以将“/stop\n”发送到输入。
[服务] ... KillSignal=SIGCONT 套接字=minecraft.socket ExecStart=/bin/sh -c "exec /usr/local/bin/services/minecraft/run.sh </run/test.control" ExecStop=/bin/sh -c "echo /stop >/run/minecraft.control"
另外,您可以echo "/command" > /run/minecraft.control
随时向服务器发送命令。
您不必担心向 .service 文件添加依赖项,它会由 Sockets= 选项自动添加,BindsTo= 选项将负责在服务停止时停止套接字并清理 FIFO 文件。
以下是根据原作者的建议做出的一些澄清。
为什么我们必须使用 KillSignal=SIGCONT?
这可防止向服务器进程发送 SIGTERM 并导致进程过早停止。除非您添加更多参数(man systemd.kill),否则它仍会在一定时间后发送 SIGKILL。
Sockets=xxx 包含您上面创建的 Socket 的名称,对吗?
是的
套接字文件(在本例中为 minecraft.socket?)必须放在与服务相同的目录中吗?
是的,如果由系统管理员添加,通常是 /etc/systemd/system/。