Running two tmux sessions as systemd service
I can successfully start/stop a service that creates a tmux session. The service is as following:
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
$ sudo systemctl start test1.service
and$ sudo systemctl stop test1.service
are both successful. Now I would like to have another tmux session that I can control from another service. So I create this 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
Problem: Any of the two works alone. I can see the corresponding tmux session by:$ tmux ls
If I start the other service, nothing happens. I only have the previous tmux session.
Can some one please help?
Solution 1:
Type=forking
is not the right type here. It makes systemd expect the tmux
process (run from ExecStart=
) to fork. But this tmux
not always forks.
-
If there is no tmux server, the
tmux
command will fork. The newtmux
process will become a server, it will survive after the originaltmux
process exits. This is exactly what systemd expects fromType=forking
. That's why any of the two services works alone. -
If there is already a tmux server, the
tmux
command will communicate with it to create a session; but it won't fork, there is no need to fork. The process will exit without leaving a forked process, still it will report success. My tests indicate that in such situationExecStop=
gets executed. In your caseExecStop=
kills the newly created session right away. You don't notice the session is there briefly, you think nothing happens.
One way to deal with the issue is to create a "master" service that starts a tmux server for sure. For it Type=forking
is right. You can start a dummy session from it or use start-server
(with exit-empty off
) and let it run without any session.
Services that create actual sessions should use Type=oneshot
with RemainAfterExit=yes
, I think. They should want (Wants=
) or require (Requires=
) the "master" service. I'm not familiar enough with systemd to propose a detailed solution; I'm not even sure if the idea with a "master" service is the best.
Anyway, now you know why in certain circumstances allegedly nothing happens.
Solution 2:
Thanks to @Kamil Maciorowski, I have a solution. Three steps:
- Define a master service, master.service, as following:
[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
- Define the first service, test1.service, as following:
[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
- Define the second service, test2.service, as following:
[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
Notes:
- @Kamil Maciorowski explains why
forking
andoneshot
are used. - The master.service creates a dummy tmux session called master that does nothing but hosts the other actual tmux sessions.
- In the test1 and test2 services,
After
is to make sure at boot-up, the test1 and test2 services start after the master service. - In the test1 and test2 services,
PartOf
is to make sure that if the master stoped, the test1 and test2 services also stop. Without this, if master stops, test1 and test2 statuses show they are still active.