\documentclass[11pt]{article} \usepackage{helvetic} \usepackage{url} \usepackage{color} \usepackage{hyperref} \usepackage{hevea} \usepackage{article} \title{Gérer les services lancés au démarrage} \begin{document} \author{L'équipe d'Andesi} \date{Juillet 2003} \maketitle \tableofcontents \section{Introduction} A la différence des distributions telles que RedHat ou Mandrake, la distribution Debian n'utilise pas de fichier rc.local permettant de faire des liens vers des scripts de démarrage. La commande \texttt{update-rc.d} provenant du paquet \texttt{sysv-rc} est spécifique à Debian et remplace avantageusement ce script. En lisant la page de manuel de update-rc.d (\texttt{# man update-rc.d}) qui décrit assez bien la fonction de cet utilitaire : \textbf{update-rc.d met à jour automatiquement les liens vers les scripts d'initialisation de type System-V}. Pour le néophyte cela signifie que cette commande permet de gérer les liens vers les scripts de démarrage, si cela vous paraît un peu confus, c'est normal à ce stade, la suite de cet article devrait éclaircir cette explication. \section{Comment sont lancés les services au démarrage et à l'arrêt de votre système} Init a pour rôle de démarrer vos services (comme par exemple gdm qui est un prompt graphique) par l'intermédiaire du fichier de configuration \texttt{/etc/inittab} qui contient les scripts à démarrer. Ce fichier permet de définir un \texttt{runlevel} (ou \texttt{niveau de démarrage}) qui permettra seulement l'exécution d'un groupe de services. Il existe par convention 6 runlevels. Les runlevels 0 et 6 sont réservés respectivement à l'arrêt et au redémarrage du système, le niveau 1 permet de démarrer le mode utilisateur unique.\\ \\ Ainsi les liens vers les scripts de démarrage se trouvent dans \texttt{rcX.d} où \texttt{X} représente le niveau de démarrage (runlevel) tandis que les scripts proprement dit se situent dans \texttt{/etc/init.d}. Les 7 niveaux de démarrage sont donc : \begin{itemize} \item \textbf{0} - arrêt du système (halt)\\ \item \textbf{1} - mode utilisateur unique (single user). Ce mode est utilisé généralement si vous rencontrez des problèmes avec certains services lancés au démarrage car le minimum de services sont démarrés et vous pouvez seulement vous identifier en tant qu'utilisateur root.\\ \item \textbf{2 à 5} - mode multi-utilisateur car sous Debian tous ces niveaux sont identiques. Ce mode vous permet de vous identifier en n'importe quel utilisateur.\\ \item \textbf{6} - redémarrage (reboot) \end{itemize} Le changement du niveau de démarrage peut être effectué par root avec la commande init en tapant par exemple : \texttt{# init 1}. Ce niveau de démarrage est défini dans le fichier \texttt{/etc/inittab} par une ligne comme celle-ci où \texttt{2} représente le niveau de démarrage actuel :\\ \texttt{id:2:initdefault:}\\ \\ Maintenant que nous avons défini les différents niveaux de démarrage et leur rôle, nous allons désormais expliquer de quelle manière se lancent les services. Pour qu'un service, que nous appellerons \texttt{exemple}, se lance au niveau de démarrage \texttt{0, 2 et 6} sans passer par la commande \texttt{update-rc.d}, il faut faire des liens symboliques vers le script de démarrage se trouvant dans \texttt{/etc/init.d} :\\ \texttt{ # ln -s /etc/init.d/exemple /etc/rc1.d/S20exemple\\ # ln -s /etc/init.d/exemple /etc/rc2.d/S20exemple}\\ \\ Nous pouvons également démarrer et arrêter manuellement un service en tapant respectivement :\\ \texttt{ # /etc/init.d/exemple start\\ # /etc/init.d/exemple stop\\} \\ Ces liens sont nommés selon une méthode précise : une lettre (\textit{K} ou \textit{S} suivant le niveau de démarrage) suivi d'un chiffre (\textit{20} dans cet exemple) et enfin du nom de votre script (\textit{exemple} ici). Le \textit{S} signifie que le script doit être lancé (argument passé au script : \textit{start}) alors que le \textit{K} signifie que le script doit être arrêté (argument passé au script : \textit{stop}). Enfin le chiffre définit l'ordre de lancement et d'arrêt des scripts, ainsi \texttt{S20exemple} sera démarré avant \texttt{S10syslogkd}, cependant \texttt{K20exemple} sera arrêté après \texttt{K10syslogkd}.\\ \\ Passons désormais à la pratique en écrivant un script de démarrage et en précisant le fonctionnement de la commande \texttt{update-rc.d} afin d'éviter la création des liens assez fastidieuse. Vous pouvez également utiliser des outils remplissant la même fonction que \texttt{update-rc.d} en mode graphique tel que \texttt{ksysv} (paquet du même nom). \section{Création d'un script de démarrage} L'écriture d'un script de démarrage se révèle en fait plus simple que vous ne le pensez. Vous devez néanmoins posséder quelques bases en programmation shell. Pour obtenir plus d'informations consultez la page de manuel de votre shell (pour bash qui est le shell par défaut sur Debian : \texttt{# man bash}).\\ \\ Voici un exemple commenté de script de démarrage possible : \begin{bgcolor}{Gray} \textit{\textcolor{PineGreen}{#!/bin/sh\\ \\ ## Script basique donné à titre d'exemple et destiné à montrer comment fonctionne un\\ ## script de démarrage.\\ ## On pourrait utiliser la commande \texttt{start-stop-daemon} comme dans le script initial\\ ## d'apache mais cela sortirait du cadre de cet article ;).\\ ## On précise tout d'abord que c'est un script écrit en shell avec la ligne ci-dessus\\ \\ ## /etc/init.d/apache\verb+_+exemple: démarre et arrête le service apache\\ \\ ## On définit la valeur de quelques variables avant de commencer le script proprement dit.\\ # Répertoires contenant de nombreux programmes exécutables}}\\ PATH=/bin:/usr/bin:/sbin:/usr/sbin\\ \textit{\textcolor{PineGreen}{# Chemin vers le programme qui démarrera Apache}}\\ DAEMON=/usr/sbin/apache\\ \textit{\textcolor{PineGreen}{# Optionnel : définit le nom et la description qui s'afficheront lors du démarrage ou de\\ # l'arrêt du script}}\\ NAME=apache\\ DESC="Webserver"\\ \\ \textit{\textcolor{PineGreen}{## Début du script proprement dit\\ # On vérifie tout d'abord que le programme \texttt{apachectl} est exécutable, sinon fin du script}}\\ test -x \verb+$+DAEMON || exit 0\\ \\ \textit{\textcolor{PineGreen}{# Suivant l'argument que l'on va ajouter après le nom du script, on va définir différentes\\ # possibilités aux script grâce à l'instruction \texttt{case}}}\\ case "\verb+$+1" in\\ \qquad \textit{\textcolor{PineGreen}{# si on tape \texttt{# /etc/init.d/apache\verb+_+exemple start}, les instructions qui suivent vont être\\ \qquad # exécutées}}\\ \qquad start)\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Affiche : « Starting Webserver: apache »\\ \qquad \qquad # \verb+$+DESC et \verb+$+NAME sont bien entendu les variables que l'on a défini plus haut}}\\ \qquad \qquad echo -n "Starting \verb+$+DESC: \verb+$+NAME"\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Lance le serveur web Apache}}\\ \qquad \qquad apache \verb+&+ >\verb+&+ /dev/null\\ \qquad \qquad echo "."\\ \qquad \qquad ;;\\ \qquad \textit{\textcolor{PineGreen}{# Fin des instructions si on met l'argument \texttt{start} après le nom du script\\ \qquad # si on tape \texttt{# /etc/init.d/apache\verb+_+exemple stop}, les instructions suivantes vont être\\ \qquad # exécutées}}\\ \qquad stop)\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Affiche : « Stopping Webserver: apache »}}\\ \qquad \qquad echo -n "Stopping \verb+$+DESC: \verb+$+NAME"\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Tue tous les processus portant le nom « apache » sauvagement (« -9 ») et n'affiche\\ \qquad \qquad # pas le résultat (« /dev/null »)}}\\ \qquad \qquad killall -9 apache >\verb+&+ /dev/null\\ \qquad \qquad echo "."\\ \qquad \qquad ;;\\ \qquad \textit{\textcolor{PineGreen}{# Fin des instructions si on met l'argument \texttt{stop} après le nom du script\\ \qquad # si on tape \texttt{/etc/init.d/apache\verb+_+exemple restart}, les instructions suivantes vont être\\ \qquad # exécutées}}\\ \qquad restart)\\ \qquad \textit{\textcolor{PineGreen}{# Affiche : « Restarting Webserver: apache»}}\\ \qquad \qquad echo -n "Restarting \verb+$+DESC: \verb+$+NAME"\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Vérifie si le processus \texttt{apache} est déjà lancé ou non}}\\ \qquad \qquad if [ -z "\verb+$+(ps ax | egrep apache)" ]; then\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Si il n'est pas lancé alors on affiche : « Apache isn't running, so not killed »}}\\ \qquad \qquad \qquad echo " Apache isn't running, so not killed" ;\\ \qquad \qquad else\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Sinon on tue tous les processus portant le nom apache comme décrit précédemment}}\\ \qquad \qquad \qquad killall -9 apache >\verb+&+ /dev/null ;\\ \qquad \qquad fi\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Attente d'une seconde avant de continuer le script}}\\ \qquad \qquad sleep 1\\ \qquad \qquad \textit{\textcolor{PineGreen}{# Enfin on démarre le serveur apache}}\\ \qquad \qquad apache >\verb+&+ /dev/null\\ \qquad \qquad echo "."\\ \qquad \qquad ;;\\ \qquad \textit{\textcolor{PineGreen}{# Si on tape \texttt{# /etc/init.d/apache} alors le script affichera les différents arguments que\\ \qquad # l'on peut donner au script}}\\ \qquad \verb+*+)\\ \qquad \qquad echo "Usage: /etc/init.d/\verb+$+NAME {start|stop|restart}" >\verb+&+2\\ \qquad \qquad exit 1\\ \qquad \qquad ;;\\ esac\\ \\ exit 0\\ \textit{\textcolor{PineGreen}{# Fin du script !}} \end{bgcolor} Une fois que vous avez enregistré ce fichier dans le répertoire \texttt{/etc/init.d} sous le nom \texttt{apache\verb+_+exemple}, il ne vous reste plus qu'à le rendre exécutable. Pour cela, vous pouvez procéder de deux manières qui aboutissent exactement au même résultat dans ce cas-là :\\ \texttt{# chmod +x /etc/init.d/apache\verb+_+exemple}\\ \textit{Ou}\\ \texttt{# chmod 755 /etc/init.d/apache\verb+_+exemple}\\ \\ Vous pouvez désormais vérifier que votre script fonctionne avec les commandes suivantes :\\ \texttt{ # /etc/init.d/apache\verb+_+exemple start\\ # /etc/init.d/apache\verb+_+exemple stop}\\ \\ Nous allons ensuite décrire le fonctionnement de la commande \texttt{update-rc.d} pour que votre script soit lancé lors du démarrage ou de l'arrêt du système. \section{Installation de liens vers les scripts de démarrage} Imaginons que vous vouliez exécuter notre script \texttt{apache\verb+_+exemple} au démarrage dans un runlevel particulier tel que décrit plus haut.\\ \\ Commençons par un exemple simple qui devrait convenir à la plupart des utilisateurs :\\ \texttt{ # update-rc.d apache\verb+_+exemple defaults 20\\ Adding system startup for /etc/init.d/apache\verb+_+exemple ...\\ /etc/rc0.d/K19apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc1.d/K19apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc6.d/K19apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc2.d/S19apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc3.d/S19apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc4.d/S19apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc5.d/S19apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple}\\ \\ De cette façon les liens sont tous créés avec la lettre \textit{S} pour les niveaux de démarrage standard du système et \textit{K} pour les autres, ainsi qu'avec le chiffre \textit{20} quelque soit le niveau de démarrage.\\ \\ Un autre exemple d'utilisation, cette fois-ci un peu plus poussé :\\ \texttt{ # update-rc.d apache\verb+_+exemple start 20 5 . stop 40 6 .\\ Adding system startup for /etc/init.d/apache\verb+_+exemple ...\\ /etc/rc6.d/K40apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc5.d/S10apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple}\\ \\ De cette autre façon les liens sont créés uniquement pour les niveaux \textit{5 et 6} de démarrage. De plus on a assigné des numéros différents suivant le runlevel. Le point à la fin de ligne est très important car il marque \textbf{la fin} de votre commande.\\ \\ Enfin un dernier exemple dans lequel le script \texttt{apache\verb+_+exemple} ne sera pas lier dans les répertoires destiné à l'arrêt du système (notez le point à la fin de la commande) :\\ \texttt{ # update-rc.d apache\verb+_+exemple start 20 2 3 4 5 .\\ Adding system startup for /etc/init.d/apache\verb+_+exemple ...\\ /etc/rc2.d/S20apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc3.d/S20apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc4.d/S20apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\ /etc/rc5.d/S20apache\verb+_+exemple -> ../init.d/apache\verb+_+exemple\\} \\ Vérifiez bien que les liens sont bien placés et grâce à cette magnifique commande qu'est \texttt{update-rc.d} votre script sera lancé au prochain redémarrage. \section{Désinstallation de liens vers les scripts de démarrage} Imaginons maintenant que vous voulez désinstaller le script précédent afin qu'il ne soit plus lancé au démarrage. Deux cas de figure se présentent à vous : \begin{itemize} \item Vous n'avez plus besoin du script donc vous supprimez le script du répertoire \texttt{/etc/init.d}.\\ \item Sinon vous gardez ce script afin de pouvoir éventuellement le réutiliser plus tard. \end{itemize} Dans le premier cas, il vous suffit de taper :\\ \texttt{ # rm /etc/init.d/apache\verb+_+exemple\\ # update-rc.d apache\verb+_+exemple remove}\\ \\ Dans le second cas vous taperez alors :\\ \texttt{ # update-rc.d apache\verb+_+exemple remove}\\ \section {Pour en savoir plus} Si vous voulez en apprendre davantage sur la commande \texttt{update-rc.d} et sur le système \texttt{init}, les pages de manuel sont très utiles surtout si vous les installez en français (\texttt{apt-get install manpages-fr}) :\\ \texttt{ # man update-rc.d\\ # man init} \section{Remerciements} Cet article a été écris avec l'aide de visiteurs du site et du forum et modifié par moi même (Arnaud Fontaine). Voici les pseudo des personnes qui ont participé à cet article :\\ \begin{itemize} \item kagou \item Stéphane \item crayongomme \item kakaouete \item y0m \item ptitlouis \item Fusco \item ioguix \end{itemize} \textbf{Modifications du document :}\\ \textit{- Mises à jour effectuées le 20 juillet 2003 : corrections de fautes d'orthographe.} \end{document}