Daemontools - náhrada za init skripty

Daemontools je kolekce nástrojů pro managování služeb v unixových systémech. Je to alternativa, nebo spíše vylepšení inittab, ttys, init.d nebo rc.local. Autor D. J. Bernstein je znám svým stylem zameřeným na stabilitu a bezpečnost, a proto je nasazení tohoto software vhodné zejména na kritických systémech.

Daemontools dohlíží nad službami a poskytuje tyto operace:

  • zapínání a vypínání služeb
  • spuštění služby po startu systému
  • restartování a posílání signálů
  • znovunahození služby po pádu
  • logování

Instalace

Daemontools je v mnoha distribucích Linuxu instalovatelný z repozitářů.
Např. v Gentoo emerge daemontools, v Debianu apt-get install daemontools a podobně. Pokud tomu tak není, je možné si ho zkompilovat ze zdrojáků podle návodu na stránkách autora. Po instalaci by v rootu filesystému měl být nový adresář /service a nové binárky zpravidla v /usr/bin. Pro kontrolu - jedna z nich je např. program svc, měl by být dostupný a spustitelný.

Proces svscanboot

Protože sa bavíme o náhradě za init skripty, je třeba zajistit spouštění všech potřebných procesů, na které navazuje celá hierarchie dohlížených služeb. Základní proces sloužící k nastartování všech ostatních je svscanboot. Jeho nahození zajistíme přidáním nového řádku do /etc/inittab:
SV:12345:respawn:/usr/bin/svscanboot

Po editaci inittabu není třeba rebootovat, změny se promítnou do systému zavoláním telinit q.
Pomocí ps, nebo pstree si zkontrolujeme zda běží, včetně dalších dvou procesů:

  • svscan (bude startovat a monitorovat služby)
  • readproctitle (skrz něho bude logovat výstup a chyby)
init─┬─ ....
     ├─ ....
     ├─svscanboot─┬─readproctitle
     │            └─svscan
     └ ....

Vytvoření run skriptů

Pro ty, kteří s daemontools nikdy nepracovali, nemá asi cenu ukazovat rozchození první služby hned na nějaké složitější aplikaci, která by komplikova situaci svou vlastní konfigurací (http server a podobně). Pro účely demostrace si vybereme nějaký program, který v nekonečné smyčce pouze něco vypisuje na standardní výstup. Cílem bude provozovat tento program jako démon.
Jako vhodného kandidáta jsem vybral vmstat s parametrem 1, aby peridicky po vteřině vypisoval stav paměti.
Po spuštění v shellu vmstat 1 dělá následující výpis:

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 1  0      0 785184 316732 1125456    0    0     7    50  127  236  2  0 97  0
 0  0      0 781784 316732 1129416    0    0     0     0  250  337  0  0 99  0
 0  0      0 781780 316732 1129552    0    0     0     0  312  514  0  0 100  0
...
...

Pro umístění run skriptů si vytvoříme supervise adresář, například v /etc: mkdir /etc/vmstatd.
Zároveň budeme ještě potřebovat mkdir /etc/vmstatd/log.

V /etc/vmstatd vytvoříme soubor pojmenovaný run, který bude spustitelný: touch /etc/vmstatd/run && chmod 755 /etc/vmstatd/run.
To samé v adresáři log touch /etc/vmstatd/log/run && chmod 755 /etc/vmstatd/log/run.

Nyní už stačí vzít svůj oblíbený editor a doplnit obsah run souborů:

/etc/vmstatd/run

#!/bin/sh

echo "starting..."
exec 2>&1

exec /usr/bin/vmstat 1

Co tento jednoduchý kód bude dělat je myslím patrné. Vypíše hlášku, přesměruje chybový výstup na standarní a stávající proces (bash) bude nahrazen vmstatem (exec).

Dále poeditujeme /etc/vmstatd/log/run

#!/bin/sh

exec multilog t n20 s1048576 /var/log/vmstatd

