Table des matières

, ,

Créer un nouveau service avec systemd

Ce tutoriel décrit la démarche à suivre pour transformer un programme en un service systemd pouvant être lancé automatiquement au démarrage du système.

Pré-requis

Principes de base

Comme Upstart, systemd utilise des fichiers de configuration correspondant aux différents services à manipuler. Il n'est (en général) plus nécessaire de créer des fichiers bash pour gérer le service, systemd s'occupe de tout (lancement, arrêt, redémarrage, status, gestion des logs, etc)
Ces fichiers de configuration se trouvent dans /etc/systemd/system/ et permettent d'indiquer les conditions d'activation ou désactivation d'un service, leur propriétaire, etc.

Ce dossier étant essentiel au bon fonctionnement de votre système, il est conseillé d'en faire une sauvegarde avant toute modification de fichier.
Dans un terminal saisissez:
sudo cp -r /etc/systemd/system /etc/systemd/system.save$(date +%Y%m%d)

Une fois le fichier de configuration de service créé, il faut l'activer pour qu'il soit pris en compte par le système et lancé à chaque démarrage.

systemctl enable <nom du service>.service

On peut ensuite le lancer pour test et contrôler sa bonne marche avec les commandes suivantes :

systemctl start <nom du service>.service
systemctl status <nom du service>.service

Pour plus d'infos sur les diverses commandes de gestion, voir la page systemd

Il est possible d'utiliser un service au niveau utilisateur, dans ce cas, les fichiers de configuration se trouvent dans ~/.config/systemd/user/

Pour un service utilisateur il faut ajouter aux commandes le paramètre –user :

systemctl --user enable <nom du service>.service
systemctl --user start <nom du service>.service
systemctl --user status <nom du service>.service

Pour créer un service utilisateur :

systemctl --user edit <nom du service>.service --full --force

Pour éditer un service utilisateur :

systemctl --user edit <nom du service>.service --full

Pour ajouter une surcharge (drop-in) sur un service utilisateur :

systemctl --user edit <nom du service>.service
Attention : pour un service user, il faut remplacer WantedBy=multi-user.target par WantedBy=default.target.

Type de services systemd

Systemd définit différents types de services :

Exemples de services et leur fichier de configuration

Exemples de service de type "oneshot"

Un exemple est le service iptables. Voici un extrait de son fichier de configuration :

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/iptables.init start
ExecStop=/usr/libexec/iptables.init stop


Exemple de service de type "simple"

Un exemple est le service deluged qui permet de lancer le service correspondant à la version daemon du client bit-torrent deluge.

/etc/systemd/system/deluged.service
[Unit]
Description=Deluge Bittorrent Client Daemon
After=network-online.target
 
[Service]
Type=simple
 
User=deluge
Group=deluge
UMask=007
 
ExecStart=/usr/bin/deluged -d
 
Restart=on-failure
 
# Configures the time to wait before service is stopped forcefully.
TimeoutStopSec=300
 
[Install]
WantedBy=multi-user.target

Exemple de service modèle

Il est possible de créer plusieurs services à partir d'un même modèle. Par exemple, la gestion des consoles est gérée par un seul modèle getty@.service qui est décliné en getty@tty1.service, getty@tty2.service, etc pour chacune des consoles tty de votre machine. On peut aussi imaginer des services où chaque instance correspond à un utilisateur de la machine. Par exemple, on peut lancer le service syncthing@.service pour synchroniser en parallèle avec syncthing les fichiers de Toto, Gerard et Milou :

syncthing@.service
[Unit]
Description=Syncthing - Open Source Continuous File Synchronization for %I
Documentation=man:syncthing(1)
After=network.target
Wants=syncthing-inotify@.service
 
[Service]
User=%i
ExecStart=/usr/bin/syncthing -no-browser -no-restart -logflags=0
Restart=on-failure
SuccessExitStatus=3 4
RestartForceExitStatus=3 4
UMask=0002
 
[Install]
WantedBy=multi-user.target
systemctl list-dependencies [<unit>] 
systemctl enable syncthing@Toto.service
systemctl enable syncthing@Gerard.service
systemctl enable syncthing@Milou.service

**Qu'est ce qu'un timer–

Les timers sont des fichiers de programmation qui vont se charger de lancer des services à intervalles réguliers.

Quand vous créez un timer, il doit avoir l'extension .timer. Un service .service du même nom doit exister. (le service est souvent un service minimaliste, de type oneshot, permettant de lancer une commande)

Les timers «pourraient presque» remplacer le planificateur de tâches cron.

Exemple de service cyclique.

Service systeme

Création du fichier de timer

/etc/systemd/system/MAJ0.timer
[Unit]
Description=Lance une mise à jour de l'ordinateur quinze minutes après le démarrage de la machine et  itère toutes les trente minutes.
[Timer]
OnBootSec=15minutes
# le service démarrera 15 minutes après le démarrage de la machine
OnUnitActiveSec=30minutes
Persistent=true
# le service démarrera toutes les trente minutes après la dernière activation du timer
###    voir toutes les possibilités de choix  dans ce  document https://man7.org/linux/man-pages/man7/systemd.time.7.html
[Install]
WantedBy=timers.target

Création du fichier de service

/etc/systemd/system/MAJ0.service
[Unit]
Description=Service de mise a jour
After=network.target
 
[Service]
ExecStart=apt-get update && apt-get upgrade
Type=oneshot

Avec les commandes de gestion associées

sudo systemctl enable MAJ0.timer 
sudo systemctl start  MAJ0.timer
sudo systemctl status MAJ0.timer

Service utilisateur

Création et activation du service

