Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

9.6. Créer et modifier des fichiers d'unité systemd

Un fichier d'unité contient des directives de configuration qui décrivent l'unité et définissent son comportement. Plusieurs commandes systemctl fonctionnent avec des fichiers d'unité dans l'arrière-plan. Pour faire des ajustements plus précis, l'administrateur systèmes doit modifier ou créer des fichiers d'unité manuellement. La Tableau 9.2, « Emplacements des fichiers d'unités systemd » répertorie trois répertoires principaux sur lesquels les fichiers d'unités sont stockés sur le système, le répertoire /etc/systemd/system/ est réservé aux fichiers d'unité créés ou personnalisés par l'administrateur systèmes.
Les noms des fichiers d'unité prennent la forme suivante :
unit_name.type_extension
Ici, unit_name correspond au nom de l'unité et type_extension identifie le type de l'unité, veuillez consulter la Tableau 9.1, « Types d'unités systemd disponibles » pour afficher la liste complète des types d'unité. Par exemple, une unité sshd.service et une unité sshd.socket sont habituellement présentes sur votre système.
Les fichiers d'unité peuvent être complétés d'un répertoire pour des fichiers de configuration supplémentaires. Par exemple, pour ajouter des options de configuration personnalisées à sshd.service, veuillez créer le fichier sshd.service.d/custom.conf et insérez-y les directives supplémentaires. Pour obtenir davantage d'informations sur les répertoires de configuration, veuillez consulter la Section 9.6.4, « Modifier les fichiers d'unité existants ».
Les répertoires sshd.service.wants/ et sshd.service.requires/ peuvent également être créés. Ces répertoires contiennent des liens symboliques vers les fichiers d'unités qui sont des dépendances du service sshd. Les liens symboliques sont automatiquement créés pendant l'installation selon les options du fichiers de l'unité [Install] (veuillez consulter la Tableau 9.11, « Options importantes de la section [Install] ») ou pendant le temps d'exécution basé sur les options [Unit] (veuillez consulter la Tableau 9.9, « Options importantes de la section [Unit] »). Il est également possible de créer ces répertoires et les liens symboliques manuellement.
De nombreuses options de fichiers d'unité peuvent être définies en utilisant des spécificateurs d'unités – des chaînes de caractères génériques dynamiquement remplacées par des paramètres d'unités lorsque le fichier d'unité est chargé. Ceci permet la création de fichiers d'unité génériques qui serviront de modèle pour générer des unités instanciées. Veuillez consulter la Section 9.6.5, « Travailler avec des unités instanciées » pour obtenir plus de détails.

9.6.1. Comprendre la structure des fichiers d'unité

Les fichiers d'unité consistent habituellement de trois sections :
  • [Unit] — contient des options génériques qui ne sont pas dépendantes du type de l'unité. Ces options fournissent une description de l'unité, spécifient le comportement de l'unité, et définissent les dépendances avec d'autres unités. Pour une liste des options [Unit] les plus fréquemment utilisées, veuillez consulter la Tableau 9.9, « Options importantes de la section [Unit] ».
  • [unit type] — si une unité possède des directives spécifiques au type, celles-ci seront regroupées dans une section nommée par le type d'unité. Par exemple, les fichiers de l'unité de service contiennent la section [Service], veuillez consulter la Tableau 9.10, « Options importantes de la section [Service] » pour voir les options [Service] les plus fréquemment utilisées.
  • [Install] — contient des informations sur l'installation de l'unité utilisée par les commandes systemctl enable et disable, veuillez consulter la Tableau 9.11, « Options importantes de la section [Install] » pour voir une liste des options [Install].

Tableau 9.9. Options importantes de la section [Unit]

Option[a]Description
DescriptionDescription significative de l'unité. En tant qu'exemple, le texte est affiché dans la sortie de la commande systemctl status.
DocumentationFournit une liste des URI référençant la documentation de l'unité.
After[b]Définit l'ordre dans lequel les unités sont lancées. L'unité est lancée uniquement après l'activation des unités spécifiées dans After. Contrairement à Requires, After n'active pas explicitement les unités spécifiées. L'option Before offre une fonctionnalité contraire à After.
RequiresConfigure les dépendances sur d'autres unités. Les unités répertoriées dans Requires sont activées ensembles avec l'unité. Si le lancement de l'une des unités requises échoue, l'unité n'est pas activée.
WantsConfigure les dépendances plus faibles que Requires. Si l'une des unités répertoriées ne démarre pas, cela n'aura pas d'impact sur l'activation de l'unité. C'est la méthode recommandée pour établir des dépendances d'unité personnalisées.
ConflictsConfigure des dépendances négatives, à l'opposé de Requires.
[a] Pour une liste complète des options configurables dans la section [Unit], veuillez consulter la page man de systemd.unit(5).
[b] Dans la plupart des cas, il est suffisant de ne déterminer que les dépendances d'ordonnancement qu'avec les options de fichier After et Before. Si vous définissez aussi une dépendance avec Wants (conseillé) ou Requires, la dépendance d'ordonnancement devra toujours être spécifiée. C'est parce que l'ordonnancement et les exigences de dépendances fonctionnent indépendamment.

Tableau 9.10. Options importantes de la section [Service]

