Ejecutar un script al apagar antes de que la red se caiga

Ejecutar un script al apagar antes de que la red se caiga

Me gustaría ejecutar un script cuando mi computadora (Ubuntu 22.04) se apague, pero mientras la red aún esté disponible.

el consejo eneste hiloExpliqué útilmente cómo crear un archivo de servicio systemd que se ejecutaría al apagar, y el script efectivamente se ejecutó, pero el script no pudo completar una tarea que requería acceso a la red, por lo que supongo que la red ya se había cerrado.

Si se encuentran varios hilos (p. ej.Éste) sobre cómo asegurarse de que un script se ejecute antes de que se cierre la red, pero todos parecían tener consejos ligeramente diferentes. Probé varias permutaciones de Before=network-online.target, After=network-online.target y Requires=network-online.target, pero ninguna pareció funcionar.

¿Alguien sabe cómo asegurarse de que el script pueda ejecutarse mientras la red aún esté disponible?

Por cierto, no estoy comprometido a hacer esto como un trabajo de systemd. Supuse que esa sería la mejor manera de hacerlo, pero si hay otra manera de lograr lo mismo, estaría bien.

Respuesta1

No sé si esto ayudará, pero considere mirar los archivos .target de systemd. Esto es lo que realmente ejecuta systemd cuando se apaga. Aquí hay un enlace.

https://documentation.suse.com/smart/linux/html/reference-managing-systemd-targets-systemctl/index.html

shutdown.target
       A special target unit that terminates the services on system
       shutdown.

       Services that shall be terminated on system shutdown shall add
       Conflicts= and Before= dependencies to this unit for their service
       unit, which is implicitly done when DefaultDependencies=yes is set
       (the default).

Los archivos .target conviven /usr/lib/systemd/systemcon los archivos .service. Si fuera yo, estaría haciendo esto en una máquina virtual donde puedo revertir fácilmente una instantánea;)

Respuesta2

Bien, he jugado un poco más y he progresado, pero todavía no he resuelto el problema.

Resulta que la red funciona, más o menos, si tengo After=network.target en el archivo de servicio. Parece ser la resolución de nombres la que no funciona. Entonces, si ejecuto la interacción con la computadora remota especificando el nombre de host de la computadora remota, entonces no funciona, pero si la especifico usando su dirección IP, entonces sí funciona.

Esperaba poder solucionar este problema teniendo After=network.target nss-lookup.target, pero eso no solucionó el problema.

¿Alguna idea de qué más podría probar?

Respuesta3

Desde lo alto de mi cabeza antigua y calva, ¿por qué no hacer un script bash?

#!/bin/bash
Your Commands;
shutdown -h now

El apagado no debería ejecutarse hasta que 'Sus comandos' hayan completado la ejecución.

El script podría llamarse 'myshutdown' e incluso tener un alias para el comando del sistema.

(¡Me parece demasiado simplista y estoy seguro de que alguien señalará mis errores!) (Gracias por la edición para ordenar el código 'Marco')

Respuesta4

La clave para entender cómo hacer que un servicio se detenga en el momento del cierre antes de perder la red es saber queel orden de apagado es el orden de inicio inverso. Por lo tanto, su servicio debería comenzardespués network-online.targety al mismo tiempo depende de network-online.target, porque requiere que la red esté activa. Además, existen ExecStart=acciones ExecStop=que puedes definir. Como desea que el script se ejecute al apagar, que es cuando se detiene el servicio, desea definir ExecStop=el apuntamiento a su script.

Para configurar esto, haga lo siguiente:

  • En el[Unidad]sección, crear una Requires=network-online.targetdependencia
  • Establece el orden en After=network-online.target.
  • En el[Servicio]sección, no defina una ExecStart=acción.
  • Establecer RemainAfterExit=true, porque no creamos una ExecStart=acción.
  • Finalmente, cree una ExecStop=acción que apunte a su secuencia de comandos, como ExecStop=/home/username/bin/testscript.sh.

Recordar,el orden de apagado es el orden de inicio inverso. Por lo tanto, cuando se detenga su servicio, ExecStop=se ejecutará su secuencia de comandos, que se encuentra en . Y porque iniciamos este servicio.después network-online.target, se cerraráantestodos los servicios network-online.targetestán cerrados.

Como ejemplo...

Aquí hay un script de prueba simple que se utiliza curlpara obtener su dirección IP pública. Como tal, se requiere DNS para que esto funcione correctamente.

#!/bin/bash

# NAME: testscript.sh
# PATH: /home/username/bin

NOW=`date`
IP=`curl -s https://ipinfoio/ip`

echo $NOW $IP >> /home/username/ipaddresses

A continuación, cree un archivo de unidad/servicio systemd en formato /etc/systemd/system. Nombré esto testservice.service.

[Unit]
Description:Test service to execute at shutdown prior to losing network
Requires=network-online.target
After=network-online.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=/home/username/bin/testscript.sh

[Install]
WantedBy=multi-user.target

Dile a systemd que lea nuestro archivo:

sudo systemctl daemon-reload

Habilite el servicio:

sudo systemctl enable testservice.service

Luego reinicie el sistema y verá que el archivo /home/username/ipaddressse actualizará con una marca de tiempo al apagar y su dirección IP pública.

información relacionada