Jak uruchomić skrypt przed zamknięciem systemu przy pomocy systemd?

17

Uwaga: Krótko sformułowane pytanie znajduje się na dole.

Mam skrypt, który tworzy kopię zapasową moich plików na zewnętrzny dysk USB. Wykonanie tego może chwilę potrwać, w zależności od ilości nowych danych, które utworzyłem. Chcę uruchomić go automatycznie przy każdym wyłączeniu systemu.

Korzystam z Fedory 23 z najnowszymi aktualizacjami (systemd).

Próbowałem to osiągnąć na kilka sposobów, ale nie udało mi się tego uruchomić.

Długotrwały proces dzięki 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

Aktywowałem to systemctl enable autobackup.servicei zacząłem od systemctl start autobackup.service.

Część mojego dziennika rozruchu ( 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.

Pamiętaj, że nie skróciłem niczego pomiędzy, to naprawdę odmontowałem / mnt / BACKUP tuż przed rozpoczęciem skryptu, zabawny zbieg okoliczności.

Przed zamknięciem. Cel

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

Dane wyjściowe są w zasadzie takie same.

Problem

Myślę, że problem polega na tym, że systemd uruchamia mój skrypt równolegle ze wszystkimi pozostałymi skryptami zamykającymi w obu przypadkach, które odmontowują BACKUP i dezaktywują infrastrukturę potoku (czasami pojawia się inny błąd, gdy odmontowanie nie jest wystarczająco szybkie).

Pytanie

Jak mogę nauczyć systemd, aby najpierw uruchamiał mój skrypt przy zamykaniu systemu, czekał, aż zakończy działanie, a następnie uruchamiał pozostałe skrypty zamykające / cele / jednostki / cokolwiek innego?

le_me
źródło

Odpowiedzi:

12

Nie trzeba tworzyć ani edytować plików usług. Po prostu upuść skrypt

/usr/lib/systemd/system-shutdown/

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

Bezpośrednio przed wykonaniem faktycznego zatrzymania systemu / poweroff / restartu / kexec systemd-shutdown uruchomi wszystkie pliki wykonywalne w / usr / lib / systemd / system-shutdown / i przekaże im jeden argument: „halt”, „poweroff”, „restart ”lub„ kexec ”, w zależności od wybranej akcji. Wszystkie pliki wykonywalne w tym katalogu są wykonywane równolegle, a wykonywanie akcji nie jest kontynuowane przed zakończeniem wszystkich plików wykonywalnych.

Używam go, aby po prostu wydać dźwięk na głośnik komputera.

Joost
źródło
2
Czy musiałeś zrobić ten katalog? Nie mam go ani na Ubuntu 16.04, ani na Raspbian (jessie) - oba są oparte na systemie.
WoJ
2
Systemy Debian używają innej ścieżki /lib/systemd/system-shutdown/. Ponadto należy pamiętać, że te skrypty są uruchamiane bardzo późno podczas zamykania, po tym, jak systemy plików są już zamontowane tylko do odczytu. Dlatego dostęp do zapisu w systemie plików zakończy się niepowodzeniem, chyba że zostanie ponownie zamontowany jako read-write ( mount -oremount,rw /). Zobacz Jak wykonywać skrypty w / usr / lib / systemd / system-shutdown / at reboot or shutdown?
Frank Breitling
9
OP poprosił o skrypt wykonywany „przed wszystkim innym” podczas zamykania. Skrypty zamykające system są wykonywane po wszystkim innym, bezpośrednio przed zabiciem jądra.
Greg Alexander
11

Mam to!

Weź rozwiązanie Długotrwały proces z StopExec i zmodyfikuj go w następujący sposób:

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

Uwaga linia:

RequiresMountsFor=/mnt/BACKUP /home

W ten sposób działa zgodnie z oczekiwaniami.

le_me
źródło
2
Nie powinieneś tego robić systemctl edit. systemctl enable autobackupma ten sam efekt i jest bardziej idiomatyczny i powinien działać, ponieważ masz już [Install]sekcję w swojej jednostce. Musisz jednak poprawić tę literówkę w nazwie docelowej. ;)
Stefan Majewsky
OMG Tak długo szukałem rozwiązania do wywołania skryptu kopii zapasowej PRZED odmontowaniem dysków. Dziękuję Ci!
deanresin
2
To mi nie działa. Nie mam żadnych montowań, chcę tylko upewnić się, że mój skrypt działa, zanim inne jednostki zostaną zamknięte.
2rs2ts