Handbook:SPARC/Working/Initscripts/fr
Le contenu de cette page ne s’applique pas aux utilisateurs qui ont choisi un profil systemd dans cette section.
Runlevels
Démarrer le système
Pendant que le système démarre, beaucoup de texte va défiler. En regardant attentivement, vous pourriez apercevoir ce texte (généralement), le même à chaque fois que le système est redémarrer. L’enchaînement de toutes ces actions est appelée la séquence de démarrage et est (plus ou moins) statique.
D’abord, le programme d’amorçage va charger l’image du noyau définie dans sa configuration. Ensuite, il demandera aux CPU de lancer le noyau. Pendant que le noyau est chargé et lancé, il initialise toutes les structures spécifiques au noyaux, lance les tâches et démarre le processus init.
Le processus init s’assure que toutes les partitions (définies dans /etc/fstab) soient montées et prêtes à l’emploi. Ensuite, il lance de nombreux scripts localisés dans /etc/init.d/, lesquels vont lancer les services nécessaires pour un démarrage réussi du système.
Dernièrement, une fois tous les scripts exécutés, init active les consoles virtuelles accessibles via Ctrl+Alt+ F1, Ctrl+Alt + F2, etc. Attachant chacun à un processus spécial appelé agetty. Ce processus s’assure que les utilisateurs peuvent se connecter avec login.
Scripts d’initialisation
Les scripts dans /etc/init.d/ ne sont pas exécutés aléatoirement. init ne lance pas tous les scripts, seulement ceux dont il a été demandé de les lancer via /etc/runlevels/.
D’abord, init lance tous les scripts de /etc/init.d/ qui ont un lien symbolique dans /etc/runlevels/boot/. Généralement, il lancera les scripts dans l’ordre alphabétique, mais certains ont des informations de dépendance qui informeront le système que d’autres scripts doivent être lancés avant leur démarrage.
Une fois tous les scripts référencés dans /etc/runlevels/boot/ sont lancés, init va lancer ceux de /etc/runlevels/default/. À nouveau, l’ordre alphabétique sera utilisé pour décider lesquels lancer en premier, sauf si une information de dépendance vient modifier l’ordre valide de la séquence de démarrage. C’est pour cela que les commandes lors de l’installation de Gentoo Linux utilisent le runlevel default (i.e. rc-update add sshd default).
Fonctionnement d’init
Évidemment, init ne décide pas tout tout seul. Il a besoin d’un fichier de configuration qui lui indique les actions à mener. Le fichier /etc/inittab est utilisé par init pour déterminer cela.
Comme décrit ci-dessus, la 1re action d’init est de monter tous les systèmes de fichiers. Cela est défini par la ligne suivante de /etc/inittab :
/etc/inittabCommande d’initialisationsi::sysinit:/sbin/openrc sysinit
Cette ligne demande à init de lancer obligatoirement /sbin/openrc sysinit pour initialiser le système. Le script /sbin/openrc s’occupe de l’initialisation, donc il pourrait être tentant de dire qu’init ne fait pas grand-chose – il délègue la tâche d’initialisation à un autre processus.
Dans un deuxième temps, init lance tous les scripts qui ont un lien symbolique dans /etc/runlevels/boot/. C’est défini avec la ligne suivante :
/etc/inittabAppel du démarrage bootrc::bootwait:/sbin/openrc boot
À nouveau, le script OpenRC lance les tâches nécessaires. Notez que l’option donnée à OpenRC (« boot ») est la même que le sous-répertoire de /etc/runlevels/.
Maintenant, init vérifie son fichier de configuration pour analyser quel niveau de lancement (runlevel) il devrait lancer. Pour décider cela, il lit les lignes de /etc/inittab :
/etc/inittabSélection du runlevel par défautid:3:initdefault:
Dans cette situation (qui est celle de la majorité des utilisateurs de Gentoo), l’identifiant du niveau de lancement est 3. À partir de cette information, init identifie ce qu’il doit lancer pour démarrer au niveau 3 :
/etc/inittabDéfinition des niveauxl0:0:wait:/sbin/openrc shutdown l1:S1:wait:/sbin/openrc single l2:2:wait:/sbin/openrc nonetwork l3:3:wait:/sbin/openrc default l4:4:wait:/sbin/openrc default l5:5:wait:/sbin/openrc default l6:6:wait:/sbin/openrc reboot
La ligne qui définit le niveau 3, à nouveau utilise le script OpenRC pour démarrer les services (maintenant avec l’argument default). Notez que l’option donnée à OpenRC (« boot ») est la même que le sous-répertoire de /etc/runlevels/.
Lorsqu’OpenRC a terminé, init décide quelles consoles virtuelles il doit activer et quelles commandes doivent être lancées dans chacune :
/etc/inittabDéfinitions des terminauxc1:12345:respawn:/sbin/agetty 38400 tty1 linux c2:12345:respawn:/sbin/agetty 38400 tty2 linux c3:12345:respawn:/sbin/agetty 38400 tty3 linux c4:12345:respawn:/sbin/agetty 38400 tty4 linux c5:12345:respawn:/sbin/agetty 38400 tty5 linux c6:12345:respawn:/sbin/agetty 38400 tty6 linux
Niveaux de lancement (runlevels) disponibles
Dans la section précédente, nous avons vu qu’init utilise un chiffre pour décider le niveau de lancement qu’il doit activer. Un niveau de lancement est un état dans lequel le système est démarré et contient un ensemble de scripts (unlevel scripts ou initscripts) qui doivent être lancés ou arrêtés pour un niveau de lancement.
Dans Gentoo, il y a sept niveaux de lancement définis : trois internes et quatre définis par l’utilisateur. Ceux internes sont sysinit, shutdown and reboot et font exactement ce que dit leur nom : initialiser, arrêter ou redémarrer le système.
Les niveaux de lancement définis par l’utilisateur sont ceux qui sont dans le sous-répertoire /etc/runlevels/ : boot, default, nonetwork et single. boot démarre tous les services systèmes nécessaires utilisés par les autres niveaux de lancement. Les trois autres diffèrent dans les services qui sont lancés. : default est pour l’usage quotidien, nonetwork est utilisable lorsqu’aucune connexion réseau n’est requise et single est usité lorsque le système doit être réparé.
Utiliser des scripts d’initialisation (initscripts)
Les scripts que le processus openrc lance sont appelés scripts d’initialisation (initscripts). Chaque script dans /etc/init.d/ peut être lancé avec le paramètre start, stop, restart, zap, status, ineed, iuse, iwant, needsme, usesme ou wantsme.
Pour démarrer, arrêter ou relancer un service (et toutes ses dépendances), le paramètre start, stop ou restart doivent être utilisés :
root #rc-service postfix startSeuls les services qui ont besoin du service demandé sont lancés ou redémarrés. Les autres services dépendants (ceux qui utilisent le service mais n’en ont pas besoin) ne sont pas concernés.
Pour arrêter un service, mais pas ceux qui dépendent de lui, utilisez l’option --nodeps en même temps que stop :
root #rc-service --nodeps postfix stopPour connaître le statut d’un service (démarré, arrêté...), utilisez le paramètre « status » :
root #rc-service postfix statusSi le statut indique que le service est démarré alors qu’il ne l’est pas, il est possible de réinitialiser l’information du statut à « arrêté » avec le paramètre zap :
root #rc-service postfix zapPour savoir également quelles dépendances le service a, utilisez iwant, iuse ou ineed. Avec ineed, il est possible d’identifier les services qui ont vraiment besoin du service pour un fonctionnement correct. iwant ou iuse, dans un autre sens, montrent les services qui peuvent être utilisés par le service, mais ne sont pas nécessaires au fonctionnement correct dudit service.
root #rc-service postfix ineedSimilairement, il est possible de demander quels services sont nécessaires pour un service (needsme) ou ceux qui l’utilisent (usesme ou wantsme) :
root #rc-service postfix needsmeMettre à jour les niveaux de lancement
rc-update
Le système d’initialisation Gentoo utilise un arbre de dépendances pour déterminer quel service doit être démarré en premier. Comme c’est une tâche rébarbative et que nous ne voulons pas que les utilisateurs aient à le faire manuellement, nous avons créé des outils qui simplifient l’administration des niveaux de lancement et des scripts init.
Avec rc-update, il est possible d’ajouter ou supprimer un script init d’un niveau de lancement. L’outil rc-update va automatiquement appeler le script depscan.sh pour reconstruire l’arbre de dépendances.
Ajouter et supprimer des services
Dans les instructions précédentes, les scripts init ont déjà été ajoutée au niveau de lancement default. Ce que default signifie est expliqué plus tôt dans cette page. Après le niveau de lancement, le script rc-update a besoin d’une deuxième paramètre qui définit une action : add, del ou show.
En plus du niveau de lancement, le script rc-update a besoin d’une deuxième paramètre qui définit une action : add, del ou show. Par exemple :
root #rc-update del postfix defaultLa commande rc-update -v show va montrer tous les scripts init et tous les niveaux de lancement dans lesquels il va s’exécuter :
root #rc-update -v showIl est également possible de lancer rc-update show (sans -v) pour simplement voir les scripts init activé et leurs niveaux de lancement.
Configurer des services
Pourquoi une configuration supplémentaire est nécessaire
Les scripts init peuvent être complexes. Il n’est pas souhaitable que les utilisateurs les modifient directement, car cela pourrait les rendre plus sensibles aux erreurs. Cependant, il est important de configurer les services : par exemple, les utilisateurs pourraient vouloir lancer le service avec des options supplémentaires.
Une autre raison d’externaliser le configuration en dehors du script init est pour permettre de mettre à jour ce dernier sans écraser la configuration de l’utilisateur.
Le répertoire conf.d
Gentoo fournit une façon facile pour configurer un tel service : chaque script init peut être configuré avec un fichier dans /etc/conf.d/. Par exemple, le script init apache2 (appelé /etc/init.d/apache2) a un fichier de configuration appelé /etc/conf.d/apache2, lequel peut contenir les options pour le démarrage du serveur Apache 2.
/etc/conf.d/apache2Exemple d’options pour le script init d’apache2APACHE2_OPTS="-D PHP5"
Un tel fichier de configuration contient seulement des variables (comme /etc/portage/make.conf le fait), rendant très simple le paramétrage des services. Il fournit aussi des informations sur les variables (en commentaire).
Écrire des scripts d’initialisation
Une autre ressource est le guide OpenRC des scripts de service.
Est-ce nécessaire ?
Non, écrire un script d’initialisation n’est généralement pas utile car Gentoo en fournit des prêts à l’emploi pour tous les services inclus. Cependant, certains utilisateurs pourraient souhaiter installer un service en dehors de Portage, dans ce cas, ils devront probablement créer un script d’initialisation.
N’utilisez pas de script d’initialisation s’il n’a pas explicitement été écrit pour Gentoo : les scripts d’initialisation Gentoo ne sont pas compatibles avec ceux d’autres distributions, sauf si cette dernière utilise OpenRC.
Structure
La structure basique pour un script d’initialisation est indique ci-dessous.
#!/sbin/openrc-run depend(){ # (Information de dépendances) } start(){ # (Commandes nécessaires pour démarrer le service) } stop(){ # (Commandes nécessaires pour arrêter le service) }
#!/sbin/openrc-run command=/usr/bin/foo command_args="${foo_args} --bar" pidfile=/var/run/foo.pid name="Démon MachinTruc" description="MachinTruc est un démon qui boit" extra_started_commands="boire" description_boire="Ouvre la bouche et avale par réflexe" depend(){ # (Information de dépendances) } start_pre(){ # (Commands necessary to prepare to start the service) # Vérifier que le répertoire de sorti est bien configuré checkpath--directory--ownermachin:machin--mode0775\ /var/run/machin/var/cache/machin } stop_post(){ # (Commandes nécessaires pour arrêter le service) # Nettoyer ce qui est tombé à côté rm-rf/var/cache/machin.* } boire(){ ebegin"Commencer à boire" ${command}--boirebière eend$?"Échec à boire une bière :(" }
Chaque script d’initialisation nécessite une fonction start() or une variable commande command définie. Toutes les autres sections sont optionnelles.
Dépendances
There are three dependency-related settings which can influence the start-up or sequencing of init scripts:: want, use and need. Next to these, there are also two order-influencing methods called before and after. These last two are not dependencies per se - they don't make the init script fail if the specified dependency isn't scheduled to start (or fails to start).
- The
usesetting informs the init system that the script uses functionality offered by the selected script, but does not directly depend on it. Some examples areuse loggeranduse dns: if the services are available, they will be used, but if the system does not have a logger or DNS server, the services will still work. If the services exist, then they are started before the script that uses them. - The
wantsetting is similar tousewith one exception.useonly considers services which were added to a runlevel;wantwill try to start any available service even if not added to any runlevel.wantwill try to start any available service even if not added to an init level. - The
needsetting indicates a hard dependency: a script thatneeds another script will not start before the latter script is started successfully. Also, if theneeded script is restarted, the script needing it will be restarted as well. - The
beforesetting ensures the script is launched before a specified script, if the latter is part of the runlevel. So an init script xdm that definesbefore alsasoundwill start before the alsasound script, but only if alsasound is scheduled to start in the same runlevel. If alsasound is not scheduled to start in that runlevel, then thebeforehas no effect, and xdm will be started when the init system deems it most appropriate. - Similarly,
afterinforms the init system that the given script should be launched after a specified script if the latter is part of the same runlevel. If not, then the setting has no effect and the script will be launched by the init system when it deems it most appropriate.
It should be clear from the above that need is the only "true" dependency setting, as it affects whether the script will be started or not. All the others merely tell the init system the order in which scripts can be (or should be) started.
Virtual dependencies
Many of Gentoo's init scripts depend on things that are themselves not init scripts: virtual dependencies.
A virtual dependency is a dependency that a service provides, but that is not provided solely by that service. An init script can depend on a system logger, but there are many system loggers available (metalogd, syslog-ng, sysklogd, ...). As the script cannot need every single one of them (no sensible system has all these system loggers installed and running) we made sure that all these services provide a virtual dependency.
For instance, consider the dependency information in the postfix script:
/etc/init.d/postfixDependency information of the postfix servicedepend(){ neednet useloggerdns providemta }
As can be seen, the postfix service:
- Requires the (virtual)
netdependency (which is provided by, for instance, /etc/init.d/net.eth0). - Uses the (virtual)
loggerdependency (which is provided by, for instance, /etc/init.d/syslog-ng). - Uses the (virtual)
dnsdependency (which is provided by, for instance, /etc/init.d/named). - Provides the (virtual)
mtadependency (which is common for all mail servers).
Contrôler l'ordre
As described in the previous section, it is possible to tell the init system what order it should use for starting (or stopping) scripts. This ordering is handled both through the dependency settings use and need, but also through the order settings before and after. As we have described these earlier already, let's take a look at the portmap service as an example of such init script.
/etc/init.d/portmapDependency information of the portmap servicedepend(){ neednet beforeinetd beforexinetd }
It's possible to use the * glob to refer to all services in the same runlevel, although this isn't advisable.
depend(){ before* }
If the service must write to local disks, it should need localmount. If it places anything in /var/run/, such as a PID file, then it should start after bootmisc:
depend(){ needlocalmount afterbootmisc }
Fonctions standards
In addition to the depend() functionality, it's also necessary to define the start() function. This function contains all the commands necessary to initialize the service. It's advisable to use the ebegin and eend functions to inform the user about what's happening:
start(){ if["${RC_CMD}"="restart"]; then # Do something in case a restart requires more than stop, start fi ebegin"Starting my_service" start-stop-daemon--start--exec/path/to/my_service\ --pidfile/path/to/my_pidfile eend$? }
Both --exec and --pidfile should be used in start() and stop() functions. If the service doesn't create a PID file, then use --make-pidfile if possible, though it is recommended to test this to be sure. Otherwise, don't use PID files. It is also possible to add --quiet to the start-stop-daemon options, but this is not recommended unless the service is extremely verbose. Using --quiet may hinder debugging if the service fails to start.
Note also that the above example check the contents of the RC_CMD variable. OpenRC doesn't support script-specific restart functionality; instead, the script needs to check the contents of the RC_CMD variable to see if a function (e.g. start() or stop()) is being called as part of a restart or not.
Make sure that
--exec actually calls a service and not just a shell script that launches services and exits - that's what the init script is supposed to do.For more examples of the start() function, please read the source code of the available init scripts in the /etc/init.d/ directory.
Another function that can (but does not have to) be defined is stop(). The init system is intelligent enough to fill in this function by itself if start-stop-daemon is used.
stop(){ ebegin"Stopping my_service" start-stop-daemon--stop--exec/path/to/my_service\ --pidfile/path/to/my_pidfile eend$? }
If the service runs some other script (for example, Bash, Python, or Perl), and this script later changes names (for example, from foo.py to foo), then it is necessary to add --name as an option to start-stop-daemon. This must specify the name that the script will be changed to. In this example, a service starts foo.py, which changes names to foo:
start(){ ebegin"Starting my_script" start-stop-daemon--start--exec/path/to/my_script\ --pidfile/path/to/my_pidfile--namefoo eend$? }
start-stop-daemon has an excellent man page available if more information is needed:
user $man start-stop-daemonGentoo's init script syntax is based on the POSIX shell ('sh'), so people are free to use sh-compatible constructs inside their init scripts. Keep other constructs, like Bash-specific ones, out of init scripts to ensure that the scripts remain functional regardless of any changes Gentoo might make to its init system.
Ajouter des options personnalisées
If the initscript needs to support an option other than the ones we've already encountered, add the option to one of the following variables, and create a function with the same name as the option. For instance, to support an option called restartdelay:
- extra_commands - Command is available with the service in any state
- extra_started_commands - Command is available when the service is started
- extra_stopped_commands - Command is available when the service is stopped
extra_started_commands="restartdelay" restartdelay(){ stop sleep3# Wait 3 seconds before starting again start }
The
restart() function cannot be overridden in OpenRC!Service configuration variables
In order to support configuration files in /etc/conf.d/, no specifics need to be implemented: when the init script is executed, the following files are automatically sourced (i.e. the variables are available to use):
- /etc/conf.d/YOUR_INIT_SCRIPT
- /etc/conf.d/basic
- /etc/rc.conf
Also, if the init script provides a virtual dependency (such as net), the file associated with that dependency (such as /etc/conf.d/net) will be sourced too.
Changing runlevel behavior
Who might benefit
Many laptop users know the situation: at home they need to start net.eth0, but they don't want to start net.eth0 while on the road (as there is no network available). With Gentoo the runlevel behavior can be altered at will.
For instance, a second "default" runlevel can be created, with other init scripts assigned to it. At boot time, the user can select what "default" runlevel to use.
Using softlevel
First of all, create the runlevel directory for the second "default" runlevel. As an example we create the offline runlevel:
root #mkdir /etc/runlevels/offlineAdd the necessary init scripts to the newly created runlevel. For instance, to have an exact copy of the current default runlevel but without net.eth0:
root #cd /etc/runlevels/default
root #for service in *; do rc-update add $service offline; done
root #rc-update del net.eth0 offline
root #rc-update show offline(Partial sample Output) acpid | offline domainname | offline local | offline net.eth0 |
Even though net.eth0 has been removed from the offline runlevel, udev might want to attempt to start any devices it detects and launch the appropriate services, functionality that is called hotplugging. By default, Gentoo does not enable hotplugging.
To enable hotplugging, but only for a selected set of scripts, use the rc_hotplug variable in /etc/rc.conf:
/etc/rc.confEnable hotplugging of the WLAN interfacerc_hotplug="net.wlan !net.*"
For more information on device initiated services, please see the comments inside /etc/rc.conf.
Edit the bootloader configuration and add a new entry for the offline runlevel. In that entry, add softlevel=offline as a boot parameter.
Using bootlevel
Using bootlevel is completely analogous to softlevel. The only difference here is that a second "boot" runlevel is defined instead of a second "default" runlevel.