Option[a]Description
TypeConfigure le type de démarrage de processus d'unité qui affecte la fonctionnalité d'ExecStart et des options connexes. L'une des options suivantes :
  • simple – valeur par défaut. Le processus lancé par ExecStart est le processus principal du service.
  • forking – le processus lancé par ExecStart engendre un processus enfant qui devient le processus principal du service. Le processus parent s'arrête lorsque le startup est terminé.
  • oneshot – ce type est similaire à simple, mais le processus s'arrête avant de lancer les unités suivantes.
  • dbus – ce type est similaire à simple, mais les unités suivantes sont lancées uniquement après que le processus principal ait obtenu un nom D-Bus.
  • notify – ce type est similaire à simple, mais les unités suivante sont lancées uniquement après l'envoi d'un message de notification via la fonction sd_notify().
  • idle – similaire à simple, l'exécution du binaire du service est retardée jusqu'à ce que toutes les tâches soient terminées, ce qui permet d'éviter de mélanger la sortie du statut avec la sortie shell des services.
ExecStartSpécifie les commandes ou scripts à exécuter lorsque l'unité est lancée. ExecStartPre et ExecStartPost spécifient des commandes personnalisées à exécuter avant et après ExecStart. Type=oneshot permet de spécifier des commandes multiples personnalisées exécutées de manière séquentielle par la suite.
ExecStopSpécifie les commandes ou scripts à exécuter lorsque l'unité est arrêtée.
ExecReloadSpécifie les commandes ou scripts à exécuter lorsque l'unité est rechargée.
RestartAvec cette option activée, le service est redémarré après que son processus se soit arrêté, à l'exception d'un arrêt gracieux avec la commande systemctl.
RemainAfterExitSi défini sur True, le service est considéré comme actif, même lorsque tous ses processus sont arrêtés. La valeur par défaut est False. Cette option est particulièrement utile si Type=oneshot est configuré.
[a] Pour une liste complète des options configurables dans la section [Service], veuillez consulter la page man de systemd.service(5).

Tableau 9.11. Options importantes de la section [Install]

Option[a]Description
AliasFournit une liste de noms supplémentaires de l'unité séparés par des espaces. La plupart des commandes systemctl, sauf systemctl enable, peuvent utiliser des alias à la place du nom de l'unité.
RequiredByUne liste des unités qui dépendent de l'unité. Lorsque cette unité est activée, les unités répertoriées dans RequiredBy obtiennent une dépendance Require de l'unité.
WantedByUne liste des unités qui dépendent faiblement de l'unité. Lorsque cette unité est activée, les unités répertoriées dans WantedBy obtiennent une dépendance Want de l'unité.
AlsoIndique une liste des unités à installer ou désinstaller avec l'unité.
DefaultInstanceLimitée aux unités instanciées, cette option indique l'instance par défaut pour laquelle l'unité est activée. Veuillez consulter la Section 9.6.5, « Travailler avec des unités instanciées »
[a] Pour voir une liste complète des options configurables dans la section [Install], veuillez consulter la page man de systemd.unit(5).
Une gamme entière d'options qui peuvent être utilisées pour régler de manière détaillée la configuration de l'unité, l'Exemple 9.17, « Fichier d'unité postfix.service » montre un exemple d'unité de service installée sur le système. En outre, les options de fichier d'unité peuvent être définies d'une manière permettant la création dynamique d'unités, comme décrit dans la Section 9.6.5, « Travailler avec des unités instanciées ».

Exemple 9.17. Fichier d'unité postfix.service

Ci-dessous figure le contenu du fichier de l'unité /usr/lib/systemd/system/postifix.service tel qu'il est fourni par le paquet postfix :
[Unit]
Description=Postfix Mail Transport Agent
After=syslog.target network.target
Conflicts=sendmail.service exim.service

[Service]
Type=forking
PIDFile=/var/spool/postfix/pid/master.pid
EnvironmentFile=-/etc/sysconfig/network
ExecStartPre=-/usr/libexec/postfix/aliasesdb
ExecStartPre=-/usr/libexec/postfix/chroot-update
ExecStart=/usr/sbin/postfix start
ExecReload=/usr/sbin/postfix reload
ExecStop=/usr/sbin/postfix stop

[Install]
WantedBy=multi-user.target
La section [Unit] décrit le service, spécifie les dépendances d'ordre, ainsi que les unités contradictoires. Dans [Service], une séquence de scripts personnalisés est spécifiée pour être exécutée pendant l'activation de l'unité, pendant l'arrêt, et le rechargement. EnvironmentFile désigne l'emplacement où les variables d'environnement du service sont définies, PIDFile spécifie un PID stable pour le processus principale du service. Finalement, la section [Install] répertorie les unités qui dépendent de ce service.

9.6.2. Créer des fichiers d'unité personnalisés

