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.
Wenn Sie also /bin/sh -c '/var/ossec/bin/ossec-control start'
Folgendes passiert:
- systemd verzweigt, was es als Dienstprozess erwartet.
- Das ist die Shell, die
ossec-control
verzweigt . - Das wiederum ergibt zwischen 4 und 10 Enkelkindern.
- Die Enkelkinder teilen sich alle und gehen der Reihe nach aus.
- Die Urenkel gabeln und verlassen alle parallel.
ossec-control
Ausgänge.- Die erste Shell wird beendet.
- Die Serviceprozesse waren der Ur-Ur- Enkel, sondern weil diese Arbeitsweise zu beidem passt das
forking
noch dassimple
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.