Como executo um script antes de tudo no desligamento com o systemd?


17

Nota: A pergunta formulada brevemente pode ser encontrada na parte inferior.

Eu tenho um script que faz um backup dos meus arquivos em uma unidade USB externa. A execução pode demorar um pouco, dependendo da quantidade de novos dados que eu criei. Quero executá-lo automaticamente em todos os desligamentos do sistema.

Estou usando o fedora 23 com as atualizações mais recentes (systemd).

Tentei fazer isso de várias maneiras, mas não consegui fazê-lo funcionar.

Processo de longa execução com StopExec

autobackup.service:

[Unit]
Description=Slow backup script
Requires=local-fs.target

[Service]
ExecStart=/bin/true
ExecStop=/etc/systemd/system/do_backup.sh
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multiuser.target

Eu o ativei systemctl enable autobackup.servicee iniciei com systemctl start autobackup.service.

Parte do meu log de inicialização ( journalctl -b-1):

Dez 22 17:45:27 localhost systemd[1]: Unmounted /mnt/BACKUP.
Dez 22 17:45:27 localhost do_backup.sh[4296]: At subvol /home/BACKUP.2015_12_22-17_45_25
Dez 22 17:45:27 localhost do_backup.sh[4296]: ERROR: parent subvol is not reachable from inside the root subvol.
Dez 22 17:45:27 localhost do_backup.sh[4296]: At snapshot BACKUP.2015_12_22-17_45_25
Dez 22 17:45:27 localhost do_backup.sh[4296]: ERROR: failed to dump stream. Broken pipe
Dez 22 17:45:27 localhost systemd[1]: autobackup.service: Control process exited, code=exited status=1
Dez 22 17:45:27 localhost systemd[1]: Stopped Slow backup script.
Dez 22 17:45:27 localhost systemd[1]: autobackup.service: Unit entered failed state.

Note que eu não reduzi nada no meio, ele realmente desmontou / mnt / BACKUP pouco antes do início do script, coincidência engraçada ..

Antes de shutdown.target

autobackup.service:

[Unit]
Description=Slow backup script
DefaultDependencies=no
Before=shutdown.target

[Service]
ExecStart=/etc/systemd/system/do_backup.sh
Type=oneshot

systemctl edit shutdown.target

[Unit]
Requires=autobackup.service

A saída é basicamente a mesma.

O problema

Acho que o problema é que o systemd inicia meu script em paralelo com todos os outros scripts de desligamento nos dois casos, que desmontam BACKUP e desativam a infraestrutura do canal (outro erro que às vezes recebia quando a desmontagem não era rápida o suficiente).

A questão

Como posso ensinar ao systemd que inicie meu script primeiro no desligamento, aguarde até que ele saia e inicie o restante dos scripts / destinos / unidades / o que for?

Respostas:


12

Não há necessidade de criar ou editar arquivos de serviço. Basta soltar seu script

/usr/lib/systemd/system-shutdown/

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

Imediatamente antes de executar o sistema, o comando 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.

Eu o uso para simplesmente emitir um bipe no alto-falante do PC.


2
Você precisou criar esse diretório? Eu não o tenho nem no Ubuntu 16.04 nem no Raspbian (jessie) - ambos são baseados em systemd.
woj

2
Os sistemas Debian usam o caminho diferente /lib/systemd/system-shutdown/. Além disso, esteja ciente de que esses scripts são executados muito tarde no encerramento, depois que os sistemas de arquivos já estiverem montados como somente leitura. Portanto, qualquer acesso de gravação ao sistema de arquivos falhará, a menos que seja remontado como read-write ( mount -oremount,rw /). Consulte Como executar scripts em / usr / lib / systemd / system-shutdown / na reinicialização ou desligamento?
24517 Frank Breitling

9
O OP solicitou o script executado "antes de tudo" no desligamento. Os scripts de desligamento do sistema são executados depois de todo o resto, imediatamente antes de matar o kernel.
Greg Alexander

11

Deixa comigo!

Pegue a solução Processo de execução longa com StopExec e modifique-o da seguinte maneira:

autobackup.service:

[Unit]
Description=Slow backup script
RequiresMountsFor=/mnt/BACKUP /home

[Service]
ExecStop=/etc/systemd/system/do_backup.sh
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Observe a linha:

RequiresMountsFor=/mnt/BACKUP /home

Funciona como esperado dessa maneira.


2
Você não precisa fazer o systemctl edit. systemctl enable autobackuptem o mesmo efeito e é mais idiomático e deve funcionar, pois você já possui a [Install]seção em sua unidade. Você precisará corrigir esse erro de digitação no nome do destino. ;)
Stefan Majewsky

OMG Eu estava procurando por uma solução há muito tempo para chamar meu script de backup ANTES de qualquer unidade ser desmontada. Obrigado!
deanresin

2
Isso não funciona para mim. Não tenho montagens, só quero garantir que meu script seja executado antes que outras unidades sejam desligadas.
2rs2ts
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.