Il existe plusieurs cas dans lesquels il est nécessaire de créer des fichiers d'unité depuis le début : vous pourriez devoir exécuter un démon personnalisé, créer une seconde instance d'un service existant (comme dans l'Exemple 9.19, « Création d'une seconde instance du service sshd »), ou importer un script init SysV (consultez la Section 9.6.3, « Convertir des scripts init SysV en fichiers d'unité »). En revanche, si vous souhaitez simplement modifier ou étendre le comportement d'une unité existante, veuillez utiliser les instructions de la Section 9.6.4, « Modifier les fichiers d'unité existants ». La procédure suivante décrit le processus général de création d'un service personnalisé :
  1. Préparez le fichier exécutable avec le service personnalisé. Il peut s'agir d'un script créé et personnalisé, ou d'un exécutable remis par un fournisseur de logiciels. Si requis, veuillez préparer un fichier PID pour contenir un PID constant pour le processus principal du service personnalisé. Il est également possible d'inclure des fichiers d'environnement pour stocker des variables shell pour le service. Assurez-vous que le script source soit exécutable (en exécutant chmod a+x) et qu'il ne soit pas interactif.
  2. Créez un fichier d'unité dans le répertoire /etc/systemd/system/ et assurez-vous qu'il possède les permissions de fichier correctes. Veuillez exécuter en tant qu'utilisateur root :
    touch /etc/systemd/system/name.service
    chmod 664 /etc/systemd/system/name.service
    Remplacez name par le nom du service à créer. Remarquez que le fichier n'a pas besoin d'être exécutable.
  3. Ouvrez le fichier name.service créé dans l'étape précédente, et ajoutez les options de configuration du service. Une variété d'options peut être utilisée selon le type de service que vous souhaitez créer, consulter Section 9.6.1, « Comprendre la structure des fichiers d'unité ». Voici un exemple de configuration d'unité pour un service concernant le réseau :
    [Unit]
    Description=service_description
    After=network.target
    
    [Service]
    ExecStart=path_to_executable
    Type=forking
    PIDFile=path_to_pidfile
    
    [Install]
    WantedBy=default.target
    Quand :
    • service_description est une description informative affichée dans les fichiers journaux et dans la sortie de la commande systemctl status.
    • le paramètre After permet de s'assurer que le service est démarré uniquement après l'exécution du réseau. Ajoutez une liste séparée par des espaces d'autres services ou cibles connexes.
    • path_to_executable correspond au chemin vers l'exécutable du service.
    • Type=forking est utilisé pour les démons effectuant l'appel système « fork ». Le processus principal du service est créé avec le PID spécifié dans path_to_pidfile. D'autres types de démarrage se trouvent dans la Tableau 9.10, « Options importantes de la section [Service] ».
    • WantedBy fait état de la cible ou des cibles sous laquelle ou sous lesquelles le service devrait être lancé. Ces cibles peuvent être vues comme remplaçant l'ancien concept des niveaux d'exécution, veuillez consulter la Section 9.3, « Travailler avec des cibles Systemd » pour obtenir des détails supplémentaires.
  4. Notifier systemd qu'un nouveau fichier name.service existe en exécutant la commande suivante en tant qu'utilisateur root :
    systemctl daemon-reload
    systemctl start name.service

    Avertissement

    Exécutez la commande systemctl daemon-reload à chaque fois que vous créez des nouveaux fichiers d'unités ou lorsque vous modifiez des fichiers d'unités existants. Sinon, les commandes systemctl start ou systemctl enable peuvent échouer à cause d'une mauvaise correspondance entre les états de systemd et les fichiers d'unités de service qui se trouvent sur le disque.
    L'unité name.service peut désormais être gérée comme tout autre service système par des commandes décrites dans la Section 9.2, « Gérer les services système ».

Exemple 9.18. Créer le fichier emacs.service

Lors de l'utilisation de l'éditeur de texte Emacs, il est souvent plus rapide et plus pratique de le laisser exécuter en arrière-plan plutôt que de lancer une nouvelle instance du programme à chaque fois qu'un fichier doit être modifié. Les étapes suivantes montrent comment créer un fichier d'unité pour Emacs afin qu'il puisse être géré en tant que service.
  1. Créez un fichier d'unité dans le répertoire /etc/systemd/system/ et assurez-vous qu'il possède les permissions de fichier correctes. Veuillez exécuter en tant qu'utilisateur root :
    ~]# touch /etc/systemd/system/emacs.service
    ~]# chmod 664 /etc/systemd/system/emacs.service
  2. Ajouter le contenu suivant au fichier de configuration :
    [Unit]
    Description=Emacs: the extensible, self-documenting text editor
               
    [Service]
    Type=forking
    ExecStart=/usr/bin/emacs --daemon
    ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
    Environment=SSH_AUTH_SOCK=%t/keyring/ssh
    Restart=always
               
    [Install]
    WantedBy=default.target
    Avec la configuration ci-dessus, l'exécutable /usr/bin/emacs est lancé en mode démon pendant le démarrage du service. La variable d'environnement SSH_AUTH_SOCK est paramétrée en utilisant le spécificateur d'unité « %t » qui correspond au répertoire du runtime. Le service redémarre également le processus Emacs s'il s'arrête de manière inattendue.
  3. Veuillez exécuter les commandes suivantes pour recharger la configuration et lancer le service personnalisé :
    ~]# systemctl daemon-reload
    ~]# systemctl start emacs.service
Comme l'éditeur est désormais enregistré en tant que service systemd, vous pouvez utiliser toutes les commandes systemctl standard. Ainsi, exécutez systemctl status emacs pour afficher le statut de l'éditeur ou systemctl enable emacs pour le lancer automatiquement pendant le démarrage système.

