作为 systemd 服务运行两个 tmux 会话

afa*_*far 7 linux tmux systemd

我可以成功启动/停止创建 tmux 会话的服务。服务如下:
test1.service:

[Unit]
Description=First test service

[Service]
Type=forking
User=lancer
ExecStart=/usr/bin/tmux new-session -s test1 -d
ExecStop=/usr/bin/tmux kill-session -t test1

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

$ sudo systemctl start test1.service

$ sudo systemctl stop test1.service

都成功了。现在我想要另一个 tmux 会话,我可以从另一个服务控制它。所以我创建了这个 test2.service:

    [Unit]
    Description=Second test service
    
    [Service]
    Type=forking
    User=lancer
    ExecStart=/usr/bin/tmux new-session -s test2 -d
    ExecStop=/usr/bin/tmux kill-session -t test2
    
    [Install]
    WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

问题:两者中的任何一个都可以单独工作。我可以通过以下方式查看相应的 tmux 会话:
$ tmux ls
如果我启动其他服务,则不会发生任何情况。我只有之前的 tmux 会话。有人可以帮忙吗?

Kam*_*ski 10

Type=forking这里的类型不正确。它使 systemd 期望tmux进程(从 运行ExecStart=)进行 fork。但这tmux并不总是分叉。

  • 如果没有 tmux 服务器,该tmux命令将分叉。新tmux进程将成为一个服务器,在原进程退出后仍然存在tmux。这正是 systemd 所期望的Type=forking。这就是为什么这两项服务中的任何一项都单独工作的原因。

  • 如果已经存在 tmux 服务器,该tmux命令将与其通信以创建会话;但它不会fork,没有必要fork。该进程将退出而不留下分叉进程,但仍会报告成功。我的测试表明在这种情况下ExecStop=会被执行。在您的情况下,ExecStop=立即终止新创建的会话。您没有注意到会话的短暂存在,您认为什么也没有发生。

处理这个问题的一种方法是创建一个“主”服务来启动 tmux服务器。因为这Type=forking是对的。您可以从中启动一个虚拟会话,或者使用start-server(with exit-empty off) 并让它在没有任何会话的情况下运行。

我认为创建实际会话的服务应该使用Type=oneshotwith RemainAfterExit=yes。他们应该想要 ( Wants=) 或需要 ( Requires=) “主”服务。我对systemd不够熟悉,无法提出详细的解决方案;我什至不确定“主”服务的想法是否是最好的。

不管怎样,现在你知道为什么在某些情况下据称什么也没有发生了。


afa*_*far 5

感谢@Kamil Maciorowski,我有一个解决方案。三个步骤:

  1. 定义主服务master.service,如下所示:
[Unit]
Description=tmux master service

[Service]
Type=forking
User=lancer
ExecStart=/usr/bin/tmux new-session -s master -d
ExecStop=/usr/bin/tmux kill-session -t master

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)
  1. 定义第一个服务 test1.service,如下所示:
[Unit]
Description=tmux test 1 service
PartOf=master.service
After=master.service

[Service]
Type=oneshot
RemainAfterExit=yes
User=lancer
ExecStart=/usr/bin/tmux new-session -s test1 -d
ExecStop=/usr/bin/tmux kill-session -t test1

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)
  1. 定义第二个服务 test2.service,如下所示:
[Unit]
Description=tmux test 2 service
PartOf=master.service
After=master.service

[Service]
Type=oneshot
RemainAfterExit=yes
User=lancer
ExecStart=/usr/bin/tmux new-session -s test2 -d
ExecStop=/usr/bin/tmux kill-session -t test2

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

注意事项

  1. @Kamil Maciorowski 解释了为什么使用forking和。oneshot
  2. master.service 创建一个名为master的虚拟 tmux 会话,它除了托管其他实际 tmux 会话外什么也不做。
  3. 在test1和test2服务中,After是为了确保在启动时,test1和test2服务在master服务之后启动。
  4. 在test1和test2服务中,PartOf是为了确保如果master停止了,test1和test2服务也停止。如果没有这个,如果主站停止,test1 和 test2 状态显示它们仍然处于活动状态。