J'ai récemment rencontré deux problèmes différents sur deux hôtes Linux différents. Chacun a nécessité un contournement unique car je n'ai pas encore trouvé de véritable solution. Cependant, la méthode de livraison de chaque contournement était la même :exécutez une commande pendant ou peu après le démarrage de Linux.
Le rc.local
Le fichier était - et dans certains cas est toujours - l'endroit où les administrateurs système Linux pouvaient placer les commandes qui doivent être exécutées au démarrage. Utilisation du rc.local
Le fichier est non seulement obsolète, mais après quelques heures de tentatives, il ne fonctionnait en aucun cas. Ceci malgré le fait que le systemd
la documentation mentionne l'utilisation d'un "générateur" qui génère systemd
services depuis un rc.local
fichier s'il existe. (Cela semble être un bon moyen, comme n'importe quel autre, d'appliquer la dépréciation - faites en sorte que cela ne fonctionne pas.)
Les détails de mon problème spécifique ne sont pas particulièrement pertinents pour cette discussion, je vais donc utiliser une commande simple et facile à suivre comme contenu de notre fichier de démarrage local. Nous ajouterons une ligne horodatée à un fichier journal local pour vérifier que le programme Bash que nous devons exécuter au démarrage fonctionne réellement.
Démarrage contre démarrage
Il est important de comprendre le processus de démarrage et de démarrage de Linux pour configurer Linux et résoudre les problèmes de démarrage. En réalité, deux séquences d'événements sont nécessaires pour démarrer un ordinateur Linux et le rendre utilisable :démarrage et démarrage. La séquence de démarrage commence lorsque l'ordinateur est allumé et se termine lorsque le noyau est initialisé et systemd
est lancé. Le processus de démarrage prend alors le relais et termine la tâche de mettre l'ordinateur Linux dans un état opérationnel.
Dans l'ensemble, le processus de démarrage et de démarrage de Linux est assez simple à comprendre. Il comprend les étapes suivantes, qui seront décrites plus en détail ultérieurement :
- Autotest de démarrage du BIOS (POST)
- Chargeur de démarrage (GRUB2)
- Noyau
systemd
Pour une description beaucoup plus détaillée des séquences de démarrage et de démarrage, reportez-vous à mon article, Une introduction aux processus de démarrage et de démarrage de Linux.
Démarrage local
Les administrateurs système ajoutent parfois des commandes à la séquence de démarrage qui sont localement utiles. Ces ajouts peuvent viser à démarrer ou exécuter des processus locaux qui ne font pas partie du standard systemd
Commencez. Il est possible d'ajouter un nouveau systemd
unité de service pour lancer chaque programme nécessaire au démarrage, mais l'ancien rc.local
fournissait un seul fichier exécutable pour tous les besoins de démarrage local. Nous aussi, nous pouvons utiliser cette approche de fichier unique avec systemd
. L'élégance de cette solution est qu'elle permet d'ajouter facilement plus de commandes de démarrage ultérieurement, sans avoir besoin d'ajouter plus d'unités de service à systemd
.
Notre solution consiste à créer un seul systemd
unité de service et placez toutes les commandes Linux nécessaires dans le fichier exécutable. Il y a deux parties dans cette solution. L'une est évidente :nous avons besoin d'un fichier exécutable. Et deuxièmement, nous devons créer une unité de service pour systemd
qui exécute l'exécutable.
Créer le fichier exécutable
Il s'agit d'un exercice trivial pour tout administrateur système familiarisé avec la programmation Bash. En fait, nous allons créer un programme Bash et le placer à l'emplacement Linux Filesystem Hierarchical Standard (FHS) pour les fichiers exécutables locaux, /usr/local/bin
. Un argument pourrait être avancé pour placer ce fichier exécutable à un autre emplacement, mais /usr/local/bin
est celui qui a le plus de sens pour moi puisque cet emplacement permet à l'administrateur système d'exécuter facilement le script à partir de la ligne de commande si nécessaire. Le /usr/local/bin
répertoire est toujours dans le $PATH
de chaque utilisateur , y compris celui de l'utilisateur root.
Créez le mystartup.sh
fichier montré ici et placez-le dans /usr/local/bin
(assurez-vous de le rendre exécutable). Assurez-vous d'utiliser l'emplacement de Bash qui convient à votre distribution. Par exemple, les distributions basées sur Debian localisent Bash dans /bin/bash
.
#!/usr/bin/bash
################################################################################
# mystartup.sh
#
# This shell program is for testing a startup like rc.local using systemd.
# By David Both
# Licensed under GPL V2
#
################################################################################
# This program should be placed in /usr/local/bin
################################################################################
# This is a test entry
echo `date +%F" "%T` "Startup worked" >> /root/mystartup.log
Remarque : Les commentaires dans les fichiers inclus vous indiquent où ils doivent être situés.
Assurez-vous de tester cet exécutable en l'exécutant à partir de la ligne de commande. La première fois que vous exécutez ce script shell, vous devriez voir un nouveau fichier, /root/mystartup.log
, avec une heure et une date avec le texte, "Startup worked"
. Nous créons ce fichier journal et y ajoutons des lignes chaque fois que le script est exécuté comme un simple test pour nous assurer que notre script fonctionne.
Exécutez le script plusieurs fois. Vos résultats devraient ressembler à ceux présentés ici :
[root@testvm1 ~]# mystartup.sh
[root@testvm1 ~]# cat mystartup.log
2019-09-12 19:58:00 Startup worked
2019-09-12 19:58:17 Startup worked
2019-09-12 19:58:54 Startup worked
2019-09-12 19:59:00 Startup worked
2019-09-12 20:01:08 Startup worked
2019-09-12 20:04:01 Startup worked
2019-09-12 20:04:13 Startup worked
2019-09-12 20:06:11 Startup worked
2019-09-12 20:06:28 Startup worked
2019-09-16 09:51:21 Startup worked
2019-09-16 09:51:51 Startup worked
C'est tout ce que nous devons faire pour créer le fichier qui pourrait éventuellement contenir nos commandes de démarrage locales. Ajoutez simplement tout ce qui doit s'exécuter au démarrage dans ce fichier.
Créer le service systemd
L'unité de service que nous allons maintenant créer est un systemd
standard fichier d'unité de service. Ce fichier simple est utilisé uniquement pour exécuter le mystartup.sh
script au démarrage.
Créez un nouveau fichier, /usr/local/lib/systemd/system/mystartup.service
, et ajoutez le contenu ci-dessous :
################################################################################
# mystartup.service
#
# This service unit is for testing my systemd startup service
# By David Both
# Licensed under GPL V2
#
################################################################################
# This program should be placed in /usr/local/lib/systemd/system/.
# Create a symlink to it from the /etc/systemd/system directory.
################################################################################
[Unit]
Description=Runs /usr/local/bin/mystartup.sh
[Service]
ExecStart=/usr/local/bin/mystartup.sh
[Install]
WantedBy=multi-user.target
Ce fichier n'a pas besoin d'être exécutable. Ce fichier peut également se trouver dans /etc/systemd/system
, mais en tant que fichier local, il est préférable de le placer dans /usr/local
branche de la structure du répertoire, avec un lien vers celle-ci depuis /etc/systemd.system
.
Maintenant, allez dans /etc/systemd/system
et créez le lien symbolique dans le fichier unité de service :
[root@testvm1 system]# ln -s /usr/local/lib/systemd/system/mystartup.service
Tester l'unité de service
Nous devons tester le fichier d'unité de service final avant de redémarrer l'hôte Linux pour le test final. Tout d'abord, vérifions que systemd
voit le service :
[root@testvm1 ~]# systemctl status mystartup
● mystartup.service - Runs /usr/local/bin/mystartup.sh
Loaded: loaded (/usr/local/lib/systemd/system/mystartup.service; linked; vendor preset: disabled)
Active: inactive (dead)
[root@testvm1 ~]#
Ce résultat nous indique que le service est reconnu par systemd
. Maintenant, commençons le service. Cela exécutera le script mais ne configurera pas le nouveau service pour qu'il s'exécute au démarrage :
[root@testvm1 ~]# systemctl start mystartup
Vérifiez le contenu du fichier journal pour vérifier que la nouvelle ligne a été ajoutée.
Activer le service
Il ne reste plus qu'à activer le service pour qu'il s'exécute au démarrage :
[root@testvm1 ~]# systemctl enable mystartup
Created symlink /etc/systemd/system/multi-user.target.wants/mystartup.service →
/usr/local/lib/systemd/system/mystartup.service.
[root@testvm1 ~]#
Test final
Avant de redémarrer, regardons le journalctl
commande et comment nous pouvons l'utiliser pour afficher les entrées de journal relatives à mystartup.service
. On peut aussi utiliser le journalctl
commande pour vérifier cela car systemd
tient un journal de tout ce qu'il fait.
Dans la commande suivante, le -u
l'option affiche uniquement les entrées pour mystartup
unité :
[root@testvm1 ~]# journalctl -u mystartup
-- Logs begin at Mon 2019-04-15 22:50:27 EDT, end at Mon 2019-09-16 11:44:30 EDT. --
Sep 16 11:09:28 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]#
Maintenant, redémarrez l'hôte Linux et vérifiez le fichier journal pour vous assurer qu'une nouvelle ligne a été ajoutée :
[root@testvm1 ~]# systemctl status mystartup
● mystartup.service - Runs /usr/local/bin/mystartup.sh
Loaded: loaded (/usr/local/lib/systemd/system/mystartup.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2019-09-16 11:45:59 EDT; 1min 30s ago
Process: 819 ExecStart=/usr/local/bin/mystartup.sh (code=exited, status=0/SUCCESS)
Main PID: 819 (code=exited, status=0/SUCCESS)
Sep 16 11:45:55 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]# journalctl -u mystartup
-- Logs begin at Mon 2019-04-15 22:50:27 EDT, end at Mon 2019-09-16 11:47:45 EDT. --
Sep 16 11:09:28 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
-- Reboot --
Sep 16 11:45:55 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]#
Conclusion
Le script shell Bash que nous avons créé pour cette expérience s'exécute une fois au démarrage, puis se ferme. Il ne reste pas en mémoire en tant que démon car il n'a pas été conçu pour cela.
Au cas où vous ne l'auriez pas remarqué, la procédure que nous avons utilisée pour créer notre service de démarrage local peut également être utilisée pour créer tout nouveau service pour systemd
. Ce n'est pas si difficile une fois qu'on sait comment faire.
Mettre à jour
Peu de temps après la publication de cet article, j'ai reçu un e-mail de Tom Murphy qui m'a informé de l'existence du rc-local
service qui fait partie de systemd
. J'apprécie cet e-mail car je n'étais pas au courant de ce service, j'ai donc appris quelque chose de nouveau.
Il est possible d'ajouter le support de l'ancien rc.local
fichier en activant le service avec la commande, systemctl enable rc-local
. Les commandes du fichier rc.local s'exécuteront au prochain démarrage. Bien sûr, vous pouvez utiliser systemctl enable rc-local
pour exécuter rc.local
immédiatement.
Cependant, il est toujours vrai que rc.local est obsolète. La page de manuel de systemd-rc-local-generator
indique :« La prise en charge de /etc/rc.local est fournie pour la compatibilité avec des systèmes System V spécifiques uniquement. Cependant, il est fortement recommandé d'éviter d'utiliser ce script aujourd'hui et de fournir à la place des fichiers d'unité appropriés avec des dépendances appropriées pour que tous les scripts s'exécutent pendant le processus de démarrage."
Ressources
-
Livre de données FHS (Linux Filesystem Hierarchical Standard) pour Linux
-
Informations GNU GRUB
-
Manuel GNU GRUB
-
Enregistrement de démarrage principal
-
Spécification multiboot
-
informations système
-
processus de démarrage de systemd
-
index systemd des pages de manuel
-
Une introduction aux processus de démarrage et de démarrage de Linux
[Vous voulez essayer Red Hat Enterprise Linux ? Téléchargez-le maintenant gratuitement.]