Exemple 9.19. Création d'une seconde instance du service sshd

Les administrateurs système ont souvent besoin de configurer et d'exécuter de multiples instances d'un service. Ceci est effectué en créant des copies des fichiers de configuration du service d'origine et en modifiant certains paramètres pour éviter les conflits avec l'instance principale du service. La procédure suivante montre comment créer une seconde instance du service sshd :
  1. Veuillez créer une copie du fichier sshd_config qui sera utilisée par le second démon :
    ~]# cp /etc/ssh/sshd{,-second}_config
  2. Veuillez modifier le fichier sshd-second_config créé dans l'étape précédente pour assigner un numéro de port différent et un fichier PID au second démon :
    Port 22220
    PidFile /var/run/sshd-second.pid
    Veuillez consulter la page man de sshd_config(5) pour obtenir plus d'informations sur les options Port et PidFile. Assurez-vous que le port choisi n'est pas en cours d'utilisation par un autre service. Le fichier PID ne doit pas forcément exister avant l'exécution du service, il est généré automatiquement lors du démarrage du service.
  3. Veuillez créer une copie du fichier d'unité systemd pour le service sshd.
    ~]# cp /usr/lib/systemd/system/sshd.service /etc/systemd/system/sshd-second.service
  4. Veuillez altérer le fichier sshd-second.service créé pendant l'étape précédente comme suit:
    1. Modifiez l'option Description :
      Description=OpenSSH server second instance daemon
    2. Veuillez ajouter sshd.service aux services spécifiés dans l'option After, afin que la seconde instance soit lancée uniquement après le lancement de la première :
      After=syslog.target network.target auditd.service sshd.service
    3. La première instance de sshd inclut la génération de clés, veuillez donc supprimer la ligne ExecStartPre=/usr/sbin/sshd-keygen.
    4. Ajoutez le paramètre -f /etc/ssh/sshd-second_config à la commande sshd afin que le fichier de configuration alternatif soit utilisé :
      ExecStart=/usr/sbin/sshd -D -f /etc/ssh/sshd-second_config $OPTIONS
    5. Après les modifications indiquées ci-dessus, le fichier sshd-second.service devrait ressembler à ce qui suit :
      [Unit]
      Description=OpenSSH server second instance daemon
      After=syslog.target network.target auditd.service sshd.service
      
      [Service]
      EnvironmentFile=/etc/sysconfig/sshd
      ExecStart=/usr/sbin/sshd -D -f /etc/ssh/sshd-second_config $OPTIONS
      ExecReload=/bin/kill -HUP $MAINPID
      KillMode=process
      Restart=on-failure
      RestartSec=42s
      
      [Install]
      WantedBy=multi-user.target
  5. Si vous utilisez SELinux, veuillez ajouter le port pour la seconde instance de sshd sur les ports SSH, sinon la seconde instance de sshd sera rejetée pour lier le port :
    ~]# semanage port -a -t ssh_port_t -p tcp 22220
  6. Veuillez activer sshd-second.service, afin qu'il soit lancé automatiquement pendant le démarrage :
    ~]# systemctl enable sshd-second.service
    Vérifiez si sshd-second.service est en cours d'utilisation par la commande systemctl status. Veuillez également vérifier si le port est activé correctement en effectuant une connexion au service :
    ~]$ ssh -p 22220 user@server
    Si le pare-feu est en cours d'utilisation, veuillez vous assurer qu'il soit correctement configuré de manière à permettre des connexions à la seconde instance de sshd.

9.6.3. Convertir des scripts init SysV en fichiers d'unité

Avant de prendre le temps de convertir un script init SysV en fichier d'unité, assurez-vous que la conversion n'a pas déjà été effectuée ailleurs. Tous les services de base installés sur Red Hat Enterprise Linux 7 sont offerts avec des fichiers d'unité par défaut, et la même chose s'applique à de nombreux paquets logiciels de tierce partie.
Convertir un script init en fichier d'unité requiert d'analyser le script et d'en extraire les informations nécessaires. En se basant sur ces données, il est possible de créer un fichier d'unité comme décrit dans la Section 9.6.2, « Créer des fichiers d'unité personnalisés ». Comme les scripts init peuvent largement varier en fonction du type de service, vous pourriez devoir employer davantage d'options de configuration pour la traduction que ce qui est indiqué dans ce chapitre. Veuillez remarquer que certains niveaux de personnalisation qui étaient disponibles avec les scripts init ne sont plus pris en charge par les unités systemd, veuillez consulter la Section 9.1.2, « Changements de compatibilité ».
La majorité des informations nécessaires à une conversion est fournie dans l'en-tête du script. L'exemple suivant montre la section au début du script init utilisée pour lancer le service postfix sur Red Hat Enterprise Linux 6 :
#!/bin/bash
#
# postfix      Postfix Mail Transfer Agent
#
# chkconfig: 2345 80 30
# description: Postfix is a Mail Transport Agent, which is the program \
#              that moves mail from one machine to another.
# processname: master
# pidfile: /var/spool/postfix/pid/master.pid
# config: /etc/postfix/main.cf
# config: /etc/postfix/master.cf

