Exécuter une commande avant l'arrêt


52

Je veux exécuter une commande simple juste avant que l'ordinateur ne s'éteigne (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 de script personnalisé chaque fois que je ferme le terminal - cela doit être automatique.

Réponses:


42

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 les /etc/rc[0-6].drépertoires. Le niveau d'exécution 0 correspond à l'arrêt et 6 au redémarrage.

Généralement, le script lui-même est stocké /etc/init.d, puis les liens symboliques sont placés dans les répertoires correspondant aux niveaux d'exécution requis.

Donc, dans votre cas, écrivez votre script, stockez-le /etc/init.d/, puis créez un lien symbolique dans chacun d’eux /etc/rc0.det /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 un ordre similaire . Par conséquent, si l’ordre dans le niveau d’exécution vous importe, choisissez le nom de votre lien symbolique en conséquence.


Je viens de jeter un coup d'œil au fichier squelette dans init.d (précisez kubuntu) et me suis un peu intimidé. Je veux juste ajouter quelques commandes qui font écho à la date d'arrêt dans un fichier sous / var / log. Puis-je simplement faire cela ou dois-je traiter d'autres éléments du fichier squelette?
Joe

2
@ Joe - Vous n'avez pas besoin de la plupart de ces éléments, sauf si vous souhaitez que votre script puisse être contrôlé en tant que service standard. Vous ne casserez rien avec un simple écho dans votre propre fichier journal, essayez-le et voyez.
ire_and_curses

1
Voici un exemple de script init.d simple. En outre, il est plus facile et plus robuste de créer les liens symboliques avecsudo update-rc.d /etc/init.d/myservice defaults
RolfBly

J'ai écrit /etc/init.d/spark_shutdown.sh et créé un lien dans /etc/rc0.d & /etc/rc6.d maintenant comment puis-je confirmer que ce script a été exécuté dans une instance ec2
Ashish Karpe

10

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

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


Version graphique

Commencez par créer 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 à la fois exécutable en cliquant droit sur le fichier, la sélection des propriétés et faire en sorte que, dans les autorisations, vous avez coché Autoriser l' exécution du fichier comme un programme.

Les deux fichiers que j'ai créés peuplent et enregistrent le contenu d'un disque mémoire. 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

Ensuite, j'ai ouvert mon gestionnaire de fichiers en tant que root, /etc/systemd/systempuis créé 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. Il suffit de ne pas choisir les noms de services 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 remplaçant le chemin complet de votre script exécutable par le mien.

Enfin, pour chacun d'eux, exécutez la commande systemctl enable your_files_name (mais sans le service de suffixe). Donc mon premier étaitsystemctl 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 entrera dans la cible multi-utilisateurs et le service d’arrêt lorsqu’il quittera 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 depuis votre répertoire personnel plutôt que / home / john, utilisez sudo si nécessaire et votre choix d'éditeur dans lequel j'écris vim ou svim.

Créez des scripts de shell de démarrage et d’arrêt avec la première ligne #!/bin/shet rendez-les 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 sur Stack Exchange .

vim /etc/systemd/system/start_and_stop.service

et copier 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

Puis activez 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_stopet systemctl is-active start_and_stoppeuvent être utilisées 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. Ajouter ou supprimer les cibles sur la ligne Avant + la ligne WantedBy vous permettra d’établir des distinctions plus précises:

Ce fichier a été proposé dans la deuxième réponse de ce message, mais je n’ai pas pu le faire fonctionner tant que j’avais ajouté une section d’installation.

Encore une fois, éditez le script /etc/systemd/service/et activez-le avec systemctl enable your_file_name. Quand j'ai changé les cibles, j'ai utilisé la systemclt disable file_namecommande, puis je l'ai réactivée, ce qui l'a liée symboliquement 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

7

Vous devez utiliser rc.shutdownle script d'arrêt pour le noyau Linux. Citation de la page de manuel OpenBSD :

Lorsque le système est arrêté à l'aide des commandes reboot (8) ou halt (8), ou lorsque init (8) le lui indique, 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 ''.

Donc, vous ouvrez simplement votre fichier rc.shutdown et ajoutez les commandes shell que vous voulez y exécuter.

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

Ecrivez le script shell que vous souhaitez exécuter et copiez-le dans le répertoire approprié de votre /etc/rc*.d/. Le *correspond au niveau d'exécution auquel vous voulez que le script s'exécute.
Ubuntu suit la numérotation du niveau d'exécution Debian, vous avez donc le niveau d'exécution 0 pour halte et le niveau d'exécution 6 pour le redémarrage.


1

Pour les systèmes init 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 l' rc.shutdownanalogique pour rc.localressembler à ce qui suit:

Ajoutez vos commandes au squelette suivant /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.

Ajoutez ensuite 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

Rendre également ce script exécutable.

Créez les liens symboliques dans /etc/rc[06].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 insservpour 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.


J'ai perdu mon temps avec celui-ci pendant un peu aujourd'hui et je ne pouvais pas le faire fonctionner avec Ubuntu 16, c'était peut-être moi mais la solution ci-dessus fonctionnait immédiatement.
Mike Q
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.