Evite a eliminação do escopo do usuário do systemd no desligamento

Evite a eliminação do escopo do usuário do systemd no desligamento

Eu crio uma máquina Debian Bookworm para servir como gerenciador de contêineres LXC. Eu uso contêineres LXC sem privilégios iniciados com o comando lxc-unpriv-start que cria um escopo de usuário systemd. Eu crio um serviço que inicia meus contêineres na inicialização do servidor e inicia um desligamento limpo na parada do serviço. Cada contêiner pode levar 2 ou 3 minutos para desligar. Se eu interromper o serviço principal manualmente, tudo funcionará bem. O problema surge quando eu desligo o servidor porque meu serviço aguarda corretamente o encerramento dos contêineres, mas enquanto isso o systemd-logind mata todas as sessões do usuário, matando brutalmente meu contêiner também.

Eu simulo a situação criando um shell sleep only e o executo com

/usr/bin/systemd-run --user --scope -p "Delegado = sim" wait.sh &

e ele morre no desligamento. Como posso evitar essa morte?

Responder1

Linger deve resolver esse problema.

Dehttps://www.freedesktop.org/software/systemd/man/loginctl.html

Habilitar/desabilitar usuário persistente para um ou mais usuários. Se ativado para um usuário específico, um gerenciador de usuários é gerado para o usuário na inicialização e mantido após o logout. Isso permite que usuários que não estão logados executem serviços de longa duração. Recebe um ou mais nomes de usuário ou UIDs numéricos como argumento. Se nenhum argumento for especificado, habilita/desabilita a permanência para o usuário da sessão do chamador.

loginctl enable-linger <username>

Habilitar o atraso para a sessão do usuário permitirá que seus contêineres continuem em execução mesmo após você sair ou durante o desligamento do sistema. Isso deve evitar que o systemd-logind encerre à força a sessão do usuário e os contêineres associados, dando-lhes a oportunidade de encerrar normalmente.

Responder2

Supondo que o comando de parada do contêiner "bloqueie" (ou seja, saia após o contêiner ter sido interrompido), você provavelmente poderá executar o comando de inicialização do contêiner com um serviço de usuário do systemd em vez de diretamente de um shell. Suponha que você precise iniciar vários contêineres, você pode gravar um modelo de serviço no $HOME/.config/systemd/user/. O nome do arquivo de um modelo de serviço deve ter @antes .service(por exemplo [email protected]).

Aqui está um exemplo para você:

[Unit]
PartOf=%i.scope
After=%i.scope

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemd-run --user --scope -u %i sh -c 'sleep 1d &'
ExecStop=/usr/bin/sleep 1m

Como você pode ver, o nome do escopo precisa ser "conhecido" em vez de gerado.

Com o modelo, agora você pode iniciar o contêiner, por exemplo systemctl --user start test@container-a. Agora você deve ver o escopo correspondente permanecer até que seu serviço de "agente" seja interrompido (ou seja, o ExecStop=comando seja encerrado).

Talvez seja necessário executar systemctl --user daemon-reloadsempre que fizer alterações nos arquivos de serviço (modelo).

PS Obviamente, se você precisar passar argumentos extras específicos do contêiner (que não são a mesma string do nome do escopo) para o comando de inicialização/parada do contêiner, provavelmente precisará escrever vários arquivos de serviço em vez de usar um modelo.

informação relacionada