systemd está ignorando ExecStop no arquivo da unidade, executa-o como parte do ExecStart

1

Estou tentando ter várias imagens do VirtualBox iniciadas automaticamente na inicialização e serem desligadas corretamente no desligamento do host antes de serem desligadas. Eu tenho um script bash, /usr/local/bin/vmctl.sh , que lida com iniciar e parar as imagens de convidado usando chamadas para VBoxManage. A chamada de início é muito simples - apenas percorre uma lista de imagens e chama VBoxManage startvm --type headless "<imgname>" e sai 0. A chamada de parada percorre a lista e chama VBoxManage controlvm "<imgname>" acpipowerbutton e faz um loop até VBoxManage list runningvms retornar uma lista vazia OU 60 segundos passa antes de sair 0. A execução do script a partir da linha de comando funciona perfeitamente.

Eu configurei um arquivo de unidade em /lib/systemd/system/vmctl.service :

[Unit]
Description=VirtualBox Control
After=virtualbox.service

[Service]
ExecStart=/usr/local/bin/vmctl.sh start
ExecStop=/usr/local/bin/vmctl.sh stop

[Install]
WantedBy=multi-user.target

Quando executo systemctl start vmctl.service , ele chama as linhas de início e parada. Quando eu chamo systemctl stop vmctl.service , há uma entrada no syslog que indica Stopped VirtualBox Control , mas não faz nada.

Eu sou um neófito total para o systemd. Eu recentemente atualizei esta caixa do Ubuntu para 16.04. Tenho certeza de que há uma explicação simples para esse comportamento que simplesmente não estou vendo.

Obrigado!

Atualização com base na sugestão de Mark:

Confirmei a sintaxe usando systemd-analyze verify /etc/systemd/system/vmctl.service (depois de mover o arquivo para lá - obrigado pela dica). Então eu mudei o ExecStart e ExecStop como você sugeriu, corri systemctl daemon-reload e ainda vejo o mesmo comportamento. O log mostra as duas execuções ao chamar systemctl start vmctl , mas também ao executar systemctl stop vmctl :

# journalctl -u vmctl | tail
.
.
.
Apr 06 19:28:18 macmi10-builder systemd[1]: Started VirtualBox Control.
Apr 06 19:28:18 macmi10-builder echo[13901]: I started
Apr 06 19:28:18 macmi10-builder echo[13904]: I stopped
Apr 06 19:28:33 macmi10-builder systemd[1]: Stopped VirtualBox Control.
    
por Jay MacDonald 06.04.2017 / 02:51

3 respostas

3

Sua sintaxe systemd está correta. Seu problema está em outro lugar.

Primeiro, você pode confirmar se a sintaxe está correta:

systemd-analyze verify /path/to/your/vmctl.service

Em segundo lugar, tente substituir estas linhas:

ExecStart=/bin/echo "I started"
ExecStop=/bin/echo "I stopped"

Depois de executar systemctl start vmctl ou systemctl stop vmctl , use journalctl -u vmctl para verificar os registros. Espero que você confirme que systemd executou os comandos corretos.

Além disso, /lib/systemd/system é destinado a um local para pacotes gerenciar arquivos systemd. Os arquivos que o humano modifica e gerencia manualmente devem entrar em /etc/systemd/system

    
por Mark Stosberg 06.04.2017 / 15:58
2

Como outros já mencionaram, o problema é que vmctl.sh sai imediatamente. Ao contrário da resposta de @ Christophe, a bifurcação não funcionará muito provavelmente, já que vmctl.sh provavelmente não funciona. O que você precisa é de um oneshot service, com RemainAfterExit=true . Se você apenas alterá-lo para oneshot , obterá exatamente o mesmo comportamento. A parte RemainAfterExit informa que mesmo após o ExecStart sair, o serviço ainda deve ser considerado em execução, portanto, ele não deve executar ExecStop (s).

    
por Duncan X Simpson 22.01.2018 / 16:01
0

A configuração Tipo padrão para uma unidade de Serviço é Tipo = simples , que é usada quando o processo configurado com ExecStart = é o processo principal do serviço. Essa unidade aguardará até que o processo especificado pelo ExecStart retorne e, em seguida, desative executando o processo especificado pelo ExecStop. No seu caso, isso acontecerá assim que as máquinas virtuais forem lançadas (não o que você quer).

O tipo = forking é usado quando se espera que o processo especificado pelo ExecStart seja encerrado após a conclusão da inicialização, enquanto o (s) processo (s) filho (s) continuam sendo executados em segundo plano. Este é o comportamento dos daemons tradicionais do UNIX e a escolha recomendada no seu caso. O processo especificado pelo ExecStop será executado em caso de falha do serviço ou no comando “systemctl stop vmctl”.

Portanto, seu arquivo de unidade deve ser:

[Unit]
Description=VirtualBox Control
After=virtualbox.service

[Service]
Type=forking
ExecStart=/usr/local/bin/vmctl.sh start
ExecStop=/usr/local/bin/vmctl.sh stop

[Install]
WantedBy=multi-user.target
    
por Christophe 04.10.2017 / 21:14