Product SiteDocumentation Site

Chapitre 9. Services Unix

9.1. Démarrage du système
9.1.1. Le système d'initialisation systemd
9.1.2. Le système d'initialisation System V
9.2. Connexion à distance
9.2.1. Connexion à distance sécurisée : SSH
9.2.2. Accéder à distance à des bureaux graphiques
9.3. Gestion des droits
9.4. Interfaces d'administration
9.4.1. Administrer sur interface web : webmin
9.4.2. Configuration des paquets : debconf
9.5. Les événements système de syslog
9.5.1. Principe et fonctionnement
9.5.2. Le fichier de configuration
9.6. Le super-serveur inetd
9.7. Planification de tâches : cron et atd
9.7.1. Format d'un fichier crontab
9.7.2. Emploi de la commande at
9.8. Planification asynchrone : anacron
9.9. Les quotas
9.10. Sauvegarde
9.10.1. Sauvegarde avec rsync
9.10.2. Restauration des machines non sauvegardées
9.11. Branchements « à chaud » : hotplug
9.11.1. Introduction
9.11.2. La problématique du nommage
9.11.3. Fonctionnement de udev
9.11.4. Cas pratique
9.12. Gestion de l'énergie : Advanced Configuration and Power Interface (ACPI)
Ce chapitre parcourt un ensemble de services fondamentaux, souvent communs à beaucoup d'Unix. Tout administrateur se doit de les connaître.

9.1. Démarrage du système

Lorsque l'ordinateur démarre, les messages défilant sur la console révèlent de nombreuses initialisations et configurations automatiques. Parfois, il est souhaitable de modifier légèrement le déroulement de cette étape, ce qui implique de bien la comprendre. C'est l'objet de cette section.
En tout premier lieu, le BIOS prend le contrôle de l'ordinateur, détecte les disques, charge le Master Boot Record (enregistrement d'amorçage maître) et l'exécute. Le chargeur d'amorçage prend alors le relais, trouve le noyau sur le disque, le charge et l'exécute. Le noyau s'initialise alors et se met en devoir de trouver et monter la partition contenant la racine de l'arborescence pour enfin démarrer le premier programme : init. Il est fréquent que cette « partition racine » et cet init soient en réalité sur un système de fichiers virtuel qui n'existe qu'en mémoire vive (d'où son nom initramfs, anciennement appelé initrd pour initialization RAM disk). Ce système de fichiers est chargé en mémoire par le chargeur d'amorçage, souvent à partir d'un fichier sur un disque dur ou sur le réseau. Il contient le strict minimum qui peut être requis par le noyau pour charger le « vrai » système de fichiers racine : il peut s'agir de modules de pilotes pour les disques durs ou d'autres périphériques sans lesquels le système ne peut pas démarrer, ou, plus fréquemment, des modules et des scripts d'initialisation permettant d'assembler des grappes RAID, d'ouvrir des partitions chiffrées, d'activer des volumes LVM… Une fois que la partition racine est montée, l'initramfs passe la main au vrai init et on revient sur le processus de démarrage standard.
Étapes du démarrage d'un ordinateur sous Linux avec systemd

Figure 9.1. Étapes du démarrage d'un ordinateur sous Linux avec systemd

9.1.1. Le système d'initialisation systemd

