GNU/Linux >> LINUX-Kenntnisse >  >> Cent OS

Centos – Systemd killt Dienst sofort nach Start?

Ich schreibe systemd Unit-Dateien für OSSEC HIDS. Das Problem ist, dass wenn systemd startet die Dienste und stoppt sie sofort.

Wenn ich den folgenden ExecStart verwende Direktive funktioniert alles einwandfrei.

ExecStart=/var/ossec/bin/ossec-control start

Aber wenn ich die folgende kleine Verbesserung mache, finde ich in OSSEC-Protokollen, dass es SIG 15 erhält nach dem Start.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'

Wenn ich noch eine kleine Änderung vornehme, erhält der Dienst SIG 15 nach 20 Sekunden.

ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'

Also, ich schätze, das systemd beendet /bin/sh Prozess nach Dienststart und /bin/sh tötet dann OSSEC .

Wie kann ich dieses Problem lösen?

Akzeptierte Antwort:

Nichtübereinstimmung des Bereitschaftsprotokolls

Wie Wieland andeutete, der Type des Dienstes ist wichtig. Diese Einstellung gibt an, welches Bereitschaftsprotokoll verwendet wird systemd erwartet, dass der Dienst spricht. Ein simple Der Dienst wird als sofort bereit vorausgesetzt. Ein forking Der Dienst wird als bereit angesehen, nachdem sein anfänglicher Prozess ein untergeordnetes Element gegabelt und dann beendet hat. Ein dbus Der Dienst gilt als bereit, wenn ein Server auf dem Desktop-Bus erscheint. Und so weiter.

Wenn Sie das Bereitschaftsprotokoll, das in der Diensteinheit deklariert ist, nicht mit dem übereinstimmen, was der Dienst tut, dann laufen die Dinge schief. Nichtübereinstimmungen im Bereitschaftsprotokoll führen dazu, dass Dienste nicht korrekt gestartet werden oder (häufiger) von systemd (falsch) als fehlerhaft diagnostiziert werden. Wenn festgestellt wird, dass ein Dienst nicht gestartet werden kann, stellt Systemd sicher, dass jeder verwaiste zusätzliche Prozess des Dienstes das möglicherweise als Teil des Fehlers (aus seiner Sicht) weiter ausgeführt wurde, wird beendet, um den Dienst ordnungsgemäß wieder in den inaktiven Zustand zu versetzen.

Du tust genau das.

Zuerst einmal das Einfache:sh -c stimmt nicht mit Type=simple überein oder Type=forking .

Im simple Protokoll, wird der anfängliche Prozess als be angesehen der Serviceprozess. Aber eigentlich ein sh -c Wrapper führt das eigentliche Serviceprogramm als untergeordneten Prozess aus . Also MAINPID geht schief und ExecReload hört auf zu arbeiten, für den Anfang. Bei Verwendung von Type=simple , muss man entweder sh -c 'exec …' verwenden oder nicht verwenden sh -c an erster Stelle. Letzteres ist häufiger der richtige Weg, als manche denken.

sh -c stimmt nicht mit Type=forking überein entweder. Das Bereitschaftsprotokoll für ein forking Service ist ziemlich spezifisch. Der anfängliche Prozess muss ein Kind forken und dann beenden. systemd wendet ein Timeout auf dieses Protokoll an. Wenn der anfängliche Prozess nicht innerhalb der vorgegebenen Zeit verzweigt wird, ist es ein Versäumnis, bereit zu werden. Wenn der anfängliche Prozess nicht innerhalb der vorgegebenen Zeit beendet wird, ist dies ebenfalls ein Fehler.

der unnötige Horror, der ossec-control ist

Das bringt uns zu den komplexen Dingen:dieser ossec-control Skript.