### BEGIN INIT INFO
# Provides: postfix MTA
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start and stop postfix
# Description: Postfix is a Mail Transport Agent, which is the program that 
#              moves mail from one machine to another.
### END INIT INFO
Dans l'exemple ci-dessus, seules les lignes commençant par # chkconfig et # description sont obligatoires, donc vous risquez de ne pas trouver le reste dans des fichiers init différents. Le texte situé entre les lignes ### BEGIN INIT INFO et ### END INIT INFO est appelé un en-tête LSB (« Linux Standard Base »). Si spécifiés, les en-têtes LSB contiennent des directives définissant la description du service, les dépendances, et les niveaux d'exécution. Ce qui suit est un ensemble de tâches analytiques visant à collecter les données nécessaires à un nouveau fichier d'unité. Le script init postfix est utilisé comme exemple. Veuillez consulter le fichier d'unité postfix résultant dans l'Exemple 9.17, « Fichier d'unité postfix.service ».

Trouver la description du service

Vous trouverez des informations descriptives concernant le script sur la ligne commençant par #description. Veuillez utiliser cette description avec le nom du service dans l'option Description de la section [Unit] du fichier d'unité. L'en-tête LSB peut contenir des données similaires sur les lignes #Short-Description et #Description.

Trouver les dépendances de service

L'en-tête LSB peut contenir plusieurs directives qui forment des dépendances entre services. La plupart d'entres elles peuvent être traduites en options d'unité systemd, veuillez consulter la Tableau 9.12, « Options de dépendances d'en-tête LSB »

Tableau 9.12. Options de dépendances d'en-tête LSB

Option LSBDescriptionÉquivalent de fichier d'unité
ProvidesSpécifie le nom de l'installation de démarrage du service, à qui il peut être fait référence dans d'autres scripts init (avec le préfixe « $ »). Ceci n'est plus nécessaire car les fichiers d'unité font référence aux autres unités par leur nom de fichier.
Required-StartContient les noms des installations de démarrage des services requis. Ceci se traduit par une dépendance d'ordre, les noms d'installations de démarrage sont remplacés par les noms des fichiers d'unité des services correspondants ou les cibles auxquelles ils appartiennent. Par exemple, dans le cas de postfix, la dépendance « Required-Start » sur « $network » a été traduite sur la dépendance « After » sur « network.target ».After, Before
Should-StartConstitue des dépendances plus faibles que Required-Start. Les dépendances Should-Start échouées n'affecteront pas le démarrage du service.After, Before
Required-Stop, Should-StopConstitue des dépendances négatives.Conflicts

Trouver les cibles par défaut du service

La ligne commençant par #chkconfig contient trois valeurs numériques. La plus importante est le premier numéro qui représente les niveaux d'exécution par défaut dans lesquels le service est lancé. Veuillez utiliser la Tableau 9.6, « Comparaison des niveaux d'exécution SysV avec les cibles Systemd » pour faire correspondre ces niveaux d'exécution à leurs cibles systemd équivalentes. Puis, répertoriez ces cibles dans l'option WantedBy de la section [Install] du fichier d'unité. Par exemple, postfix avait auparavant été lancé dans les niveaux d'exécution 2, 3, 4, et 5, qui se traduisent par multi-user.target et graphical.target dans Red Hat Enterprise Linux 7. Veuillez remarquer que graphical.target dépend de multiuser.target, donc il n'est pas nécessaire de spécifier les deux, comme dans l'Exemple 9.17, « Fichier d'unité postfix.service ». Vous trouverez également des informations sur les niveaux d'exécution par défaut et interdits dans les lignes #Default-Start et #Default-Stop de l'en-tête LSB.
Les deux autres valeurs spécifiées sur la ligne #chkconfig représentent les priorités de démarrage et de fermeture du script init. Ces valeurs sont interprétées par systemd si le script init est chargé, mais il n'y a pas de fichier d'unité équivalent.

Trouver les fichiers utilisés par le service

Les scripts init requièrent le chargement d'une bibliothèque de fonction à partir d'un répertoire dédié et autorisent l'importation de configurations, d'environments, et de fichiers PID. Les variables d'environnement sont spécifiées sur la ligne commençant par #config dans l'en-tête du script init, qui se traduit par l'option du fichier d'unité EnvironmentFile. Le fichier PID spécifié sur la ligne du script init #pidfile est importé sur le fichier d'unité avec l'option PIDFile.
L'information-clé qui n'est pas incluse dans l'en-tête du script init est le chemin vers l'exécutable du service, et d'autres fichiers potentiellement requis par le service. Dans des versions précédentes de Red Hat Enterprise Linux, les scripts init utilisaient une déclaration de cas Bash pour définir le sur les actions par défaut, comme start, stop, ou restart, ainsi que des actions définies de manière personnalisées. L'extrait suivant du script init postfix affiche le bloc de code à exécuter lors du lancement du service.
conf_check() {
    [ -x /usr/sbin/postfix ] || exit 5
    [ -d /etc/postfix ] || exit 6
    [ -d /var/spool/postfix ] || exit 5
}