Le « vrai init » est actuellement fourni par systemd, sur lequel cette section se focalise.
systemd exécute plusieurs processus qui ont la responsabilité de mettre en place le système : clavier, pilotes, systèmes de fichiers, réseau et services. Il effectue cela en conservant une vue globale du système et des exigences de chaque composant. Chaque composant est décrit par un (ou plusieurs) « fichier unité » (unit file) ; la syntaxe générale est dérivée de celle des « fichiers *.ini », avec des paires clé = valeur regroupées entre des en-têtes [section]. Ces fichiers sont placés dans /lib/systemd/system/ et dans /etc/systemd/system/ ; ils en existent plusieurs sortes (chacune avec sa spécialité) mais dans cette section on ne traitera que des services et des targets (« cibles »).
Un « fichier service » de systemd décrit un processus géré par systemd. Il contient approximativement les mêmes informations que les anciens scripts d'initialisation, mais exprimés d'une manière déclarative (et bien plus concise). systemd s'occupe de toutes les tâches répétitives (démarrer et arrêter le processus, vérifier son état, enregistrer des logs, abandonner des privilèges, etc.), et le fichier service n'a plus qu'à préciser les particularités du processus. Voici par exemple celui pour SSH :
[Unit]
Description=OpenBSD Secure Shell server
After=network.target auditd.service
ConditionPathExists= !/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target
Alias=sshd.service
On constate qu'il y a très peu de code dans ce fichier, juste des déclarations. systemd s'occupe d'afficher l'état d'avancement, garde une trace des processus, et les redémarre même lorsque c'est nécessaire.
Un « fichier target » de systemd décrit un état « cible » du système, dans lequel un certain nombre de services sont réputés être fonctionnels. On peut le concevoir comme l'équivalent d'un « niveau d'exécution » (runlevel) de l'ancien système. Une de ces cibles est local-fs.target ; lorsqu'elle est atteinte, le reste du système peut considérer que tous les systèmes de fichiers locaux sont montés et accessibles. Parmi les autres cibles existantes, citons network-online.target (« réseau en ligne ») et sound.target (« son »). Les dépendances d'une cible peuvent être listées soit dans le fichier target lui-même (sur la ligne Requires=), soit en créant un lien symbolique vers un fichier service dans le répertoire /lib/systemd/system/nom-de-la-cible.target.wants/. Ainsi, /etc/systemd/system/printer.target.wants/ contient un lien vers /lib/systemd/system/cups.service ; systemd s'assurera donc que CUPS soit bien démarré pour atteindre la cible printer.target.
Puisque les fichiers de systemd ne sont pas des scripts ou des programmes, ils ne peuvent être exécutés directement : ils doivent être interprétés par systemd. C'est pourquoi l'administrateur dispose de plusieurs utilitaires pour interagir avec systemd, et contrôler l'état du système et de chacun de ses composants.
Le premier de ces outils est systemctl. Lorsqu'il est exécuté sans paramètres, il liste toutes les « unités » connues de systemd (à l'exception de celles qui ont été désactivées), ainsi que leur état. systemctl status donne une meilleure vue des services, et des processus associés. En lui passant un nom de service (comme dans systemctl status ntp.service), il renvoie encore plus de détails, ainsi que les dernières lignes de log en rapport avec le service (nous reviendrons là dessus plus loin).
Démarrer un service manuellement se fait simplement avec systemctl start nom-de-service.service. Inversement et sans surprise, arrêter un service se fait avec systemctl stop nom-de-service.service ; d'autres sous-commandes existent, comme reload (« recharger ») et restart (« redémarrer »).
Pour activer un service (autrement dit pour qu'il soit lancé automatiquement au démarrage de l'ordinateur), il convient de faire systemctl enable nom-du-service.service (ou disable pour le désactiver). La sous-commande is-enabled permet de vérifier l'état d'activation du service.
Une autre particularité de systemd est son système de journalisation – journald. Il peut être employé en complément des outils de journalisation traditionnels comme syslogd : il rajoute des fonctionnalités intéressantes comme l'association d'un message au service qui l'a généré, et la capacité de capturer les messages émis sur la sortie d'erreur des processus gérés. Les messages peuvent être consultés après coup, grâce à la commande journalctl. Sans arguments, elle affiche simplement tous les messages enregistrés depuis le démarrage du système ; on ne l'emploie que rarement de cette manière. La plupart du temps, on lui communique un identifiant de service dont on veut voir les messages :
# journalctl -u ssh.service
-- Logs begin at mar. 2015-03-31 10:08:49 CEST, end at mar. 2015-03-31 17:06:02 CEST. --
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Received SIGHUP; restarting.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:32 mirtuel sshd[1151]: Accepted password for roland from 192.168.1.129 port 53394 ssh2
Mar 31 10:09:32 mirtuel sshd[1151]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Une autre option très utile est -f, qui demande à journalctl d'afficher les nouveaux messages au fur et à mesure de leur émission (de manière similaire à ce que réalise tail -f fichier).
Lorsqu'un service n'a pas l'air de fonctionner correctement, la première étape pour résoudre le problème est de vérifier si le service est lancé avec systemctl status ; si ce n'est pas le cas, et si les messages affichés par cette première commande ne suffisent pas à identifier le problème, il convient alors de consulter les messages que journald a collecté au sujet de ce service. Prenons le cas d'un serveur SSH qui ne fonctionne pas :
# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: failed (Result: start-limit) since mar. 2015-03-31 17:30:36 CEST; 1s ago
  Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
  Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255)
 Main PID: 1188 (code=exited, status=255)

Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
# journalctl -u ssh.service
-- Logs begin at mar. 2015-03-31 17:29:27 CEST, end at mar. 2015-03-31 17:30:36 CEST. --
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2
Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
# vi /etc/ssh/sshd_config
# systemctl start ssh.service
# systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
   Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
   Active: active (running) since mar. 2015-03-31 17:31:09 CEST; 2s ago
  Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
 Main PID: 1222 (sshd)
   CGroup: /system.slice/ssh.service
           └─1222 /usr/sbin/sshd -D
# 
Après avoir vérifié l'état du service (failed, en échec), nous avons consulté les messages du journal ; ils indiquaient une erreur dans le fichier de configuration. Après avoir corrigé ce dernier, nous avons redémarré le service et nous avons vérifié qu'il fonctionnait pour de bon.

9.1.2. Le système d'initialisation System V

Le système d'initialisation System V exécute tout un ensemble de processus en suivant les indications du fichier /etc/inittab. Le premier programme exécuté (correspondant à l'étape sysinit) est /etc/init.d/rcS, script qui exécute tous les programmes du répertoire /etc/rcS.d/.
Parmi ceux-ci, on trouve successivement :
  • la configuration du clavier de la console ;
  • le chargement des pilotes : la plupart des modules noyau sont chargés par le noyau lui-même en fonction du matériel détecté ; certains pilotes peuvent ensuite être systématiquement chargés, les modules correspondants doivent être listés dans /etc/modules ;
  • la vérification de l'intégrité des systèmes de fichiers ;
  • le montage des partitions locales ;
  • la configuration du réseau ;
  • le montage des systèmes de fichiers distants (NFS).