Es stellt sich heraus, dass es sich um einen System 5 rc handelt Skript, das zwischen 4 und 10 Prozesse abzweigt, die sich wiederum abzweigen und auch beenden. Es ist einer dieser System 5 rc Skripte, die versuchen, eine ganze Reihe von Serverprozessen in einem einzigen Skript zu verwalten, mit for Loops, Race Conditions, beliebiger sleep s zu versuchen, sie zu vermeiden, Fehlermodi, die das System in einem halb gestarteten Zustand ersticken können, und all die anderen Schrecken, die Menschen dazu brachten, Dinge wie den AIX System Resource Controller und Daemontools vor zwei Jahrzehnten zu erfinden. Und vergessen wir nicht das versteckte Shell-Skript in einem Binärverzeichnis, das es spontan umschreibt, um idiosynkratisches enable zu implementieren und disable Verben.

Siehe auch:Debian – Wie finde ich heraus, wie ein bestimmtes Paket installiert wurde?

Wenn Sie also /bin/sh -c '/var/ossec/bin/ossec-control start' Folgendes passiert:

  1. systemd verzweigt, was es als Dienstprozess erwartet.
  2. Das ist die Shell, die ossec-control verzweigt .
  3. Das wiederum ergibt zwischen 4 und 10 Enkelkindern.
  4. Die Enkelkinder teilen sich alle und gehen der Reihe nach aus.
  5. Die Urenkel gabeln und verlassen alle parallel.
  6. ossec-control Ausgänge.
  7. Die erste Shell wird beendet.
  8. Die Serviceprozesse waren der Ur-Ur- Enkel, sondern weil diese Arbeitsweise zu beidem passt das forking noch das simple Bereitschaftsprotokoll betrachtet systemd den Dienst als Ganzes als ausgefallen und fährt ihn wieder herunter.

Nichts von diesem Horror ist unter systemd überhaupt notwendig. Nichts davon.

eine systemd-Vorlagendiensteinheit

Stattdessen schreibt man eine sehr einfache Vorlageneinheit :

[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

Speichern Sie dies unter /etc/systemd/system/[email protected] .

Die verschiedenen eigentlichen Dienste sind Instanziierungen dieser Vorlage mit dem Namen:

  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]
  • [email protected]

Die Aktivierungs- und Deaktivierungsfunktion kommt dann direkt aus dem Dienstverwaltungssystem (mit RedHat-Fehler 752774 behoben), ohne dass versteckte Shell-Skripte erforderlich sind.

 systemctl enable [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]

Darüber hinaus lernt systemd jeden aktuellen Dienst direkt kennen und kann ihn verfolgen. Es kann ihre Protokolle mit journalctl -u filtern . Es kann erkennen, wann ein einzelner Dienst ausgefallen ist. Es weiß, welche Dienste aktiviert und ausgeführt werden sollen.

Übrigens:Type=simple und das -f Option sind hier genauso richtig wie in vielen anderen Fällen. Sehr wenige Dienste in freier Wildbahn signalisieren tatsächlich ihre Bereitschaft durch den exit , und das hier sind auch keine solchen Fälle. Aber darum geht es beim forking Typ bedeutet. Dienste in freier Wildbahn gabeln und verlassen sich hauptsächlich aufgrund einer irrtümlichen Annahme, dass Dämonen dies tun sollten. Tatsächlich ist es das nicht. Seit den 1990er Jahren nicht mehr. Es ist Zeit, aufzuholen.

Weiterführende Literatur

  • Jonathan de Boyne Pollard (2015). Bereitschaftsprotokollprobleme mit Unix-Dämonen . Häufig gegebene Antworten.

Cent OS
  1. Warum stoppt Systemd den Dienst sofort nach dem Start?

  2. Centos – Fehler beim Starten des Apache Http-Servers – Httpd.service fehlgeschlagen?

  3. Systemd-Dienst startet Nodejs nicht?

  4. CentOS / RHEL 7 :So konfigurieren Sie Serial Getty mit Systemd

  5. Nagios-Dienst kann nicht gestartet werden (CentOS/RHEL)

So starten Sie den Dienst beim Booten mit RHEL 8 / CentOS 8 Linux

So starten, stoppen oder starten Sie Dienste in CentOS 8 neu

CentOS / RHEL 7:Leitfaden für Anfänger zu systemd-Diensteinheiten

systemd:SIGTERM unmittelbar nach dem Start

Der postgresql-Dienst kann unter CentOS 7 nicht gestartet werden

CentOS 7-Netzwerkdienst kann nicht gestartet werden