Ejecute un comando antes de apagar

52

Quiero ejecutar un comando simple justo antes de que la computadora se apague (el tiempo no es esencial).

Para el inicio, puedo usar /etc/rc.local; ¿Hay algo similar para el apagado?

Tenga en cuenta que todavía me gustaría usar el botón de apagado integrado del menú; es decir, no quiero usar un script personalizado cada vez que apago a través de la terminal; debe ser automático.

Primož Kralj
fuente

Respuestas:

42

Linux Mint se basa en Ubuntu, así que supongo que el sistema de nivel de ejecución es probablemente el mismo. En Ubuntu, los scripts para los diferentes niveles de ejecución se ejecutan de acuerdo con su presencia en los /etc/rc[0-6].ddirectorios. El nivel de ejecución 0 corresponde al apagado y el 6 al reinicio.

Por lo general, el script en sí se almacena /etc/init.dy luego los enlaces simbólicos se colocan en los directorios correspondientes a los niveles de ejecución que necesita.

Entonces, en su caso, escriba su guión, guárdelo /etc/init.d/, luego cree un enlace simbólico en cada uno de ellos /etc/rc0.dy /etc/rc6.d(si desea ambos) apuntando a su guión.

Los scripts en cada directorio de nivel de ejecución se ejecutarán en orden asciibético , por lo que si el orden dentro del nivel de ejecución es importante para usted, elija el nombre de su enlace simbólico en consecuencia.

ire_and_curses
fuente
Acabo de echar un vistazo al archivo de esqueleto en init.d (kubuntu preciso) y me sentí un poco intimidado. Solo quiero agregar un par de comandos que hagan eco de la fecha de apagado en un archivo en / var / log. ¿Puedo hacer eso o tengo que lidiar con algunas de las otras cosas en el archivo de esqueleto?
Joe
2
@ Joe: no necesita la mayoría de esas cosas a menos que desee que su script sea controlable como un servicio estándar. No romperá nada con un simple eco en su propio archivo de registro, así que pruébelo y vea.
ire_and_curses
1
Aquí hay un ejemplo simple de script init.d. Además, es más fácil y más robusto hacer los enlaces simbólicos usandosudo update-rc.d /etc/init.d/myservice defaults
RolfBly
Escribí /etc/init.d/spark_shutdown.sh y creé el enlace de /etc/rc0.d & /etc/rc6.d ahora, ¿cómo confirmo que este script se ejecutó en la instancia de ubuntu aws ec2
Ashish Karpe
10

Ahora que las variantes de Ubuntu y Mint se han movido a systemd, encontré que mis soluciones antiguas basadas en lo anterior son menos satisfactorias. Busqué en la web para averiguar cómo hacerlo con systemd y terminé combinando la sabiduría de otros y documentándolo como una publicación de blog en blogspot.com.au que contiene el siguiente tutorial.

Con systemd, crea uno o dos archivos para llamar a sus scripts utilizando las plantillas a continuación y ejecuta un par de comandos. Sencillo.


Versión GUI

Primero cree los scripts que desea ejecutar al inicio y / o apagado. Creé .scopening_atstart y .scfullcopy_atend.

Luego, asegúrese de que ambos sean ejecutables haciendo clic con el botón derecho en el archivo, seleccionando propiedades y asegurándose de que, bajo permisos, haya marcado Permitir ejecutar el archivo como un programa.

Los dos archivos que creé se completan y guardan el contenido de un disco RAM. También crean un archivo en mi directorio de inicio para probar que el servicio está funcionando. Eran de la forma:

