Como executar um script com systemd antes do desligamento?

58

O que preciso colocar na [install]seção, para que o systemd seja executado /home/me/so.plimediatamente antes do desligamento e também antes que /proc/self/net/devseja destruído?

[Unit]
Description=Log Traffic

[Service]
ExecStart=/home/me/so.pl

[Install]
?
sid_com
fonte

Respostas:

66

A solução sugerida é executar a unidade de serviço como um serviço normal - consulte a [Install]seção. Então, tudo tem que ser pensado ao contrário, também dependências. Porque a ordem de desligamento é a ordem de inicialização inversa. É por isso que o script deve ser inserido ExecStop=.

A seguinte solução está funcionando para mim:

[Unit]
Description=...

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=<your script/program>

[Install]
WantedBy=multi-user.target

RemainAfterExit=trueé necessário quando você não tem uma ExecStartação.

Após criar o arquivo, verifique systemctl daemon-reloade systemctl enable yourservice --now.

Acabei de obtê-lo no systemd IRC, os créditos estão indo para o mezcalero.

Matthias
fonte
6
No ubuntu 16.04 você deve ter um ExecStart=/bin/true.
Niels
3
Minha suposição para WHY RemainAfterExit=true é necessária quando não existe ExecStartporque systemdnão tentará executar ExecStopse achar que o serviço não está sendo executado. RemainAfterExit=trueprovoca systemda acreditar que o serviço está sendo executado, causando assim que ele seja executado ExecStopno desligamento.
Felipe Alvarez
11
Existe alguma maneira de garantir que esse script seja executado e concluído antes das sessões e processos do usuário serem encerrados?
richmb
@ richmb Nem um pouco. Dos documentos :Note that it is usually not sufficient to specify a command for this setting that only asks the service to terminate (for example, by queuing some form of termination signal for it), but does not wait for it to do so.
svenwltr 30/11
Eu tentei isso e várias iterações nele, mas ele não funciona no Debian Stretch.
2rs2ts
8

Tanto quanto eu posso ver, faz o que eu preciso (mas não sei exatamente por que).

[Unit]
Description=Log Traffic
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target


[Service]
ExecStart=/usr/local/bin/perl /home/me/log_traffic.pl --stop
Type=oneshot
sid_com
fonte
3
Isso funciona devido a duas coisas: 1) DefaultDependencies = no faz com que ele ignore todas as dependências e execute "no início" no início e "no final" na parada, sempre respeitando as cláusulas "Antes" e "Depois". 2) Por acaso há uma cláusula Before nos destinos de desligamento / reinicialização / interrupção, portanto, ela será executada imediatamente antes que o desligamento / reinicialização / parada seja atingido na parada (porque eles são executados apenas na parada, acontece o que você deseja).
RDP
Você pode querer adicionar kexec.targetao pouco antes
hanetzer
Isso não funciona para mim
assassino Bug
Não vejo como isso funcionará, a menos que você também adicione WantedBy=shutdown.target reboot.target halt.targetà [Unit]seção. Before=& After=não mude dependências.
rsaw 8/09/16
11
@FelipeAlvarez: removi meu comentário.
sid_com 22/06/18
7
  • Para executar um serviço imediatamente antes de iniciar qualquer serviço de reinicialização / desligamento / interrupção / kexec (ou seja, no último momento antes de o sistema de arquivos raiz ser remontado como somente leitura), use esta configuração de serviço:

    [Unit]
    Description=Save system clock on shutdown
    DefaultDependencies=no
    After=final.target
    
    [Service]
    Type=oneshot
    ExecStart=/usr/lib/systemd/scripts/fake-hwclock.sh save
    
    [Install]
    WantedBy=final.target
    

    Ative-o com:

    systemctl enable my_service.service
    
  • Para executar um script imediatamente antes da reinicialização real / shutdown / halt / kexec (quando você não pode gravar no sistema de arquivos raiz, porque foi remontado como somente leitura), adicione esse script executável ao /usr/lib/systemd/system-shutdowndiretório.

    Imediatamente antes de executar o sistema, halt / poweroff / reboot / kexec systemd-shutdown executará todos os executáveis ​​em / usr / lib / systemd / system-shutdown / e transmitirá um argumento para eles: "halt", "poweroff", "reboot "ou" kexec ", dependendo da ação escolhida. Todos os executáveis ​​neste diretório são executados em paralelo e a execução da ação não é continuada antes que todos os executáveis ​​sejam concluídos.

Veja também:

https://www.freedesktop.org/software/systemd/man/bootup.html

https://www.freedesktop.org/software/systemd/man/systemd-halt.service.html

Piotr Jurkiewicz
fonte
11
Eu quero executar algo o mais próximo possível depois de iniciar uma reinicialização, muito antes da final.target. Idealmente, gostaria que fosse a primeira coisa a ser executada após o usuário fazer $ sudo reboot.
Jaime Hablutzel
5

Não tenho certeza, mas acho que você não precisa da parte da instalação, embora a tenha adicionado explicitamente. Também não testei, mas acho que deve ajudar você a começar:

[Unit]
Description=Log Traffic
Requires=network.target
After=network.target
Before=shutdown.target
DefaultDependencies=no

[Service]
ExecStart=/home/me/so.pl
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=shutdown.target
Ulrich Dangel
fonte
Quando eu tento isso, o script é executado logo após o início (inicialização).
Sid_com 24/05
@sid_com Depois de ler thread.gmane.org/gmane.comp.sysutils.systemd.devel/4515/…, tente adicionar DefaultDependencies = no e talvez remova a seção de instalação. Caso contrário, pode ajudar a controlar remotamente as linhas depois / requer.
Ulrich Dangel