¿Cómo ejecutar un script con systemd justo antes del apagado?

58

¿Qué necesito poner en la [install]sección, para que systemd se ejecute /home/me/so.pljusto antes del apagado y también antes de que /proc/self/net/devse destruya?

[Unit]
Description=Log Traffic

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

[Install]
?
sid_com
fuente

Respuestas:

66

La solución sugerida es ejecutar la unidad de servicio como un servicio normal; eche un vistazo a la [Install]sección. Así que todo tiene que pensarse al revés, las dependencias también. Porque el orden de apagado es el orden de inicio inverso. Es por eso que se debe colocar el guión ExecStop=.

La siguiente solución me funciona:

[Unit]
Description=...

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

[Install]
WantedBy=multi-user.target

RemainAfterExit=truees necesario cuando no tienes una ExecStartacción.

Después de crear el archivo, asegúrese de systemctl daemon-reloady systemctl enable yourservice --now.

Lo acabo de obtener de systemd IRC, los créditos van al mezcalero.

Matías
fuente
66
En ubuntu 16.04 debes tener a ExecStart=/bin/true.
Niels
3
Mi suposición de POR QUÉ RemainAfterExit=true se requiere cuando no existe ExecStartes porque systemdno intentará ejecutarse ExecStopsi cree que el servicio no se está ejecutando. RemainAfterExit=truecausa systemda creer que el servicio se está ejecutando, lo que provoca que se ejecute ExecStopal apagar el equipo.
Felipe Alvarez
1
¿Hay alguna forma de garantizar que este script se ejecutará y completará antes de que finalicen las sesiones de usuario y los procesos de usuario?
richmb
@richmb Para nada. De los 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
He intentado esto y varias iteraciones, pero no funciona en Debian Stretch.
2rs2ts
8

Por lo que puedo ver, esto hace lo que necesito (pero no sé exactamente por qué).

[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
fuente
3
Sucede que funciona debido a 2 cosas: 1) DefaultDependencies = no hace que ignore todas las dependencias y ejecute "al principio" al inicio y "al final" al parar, siempre respetando las cláusulas "Antes" y "Después". 2) Resulta que tiene una cláusula Before en los objetivos de apagado / reinicio / detención, por lo que se ejecutará justo antes de que se llegue al apagado / reinicio / detención en la detención (porque solo se ejecutan en la detención, sucede lo que desea).
RDP
Es posible que desee agregar kexec.targetal bit Antes
hanetzer
Esto no funciona para mí
Bug Killer
No veo cómo funcionará esto a menos que también agregue WantedBy=shutdown.target reboot.target halt.targeta la [Unit]sección. Before=& After=no cambiar dependencias.
rsaw
1
@FelipeAlvarez: he eliminado mi comentario.
sid_com
7
  • Para ejecutar un servicio justo antes de iniciar cualquiera de los servicios de reinicio / apagado / detención / kexec (es decir, en el último momento antes de que el sistema de archivos raíz se vuelva a montar de solo lectura), use esta configuración de servicio:

    [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
    

    Habilítelo con:

    systemctl enable my_service.service
    
  • Para ejecutar una secuencia de comandos justo antes de reiniciar / apagar / detener / kexec (cuando no puede escribir en el sistema de archivos raíz, porque se volvió a montar de solo lectura) agregue esta secuencia de comandos ejecutable al /usr/lib/systemd/system-shutdowndirectorio.

    Inmediatamente antes de ejecutar el sistema actual, detener / apagar / reiniciar / kexec systemd-shutdown ejecutará todos los ejecutables en / usr / lib / systemd / system-shutdown / y les pasará un argumento: "detener", "apagar", "reiniciar" "o" kexec ", dependiendo de la acción elegida. Todos los ejecutables en este directorio se ejecutan en paralelo, y la ejecución de la acción no continúa antes de que finalicen todos los ejecutables.

Ver también:

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

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

Piotr Jurkiewicz
fuente
1
Quiero ejecutar algo lo más cerca posible después de iniciar un reinicio, mucho antes del final.target. Idealmente, me gustaría que sea lo primero que se ejecute después de que el usuario lo haga $ sudo reboot.
Jaime Hablutzel
5

No estoy totalmente seguro, pero no creo que necesite la parte de instalación, aunque la agregué explícitamente. Tampoco lo probé, pero creo que debería ayudarte a comenzar:

[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
fuente
Cuando intento esto, el script se ejecuta poco después del inicio (arranque).
sid_com
@sid_com Después de leer thread.gmane.org/gmane.comp.sysutils.systemd.devel/4515/… intente agregar DefaultDependencies = no y tal vez elimine la sección de instalación. De lo contrario, puede ser útil controlar las líneas after / require.
Ulrich Dangel