#!/bin/sh
cp -pru /home/john/zRamdisk/subdirectory1/* /home/john/.wine/drive_c/subdirectory1/
rm /home/john/stop_time
date +%D' '%T > /home/john/stop_time

Luego abrí mi administrador de archivos como root, abrí /etc/systemd/systemy creé un archivo startup.service y un archivo save-ramdisk.service. Obviamente, puede elegir sus propios nombres y los nombres genéricos podrían haber incluido un archivo de inicio llamado johns_start.service y un archivo de apagado llamado johns_shutdown.service. Simplemente no elija nombres de servicios existentes.

[Unit]
Description=Startup Applications

[Service]
Type=oneshot
RemainAfterExit=false
ExecStart=/home/john/.scopening_atstart

[Install]
WantedBy=multi-user.target

y

[Unit]
Description=Save Ramdisk to Wine drive C

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/home/john/.scfullcopy_atend

[Install]
WantedBy=multi-user.target

Puede usar los mismos archivos de servicio, sustituyendo la ruta completa de su script ejecutable por la mía.

Finalmente, para cada uno, ejecute el comando systemctl enable your_files_name (pero sin el servicio de sufijo). Entonces mi primero fuesystemctl enable startup

Reinicie la computadora una vez para iniciar los servicios. El servicio de inicio se ejecutará siempre que systemd entre en el objetivo multiusuario y el servicio de detención cuando salga del objetivo multiusuario. Los archivos de servicio alternativos con diferentes condiciones de activación se describirán a continuación.


Versión CLI (línea de comando)

Esta descripción asume que usted opera desde su directorio de inicio en lugar de / home / john, usa sudo según sea necesario y su elección de editor donde escribo vim o svim.

Crea scripts de shell de inicio y apagado con la primera línea #!/bin/shy hazlos ejecutables usando chmod +x my_new_filename.

Cree dos archivos como el anterior, o en este ejemplo, un archivo para manejar las tareas de inicio y apagado. Ejecutaré scripts en mi directorio de inicio, pero @don_crissti muestra algunas alternativas en Stack Exchange .

vim /etc/systemd/system/start_and_stop.service

y copie en el contenido del archivo:

[Unit]
Description=Run Scripts at Start and Stop

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/home/john/.startup_commands  #your paths and filenames
ExecStop=/home/john/.shutdown_commands

[Install]
WantedBy=multi-user.target

Luego habilite el servicio con el comando:

systemctl enable start_and_stop

y reinicie su sistema después de lo cual los servicios estarán activos. Los comandos systemctl is-enabled start_and_stopy systemctl is-active start_and_stopse pueden utilizar para monitorear sus nuevos servicios.


Cambio de las condiciones de activación para el apagado

Los archivos sobre todo usan la apertura o cierre del entorno multiusuario para iniciar la ejecución de los scripts. El siguiente archivo utiliza el comienzo de cuatro posibles procesos de apagado para iniciar sus scripts. Agregar o eliminar los objetivos en la línea Antes + la línea WantedBy le permitirá hacer distinciones más finas:

Este archivo fue propuesto en la segunda respuesta de esta publicación, pero no pude ejecutarlo hasta que agregué una sección de Instalación.

Nuevamente, edite el script /etc/systemd/service/y habilítelo usando systemctl enable your_file_name. Cuando cambié los objetivos, usé el systemclt disable file_namecomando y luego lo volví a habilitar, lo que lo vinculó a los directorios de destino. Reinicie y el servicio estará operativo.

[Unit]
Description=Do something required
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target
# This works because it is installed in the target and will be
#   executed before the target state is entered
# Also consider kexec.target

[Service]
Type=oneshot
ExecStart=/home/john/.my_script  #your path and filename

[Install]
WantedBy=halt.target reboot.target shutdown.target
John 9631
fuente
7

Debe usar rc.shutdownel script de apagado para el kernel de Linux. Citando la página de manual de OpenBSD :

Cuando el sistema se apaga utilizando los comandos reiniciar (8) o detener (8), o cuando se indica init (8) para hacerlo, o cuando se emite una detención solicitada por el teclado (si la arquitectura lo admite), rc ( 8) se invoca con el argumento `` apagado ''.

Entonces, simplemente abra su rc.shutdown y agregue cualquier comando de shell que desee ejecutar.

ACTUALIZACIÓN: Dado que Linux Mint se basa en Ubuntu, que tiene un procedimiento de inicio / apagado diferente, este es el procedimiento relevante para usted:

Escriba el script de shell que desea ejecutar y cópielo en el directorio correspondiente en su /etc/rc*.d/. El *corresponde al nivel de ejecución en el que desea que se ejecute el script.
Ubuntu sigue la numeración del nivel de ejecución de Debian, por lo que tiene el nivel de ejecución 0 para detener y el nivel de ejecución 6 para reiniciar.

Darnir
fuente
1

Para los sistemas de inicio basados ​​en dependencia SysV utilizados en Debian Wheezy, Devuan y sus derivados y tal vez otros, puede imitar el comportamiento de lo rc.shutdownanalógico para que le rc.localguste lo siguiente:

Agregue sus comandos al siguiente esqueleto de /etc/rc.shutdown:

#!/bin/sh -e
#
# rc.shutdown
#

# <add your commands here, before exit 0>

exit 0

Guarde el script y haga que el archivo sea ejecutable con chmod a+x /etc/rc.shutdown.

Luego, agregue un nuevo script /etc/init.d/rc.shutdowna su sistema con el siguiente contenido:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          rc.shutdown
# Required-Start:
# Required-Stop:
# X-Stop-After:      umountroot
# Default-Start:
# Default-Stop:      0 6
# Short-Description: Run /etc/rc.shutdown if it exist
### END INIT INFO


PATH=/sbin:/usr/sbin:/bin:/usr/bin

. /lib/init/vars.sh
. /lib/lsb/init-functions

do_stop() {
    if [ -x /etc/rc.shutdown ]; then
            [ "$VERBOSE" != no ] && log_begin_msg "Running local shutdown scripts (/etc/rc.shutdown)"
        /etc/rc.shutdown
        ES=$?
        [ "$VERBOSE" != no ] && log_end_msg $ES
        return $ES
    fi
}

case "$1" in
    start)
        # No-op
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop|status)
    do_stop
        exit 0
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

También haga que este script sea ejecutable.

Cree los enlaces simbólicos en /etc/rc[06font>.d:

cd /etc/rc0.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown

y

cd /etc/rc6.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown

Use insservpara corregir los enlaces simbólicos y para crear los archivos .depend.boot, .depend.start y .depend.stop necesarios:

insserv -v

Debe ser root o usar sudo para todos los comandos mencionados anteriormente.

Adrian Zaugg
fuente
Hoy perdí mi tiempo con este por un momento y no pude hacerlo funcionar con Ubuntu 16, tal vez fui yo, pero la solución anterior funcionó de inmediato.
Mike Q