make_aliasesdb() {
	if [ "$(/usr/sbin/postconf -h alias_database)" == "hash:/etc/aliases" ]
	then
		# /etc/aliases.db might be used by other MTA, make sure nothing
		# has touched it since our last newaliases call
		[ /etc/aliases -nt /etc/aliases.db ] ||
			[ "$ALIASESDB_STAMP" -nt /etc/aliases.db ] ||
			[ "$ALIASESDB_STAMP" -ot /etc/aliases.db ] || return
		/usr/bin/newaliases
		touch -r /etc/aliases.db "$ALIASESDB_STAMP"
	else
		/usr/bin/newaliases
	fi
}

start() {
	[ "$EUID" != "0" ] && exit 4
	# Check that networking is up.
	[ ${NETWORKING} = "no" ] && exit 1
	conf_check
	# Start daemons.
	echo -n $"Starting postfix: "
	make_aliasesdb >/dev/null 2>&1
	[ -x $CHROOT_UPDATE ] && $CHROOT_UPDATE
	/usr/sbin/postfix start 2>/dev/null 1>&2 && success || failure $"$prog start"
	RETVAL=$?
	[ $RETVAL -eq 0 ] && touch $lockfile
        echo
	return $RETVAL
}
L'extensibilité du script initi autorise la spécification de deux fonctions personnalisées, conf_check() et make_aliasesdb(), qui sont appelées à partir du bloc de la fonction start(). En examinant cela de plus près, plusieurs fichiers externes et plusieurs répertoires sont mentionnés dans le code ci-dessus : l'exécutable du service principal, /usr/sbin/postfix, les répertoires de configuration/etc/postfix/ et /var/spool/postfix/, ainsi que le répertoire /usr/sbin/postconf/.
Systemd prend uniquement en charge les actions prédéfinies, mais permet l'exécution d'exécutables personnalisés avec les options ExecStart, ExecStartPre, ExecStartPost, ExecStop, et ExecReload. Dans le cas de postfix dans Red Hat Enterprise Linux 7, /usr/sbin/postfix accompagné de scripts pris en charge sont exécutés pendant le lancement du service. Veuillez consulter le fichier d'unité postfix dans l'Exemple 9.17, « Fichier d'unité postfix.service ».
Convertir des scripts init complexes requiert une bonne compréhension du but de chaque déclaration présente dans le script. Certaines déclarations sont spécifiques à la version du système d'exploitation, vous ne devrez donc pas forcément les traduire. D'autre part, certains ajustements peuvent être nécessaire dans le nouvel environnement, dans le fichier d'unité, ainsi que dans l'exécutable du service et les fichiers de support.

9.6.4. Modifier les fichiers d'unité existants

Les services installés sur le système sont fournis avec des fichiers d'unité par défaut qui sont stockés dans le répertoire /usr/lib/systemd/system/. Les administrateurs systèmes ne doivent pas modifier ces fichiers directement, ainsi toute personnalisation doit être confinée aux fichiers de configuration dans le répertoire /etc/systemd/system/. Veuillez choisir l'une des approches suivantes, en fonction de l'étendue des changements requis :
  • Veuillez créer un répertoire pour les fichiers de configuration supplémentaires dans /etc/systemd/system/unit.d/. Cette méthode est recommandée pour la plupart des cas d'utilisation. Elle permet d'étendre la configuration par défaut avec des fonctionnalités supplémentaires, tout en continuant à faire référence au fichier d'unité d'origine. Les changements apportés à l'unité par défaut qui ont eu lieu lors d'une mise à niveau de paquet(s) sont ainsi appliqués automatiquement. Veuillez consulter la section intitulée « Étendre la configuration de l'unité par défaut » pour obtenir davantage d'informations.
  • Veuillez créer une copie du fichier d'unité d'origine /usr/lib/systemd/system/ dans /etc/systemd/system/ et effectuez-y les changements souhaités. La copie remplace le fichier d'origine, donc les changement introduits par la mise à jour du paquet ne sont pas appliqués. Cette méthode est utile pour effectuer des changements significatifs qui devront être persistants, quelles que soient les mises à jour de paquets se produisant. Veuillez consulter la section intitulée « Remplacer la configuration de l'unité par défaut » pour obtenir des détails.
Pour retourner à la configuration par défaut de l'unité, veuillez supprimer les fichiers de configuration créés de manière personnalisée dans /etc/systemd/system/. Pour appliquer les changements aux fichiers d'unité sans redémarrer le système, veuillez exécuter :
systemctl daemon-reload
L'option daemon-reload recharge tous les fichiers d'unité et recrée la totalité de l'arbre de dépendances, ce qui est nécessaire pour appliquer immédiatement tout changement sur un fichier d'unité. Alternativement, le même résultat peut être atteint à l'aide de la commande suivante :
init q
Si le fichier d'unité modifié appartient à un service en cours d'exécution, ce service doit être redémarré pour accepter les nouveaux paramètres :
systemctl restart name.service

Étendre la configuration de l'unité par défaut

