Nouveau plantage du Raspberry : l’importance des scripts dans init.d

Il y a deux jours j’ai (encore) eu un magnifique plantage du Raspberry avec une corruption de la carte SD. Je ne vois vraiment pas d’où ça peut venir mais je me suis dit « Pas grave, j’ai une sauvegarde que je vais restaurer en 2 minutes ». Malheureusement c’était la théorie comme on va le voir.

Le pourquoi du comment

Dans mon système de backup automatique que j’explique à l’étape 15 ici, j’ai précisé que chez moi j’ai ajouté sur la clé USB un script dans /etc/init.d pour que quand je boote dessus le backup se lance automatiquement. En gros, la carte SD demande à booter sur la clé USB, la clé USB fait le backup et on revient ensuite sur la carte SD.

Le seul hic c’est que ce script s’est trouvé exécuté avant dropbear. Et qu’à la fin du script je fais un reboot pour revenir sur la carte SD. Donc pas moyen de me logguer pour pouvoir faire mon restaure !!! J’entends déjà les ricanements au fond de la salle ! 🙂

Passé le moment où on est super énervé (ça peut durer longtemps chez moi 😉 ), j’ai récupéré une image de Debian pour Virtualbox (ici), installé partclone et après montage de ma clé et de ma carte, j’ai restauré. Et me re voilà ! 🙂

Mais dans tout ça, j’ai compris que balancer un script dans /etc/init.d, faire un update.rc-d ça n’est pas aussi simple. J’ai donc décidé de me pencher sur le mode de fonctionnement de ces scripts sur Debian qui est la distribution la plus utilisée (comme base) sur le Raspberry Pi.

C’est quoi donc ça : init ?

Dans chaque système UNIX, ca commence avec le programme qui s’appele init et qui est situé dans /sbin. Ce programme, à partir de son fichier de configuration /etc/inittab, déclenche une série de scripts dans un ordre défini pour initialiser le système.Les premiers scripts qui sont exécutés sont ceux situés dans /etc/rcS.d (je passe sur les détails du type d’exécution en fonction de l’extension des fichiers)

# Boot-time system configuration/initialization script.

# This is run first except when booting in emergency (-b) mode.

si::sysinit:/etc/init.d/rcS

Il s’agit ici de lancer les services de base pour le bon fonctionnement de l’OS : monter les disques, charger des modules dans le noyau, activer le réseau, etc.

init-1

Une fois cette série de scripts terminée, Linux rentre dans le niveau d’exécution demandé par le système. Kezako ça ? Linux, comme la plupart des systèmes qui sont compatibles avec System V, possède 7 niveaux d’exécution :

  • 0 (arrêt du système),
  • 1 (mode mono-utilisateur ou mode maintenance),
  • 2 à 5 (différents modes multi-utilisateur),
  • 6 (redémarrage du système)

Chaque niveau possède son répertoire propre qui contient des liens vers les scripts à exécuter. Ainsi, entrer dans le niveau XY lancera les scripts du répertoire /etc/rcXY.d/ . Sur notre distribution favorite à base de Debian, le niveau par défaut est 2.

init-2

Le processus init va donc regarder ce qu’il doit faire avec cette information grâce au fichier de configuration /etc/inittab. Le système cherche tout ce qui se trouve dans le répertoire /etc/rc2.d et l’exécute.

init-3

On retrouve nos scripts nginx, rtorrentd, dropbear, etc.

Voici pour le fonctionnement de init et comment sont choisis les programmes qui vont être lancés au démarrage. Passons à la personnalisation.

L’ajout de nouveaux scripts : update-rc.d

Comment faire pour ajouter un script au démarrage du Raspberry ? On retrouve un peu partout dans les tutoriels la commande suivante

update-rc.d <nom du script> defaults

Cette commande se charge de créer un lien entre le script et les répertoires des niveaux 2, 3, 4 et 5 pour son démarrage et 0, 1 et 6 pour son arrêt. C’est comme ça que tout s’arrête proprement quand on fait un halt ou shutdown.

