Piszę plik jednostki systemowej dla OSSEC HIDS. Problem polega na tym, że gdy systemd uruchamia usługę, natychmiast je zatrzymuje.
Kiedy używam tej dyrektywy ExecStart, wszystko działa dobrze.
ExecStart=/var/ossec/bin/ossec-control start
Ale kiedy dokonam niewielkiej poprawy, w dziennikach OSSEC jest dobrze, że po uruchomieniu otrzymuje SIG 15.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start'
Jeśli dokonam kolejnej małej zmiany, usługa otrzyma SIG 15 po 20 sekundach.
ExecStart=/bin/sh -c '${DIRECTORY}/bin/ossec-control start && sleep 20'
Sądzę więc, że systemd zabija proces / bin / sh po uruchomieniu usługi, a bin / sh zabija OSSEC.
Jak mogę rozwiązać ten problem?
Odpowiedzi:
niedopasowanie protokołu gotowości
Jak sugerował Wieland,
Type
usługa jest ważna. To ustawienie oznacza, który system protokołu gotowości oczekuje, że usługa będzie mówić.simple
Usługa zakłada się natychmiast gotowy.forking
Usługa zostanie podjęta ma być gotowy po jego początkowy proces rozwidla dziecko i następnie kończy działanie.dbus
Usługi uważane jest gotowy, kiedy na pulpicie pojawi Bus serwer. I tak dalej.Jeśli nie otrzymujesz zadeklarowanego w jednostce usługowej protokołu gotowości zgodnego z tym, co robi usługa, to wszystko idzie nie tak. Niedopasowania protokołu gotowości powodują, że usługi nie uruchamiają się poprawnie lub (częściej) są (błędnie) diagnozowane przez systemd jako awarie. Gdy usługa jest postrzegana jako nieudana, systemd zapewnia, że każdy osierocony dodatkowy proces usługi, który mógł pozostawać uruchomiony jako część awarii (z jego punktu widzenia), zostanie zabity w celu przywrócenia usługi do stanu nieaktywnego stan.
Robisz dokładnie to.
Przede wszystkim proste rzeczy:
sh -c
nie pasujeType=simple
lubType=forking
.W
simple
protokole proces początkowy jest traktowany jako proces serwisowy. Ale w rzeczywistoścish -c
opakowanie uruchamia rzeczywisty program serwisowy jako proces potomny . WięcMAINPID
idzie źle iExecReload
przestaje działać, na początek. Podczas korzystaniaType=simple
należy przede wszystkim użyćsh -c 'exec …'
lub niesh -c
. Ta ostatnia jest częściej prawidłowym kursem, niż niektórzy sądzą.sh -c
też nie pasujeType=forking
. Protokół gotowościforking
usługi jest dość specyficzny. Początkowy proces musi rozwidlić dziecko, a następnie wyjść. systemd stosuje limit czasu dla tego protokołu. Jeśli początkowy proces nie rozwinie się w wyznaczonym czasie, przygotowanie się nie powiedzie. Jeśli początkowy proces nie zakończy się w wyznaczonym czasie, to również oznacza błąd.niepotrzebny horror
ossec-control
Co prowadzi nas do skomplikowanych rzeczy: tego
ossec-control
skryptu.Okazuje się , że jest to
rc
skrypt Systemu 5, który uruchamia od 4 do 10 procesów, które same z kolei rozwidlają się i wychodzą. Jest to jeden zerc
skryptów System 5, który próbuje zarządzać całym zestawem procesów serwera w jednym skrypcie, zfor
pętlami, warunkami wyścigu, arbitralnymi próbamisleep
ich uniknięcia, trybami awarii, które mogą udusić system w stanie częściowo uruchomionym, i wszystkie inne okropności, które sprawiły, że ludzie wymyślili takie rzeczy, jak AIX System Resource Controller i Daemontools dwie dekady temu. I nie zapominajmy o ukrytym skrypcie powłoki w katalogu binarnym, który przepisuje on w locie, aby zaimplementować idiosynkratyczneenable
idisable
czasowniki.Więc kiedy
/bin/sh -c '/var/ossec/bin/ossec-control start'
to się dzieje, to:ossec-control
.ossec-control
wychodzi.forking
anisimple
protokół gotowość, Systemd uważa usługę jako całości nie udało i zamyka go z powrotem w dół.Żaden z tych horrorów nie jest wcale potrzebny w systemie. Nic z tego.
systemowa jednostka usługowa szablonu
Zamiast tego pisze się bardzo prostą jednostkę szablonu :
Zapisz to jako
/etc/systemd/system/[email protected]
.Różne rzeczywiste usługi to instancje tego szablonu o nazwie:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Następnie funkcja włączania i wyłączania pochodzi bezpośrednio z systemu zarządzania usługami (z naprawionym błędem RedHat 752774 ), bez potrzeby ukrytych skryptów powłoki.
Ponadto systemd poznaje i śledzi bezpośrednio każdą rzeczywistą usługę. Może filtrować ich logi
journalctl -u
. Może wiedzieć, kiedy dana usługa uległa awarii. Wie, jakie usługi powinny być włączone i uruchomione.Nawiasem mówiąc:
Type=simple
i-f
opcje są tutaj tak samo, jak w wielu innych przypadkach. Bardzo niewiele usług na wolności faktycznie sygnalizuje ich gotowość dziękiexit
, a te również nie są takimi przypadkami. Ale to właśnieforking
oznacza ten typ. Usługi na wolności w głównym rozwidleniu i wyjściu z powodu jakiegoś pomyłki otrzymały pogląd mądrości, że to właśnie powinni zrobić demony. W rzeczywistości tak nie jest. Nie było tego od lat 90. Czas nadrobić zaległości.Dalsza lektura
źródło
Requires=
wszystkie potrzebne instancjePartOf=ossec.target
ustawią w ossec @ .service. Umożliwi to uruchomienie i zatrzymanie ossec poprzez uruchomienie i zatrzymanie ossec.target.Zachowaj Type = rozwidlaj i podaj lokalizację pliku pid, jeśli usługa startowa / aplikacja utrzymuje jakiś pid.
[Jednostka]
Opis = „Uruchom aplikację podczas rozruchu”
Po = network.target syslog.target auditd.service
[Usługa]
Typ = rozwidlanie
PIDFile = / var / run / apache2 / apache2.pid
ExecStart = / etc / init.d / apache2 start
ExecStop = / etc / init.d / apache2 stop
StandardOutput = syslog
StandardError = syslog
Restart = awaria
SyslogIdentifier = webappslog
[Zainstaluj]
WantedBy = multi-user.target
Alias = webapps
źródło
W pewnym sensie miałem usługę systemową, która wydawała się, że systemd „zabije” ją po 30 latach.
systemctl status service-name
pokaże sięmain process exited, code=exited, status=1/FAILURE
po upływie 30 lat.Działałoby dobrze „w izolacji” (jak ręcznie w terminalu z tym samym środowiskiem ).
Okazuje się, że tak było
w ciągu
my_script_to_spawn_process.sh
to robi/bin/something > /dev/null 2>&1 &
który działa, ale odrzucał informacje z dziennika wyjściowego (zwykle trafia do pliku lub, jeśli nie to, być może
journalctl
).Zmieniając go, by logował się w innym miejscu
/bin/something > /tmp/my_file
następnie śledzenie
/tmp/my_file
ujawnionej rzeczywistej przyczyny. Który był (stycznie), że nie możesz używać składniEnvironment=ABC="true"
tak, jak możesz to zrobić w bashu, to musi to być brak cudzysłowów lub wartość klucza we wszystkich cudzysłowach,Environment="ABC=true"
co spowodowało, że mój proces zakończył się „w fazie konfiguracji” po około 30s.źródło
Zauważ, że model demona systemd jest uproszczony i niekompatybilny z wieloma istniejącymi demonami, które wykonują wielokrotne rozwidlanie, wykonywanie i konfigurowanie. Najczęściej są to demony, które uruchamiają się jako root, aby skonfigurować ustawienia, a następnie przełączają się na mniej uprzywilejowany identyfikator UID do rutynowej operacji. np. inicjalizacja pliku Pid to jedna rzecz, która kończy się niepowodzeniem w systemie z powodu problemów z uprawnieniami. Istnieją obejścia (nie poprawki), ale są źle udokumentowane.
Wyjaśnienie JdeBP jest mile widziane, ale niekompletne, a jego twierdzenie, że to wszystko wina ossec-control, jest po prostu nieprawdziwe. Nawet dość trywialne rzeczy są problematyczne, np. Uzyskiwanie nieskróconych wierszy dziennika w celu debugowania problemów lub znaczących komunikatów o błędach od samego systemd, gdy zabija procesy.
źródło