Comment exécuter un script avant tout le reste à l'arrêt avec systemd?

17

Remarque: Une question brièvement formulée se trouve en bas.

J'ai un script qui fait une sauvegarde de mes fichiers sur une clé USB externe. Son exécution peut prendre un certain temps, selon la quantité de nouvelles données que j'ai créées. Je veux l'exécuter automatiquement à chaque arrêt du système.

J'utilise fedora 23 avec les dernières mises à jour (systemd).

J'ai essayé d'y parvenir de plusieurs façons, mais je n'ai pas réussi à le faire fonctionner.

Processus long avec 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

Je l'ai activé avec systemctl enable autobackup.serviceet commencé avec systemctl start autobackup.service.

Une partie de mon journal de démarrage ( 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.

Notez que je n'ai rien raccourci entre les deux, il a vraiment démonté / mnt / BACKUP juste avant le début du script, drôle de coïncidence ..

Avant 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

La sortie est fondamentalement la même.

Le problème

Je pense que le problème est que systemd démarre mon script en parallèle avec tous les autres scripts d'arrêt dans les deux cas, qui démontent BACKUP et désactivent l'infrastructure de canal (une autre erreur que j'ai parfois eue, lorsque le démontage n'était pas assez rapide).

La question

Comment puis-je apprendre à systemd à démarrer mon script en premier à l'arrêt, attendre qu'il se termine et ensuite démarrer le reste des scripts / cibles / unités / quoi que ce soit d'arrêt?

le_me
la source

Réponses:

12

Pas besoin de créer ou de modifier des fichiers de service. Déposez simplement votre script

/usr/lib/systemd/system-shutdown/

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

Immédiatement avant d'exécuter le système réel, stop / poweroff / reboot / kexec systemd-shutdown exécutera tous les exécutables dans / usr / lib / systemd / system-shutdown / et leur transmettra un argument: "halt", "poweroff", "reboot "ou" kexec ", selon l'action choisie. Tous les exécutables de ce répertoire sont exécutés en parallèle et l'exécution de l'action n'est pas poursuivie avant la fin de tous les exécutables.

Je l'utilise pour simplement émettre un bip sur le haut-parleur du PC.

Joost
la source
2
Avez-vous dû créer ce répertoire? Je ne l'ai ni sur Ubuntu 16.04 ni sur Raspbian (Jessie) - les deux sont basés sur Systemd.
WoJ
2
Les systèmes Debian utilisent le chemin différent /lib/systemd/system-shutdown/. Et sachez également que ces scripts sont exécutés très tard lors de l'arrêt, une fois que les systèmes de fichiers sont déjà montés en lecture seule. Ainsi, tout accès en écriture au système de fichiers échouera à moins qu'il ne soit remonté en lecture-écriture ( mount -oremount,rw /). Voir Comment exécuter des scripts dans / usr / lib / systemd / system-shutdown / au redémarrage ou à l'arrêt?
Frank Breitling
9
OP a demandé un script exécuté "avant tout le reste" à l'arrêt. Les scripts d'arrêt du système sont exécutés après tout le reste, immédiatement avant de tuer le noyau.
Greg Alexander
11

J? ai compris!

Prenez la solution Processus long avec StopExec et modifiez-le comme suit :

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

Notez la ligne:

RequiresMountsFor=/mnt/BACKUP /home

Cela fonctionne comme prévu de cette façon.

le_me
la source
2
Vous ne devriez pas avoir besoin de le faire systemctl edit. systemctl enable autobackupa le même effet et est plus idiomatique, et devrait fonctionner puisque vous avez déjà la [Install]section dans votre unité. Vous devrez cependant corriger cette faute de frappe dans le nom cible. ;)
Stefan Majewsky
OMG Je cherchais depuis si longtemps une solution pour appeler mon script de sauvegarde AVANT que les disques ne soient démontés. Je vous remercie!
deanresin
2
Cela ne fonctionne pas pour moi. Je n'ai pas de montures, je veux juste m'assurer que mon script s'exécute avant que d'autres unités ne s'arrêtent.
2rs2ts