cat <<"EOF" >$HOME/.config/systemd/user/Alerte.service
[Unit]
Description=Rappeler que le moment est venu.
[Service]
Type=simple
ExecStart=zenity --warning --text " C'est l'heure. Monseigneur."
EOF
sleep 1
systemctl --user enable Alerte.service;
systemctl --user start  Alerte.service;

Création et activation des déclenchements

cat <<"EOF" >$HOME/.config/systemd/user/Alerte.timer
[Unit]
Description=indique les moments retenus.
[Timer] 
OnCalendar=Mon-Sat *-*-* 10:20:30
OnCalendar=Sun *-*-* 12:14:16
[Install]
WantedBy=timers.target
EOF
sleep 1
systemctl --user enable Alerte.timer;
systemctl --user start  Alerte.timer;

Exemple de service avancé avec la base graphe neo4j

/etc/systemd/system/neo4j.service
#La configuration de Systemd se base sur des unités (units) qui ont un nom et un type.
 
######################################################################
#La section [Unit] contient de l'information générique sur le service#
######################################################################
#https://www.freedesktop.org/software/systemd/man/systemd.unit.html#
[Unit]
#Description de l'Unité.
Description=Neo4j Management Service
 
#Man page du service  "http://", "https://", "file:", "info:", "man:"
Documentation=man:neo4j(1)
 
 
# Type de l'Unité systemd.
#Les différents types d'unités sont :
#    service : pour un service/démon ;
#    socket : pour une socket réseau (de tous types : UNIX, Internet, fichier etc.) ;
#    mount : pour un système de fichiers (exemple : home.mount), tout en utilisant /etc/fstab ;
#    swap : pour les partitions d'échanges ;
#    automount : pour un système de fichiers monté à la demande ;
#    device : pour un périphérique ;
#    timer : pour l'activation basée sur une date ;
#    path : pour l'activation basée sur des fichiers ou des répertoires ;
#    target : macro-unité qui permet de grouper plusieurs unités (exemple : multi-user.target pour définir une cible) ;
#                Ce sont les niveaux d'exécutions de l'ancien init.
#    snapshot : unités utilisées pour sauvegarder l’état actuel des services et les restaurer ensuite, par exemple avant de passer en veille.
#Dans cet exemple c'est un service, celui de la base graphe neo4j, qui est notre "unité".
#########################################################################
#La section [Service] concerne l'information sur le service en lui-même.#
#########################################################################
#https://www.freedesktop.org/software/systemd/man/systemd.service.html
[Service]
#Lance le service dans un processus système indépendant.
# simple, forking, oneshot, dbus, notify ou idle sont les valeurs possibles de Type=.
Type=forking
 
#L'exécution du service se fera avec le nom d'utilisateur neo4j.
User=neo4j
 
#Le lancement de l'unité neo4j.service doit créer un répertoire neo4j dans /run.
#/var/run étant un lien vers le montage du système de fichiers tmpfs /run.
RuntimeDirectory=neo4j
 
#Droits d'accès sur le répertoire /run/neo4j.
# Utilisateur  Groupe    Les_autres
#     rwx        rwx        ---
#   7(4+2+1)   7(4+2+1)   0(0+0+0)
RuntimeDirectoryMode=770
 
#Où trouver l'identifiant PID du processus du service neo4j.
PIDFile=/var/run/neo4j/neo4j.pid
 
#Démarrer le service neo4j.
ExecStart=/usr/bin/neo4j start
 
#Arrêter le service neo4j.
ExecStop=/usr/bin/neo4j stop
 
#Redémarrer le service neo4j.
ExecReload=/usr/bin/neo4j restart
 
#Ne doit pas considérer que le service est actif lorsque le processus neo4j s'est terminé normalement.
RemainAfterExit=no
 
#Configure si le service doit être redémarré une fois le processus de service terminé, tué ou si le délai d'attente est atteint.
#                            *Restart=*    no    always    on-success    on-failure    on-abnormal    on-abort    on-watchdog
# *Choix redémarrage*                  +_______+_________+____________+_____________+______________+___________+_______________+
#           Fin normale ou par signal  |       |    X    |      X     |             |              |           |               |
#                                      +_______+_________+____________+_____________+______________+___________+_______________+
#        Fin d’exécution avec erreurs  |       |    X    |            |      X      |              |           |               |
#                                      +_______+_________+____________+_____________+______________+___________+_______________+
#                       Processus tué  |       |    X    |            |      X      |      X       |     X     |               |
#                                      +_______+_________+____________+_____________+______________+___________+_______________+
#             délai d'attente atteint  |       |    X    |            |      X      |      X       |           |               |
#                                      +_______+_________+____________+_____________+______________+___________+_______________+
#                            Watchdog  |       |    X    |            |      X      |      X       |           |       X       |
#                                      +_______+_________+____________+_____________+______________+___________+_______________+
Restart=on-failure
 
#Définit des limites logicielles ou matérielles pour le processus exécuté.
#https://www.freedesktop.org/software/systemd/man/systemd.exec.html#
# Correspond à ulimit -n 60000.
# C'est le nombre maximum de fichiers pouvant être ouvert simultanément pour les processus fils du service.
LimitNOFILE=60000
 
#Une directive pour configurer TimeoutStartSec = et TimeoutStopSec = à la valeur spécifiée.
# TimeoutStartSec= configure le délai d'attente pour attendre le démarrage du service.
# TimeoutStopSec = configure le temps d'attente pour attendre l'arrêt du service.
TimeoutSec=600
 
 
##############################################################################################################################
# La section [Install] s'occupe des circonstances et des déclencheurs dans le cadre desquels le service devrait être démarré.#
##############################################################################################################################
[Install]
#S'exécute dans le niveau d'exécution multi utilisateur
WantedBy=multi-user.target

Ressources


Contributeurs: zarmu