incompatibilité du protocole de préparation
Comme Wieland l'a laissé entendre, Type
le service est important. Ce paramètre indique quel protocole de préparation systemd attend du service qu'il parle. Un simple
service est supposé être immédiatement prêt. Un forking
service est censé être prêt après que son processus initial a forcé un enfant puis se termine. Un dbus
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 disponibilité déclarée dans l'unité de service pour correspondre à ce que fait le service, alors les choses tournent mal. L'inadéquation des protocoles de disponibilité empêche les services de démarrer correctement ou (plus généralement) d'être (mal) diagnostiqués par systemd comme défaillants. Lorsqu'un service est considéré comme ne démarrant pas systemd, il garantit que tous les processus supplémentaires orphelins du service qui pourraient avoir été laissés en cours d'exécution dans le cadre de l'échec (de son point de vue) sont tués afin de ramener correctement le service à l'inactif. Etat.
Tu fais exactement ça.
Tout d'abord, le truc simple: sh -c
ne correspond pas Type=simple
ou Type=forking
.
Dans le simple
protocole, le processus initial est considéré comme le processus de service. Mais en fait, un sh -c
wrapper exécute le programme de service réel en tant que processus enfant . Va donc MAINPID
mal et ExecReload
cesse de fonctionner, pour commencer. Lors de l'utilisation Type=simple
, il faut utiliser sh -c 'exec …'
ou ne pas utiliser sh -c
en premier lieu. Ce dernier est plus souvent le bon choix que certains ne le pensent.
sh -c
ne correspond pas non Type=forking
plus. Le protocole de préparation d'un forking
service est assez spécifique. Le processus initial doit bifurquer un enfant, puis quitter. systemd applique un délai d'attente à ce protocole. Si le processus initial ne se déroule pas dans le temps imparti, c'est un échec à devenir prêt. Si le processus initial ne se termine pas dans le temps imparti, c'est aussi un échec.
l'horreur inutile qui est ossec-control
Ce qui nous amène au truc complexe: ce ossec-control
script.
Il s'avère que c'est un rc
script System 5 qui bifurque entre 4 et 10 processus, qui eux-mêmes à leur tour bifurquent et sortent également. C'est l'un de ces rc
scripts System 5 qui tente de gérer tout un ensemble de processus serveur dans un seul script, avec des for
boucles, des conditions de concurrence, des arbitraires sleep
pour essayer de les éviter, des modes de défaillance qui peuvent étouffer le système dans un état semi-démarré, et toutes les autres horreurs qui ont poussé les gens à inventer des choses comme AIX System Resource Controller et daemontools 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 idiosyncrasiques enable
et disable
verbes.
Donc, quand vous /bin/sh -c '/var/ossec/bin/ossec-control start'
ce qui se passe, c'est que:
- systemd indique ce qu'il attend du processus de service.
- C'est la coquille, qui bifurque
ossec-control
.
- Cela à son tour fourche entre 4 et 10 petits-enfants.
- Les petits-enfants bifurquent tous et sortent tour à tour.
- Les arrière-petits-enfants bifurquent tous et sortent en parallèle.
ossec-control
sort.
- Le premier obus sort.
- Les processus de service étaient les arrière-arrière- petits - enfants, mais parce que cette façon de travailler ne correspond ni au protocole
forking
ni au simple
protocole de préparation, systemd considère que le service dans son ensemble a échoué et le ferme.
Aucune de ces horreurs n'est réellement nécessaire sous systemd. Rien de 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 = Le serveur OSSEC HIDS% i
Après = network.target
[Un service]
Type = simple
ExecStartPre = / usr / bin / env / var / ossec / bin /% p-% i -t
ExecStart = / usr / bin / env / var / ossec / bin /% p-% i -f
[Installer]
WantedBy = multi-user.target
Enregistrez ceci sous /etc/systemd/system/ossec@.service
.
Les différents services réels sont des instanciations de ce modèle, nommé:
ossec@dbd.service
ossec@agentlessd.service
ossec@csyslogd.service
ossec@execd.service
ossec@agentd.service
ossec@logcollector.service
ossec@syscheckd.service
ossec@maild.service
ossec@analysisd.service
ossec@remoted.service
ossec@monitord.service
Ensuite, la fonction d'activation et de désactivation 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 ossec @ dbd ossec @ agentlessd ossec @ csyslogd ossec @ maild ossec @ execd ossec @ analysisd ossec @ logcollector ossec @ remec ossec @ syscheckd ossec @ monitord
De plus, systemd apprend à connaître et à suivre directement chaque service réel. Il peut filtrer leurs journaux avec journalctl -u
. Il peut savoir lorsqu'un service individuel a échoué. Il sait quels services sont censés être activés et en cours d'exécution.
Soit dit en passant: Type=simple
et l' -f
option est aussi juste ici que dans de nombreux autres cas. Très peu de services dans la nature signalent en fait leur disponibilité à force de cela exit
, et ce ne sont pas de tels cas ici non plus. Mais c'est ce que le forking
type signifie. Les services à l'état sauvage dans la fourchette principale et la sortie principale en raison d'une notion de sagesse reçue erronée selon laquelle c'est ce que les démons sont censés faire. En fait, ce n'est pas le cas. Cela ne s'est pas produit depuis les années 1990. Il est temps de se rattraper.
Lectures complémentaires