Après cette phase, init reprend la main et démarre les programmes associés au niveau d'exécution (runlevel) normal, soit par défaut le niveau 2. Il exécute /etc/init.d/rc 2, script qui démarre tous les services donnés du répertoire /etc/rc2.d/ débutant par la lettre « S ». Le nombre (à deux chiffres) qui suit servait historiquement à classer les services pour les démarrer dans le bon ordre, mais de nos jours le système de démarrage par défaut utilise insserv, un système de démarrage où l'ordonnancement se fait en fonction des dépendances entre scripts. Chaque script de démarrage déclare ainsi les contraintes qui s'appliquent à lui (par exemple, s'il doit démarrer avant ou après tel autre service) ; init les lance alors dans un ordre qui satisfait les contraintes. La numérotation statique des scripts n'est donc plus prise en compte (mais ils doivent toujours s'appeler d'un nom composé d'un « S » suivi de deux caractères, suivis à leur tour du véritable nom du script utilisé pour les dépendances). D'une manière générale, les services de base (comme le service de collecte des journaux, rsyslog, ou celui d'attribution des ports, portmap) sont démarrés en premier, suivis par les services standards et l'interface graphique (gdm3).
Ce système de démarrage par dépendances permet d'automatiser des renumérotations qui pourraient s'avérer fastidieuses si elles devaient être faites manuellement et il prévient les erreurs humaines, puisque l'ordonnancement se fait en fonction des contraintes exprimées. Il présente également l'avantage supplémentaire de permettre le démarrage de plusieurs services en parallèle, si plusieurs scripts sont indépendants entre eux, ce qui peut accélérer la séquence de démarrage.
init distingue plusieurs niveaux d'exécution car il peut basculer de l'un à l'autre par la commande telinit nouveau-niveau. Dès son invocation, init exécute à nouveau /etc/init.d/rc avec le nouveau niveau d'exécution désiré, script qui démarre à son tour les services manquants et arrête ceux qui ne sont plus souhaités. Pour cela, il se réfère au contenu du répertoire /etc/rcX.d (où X représente le nouveau niveau d'exécution). Les scripts débutant par « S » (comme Start) sont des services à démarrer, ceux débutant par « K » (comme Kill) sont des services à stopper. Le script évite de redémarrer tout service déjà actif dans le niveau d'exécution précédent.
Dans Debian, le système d'initialisation System V n'utilise par défaut que quatre runlevels différents.
  • Le niveau 0 n'est utilisé que de manière transitoire, lors de la phase d'extinction de l'ordinateur. Il contient donc de nombreux scripts « K ».
  • Le niveau 1, aussi connu sous le nom de single-user, correspond au système en mode dégradé ; il ne contient que les services de base et est prévu pour les opérations de maintenance en dehors de l'interaction des utilisateurs.
  • Le niveau 2 est le niveau de fonctionnement normal, qui inclut les services réseau, l'interface graphique, les connexions des utilisateurs, etc.
  • Le niveau 6 est similaire au niveau 0, à ceci près qu'il est utilisé lors de la phase d'extinction qui précède un redémarrage.
D'autres niveaux existent, notamment de 3 à 5. Ils sont par défaut configurés pour fonctionner de la même manière que le niveau 2, mais l'administrateur peut les modifier (en ajoutant ou supprimant des scripts dans les répertoires /etc/rcX.d/ correspondants) pour les adapter à un besoin particulier.
Étapes du démarrage d'un ordinateur sous Linux avec le système d'initialisation System V

Figure 9.2. Étapes du démarrage d'un ordinateur sous Linux avec le système d'initialisation System V

Tous les scripts contenus dans les différents répertoires /etc/rcX.d ne sont que des liens symboliques, créés à l'installation du paquet concerné par le programme update-rc.d, et menant vers les scripts réels, stockés sous /etc/init.d/. Pour adapter à sa guise les services à démarrer ou à stopper à chaque niveau d'exécution, l'administrateur exécutera à nouveau le programme update-rc.d en lui fournissant les paramètres adéquats. La page de manuel update-rc.d(1) en détaille la syntaxe précise. Signalons au passage que supprimer tous les liens symboliques (avec le paramètre remove) n'est pas la bonne méthode pour désactiver un service. Il faut simplement le configurer pour ne pas démarrer dans les niveaux d'exécution souhaités (tout en conservant les appels correspondants pour l'arrêter au cas où le service tournait dans le niveau d'exécution précédent). L'utilisation d'update-rc.d étant quelque peu alambiquée, on pourra utiliser rcconf (du paquet rcconf) pour se voir présenter une interface plus simple à manipuler.
Enfin, init démarre les programmes de contrôle des différentes consoles virtuelles (getty). Ils affichent une invite, attendent un nom d'utilisateur, puis exécutent login utilisateur pour démarrer une session.