Tento druhý run skript bude zajišťovat logování. Na standardní vstup bude dostávat standardní výstup monitorovaného procesu a zde se definuje, jak se s výpisem bude dále nakládat.
V našem případě jsme použili další program z kolekce daemontools - multilog, který zapisuje výstup do souboru a zajišťuje rotování.
Uvedený adresář pro logování je nutné vytvořit: mkdir /var/log/vmstatd.

Spuštění služby

Adresář is run skripty nalinkujeme do /service. Tím zajistíme, že ho zaregistruje proces svscan, který zde každých 5 vteřin kontroluje podadresáře.
ln -s /etc/vmstatd /service/vmstatd

Nový démon se zároveň ihned spustí. Jeho běh můžeme ověřit pomocí utility svstat svstat /service/vmstatd.
Ve výpisu hierarchie procesů by to mělo vypadat takto:

init─┬─ ....
     ├─ ....
     └─svscanboot─┬─readproctitle
                  └─svscan─┬─supervise───vmstat
                           ├─supervise───multilog
                           └─ ....

A zárověň by se nám měl začít plnit log cat /var/log/vmstatd/current.

@4000000050f930fa30cced74 starting...
@4000000050f930fa30cdfafc procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
@4000000050f930fa30ce126c  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
@4000000050f930fa30d019f4  0  0      0 1256568 268824 936408    0    0    18    57  130  281  2  0 97  1
@4000000050f930fb30d57124  0  0      0 1256640 268832 936440    0    0     0   132  367  430  0  0 99  1
@4000000050f930fc30da476c  0  0      0 1254208 268832 936460    0    0     0     8  384  926  1  0 99  0
...
...

Ovládání služeb

Monitorované služby se ovládají pomocí utility svc. Nejpoužívanější operace jsou:

  • svc -t /service/vmstatd Restart služby. Pošle procesu TERM signál a svscan službu znovu nahodí.
  • svc -u /service/vmstatd Up. Spustí službu.
  • svc -d /service/vmstatd Down. Zastaví službu.
  • ...další možnosti svc a podrobnosti jsou uvedeny na stránce svc

Status služeb je možné ověřovat pomocí svstat. Jednotlivě svstat /service/vmstatd nebo i všechny naráz svstat /service/*.

Úplne odstranit službu ze supervisování lze následujícím postupem: cd /service/vmstatd && rm /service/vmstatd && svc -dx . ./log

Vylepšení privilegií

Uvedený příklad má jednu zásadní vadu na kráse. Procesy spouštíme s root oprávněním, včetně logování. To by na žádném produkčním stroji být rozhodně nemělo, pokud to není vyloženě potřeba. Některé aplikace (např. apache, nginx) umožňují spuštění svých procesů pod jiným userem nakonfigurovat. V našem případě to musíme změnit sami. Vezmeme prozatím tedy některého usera, kterého už v systému máme, například nobody.

V souboru /etc/vmstatd/run změníme řádek:

exec setuidgid nobody /usr/bin/vmstat 1

V souboru /etc/vmstatd/log/run změníme obdobně:

exec setuidgid nobody multilog t n20 s1048576 /var/log/vmstatd

Rovněž je potřeba dodatečně změnit práva log adresáře, aby do něho mohl nobody zapisovat chown -R nobody /var/log/vmstatd.

A restartujeme službu a její log proces: svc -t /service/vmstatd /service/vmstatd/log

Použití uživatele nobody jsem zvolil čistě jen pro učely ukázání a nemusí to být nejlepší volba do produkce. V praxi by každá služba měla bežet pod svým vlastním unikátním uživatelem (včetně logování). Filosofie daemontools k takovému bezpečnějšímu řešení přímo vybízí.

Poznámky na závěr

Jak je vidět, pomocí svscan je možné managovat aplikace, které beží na popředí. To znamená, že pokud budeme provozovat např. server Apache, je potřeba konfiguračně zajistit, aby se neforkoval na pozadí (např. u zmíněného Apache parametr -DNO_DETACH).

Doporučuji projít dokumentaci na stránkách autora cr.yp.to. Na internetu se dají rovněž nalézt hotové (více či méně dobře udělané) run skripty a návody pro nejrůznější známe služby.


Václav Vinklát 17.1.2013

TOPlist