Google PlusFacebookTwitter

Kexec et l’appel système (syscall) shutdown(8)

By on Jan 21, 2014 in Linux | 0 comments

Share On GoogleShare On FacebookShare On Twitter

Dans le doute tu rebootes, pas si facile avec kexec !

Ça vous est forcement arrivé, ce moment de solitude, mais si, vous savez, celui qui vous rend perplexe lorsque vous exécutez un simple init 6 ou reboot. Celui où vous vous attendez à voir le BIOS (qui met quinze plombes à charger) de votre serveur apparaître à l’écran alors qu’en fait ce n’est qu’une séquence de démarrage de votre noyau.

C’est bon, ça vous revient à l’esprit ? Vous vous souvenez donc ce que vous avez fait par la suite, un reboot -f bien moche qui passe outre l’init (d’ici, j’arrive à voir la honte sur votre visage). Vous n’êtes quand même pas allés jusqu’au reset matériel ?

J’avoue, je l’ai fait… Ne me regardez pas comme ça ! 😯

L’explication du pourquoi du comment

Pourquoi les commandes init 6, reboot et shutdown -r now ne fonctionnent pas alors que la commande reboot -f permet, elle de redémarrer le système ?

En soit, il n’y a quasiment pas de différence entre ces trois commandes, elles appellent toutes les trois les scripts de gestion des services.

Pour ce qui est de la commande reboot -f, c’est un peu différent. L’option -f indique au système de ne pas passer par l’init, ce qui signifie que les processus seront arrêtés de manière brutale via un SIGKILL. Qui dit SIGKILL dit possible perte de données, imaginez un SIGKILL sur une base de données MySQL en InnoDB… j’espère que vous avez une sauvegarde.

L’appel système utilisé par la commande reboot -f est reboot(2).

Un début de piste fait son apparition, l’init

Je travaille sous Debian GNU/Linux Wheezy (au travail ainsi qu’à la maison), je vais donc prendre cette distribution comme exemple.

Comme vu plus haut, lorsque la commande reboot est exécutée, elle appelle shutdown qui envoie un signal (6 dans notre cas) à l’init. Jusque là rien de nouveau allez-vous me dire, certes, certes…

L’init définit le runlevel dans lequel il se trouve puis lance /etc/init.d/rc avec le bon runlevel en paramètre pour que ce dernier puisse effectuer des tâches différentes, en fonction de l’état dans lequel se trouve le système. Si l’on regarde le script rc d’un peu plus près on peut voir ceci :

La commande startpar fait partie du paquet sysvinit-utils. startpar permet de paralléliser le lancement des services au démarrage (ainsi qu’à l’arrêt) du serveur. Pour ce faire, rc vérifie qu’au moins un des trois fichiers suivants existe et ne soit pas vide :

  1. /etc/init.d/.depend.boot
  2. /etc/init.d/.depend.start
  3. /etc/init.d/.depend.stop

Le fichier .depend.stop nous confirme que la dernière action exécutée par startpar est kexec :

Une solution \o/

Pour empêcher l’exécution de kexec, il faut indiquer au paquet kexec-tools de ne pas gérer le redémarrage du serveur. Si on regarde le code qui gère le service kexec-load, on peut voir ceci :

Le fichier /etc/default/kexec est sourcé au début du fichier, dans ce dernier se trouve la variable LOAD_KEXEC. Si cette dernière est définie à true alors kexec sera exécuté lors de l’arrêt du service. Pour passer cette valeur à false, soit on édite directement le fichier soit on passe par dpkg-reconfigure. Passons par la bonne méthode :

Voici ce que debconf vous posera comme question (répondez No) :

Reconfigure du paquet kexec-tools

Essayez, allez, faites-le, je sais que vous en mourrez d’envie ! :mrgreen:

En théorie c’est censé fonctionner. Vous aurez l’immense joie de voir apparaître le magnifique logo de votre constructeur…

Pas envie de commenter cette foutue ligne ?

Commenter cette ligne est une solution plus que correcte mais elle peut ne pas convenir à tout le monde. L’autre solution serait de faire l’équivalent de la commande init 6 mais à la main. Ça donnerait quelque chose comme ceci (à adapter en fonction des services présents sur le serveur bien sûr) :

Le sync est très important, il permet de synchroniser le cache (buffer) sur le disque et donc de s’assurer de la consistance des données. C’est chiant, c’est long mais ça fonctionne…

Édite du 28/01/2014

Sous Debian GNU/Linux il existe la commande coldreboot (qui n’est qu’un script shell), cette dernière passe outre kexec :

Le man coldboot donne la description suivante :

DESCRIPTION
coldreboot is a script that forces a cold reboot regardless of whether kexec is enabled or not in /etc/default/kexec. coldreboot takes the same arguments as /sbin/reboot and passes them on to /sbin/reboot later.

Liens

The following two tabs change content below.

Gaëtan Trellu (goldyfruit)

Cloud Operations Lead chez Ormuco
Autodidacte en informatique, depuis 2005 je parcours l’écosystème Unix à la recherche de nouvelles connaissances et de nouvelles rencontres.

CC BY 4.0 Kexec et l’appel système (syscall) shutdown(8) par Gaëtan Trellu (goldyfruit) est sous Licence Creative Commons Internationale Attribution 4.0.