J'écris systemd
fichiers unitaires pour OSSEC HIDS. Le problème est que lorsque systemd
démarre les services, il les arrête immédiatement.
Lorsque j'utilise le ExecStart
suivant directive tout fonctionne bien.
ExecStart=/var/ossec/bin/ossec-control start
Mais quand je fais la petite amélioration suivante, je trouve dans les logs OSSEC qu'il reçoit SIG 15
après le démarrage.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'
Si je fais un autre petit changement, le service recevra SIG 15
après 20 secondes.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'
Donc, je suppose que systemd
tue /bin/sh
processus après le démarrage du service, et /bin/sh
puis tue OSSEC
.
Comment puis-je résoudre ce problème ?
Réponse acceptée :
Non-concordance du protocole de préparation
Comme Wieland l'a laissé entendre, le Type
du service est important. Ce paramètre indique quel protocole de préparation systemd s'attend à ce que le service parle. Un simple
le service est supposé immédiatement prêt. Un forking
le service est considéré comme prêt après que son processus initial a créé un enfant, puis s'est arrêté. Un dbus
Le service est considéré comme prêt lorsqu'un serveur apparaît sur le bus de bureau. Et ainsi de suite.
Si vous n'obtenez pas le protocole de préparation déclaré dans l'unité de service pour correspondre à ce que fait le service, alors les choses tournent mal. Les incompatibilités de protocole de préparation font que les services ne démarrent pas correctement ou (plus généralement) sont (mal) diagnostiqués par systemd comme défaillants. Lorsqu'un service est considéré comme ne parvenant pas à démarrer, systemd s'assure que chaque processus supplémentaire orphelin du service qui aurait pu être laissé en cours d'exécution dans le cadre de l'échec (de son point de vue) est tué afin de ramener correctement le service à l'état inactif.
C'est exactement ce que vous faites.
Tout d'abord, les trucs simples :sh -c
ne correspond pas à Type=simple
ou Type=forking
.
Dans le simple
protocole, le processus initial est amené à être le processus de service. Mais en fait un sh -c
wrapper exécute le programme de service réel en tant que processus enfant . Donc MAINPID
tourne mal et ExecReload
cesse de fonctionner, pour commencer. Lors de l'utilisation de Type=simple
, il faut soit utiliser sh -c 'exec …'
ou ne pas utiliser sh -c
en premier lieu. Ce dernier est plus souvent le bon cours que certaines personnes ne le pensent.
sh -c
ne correspond pas à Type=forking
Soit. Le protocole de préparation pour un forking
le service est assez spécifique. Le processus initial doit forker un enfant, puis se terminer. systemd applique un délai d'attente à ce protocole. Si le processus initial ne se déroule pas dans le délai imparti, il s'agit d'un échec à se préparer. Si le processus initial ne se termine pas dans le délai imparti, c'est aussi un échec.
l'horreur inutile qu'est ossec-control
Ce qui nous amène aux choses complexes :cet ossec-control
script.
Il s'avère que c'est un System 5 rc
script qui bifurque entre 4 et 10 processus, qui eux-mêmes bifurquent et se terminent également. C'est l'un de ces System 5 rc
des scripts qui tentent de gérer tout un ensemble de processus serveur en un seul script, avec for
boucles, conditions de concurrence, sleep
arbitraire s pour essayer de les éviter, les modes de défaillance qui peuvent étouffer le système dans un état à moitié démarré, et toutes les autres horreurs qui ont amené les gens à inventer des choses comme le contrôleur de ressources système AIX et les démontools il y a deux décennies. Et n'oublions pas le script shell caché dans un répertoire binaire qu'il réécrit à la volée, pour implémenter idiosyncratique enable
et disable
verbes.
Ainsi, lorsque vous /bin/sh -c '/var/ossec/bin/ossec-control start'
ce qui se passe, c'est que :
- systemd bifurque ce qu'il attend d'être le processus de service.
- C'est le shell, qui bifurque
ossec-control
. - Cela génère entre 4 et 10 petits-enfants.
- Les petits-enfants bifurquent tous et sortent à tour de rôle.
- Les arrière-petits-enfants bifurquent et sortent tous en parallèle.
ossec-control
quitte.- Le premier shell sort.
- Les processus de service étaient les arrière-arrière- petits-enfants, mais parce que cette façon de travailler ne correspond aucune le
forking
ni lesimple
protocole de préparation, systemd considère que le service dans son ensemble a échoué et le ferme à nouveau.
Aucune de ces horreurs n'est réellement nécessaire sous systemd. Rien de tout cela.
une unité de service de modèle systemd
Au lieu de cela, on écrit une unité de modèle très simple :
[Unit] Description=The OSSEC HIDS %i server After=network.target [Service] Type=simple ExecStartPre=/usr/bin/env /var/ossec/bin/%p-%i -t ExecStart=/usr/bin/env /var/ossec/bin/%p-%i -f [Install] WantedBy=multi-user.target
Enregistrez ceci sous /etc/systemd/system/[email protected]
.
Les différents services réels sont des instanciations de ce modèle, nommé :
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Ensuite, activer et désactiver la fonction vient directement du système de gestion des services (avec le bogue RedHat 752774 corrigé), sans avoir besoin de scripts shell cachés.
systemctl enable [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
De plus, systemd apprend à connaître et à suivre directement chaque service réel. Il peut filtrer leurs journaux avec journalctl -u
. Il peut savoir quand un service individuel a échoué. Il sait quels services sont censés être activés et en cours d'exécution.
Au fait :Type=simple
et le -f
option sont aussi bien ici que dans de nombreux autres cas. Très peu de services dans la nature signalent réellement qu'ils sont prêts à force de exit
, et ce ne sont pas non plus de tels cas. Mais c'est ce que le forking
type signifie. Les services dans la nature ne font que bifurquer et sortir à cause d'une notion erronée de sagesse reçue selon laquelle c'est ce que les dæmons sont censés faire. En fait, ce n'est pas le cas. Ce n'était plus le cas depuis les années 1990. Il est temps de se rattraper.
Autres lectures
- Jonathan de Boyne Pollard (2015). Problèmes de protocole de préparation avec les dæmons Unix . Réponses fréquemment données.