web-dev-qa-db-fra.com

Exécuter une commande avant l'arrêt

Je veux exécuter une commande simple juste avant l'arrêt de l'ordinateur (le timing n'est pas essentiel).

Pour le démarrage, je peux utiliser /etc/rc.local; y a-t-il quelque chose de similaire pour l'arrêt?

Notez que je voudrais toujours utiliser le bouton d'arrêt intégré du menu; c'est-à-dire que je ne veux pas utiliser un script personnalisé chaque fois que j'arrête via le terminal - il doit être automatique.

55
Primož Kralj

Linux Mint est basé sur Ubuntu, donc je pense que le système de niveau d'exécution est probablement le même. Sur Ubuntu, les scripts des différents niveaux d'exécution sont exécutés en fonction de leur présence dans le /etc/rc[0-6].d répertoires. Runlevel 0 correspond à l'arrêt et 6 au redémarrage.

En règle générale, le script lui-même est stocké dans /etc/init.d, puis les liens symboliques sont placés dans les répertoires correspondant aux niveaux d'exécution dont vous avez besoin.

Donc dans votre cas, écrivez votre script, stockez-le dans /etc/init.d/, puis créez un lien symbolique dans chacun des /etc/rc0.d et /etc/rc6.d (si vous voulez les deux) pointant vers votre script.

Les scripts de chaque répertoire de niveau d'exécution seront exécutés dans ordre asciibétique , donc si l'ordre dans le niveau d'exécution vous importe, choisissez le nom de votre lien symbolique en conséquence.

44
ire_and_curses

Maintenant que les variantes d'Ubuntu et Mint sont passées à systemd, j'ai trouvé que mes anciennes solutions basées sur ce qui précède étaient moins satisfaisantes. J'ai cherché sur le Web pour savoir comment le faire avec systemd et j'ai fini par combiner la sagesse des autres et la documenter sous la forme d'un article de blog sur blogspot.com.a contenant le didacticiel suivant.

Avec systemd, vous créez un ou deux fichiers pour appeler vos scripts à l'aide des modèles ci-dessous et exécutez quelques commandes. Facile.


Version GUI

Tout d'abord créez les scripts que vous souhaitez exécuter au démarrage et/ou à l'arrêt. J'ai créé .scopening_atstart et .scfullcopy_atend.

Ensuite assurez-vous qu'ils sont tous deux exécutables en cliquant avec le bouton droit sur le fichier, en sélectionnant les propriétés et en vous assurant que, sous les autorisations, vous avez coché Autoriser l'exécution du fichier en tant que programme.

Les deux fichiers que j'ai créés remplissent et enregistrent le contenu d'un disque virtuel. Ils créent également un fichier dans mon répertoire personnel pour prouver que le service fonctionne. Ils étaient de la forme:

#!/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

Puis J'ai ouvert mon gestionnaire de fichiers en tant que root, ouvert /etc/systemd/system et créé un fichier startup.service et un fichier save-ramdisk.service. Évidemment, vous pouvez choisir vos propres noms et les noms génériques auraient pu inclure un fichier de démarrage appelé johns_start.service et un fichier d'arrêt appelé johns_shutdown.service. Ne choisissez pas les noms de service existants.

[Unit]
Description=Startup Applications

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

[Install]
WantedBy=multi-user.target

et

[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

Vous pouvez utiliser les mêmes fichiers de service, en substituant le chemin complet de votre script exécutable au mien.

Enfin pour chacun exécuter la commande systemctl activer votre_nom_fichier (mais sans le service de suffixe). Donc mon premier était systemctl enable startup

Redémarrez l'ordinateur une fois pour démarrer les services. Le service de démarrage sera exécuté chaque fois que systemd entre dans la cible multi-utilisateurs et le service d'arrêt lorsqu'il quitte la cible multi-utilisateurs. Des fichiers de service alternatifs avec différentes conditions d'activation seront décrits ci-dessous.


Version CLI (ligne de commande)

Cette description suppose que vous opérez à partir de votre répertoire personnel plutôt que/home/john, utilisez Sudo au besoin et votre choix d'éditeur où j'écris vim ou svim.

Créez des scripts Shell de démarrage et d'arrêt avec la première ligne #!/bin/sh et les rendre exécutables à l'aide de chmod +x my_new_filename.

Créez deux fichiers comme ci-dessus, ou dans cet exemple, un fichier pour gérer les tâches de démarrage et d'arrêt. J'exécuterai des scripts dans mon répertoire personnel mais @don_crissti montre quelques alternatives à Stack Exchange .

vim /etc/systemd/system/start_and_stop.service

et copiez dans le contenu du fichier:

[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

Activez ensuite le service avec la commande:

systemctl enable start_and_stop

et redémarrez votre système après quoi les services seront actifs. Les commandes systemctl is-enabled start_and_stop et systemctl is-active start_and_stop peut être utilisé pour surveiller vos nouveaux services.


Modification des conditions de déclenchement pour l'arrêt

Les fichiers utilisent avant tout l'ouverture ou la fermeture de l'environnement multi-utilisateur pour lancer l'exécution des scripts. Le fichier ci-dessous utilise le début de quatre processus d'arrêt potentiels pour lancer ses scripts. L'ajout ou la suppression des cibles sur la ligne Avant + la ligne WantedBy vous permettra de faire des distinctions plus fines:

Ce fichier a été proposé dans la deuxième réponse de cet article mais je n'ai pas pu le faire fonctionner jusqu'à ce que j'ajoute une section d'installation.

Encore une fois, modifiez le script dans /etc/systemd/service/ et activez-le à l'aide de systemctl enable your_file_name. Lorsque j'ai changé les cibles, j'ai utilisé le systemclt disable file_name, puis la réactivée, ce qui la liait aux répertoires cibles. Redémarrez et le service sera opérationnel.

[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
12
John 9631

Vous devez utiliser rc.shutdown le script d'arrêt du noyau Linux. Citant la page de manuel d'OpenBSD :

Lorsque le système est arrêté à l'aide des commandes reboot (8) ou halt (8), ou lorsque init (8) est signalé pour le faire, ou lorsqu'un arrêt demandé par le clavier est émis (si l'architecture le prend en charge), rc ( 8) est invoqué avec l'argument `` shutdown ''.

Il vous suffit donc d'ouvrir votre rc.shutdown et d'y ajouter les commandes Shell que vous souhaitez exécuter.

MISE À JOUR: Puisque Linux Mint est basé sur Ubuntu, qui a une procédure de démarrage/arrêt différente, voici la procédure qui vous concerne:

Écrivez le script Shell que vous souhaitez exécuter et copiez-le dans le répertoire correspondant dans votre /etc/rc*.d/. Le * correspond au niveau d'exécution auquel vous souhaitez que le script s'exécute.
Ubuntu suit la numérotation des niveaux d'exécution Debian, vous avez donc le niveau d'exécution 0 pour l'arrêt et le niveau d'exécution 6 pour le redémarrage.

7
darnir

Pour les systèmes d'initialisation basés sur la dépendance SysV utilisés dans Debian Wheezy, Devuan et ses dérivés et peut-être d'autres, vous pouvez imiter le comportement de rc.shutdown analogique à rc.local comme suit:

Ajoutez vos commandes au squelette suivant de /etc/rc.shutdown:

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

# <add your commands here, before exit 0>

exit 0

Enregistrez le script et rendez le fichier exécutable avec chmod a+x /etc/rc.shutdown.

Ensuite, ajoutez un nouveau script /etc/init.d/rc.shutdown à votre système avec le contenu suivant:

#! /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

Rendez également ce script exécutable.

Créez les liens symboliques dans /etc/rc[06 E5E.d:

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

et

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

Utilisez insserv pour corriger les liens symboliques et créer les fichiers .depend.boot, .depend.start et .depend.stop nécessaires:

insserv -v

Vous devez être root ou utiliser Sudo pour toutes les commandes mentionnées ci-dessus.

1
Adrian Zaugg