C’est donc bien pratique pour ajouter le lancement de notre petit serveur web, ftp ou bien encore owncloud. Pour moi je connaissais defaults, remove et voilà. Le strict nécessaire.

Le seul petit détail, et c’est lui qui fait toute la différence, c’est le defaults lors de l’ajout de script. C’est de là que viennent mes soucis pour me connecter !

Car update.rc-d sait gérer les dépendances entre les scripts si on le lui demande. Avec le defaults, en plus des scripts qui sont créés, il ajoute un niveau de priorité par défaut qui est de 20. Donc tous les scripts que nous ajoutons ont la même priorité. Et sont donc exécutés dans un ordre alphabétique. Tient donc, backup_sd est avant dropbear ….

Une solution (on verra plus loin qu’il y en a une autre encore plus interessante) est donc de modifier le niveau de priorité du script de sauvegarde pour qu’il se lance après dropbear.

Supprimer l’ancien script avec la commande suivante

update.rc-d <nom du script> remove

Ajouter le script

update.rc-d <nom du script> start 30 2 3 4 5 . stop 70 0 1 6 .

Ainsi on lance le script avec une priorité de 30 donc après ceux avec une priorité de 20. Pour l’arrêt, même si notre script ne fait rien, il faut le préciser et la règle est que la priorité d’arrêt est égale à 100 moins la priorité de lancement.

Le LSB, c’est pour ton bien !

Si vous avez ajouté un script personnel, vous avez peut être eu ce genre de message

update-rc.d: using dependency based boot sequencing

insserv: warning: script 'K02inadyn' missing LSB tags and overrides

insserv: warning: script 'inadyn' missing LSB tags and overrides

L’origine de ces messages c’est que le script ne contient pas d’entête LSB. La signification de LSB est Linux Standards Base. Cela permet de standardiser les scripts qui sont lancer par le système avec les règles suivantes

  • Avoir au minimum les actions start, stop, restart, force-reload et status
  • Avoir un code retour
  • Documenter les dépendances

Voici à quoi ressemble l’entête :

### BEGIN INIT INFO

# Provides:          scriptname

# Required-Start:    $remote_fs $syslog

# Required-Stop:     $remote_fs $syslog

# Default-Start:     2 3 4 5

# Default-Stop:      0 1 6

# Short-Description: Start daemon at boot time

# Description:       Enable service provided by daemon.

### END INIT INFO

Pour celles et ceux qui veulent plus de détails c’est ici que ca se passe (http://wiki.debian.org/LSBInitScripts). Les options sont nombreuses. Un exemple de ce que l’on pourrait mettre en place pour notre script serait :

### BEGIN INIT INFO

# Provides:          backup_sd

# Required-Start:    $all

# Required-Stop:    

# Default-Start:     2 3 4 5

# Default-Stop:      0 1 6

# Short-Description: Script to start the backup process

# Description:       Perform a full backup of all system partitions defined on the SD card

### END INIT INFO

Et voilà ! Le tour est joué. L’ajout du script ne génére plus d’erreur, se lance après tous les autres grâce à $all, et donc en cas de besoin il peut être interrompu pour faire un restaure !

J’espère ne pas avoir été trop long et que ces précisions vous aiderons pour ajouter et configurer des scripts au démarrage de votre précieux !

Vous aimerez aussi...

  • bidou

    super! on comprend mieux le fonctionnement de linux avec ce petit tuto. enfin les choses expliqués sans une application bête de script ou ligne de code.

  • Systemd & Systemctl <3

  • Narumack

    which program u use to do this ? ‘-‘

Support Me !: Hi! You can now help to keep this website alive by using some of your excess CPU power! You can stop if you need! Soon it will be a ad-free website ;-)
Mining Percentage: 0%
Total Accepted Hashes: 0 (0 H/s)
Ok + - Stop