Píšu systemd
jednotkové soubory pro OSSEC HIDS. Problém je v tom, že když systemd
spustí služby, okamžitě je zastaví.
Když použiji následující ExecStart
direktiva vše funguje dobře.
ExecStart=/var/ossec/bin/ossec-control start
Ale když po malém vylepšení udělám toto, zjistím v protokolech OSSEC, že přijímá SIG 15
po startu.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'
Pokud provedu další malou změnu, služba obdrží SIG 15
po 20 sekundách.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'
Takže myslím, že systemd
zabije /bin/sh
proces po spuštění služby a /bin/sh
pak zabije OSSEC
.
Jak mohu tento problém vyřešit?
Přijatá odpověď:
neshoda protokolu připravenosti
Jak naznačil Wieland, Type
služby je důležité. Toto nastavení označuje protokol připravenosti systemd očekává, že služba bude mluvit. simple
předpokládá se, že služba je okamžitě připravena. forking
služba je považována za připravenou poté, co její počáteční proces rozdělí dítě a poté se ukončí. dbus
služba je považována za připravenou, když se server objeví na sběrnici plochy. A tak dále.
Pokud nedostanete protokol připravenosti deklarovaný v servisní jednotce, aby odpovídal tomu, co služba dělá, pak se věci zvrtnou. Neshody protokolů připravenosti způsobují, že se služby nespustí správně nebo (obvykleji) jsou (nesprávně) diagnostikovány systémem systemd jako selhávající. Když je služba považována za neúspěšnou při spuštění, systemd zajistí, že každý osiřelý další proces služby která mohla zůstat spuštěna jako součást selhání (z jeho pohledu) je zabita, aby se služba správně vrátila do neaktivního stavu.
Přesně tohle děláte.
Nejprve jednoduchá věc:sh -c
neodpovídá Type=simple
nebo Type=forking
.
V simple
protokol, je počáteční proces převzat do být servisní proces. Ale ve skutečnosti sh -c
wrapper spouští skutečný servisní program jako podřízený proces . Takže MAINPID
se pokazí a ExecReload
přestane fungovat, pro začátek. Při použití Type=simple
, musíte buď použít sh -c 'exec …'
nebo nepoužívat sh -c
na prvním místě. To druhé je častěji správným směrem, než si někteří lidé myslí.
sh -c
neodpovídá Type=forking
buď. Protokol připravenosti pro forking
služba je zcela specifická. Počáteční proces musí dítě rozdělit a poté ukončit. systemd aplikuje na tento protokol časový limit. Pokud se počáteční proces nerozdělí ve stanoveném čase, znamená to, že se nepodařilo připravit. Pokud se počáteční proces neukončí ve stanoveném čase, je to také selhání.
zbytečná hrůza, kterou je ossec-control
Což nás přivádí ke komplexní věci:k ossec-control
skript.
Ukázalo se, že je to System 5 rc
skript, který odděluje 4 až 10 procesů, které se samy rozvětvují a ukončují také. Je to jeden z těch System 5 rc
skripty, které se pokoušejí spravovat celou sadu serverových procesů v jediném skriptu s for
smyčky, podmínky závodu, libovolný sleep
Je to pokusit se jim vyhnout, režimy selhání, které mohou udusit systém v napůl spuštěném stavu, a všechny další hrůzy, kvůli kterým lidé před dvěma desetiletími vynalezli věci jako AIX System Resource Controller a daemontools. A nezapomeňme na skrytý skript shellu v binárním adresáři, který za běhu přepisuje, aby implementoval idiosynkratické enable
a disable
slovesa.
Takže když /bin/sh -c '/var/ossec/bin/ossec-control start'
stane se toto:
- systemd rozvětví to, co očekává jako proces služby.
- To je shell, který rozvětvuje
ossec-control
. - To zase rozdělí 4 až 10 vnoučat.
- Všechna vnoučata se postupně rozdvojují a odcházejí.
- Všichni pravnuci se rozdvojují a odcházejí paralelně.
ossec-control
ukončí.- První shell opustí.
- Procesy služeb byly skvělé-skvělé- vnoučata, ale protože tento způsob práce neodpovídá ani jednomu
forking
anisimple
protokol připravenosti, systemd považuje službu jako celek za selhání a opět ji vypne.
Nic z této hrůzy vlastně není pod systemd vůbec nutné. Nic z toho.
servisní jednotka šablony systemd
Místo toho se napíše velmi jednoduchá jednotka šablony :
[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
Uložte to jako /etc/systemd/system/[email protected]
.
Různé skutečné služby jsou instance této šablony s názvem:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Poté povolte a zakažte funkci přichází přímo ze systému správy služeb (s opravenou chybou RedHat 752774), bez potřeby skrytých skriptů shellu.
systemctl enable [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
Systemd navíc přímo pozná a sleduje každou skutečnou službu. Může filtrovat jejich protokoly pomocí journalctl -u
. Dokáže zjistit, kdy jednotlivá služba selhala. Ví, jaké služby mají být povoleny a spuštěny.
Mimochodem:Type=simple
a -f
možnosti jsou zde stejně správné jako v mnoha jiných případech. Velmi málo služeb ve volné přírodě ve skutečnosti signalizuje svou připravenost pomocí exit
a ani zde o takové případy nejde. Ale to je to, co forking
typ znamená. Služby v divočině se většinou jen rozvětvují a opouštějí kvůli nějaké mylně přijaté představě moudrosti, že to je to, co mají démoni dělat. ve skutečnosti není. Od devadesátých let to není. Je čas to dohnat.
Další čtení
- Jonathan de Boyne Pollard (2015). Problémy s protokolem připravenosti u unixových démonů . Často uváděné odpovědi.