防止 systemd 创建的 tmux 会话在 Ctrl+C 时自动终止
Preventing tmux session created by systemd from automatically terminating on Ctrl+C
几天后,我在 Ubuntu 18.04 LTS 家庭服务器上成功 运行 了新的 Minecraft 基岩版 专用服务器。因为它应该 24/7 可用并在启动后自动启动我为分离的 tmux 会话创建了一个 systemd 服务:
tmux.minecraftserver.service
[Unit]
Description=tmux minecraft_server detached
[Service]
Type=forking
WorkingDirectory=/home/mine/minecraftserver
ExecStart=/usr/bin/tmux new -s minecraftserver -d "LD_LIBRARY_PATH=. /home/mine/minecraftser$
User=mine
[Install]
WantedBy=multi-user.target
一切都按预期进行,但有一件小事一直困扰着我:
如何防止 tmux 在我按下 Ctrl+C
时终止它的整个会话?
我只想终止 Minecraft 服务器进程 本身 而不是整个 tmux 会话。在手动创建的 tmux 会话中从命令行启动服务器时,此 确实 工作(会话保持活动状态)但当会话由 systemd[=29 启动时无效=].
When starting the server from the command line in a manually created tmux session this does work (session stays alive) but not when the session was brought up by systemd.
这些情况的区别其实与systemd无关。在一种情况下,您从 tmux 会话中的 shell 启动服务器,当服务器终止时,将 return 控制到 shell。在另一种情况下,您直接在 tmux 会话中启动服务器,当它终止时没有 shell 到 return 到,所以 tmux 会话也会终止。
tmux 有一个选项可以让会话在其内部进程结束后保持活动状态(在联机帮助页中查找 remain-on-exit
),但这可能不是您想要的:您希望能够 return 到交互式 shell,以重新启动服务器,调查它死掉的原因,或执行维护任务,例如。所以最好将您的命令更改为:
'LD_LIBRARY_PATH=. /home/mine/minecraftserver/…; exec bash'
也就是说,首先 运行 服务器,然后,在它终止后,替换进程(tmux 隐式生成的 shell 到 运行 命令,但是它将然后退出)与另一个交互式 shell。 (有关在命令退出后获得交互式 shell 的其他一些方法,请参见 this question – 但请注意,最佳答案中建议的 <(echo commands)
语法在 systemd 中不可用单元文件。)
我可以通过使用 systemd 的 ExecStartPost
和 tmux 的 send-keys
来解决这个问题,如下所示:
[Unit]
Description=tmux minecraft_server detached
[Service]
Type=forking
WorkingDirectory=/home/mine/minecraftserver
ExecStart=/usr/bin/tmux new -d -s minecraftserver
ExecStartPost=/usr/bin/tmux send-keys -t minecraftserver "cd /home/mine/minecraftserver/" Enter "LD_LIBRARY_PATH=. ./bedrock_server" Enter
User=mine
[Install]
WantedBy=multi-user.target
几天后,我在 Ubuntu 18.04 LTS 家庭服务器上成功 运行 了新的 Minecraft 基岩版 专用服务器。因为它应该 24/7 可用并在启动后自动启动我为分离的 tmux 会话创建了一个 systemd 服务:
tmux.minecraftserver.service
[Unit]
Description=tmux minecraft_server detached
[Service]
Type=forking
WorkingDirectory=/home/mine/minecraftserver
ExecStart=/usr/bin/tmux new -s minecraftserver -d "LD_LIBRARY_PATH=. /home/mine/minecraftser$
User=mine
[Install]
WantedBy=multi-user.target
一切都按预期进行,但有一件小事一直困扰着我:
如何防止 tmux 在我按下 Ctrl+C
时终止它的整个会话?
我只想终止 Minecraft 服务器进程 本身 而不是整个 tmux 会话。在手动创建的 tmux 会话中从命令行启动服务器时,此 确实 工作(会话保持活动状态)但当会话由 systemd[=29 启动时无效=].
When starting the server from the command line in a manually created tmux session this does work (session stays alive) but not when the session was brought up by systemd.
这些情况的区别其实与systemd无关。在一种情况下,您从 tmux 会话中的 shell 启动服务器,当服务器终止时,将 return 控制到 shell。在另一种情况下,您直接在 tmux 会话中启动服务器,当它终止时没有 shell 到 return 到,所以 tmux 会话也会终止。
tmux 有一个选项可以让会话在其内部进程结束后保持活动状态(在联机帮助页中查找 remain-on-exit
),但这可能不是您想要的:您希望能够 return 到交互式 shell,以重新启动服务器,调查它死掉的原因,或执行维护任务,例如。所以最好将您的命令更改为:
'LD_LIBRARY_PATH=. /home/mine/minecraftserver/…; exec bash'
也就是说,首先 运行 服务器,然后,在它终止后,替换进程(tmux 隐式生成的 shell 到 运行 命令,但是它将然后退出)与另一个交互式 shell。 (有关在命令退出后获得交互式 shell 的其他一些方法,请参见 this question – 但请注意,最佳答案中建议的 <(echo commands)
语法在 systemd 中不可用单元文件。)
我可以通过使用 systemd 的 ExecStartPost
和 tmux 的 send-keys
来解决这个问题,如下所示:
[Unit]
Description=tmux minecraft_server detached
[Service]
Type=forking
WorkingDirectory=/home/mine/minecraftserver
ExecStart=/usr/bin/tmux new -d -s minecraftserver
ExecStartPost=/usr/bin/tmux send-keys -t minecraftserver "cd /home/mine/minecraftserver/" Enter "LD_LIBRARY_PATH=. ./bedrock_server" Enter
User=mine
[Install]
WantedBy=multi-user.target