Pour étendre le fichier d'unité par défaut avec des options de configuration supplémentaires, veuillez commencer par créer un répertoire de configuration dans /etc/systemd/system/. Si vous étendez une unité de service, veuillez exécuter la commande suivante en tant qu'utilisateur root :
mkdir /etc/systemd/system/name.service.d/
Veuillez remplacer name par le nom du service que vous souhaitez étendre. La syntaxe ci-dessus s'applique à tous les types d'unité.
Créez un fichier de configuration dans le répertoire créé lors de l'étape précédente. Remarquez que le nom du fichier doit se terminer par le suffixe .conf. Veuillez saisir :
touch /etc/systemd/system/name.service.d/config_name.conf
Remplacez config_name par le nom du fichier de configuration. Ce fichier adhère à la structure normale du fichier d'unité, ainsi toutes les directives doivent être spécifiées sous les sections correspondantes. Veuillez consulter la Section 9.6.1, « Comprendre la structure des fichiers d'unité ».
Par exemple, pour ajouter une dépendance personnalisée, veuillez créer un fichier de configuration avec le contenu suivant :
[Unit]
Requires=new_dependency
After=new_dependency
new_dependency correspond à l'unité devant être marquée comme une dépendance. Un autre exemple consiste en un fichier de configuration qui redémarre après que son processus principal se soit arrêté, avec un délai de 30 secondes :
[Service]
Restart=always
RestartSec=30
Il est recommandé de créer des fichiers de configuration de petite taille se concentrant sur une seule tâche. De tels fichiers peuvent facilement être déplacés ou liés aux répertoires de configuration d'autres services.
Pour appliquer les changements effectués sur l'unité veuillez exécuter la commande suivante en tant que root :
systemctl daemon-reload
systemctl restart name.service

Exemple 9.20. Étendre la configuration httpd.service

Pour modifier l'unité httpd.service de manière à ce qu'un script shell personnalisé soit automatiquement exécuté lors du lancement du service Apache, veuillez effectuer les étapes suivantes. Pour commencer, veuillez créer un répertoire et un fichier de configuration :
~]# mkdir /etc/systemd/system/httpd.service.d/
~]# touch /etc/systemd/system/httpd.service.d/custom_script.conf
En supposant que le script que vous souhaitez lancer automatiquement avec Apache se situe dans /usr/local/bin/custom.sh, veuillez insérer le texte suivant dans le fichier custom_script.conf :
[Service]
ExecStartPost=/usr/local/bin/custom.sh
Pour appliquer les changements d'unité, veuillez exécuter :
~]# systemctl daemon-reload
~]# systemctl restart httpd.service

Note

Les fichiers de configuration des répertoires de configuration dans /etc/systemd/system/ ont priorité sur les fichiers d'unité dans /usr/lib/systemd/system/. Ainsi, si les fichiers de configuration contiennent une option qui peut être spécifiée une seule fois, comme Description ou ExecStart, la valeur par défaut de cette option sera remplacée. Remarquez que dans la sortie de la commande systemd-delta décrite dans la section intitulée « Surveiller les unités remplacées », de telles unités sont toujours marquées comme [EXTENDED], même si au total, certaines options sont remplacées.

Remplacer la configuration de l'unité par défaut

Pour effectuer des changements qui persisteront après la mise à jour du paquet fournissant le fichier d'unité, veuillez copier le ficher dans le répertoire /etc/systemd/system/. Pour cela, veuillez exécuter la commande suivante en tant qu'utilisateur root :
cp /usr/lib/systemd/system/name.service /etc/systemd/system/name.service
Quand name correspond au nom de l'unité du service que vous souhaitez modifier, la syntaxe ci-dessus s'applique à tous les types d'unité.
Ouvrez le fichier copié avec un éditeur de texte, et effectuez les changements souhaités. Pour appliquer les changements d'unité, veuillez exécuter ceci en tant qu'utilisateur root :
systemctl daemon-reload
systemctl restart name.service

Exemple 9.21. Modifier la limite du délai d'attente

Vous pouvez spécifier une valeur de délai d’attente par service pour empêcher un service défectueux de geler le système. Vous pouvez modifier le délai d'attente par défaut à 90 secondes pour les services normaux et à 300 secondes pour les services compatibles SysV. Pour prolonger cette limite, vous pouvez modifier le delai d'expiration par défaut en créant le fichier d'unité systemd /etc/systemd/system/network.service.d/timeout.conf et ajouter une ligne à la nouvelle configuration à ce endroit. La commande systemctl show network -p TimeoutStartUSec affichera le délai d’attente actuel maximum. Après avoir changé la limite à 10 secondes, comme dans l’exemple ci-dessous, pensez à redémarrer systemd avec systemctl daemon-reload pour que les modifications puissent entrer en vigueur :
~]# systemctl show network -p TimeoutStartUSec
TimeoutStartUSec=5min
~]# mkdir /etc/systemd/system/network.service.d/
~]# echo -e '[Service]\nTimeoutStartSec=10' > /etc/systemd/system/network.service.d/timeout.conf
~]# systemctl daemon-reload
~]# systemctl show network -p TimeoutStartUSec
TimeoutStartUSec=10s

Surveiller les unités remplacées

Pour afficher une vue d'ensemble des fichiers d'unité remplacés ou modifés, veuillez utiliser la commande suivante :
systemd-delta
Par exemple, la sortie de la commande ci-dessus pourrait ressembler à ce qui suit :
[EQUIVALENT] /etc/systemd/system/default.target → /usr/lib/systemd/system/default.target
[OVERRIDDEN] /etc/systemd/system/autofs.service → /usr/lib/systemd/system/autofs.service

