fichier d'unité systemd créant un service
La gestion des services est une chose à laquelle vous ne pensez même pas lorsque vous utilisez votre poste de travail Linux ou votre serveur Linux tous les jours, mais quand ce n'est pas là, vous le détesterez vraiment. Lorsque vous créez par exemple un nouveau programme serveur qui doit fonctionner 24h/24 et 7j/7, relever ce défi sans gestion de service est un cauchemar où vous créez en fait vous-même un petit système de service, qui ne sera évidemment pas aussi bon que le gestionnaire développé par un équipe complète pendant des années, de toute façon.
Avec ses services, systemd rend tout cela plus facile, vraiment plus facile. Dès que vous voulez que quelque chose surveille votre application et la contrôle facilement, systemd est la voie à suivre, et c'est ce que je vais vous expliquer ici !
Où sont les services Systemd
Pour ajouter un nouveau service, eh bien, vous devez répondre à cette question. Comme toujours dans systemd, cela dépend si le service est uniquement destiné à votre utilisateur ou à l'ensemble du système. Nous nous concentrerons sur le fonctionnement de systemd pour l'ensemble des services système.
L'emplacement exact dépend de pourquoi et comment le service a été installé. Si le service est installé par un gestionnaire de paquets, il sera généralement dans /usr/lib/systemd/system. Pour les logiciels que vous développez ou ceux qui ne prennent pas en charge systemd par lui-même, vous placerez le fichier de service dans /usr/local/lib/systemd/system. Veuillez garder à l'esprit que certaines distributions ne prennent pas en charge ce dossier dans /usr/local. Enfin, si vous souhaitez configurer un service systemd existant, /etc/systemd/system est la solution.
Dans ces dossiers, vous pouvez trouver plusieurs extensions de fichiers telles que *.socket, *.target ou *.service. Évidemment, nous allons nous concentrer sur le dernier. systemd utilise le nom de fichier comme nom du service lors de son démarrage ou de son arrêt, etc. Ainsi, généralement, les noms de fichiers en service ne contiennent que des caractères alphanumériques, ainsi que des traits d'union et des traits de soulignement. Pendant le développement, je recommande de le créer dans vos documents, puis de le copier dans l'emplacement systemd une fois terminé, cela vous éviterait des problèmes si vous enregistrez au milieu de l'édition.
OK alors s'il vous plaît créez votre fichier de service dans vos documents. Nous sommes maintenant prêts à examiner comment écrire ce fichier.[Remarque : Voir le rapport de bogue potentiel dans la section des commentaires de cet article de blog]
Description=Penguins Web Application HTTP server (running in port 8080)
WantedBy=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /usr/local/bin/penguin-web-app/main.py
Restart=always
Le format de fichier est en fait proche de ini. Je sais que cela peut être bizarre étant donné que les fichiers ini se trouvent souvent dans Windows, mais c'est ainsi que cela fonctionne. Le fichier de service est d'abord divisé en 2 sections : [Unité] et [Service]. Chaque section configure un aspect spécifique de systemd : [Unit] contient des éléments partagés par tous les fichiers unitaires de systemd tandis que [Service] est uniquement destiné à la configuration spécifique à la configuration d'un nouveau service.
Ensuite, la section est configurée avec des propriétés telles que Description= ou ExecStart=. La valeur est séparée du nom de la propriété par le signe égal=sans espace.
Revenons au fichier présenté ci-dessus. Il décrit un service conçu pour exécuter une application Web écrite en Python sur les pingouins. systemd le redémarrera chaque fois que le processus se terminera et démarrera le serveur au démarrage du serveur si vous l'activez avec la commande systemctl enable. Cool hein ?
Mais vous êtes peut-être que votre prochaine application Web ne concerne pas les pingouins - et c'est dommage - et elle n'est pas écrite en Python. Dans ce cas, vous voudrez en savoir plus sur les configurations possibles.
Propriétés des services Systemd
Concentrons-nous d'abord sur les propriétés dans [Unit] :
Description= consiste simplement à donner une description claire de ce que fait le service. Il est affiché dans la liste des services, les journaux de service, vous voulez donc qu'il soit descriptif, mais il doit rester sur une ligne et une phrase.
WantedBy= permet de dire à systemd : quand ce truc est démarré, me démarre aussi. Généralement, vous mettrez le nom d'une cible. Exemples de cibles communes :
multi-user.target : lorsque le serveur est OK et est prêt à exécuter des applications en ligne de commande
graphic.target : lorsque GNOME ou KDE est prêt
-
network-up.target : lorsque le serveur est correctement connecté à un réseau
OK pour le début ces propriétés de [Unit] suffisent. Jetons un coup d'œil sur [Service] maintenant.
Type= aide systemd à savoir si un service est en cours d'exécution. Voici les types courants :
simple est probablement le plus couramment utilisé : systemd considère le processus que vous lancez comme celui qui rend le service. Si le processus s'arrête, il considère que le service est également arrêté, etc.
le forking est préféré pour les applications qui ont été écrites pour être un serveur mais sans l'aide d'un système de gestion de services. Fondamentalement, il s'attend à ce que le processus lancé se bifurque et ce bifurcation est considéré comme le processus final du service. Pour être plus précis, vous pouvez également aider systemd avec un fichier PID, où le PID du processus à suivre est écrit par l'application lancée.
ExecStart= est probablement le plus important pour un service : il précise quelle application lancer au démarrage du service. Comme vous pouvez le voir dans le service Penguin, j'ai utilisé /usr/bin/python3 et non python3 tout de suite. C'est parce que la documentation systemd recommande explicitement d'utiliser des chemins absolus afin d'éviter toute surprise.
Mais c'est aussi pour une autre raison. Le système de gestion des autres services a tendance à être basé sur des scripts Shell. Cependant, systemd, pour des raisons de performances, n'exécute pas de shell par défaut. Vous ne pouvez donc pas fournir directement une commande shell dans ExecStart=. Vous pouvez cependant toujours utiliser un script shell en faisant :
Pas si dur non ? Notez que si vous devez exécuter un processus pour signaler à votre service de s'arrêter proprement, ExecStop= existe, ainsi que ExecReload= pour recharger les services.
Restart= vous permet de dire explicitement quand le service doit être redémarré. C'est l'une des caractéristiques importantes de systemd : il garantit que votre service reste actif aussi longtemps que vous le souhaitez, alors faites très attention à cette option.
- always
systemd continuera à le redémarrer chaque fois qu'il se terminera ou plantera. Eh bien, jusqu'à ce que vous fassiez systemctl stop service-name.service.
C'est parfait pour les serveurs et les services en ligne car vous préférez quelques redémarrages inutiles plutôt que de devoir redémarrer manuellement le service sans aucune raison.
- on-abnormal
Lorsque le processus de service se bloque, redémarrez le service. Cependant, si l'application se ferme proprement, ne la redémarrez pas.
C'est plus utile pour les tâches cron comme les services qui doivent effectuer une tâche de manière fiable mais qui n'ont pas besoin de s'exécuter tout le temps.
- on-failure
Un peu comme on-anormal, mais il redémarre également le service lorsque l'application se ferme proprement mais avec un code de sortie différent de zéro. Les codes de sortie non nuls signifient généralement qu'une erreur s'est produite.
- no
systemd ne redémarrera pas le service automatiquement.
Généralement utile pour accéder à d'autres fonctionnalités systemd telles que la journalisation sans la fonctionnalité de redémarrage.
WorkingDirectory= peut appliquer un répertoire de travail lors du lancement de votre application. La valeur doit être un chemin de répertoire absolu. Le répertoire de travail est utilisé lorsque vous utilisez des chemins relatifs dans le code de votre application. Pour notre service pingouins, cela pourrait être :
Ensuite, la sécurité est importante, vous ne souhaitez donc généralement pas lancer votre service avec les privilèges root. User= et Group= vous permettent de définir le nom d'utilisateur ou de groupe ou l'UID/GID sous lequel votre application sera lancée. Par exemple:
Group=penguin-web
EnvironmentFile= est une option puissante. Les applications exécutées en tant que services ont souvent besoin de fichiers de configuration et d'environnement permettant de définir cette configuration de deux manières :
L'application peut lire directement la variable d'environnement.
Mais vous pouvez également définir différents arguments de ligne de commande pour votre application sans modifier le fichier de service.
La syntaxe de ce fichier est simple : vous tapez le nom de la variable d'environnement, le signe égal=puis sa valeur. Ensuite, vous mettez le chemin absolu de votre fichier d'environnement dans la propriété EnvironmentFile.
Donc exemple :
Et le fichier /etc/penguin-web-app/environment contient :
Ensuite, notre application Web Penguins aura accès à la variable d'environnement LISTEN_PORT et écoutera le port attendu.
Enregistrer et démarrer le service Systemd nouvellement créé
Donc, si vous avez suivi mes conseils, vous avez édité votre fichier de service dans votre répertoire personnel. Une fois que vous êtes satisfait, copiez ce fichier dans /usr/local/lib/systemd/system, en supposant que votre distribution prend en charge ce chemin. Le nom de fichier de votre fichier de service sera son nom de service. Ce nom de fichier doit se terminer par .service. Par exemple, pour notre serveur penguins, ce serait penguin-web-app.service.
Ensuite, vous devez indiquer à systemd que vous avez ajouté un nouveau service, vous devez donc taper cette commande :
Bon maintenant, systemd est au courant de votre nouveau service, en supposant que votre fichier ne contient pas d'erreur de syntaxe. Après tout, c'est votre premier fichier, il est donc probable que vous fassiez des erreurs. Vous devez exécuter cette commande ci-dessus à chaque mise à jour de votre fichier de service.
Maintenant, il est temps de démarrer le service :
S'il échoue avec une erreur Unité introuvable telle que celle-ci :
Failed to start penguin-web-app.service: Unit not found.
Cela signifie que votre distribution ne prend pas en charge le répertoire ou que vous n'avez pas nommé correctement votre fichier de service. Assurez-vous de vérifier.
Si vous configurez votre service avec WantedBy= et que vous souhaitez que votre service démarre automatiquement, vous devez l'activer, avec cette commande :
Ce qui est cool avec un service, c'est qu'il s'exécute en arrière-plan. Le problème : comment savoir s'il tourne correctement et s'il tourne s'il tourne en tâche de fond ? Ne vous inquiétez pas, l'équipe systemd a également pensé à cela et a fourni une commande pour voir s'il fonctionne correctement, depuis combien de temps, etc. :