Executando duas sessões tmux como serviço systemd

Aug 29 2020

Posso iniciar / interromper com êxito um serviço que cria uma sessão tmux. O serviço é o seguinte:
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
e
$ sudo systemctl stop test1.service

ambos têm sucesso. Agora eu gostaria de ter outra sessão tmux que eu possa controlar de outro serviço. Então, eu crio este 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

Problema : qualquer um dos dois funciona sozinho. Posso ver a sessão tmux correspondente por:
$ tmux ls
Se eu iniciar o outro serviço, nada acontece. Eu só tenho a sessão anterior do tmux. Alguém pode ajudar por favor?

Respostas

1 KamilMaciorowski Aug 29 2020 at 23:25

Type=forkingnão é o tipo certo aqui. Isso faz com que o systemd espere que o tmuxprocesso (executado de ExecStart=) bifurque. Mas isso tmuxnem sempre se bifurca.

  • Se não houver servidor tmux, o tmuxcomando será bifurcado . O novo tmuxprocesso se tornará um servidor e sobreviverá após a tmuxsaída do processo original . Isso é exatamente o que o systemd espera Type=forking. É por isso que qualquer um dos dois serviços funciona sozinho.

  • Se já existe um servidor tmux, o tmuxcomando se comunicará com ele para criar uma sessão; mas não se bifurca, não há necessidade de bifurcar. O processo será encerrado sem deixar um processo bifurcado, mas relatará sucesso. Meus testes indicam que em tal situação ExecStop=é executado. No seu caso, ExecStop=mata a sessão recém-criada imediatamente. Você não percebe que a sessão está lá brevemente, você acha que nada acontece.

Uma maneira de lidar com o problema é criar um serviço "mestre" que com certeza inicie um servidor tmux . Pois Type=forkingestá certo. Você pode iniciar uma sessão fictícia a partir dele ou usar start-server(com exit-empty off) e deixá-la funcionar sem qualquer sessão.

Serviços que criam sessões reais devem ser usados Type=oneshotcom RemainAfterExit=yes, eu acho. Eles devem querer ( Wants=) ou exigir ( Requires=) o serviço "mestre". Não estou familiarizado o suficiente com o systemd para propor uma solução detalhada; Eu nem tenho certeza se a ideia de um serviço "master" é a melhor.

De qualquer forma, agora você sabe por que, em certas circunstâncias, supostamente nada acontece.

1 afar Sep 01 2020 at 18:35

Graças a @Kamil Maciorowski, tenho uma solução. Três etapas:

  1. Defina um serviço mestre, master.service , da seguinte maneira:
[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
  1. Defina o primeiro serviço, test1.service , da seguinte forma:
[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
  1. Defina o segundo serviço, test2.service , da seguinte forma:
[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

Notas :

  1. @Kamil Maciorowski explica porque forkinge oneshotsão usados.
  2. O master.service cria uma sessão tmux fictícia chamada master que não faz nada além de hospedar as outras sessões tmux reais.
  3. Nos serviços test1 e test2, Aftercertifique-se de que, na inicialização, os serviços test1 e test2 sejam iniciados após o serviço mestre.
  4. Nos serviços test1 e test2, PartOfcertifique-se de que, se o mestre for interrompido, os serviços test1 e test2 também serão interrompidos. Sem isso, se o mestre parar, os status test1 e test2 mostram que eles ainda estão ativos.