--- /usr/lib/systemd/system/autofs.service      2014-10-16 21:30:39.000000000 -0400
+++ /etc/systemd/system/autofs.service  2014-11-21 10:00:58.513568275 -0500
@@ -8,7 +8,8 @@
 EnvironmentFile=-/etc/sysconfig/autofs
 ExecStart=/usr/sbin/automount $OPTIONS --pid-file /run/autofs.pid
 ExecReload=/usr/bin/kill -HUP $MAINPID
-TimeoutSec=180
+TimeoutSec=240
+Restart=Always
 
 [Install]
 WantedBy=multi-user.target

[MASKED]     /etc/systemd/system/cups.service → /usr/lib/systemd/system/cups.service
[EXTENDED]   /usr/lib/systemd/system/sssd.service → /etc/systemd/system/sssd.service.d/journal.conf

4 overridden configuration files found.
La Tableau 9.13, « Types de différence systemd-delta » répertorie les types de remplacements qui peuvent apparaître dans la sortie de systemd-delta. Remarquez que si un fichier est remplacé, systemd-delta affiche par défaut un sommaire des changements similaires à la sortie de la commande diff.

Tableau 9.13. Types de différence systemd-delta

TypeDescription
[MASKED]
Fichiers d'unités masqués, veuillez consulter la Section 9.2.7, « Désactiver un service » pour une description du masquage d'unité.
[EQUIVALENT]
Copies non modifiées qui remplacent les fichiers d'origine mais dont le contenu, typiquement les liens symboliques, ne diffère pas.
[REDIRECTED]
Fichiers redirigés vers d'autres fichiers.
[OVERRIDEN]
Fichiers remplacés et modifiés.
[EXTENDED]
Fichiers étendus avec les fichiers .conf dans le répertoire /etc/systemd/system/unit.d/.
[UNCHANGED]
Fichiers non modifiés, uniquement affichés lorsque l'option --type=unchanged est utilisée.
L'exécution de systemd-delta après une mise à jour système pour vérifier si des mises à jour d'unités par défaut sont actuellement remplacées par une configuration personnalisée. Il est également possible de limiter la sortie à un certain type de différence uniquement. Par exemple, pour uniquement afficher les unités remplacées, veuillez exécuter :
systemd-delta --type=overridden

9.6.5. Travailler avec des unités instanciées

Il est possible d'instancier plusieurs unités à partir d'un seul fichier de configuration modèle pendant le runtime. Le caractère « @ » est utilisé pour marquer le modèle et pour y associer des unités. Les unités instanciées peuvent être lancées à partir d'un autre fichier d'unité (à l'aide des options Requires ou Wants), ou par la commande systemctl start. Les unités de service instanciées sont nommées comme suit.
template_name@instance_name.service
Quand template_name correspond au nom du fichier de configuration. Veuillez remplacer instance_name par le nom de l'instance de l'unité. Plusieurs instances peuvent pointer vers le même fichier modèle avec des options de configuration communes pour toutes les instances de l'unité. Le nom de l'unité modèle est sous le format suivant :
unit_name@.service
Par exemple, le paramètre Wants suivant dans un fichier d'unité :
Wants=getty@ttyA.service,getty@ttyB.service
cela lance avant tout une recherche systemd des unités de service données. Si de telles unités sont introuvables, la partie entre le caractère « @ » et le suffixe du type sera ignorée et systemd recherchera le fichier getty@.service, lira la configuration à partir de celui-ci, et lancera les services.
Les caractères génériques, aussi appelés des spécificateurs d'unité, peuvent être utilisés dans tout fichier de configuration. Les spécificateurs d'unité substituent certains paramètres d'unité et sont interprétés pendant le runtime. La Tableau 9.14, « Spécificateurs d'unités importantes » répertorie des spécificateurs d'unité qui sont particulièrement utiles pour les unités modèles.

Tableau 9.14. Spécificateurs d'unités importantes

Spécificateur d'unitéSignificationDescription
%nNom d'unité completCorrespond au nom d'unité complet, y compris le suffixe du type. %N possède la même signification mais remplace également les caractères interdits avec les codes ASCII.
%pNom du préfixeCorrespond à un nom d'unité avec le suffixe de type supprimé. Pour les unités instanciées, %p correspond à la partie du nom de l'unité avant le caractère « @ ».
%iNom d'instanceIl s'agit de la partie du nom d'unité instanciée entre le caractère « @ » et le suffixe du type. %I possède la même signification mais remplace également les caractères interdits par des codes ASCII.
%HNom d'hôteCorrespond au nom d'hôte du système en cours d'exécution au moment où la configuration de l'unité est chargée.
%tRépertoire du runtimeReprésente le répertoire du runtime, qui est /run pour l'utilisateur root, ou la valeur de la variable XDG_RUNTIME_DIR pour les utilisateur non-privilégiés.
Pour une liste complète des spécificateurs d'unité, veuillez consulter la page man de systemd.unit(5).
Par exemple, le modèle getty@.service contient les directives suivante :
[Unit]
Description=Getty on %I
...
[Service]
ExecStart=-/sbin/agetty --noclear %I $TERM
...
Lorsque getty@ttyA.service et getty@ttyB.service sont instanciés à partir du modèle ci-dessus, Description= est résolu en tant que Getty on ttyA et Getty on ttyB.