GNU/Linux >> Tutoriels Linux >  >> Cent OS

Centos - Systemd tue le service immédiatement après le démarrage ?

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.

Connexe :Debian – Comment savoir comment un paquet particulier a été installé ?

Ainsi, lorsque vous /bin/sh -c '/var/ossec/bin/ossec-control start' ce qui se passe, c'est que :

  1. systemd bifurque ce qu'il attend d'être le processus de service.
  2. C'est le shell, qui bifurque ossec-control .
  3. Cela génère entre 4 et 10 petits-enfants.
  4. Les petits-enfants bifurquent tous et sortent à tour de rôle.
  5. Les arrière-petits-enfants bifurquent et sortent tous en parallèle.
  6. ossec-control quitte.
  7. Le premier shell sort.
  8. 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 le simple 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.

Cent OS
  1. Démarrer, arrêter ou redémarrer les services dans CentOS 8 - Processus étape par étape ?

  2. Démarrer automatiquement le service OpenCA via Systemd dans CentOS 7

  3. Firewalld ne parvient pas à démarrer sur CentOS 8 avec une DBusException

  4. Le service Systemd ne démarre pas Nodejs ?

  5. CentOS / RHEL 7 :Comment configurer le getty série avec systemd

Comment démarrer le service au démarrage avec RHEL 8 / CentOS 8 Linux

Comment démarrer, arrêter ou redémarrer les services dans CentOS 8

CentOS / RHEL 7 :Guide du débutant sur les unités de service systemd

systemd :SIGTERM immédiatement après le démarrage

Impossible de démarrer le service postgresql sur CentOS 7

Systemd :Utiliser à la fois After et Requires