Hlavní navigace

Inicializace aneb Od Initu k Runitu (2)

Jan Molič 7. 7. 2004

Je mnoho lidí, kteří si uvědomují, že na špatných základech nejde vystavět spolehlivý systém. Jde, ale za cenu obrovského úsilí a vloženého času. Jedním z těchto lidí je Daniel J. Bernstein. Nahradil init.d skripty Daemontools, které si dnes ukážeme.

Podle mého názoru je běžný inicializační systém přesložitělý. Člověk se utápí v záplavě skriptů, které v zájmu co největší podobnosti s MS Windows obsahují konstrukce typu „zde zapni splashscreen, když je proměnná a rovna b a zároveň existuje soubor /a/b/c a xz | grep gh | sed klmn…“.

Je mnoho lidí, kteří si uvědomují, že na špatných základech nejde vystavět spolehlivý systém. Jde, ale za cenu obrovského úsilí a vloženého času. Jedním z těchto lidí je Daniel J. Bernstein. Nahradil init.d skripty Daemontools, které si dnes ukážeme.

Démonizace

Stěžejní princip i problém init.d skriptů tkví ve spouštění programů (služeb) na pozadí. Program je spuštěn jako kterýkoli jiný, avšak očekává se od něj, že se sám odebere na pozadí, tzv. se detachuje. Své vstupy a výstupy odpojí od terminálu a stane se nezávislým na ukončení konzole. Proto se takovému programu říká daemon. My tím ale ztrácíme možnost s daemonem jednoduše pracovat. Chceme-li ho ukončit, můžeme tak učinit pouze zasláním signálu jeho procesu, k čemuž potřebujeme znát jeho číslo – process id – PID.

Není nic lepšího než konkrétní příklad – budeme spouštět a ukončovat apache.

# /etc/init.d/apache start
  1. init.d skript spouští /usr/sbin/apache2
  2. apache testuje, zda mu nic nebrání ve fungování. Jelikož ne, odebírá se na pozadí a vrací exitcode 0.
  3. init.d skript na základě exitcode píše „OK“
  4. apache vytváří soubor /var/run/apache2­.pid, do něhož zapisuje číslo svého procesu
# /etc/init.d/apache2 stop
  1. init.d skript načetl ze souboru /var/run/apache2­.pid číslo PID apache
  2. apache dostává signál TERM (kill PID)
  3. kill vrací exitcode 0 a init.d skript píše „OK“

Toto je ideální stav. Jak je vidět, i v něm potřebujeme znát alespoň název pid souboru. Jaké jsou další problémy?

  • Jistě jste se setkali se situací, kdy se sice napsalo OK, ale služba se nenastartovala.
  • init.d skript předpokládá, že daemon pid soubor vytvoří

    Apache jsem vybral právě proto, že pid soubor vytváří i s několikase­kundovým zpožděním a opačně, při ukončení pid soubor zmizí, ale apache ještě několik sekund běží. Budete-li ho restartovat rychle za sebou, dojde ke kolizím, které vyústí v nemožnost ho vypnout jinak než ručním zabitím. Aby ke kolizím nedocházelo, vyřešili to dalším skriptem, apachectl.

  • předpokládáme, že pid soubor neexistuje od minule

    Nastává po pádu počítače nebo apache. Ve většině init.d skriptů je proto před spuštěním služby pid soubor smazán, případně se služba odmítne spustit, dokud ho nesmažeme ručně. Důvod? Představte si, že apache spadl. Chcete ho tedy spustit znovu. Jak má init.d skript zjistit, zda náhodou neběží a nejde o několikanásobné spuštění? Podle pozůstalého pid souboru. Co když byl ale mezitím spuštěn další proces, který obdržel stejné PID?

  • pokud byste chtěli napsat vlastního daemona, musíte v něm implementovat detachování, a to není jednoduché

Shrnutí: init.d skripty nejsou spolehlivé. Aby se spolehlivost zvýšila, bývají plné „hacků“, jejichž výsledek není stoprocentní a které vše jen zesložiťují. Přitom lze celý tento „balast“ nahradit…

DJBware

Daniel J. Bernstein je znám jako tvůrce velmi specifického software (Qmail, tinydns). Jeho programy bývají při zachování obdobných funkcí desetkrát menší (a 2× divnější). Místo monolitického programu sestávají z mnoha malých prográmků, přičemž každý umí jen minimum funkcí, zato spolehlivě. Tím je zajištěna nejen spolehlivost, ale i modularita. K vzájemné komunikaci využívá běžné unixové prostředky jako práci se soubory, shellové skripty a roury.

Jinými slovy: síla v jednoduchosti.

Daemontools

DJB přišel s geniálním nápadem: nepoužívat pid soubory vůbec. Místo toho, aby daemona nejdříve poslal na pozadí a pak ho tam složitě hledal, nechá ho na popředí. Ne tak docela. Na pozadí spustí speciální daemon „supervise“, který vůči sobě rozběhne apache na popředí. Vytvoří pojmenovanou rouru, abychom mu mohli posílat příkazy. Supervise pak bude posílat signály svému potomkovi (apache). To je stoprocentně spolehlivé.

supervise

Vyrobit startovací skript pro daemontools není těžké. Vytvoříme adresář „apache“ a v něm skript „run“ s následujícím obsahem:

#!/bin/sh
exec /usr/sbin/apache2 -D SSL -D PHP4 -D NO_DETACH

Toť vše. Parametr NO_DETACH je důležitý, aby apache zůstal na popředí. Nyní supervise, potažmo apache, spustíme. Syntaxe je jednoduchá, supervise cesta_k_adresa­ri_s_run_skrip­tem

.

# supervise apache

Jestliže se podařilo, supervise vytvořil v adresáři apache podadresář „supervise“. Všimněme si v něm pojmenované roury „control“, pomocí níž lze se supervise komunikovat. pstree -a ukáže

supervise apache
  |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   `-apache2 -D SSL -D PHP4 -DNO_DETACH

svc

Ke komunikaci se supervise samozřejmě nebudeme používat rouru, nýbrž program svc. Syntaxe je obdobná, takže

# svc -u apache
# svc -d apache
# svc -h apache
# svc -o apache

u=up, d=down, h=reload(hup), o=once

Vyrobit vlastního „daemona“ tedy není problém. Stačí obyčejný bashový skript o dvou řádcích.

svscan

Svscan každou sekundu zjišťuje změny určitého adresáře. Spouští se obdobně, svscan adresář, nejčastěji svscan /service. Nad každým podadresářem v /service spustí supervise. Stačí tedy rozběhnout svscan a všechny služby se spustí najednou. Neřeší se přitom závislosti. Víc o paralelním spouštění pojednává třetí díl.

(Používáme-li svscan vedle standardních inicializačních skriptů, spouští se, alespoň v Gentoo, jako /etc/init.d/svscan start.)

Předpokládáme tedy, že svscan nad /service běží. Ukončíme předchozí pokus s apache, zabijeme jeho supervise a uděláme symlink našeho adresáře apache do /service. Svscan to zjistí a spustí nad ním supervise. V paměti uvidíme

svscan /service
  |- supervise apache
  |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   `-apache2 -D SSL -D PHP4 -DNO_DETACH

K ovládání služeb používáme svc.

Tip: udělal jsem skript sv, kterým můžu ovládat více služeb najednou, například

# sv start apache MySQL /service/qmail-*
# sv restart apache MySQL

svstat

zobrazuje stav služby. Syntaxe svstat adresář, např. svstat /service/apache

Tip: Lze udělat jednoduchý monitor svmon, stačí spustit svstat pro všechny adresáře v /service. Výsledek:

apache: run (pid 6880) 1253212 seconds
atd: run (pid 3164) 1254850 seconds
axfrdns: run (pid 15548) 167907 seconds
dcron: run (pid 3162) 1254850 seconds
dnscache: run (pid 15542) 167908 seconds
MySQL: run (pid 11564) 68195 seconds
qmail-pop3d: run (pid 3166) 1254849 seconds
qmail-send: run (pid 3181) 1254849 seconds
qmail-smtpd: run (pid 3184) 1254849 seconds
...

multilog

je geniální program. Čte ze standardního vstupu data a loguje je do souboru. Umí ještě další kousky: rozdělovat data do více logů podle obsahu, a hlavně – rotovat logy podle velikosti. Velikost určuje za běhu, takže nemůže dojít k přeplnění disku.

Multilog se spouští stejně jako ostatní služby pomocí supervise. Jeho argumentem je adresář, do něhož bude zapisovat soubory a jejich rotace. Run skript:

#!/bin/sh
multilog /var/log/multilog/apache

Zdá se vám to složité? Svscan spouštění multilogu zjednodušuje. Jestliže v našem adresáři apache vyrobíme podadresář log a do něj umístíme run skript multilogu (totéž, ale o úroveň níž), svscan spustí supervise i nad adresářem log. Zároveň prováže standardní výstup run skriptu apache se standardním vstupem run skriptu multilogu. Vše, co apache vyprodukuje, bude logováno a rotováno.

/service/apache/
                ./run
                /log/
                       ./run

v paměti uvidíme

svscan
  |- supervise apache
  |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   |-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   |   `-apache2 -D SSL -D PHP4 -DNO_DETACH
  |   `-multilog -tt /var/log/multilog/apache

Respawning

Zajímavou vlastností supervise je respawning. Jestliže apache spadne, bude spuštěn znovu.

Námitka #1: To je blbost.

Dobrá. Skript lze upravit, aby se spustil jen jednou, takto:

#!/bin/sh
svc -o `dirname $PWD`
exec /usr/sbin/apache2 -D SSL -D PHP4 -D NO_DETACH

Osobně jsem už několikrát ocenil, když jsem nemusel fyzicky k serveru. PostgreSQL po některém dotazu zkonzumoval tolik paměti, až spadl. To však neznamenalo, že po restartu fungoval špatně.

Námitka #2: Co když služba padá pořád?

Napsal jsem bashový skript checkrespawn, který start příliš často padající služby na chvíli pozdrží. Dle filozofie DJB toto není vlastnost, která by měla být součástí supervise. Navíc si chování checkresawn můžu sám přizpůsobit. Použití skriptu je snadné – stačí ho přidat do řetězce v run:

#!/bin/sh
exec checkrespawn /usr/sbin/apache2 -D SSL -D PHP4 -D NO_DETACH 

Bohužel

Ne všechny programy jsou přizpůsobitelné daemontools. Daemon se například detachuje a není možné to zvrátit (atd, MySQL). Existuje program fghack, který by měl udržet daemon na popředí. V případě MySQL udrží jeho první proces, jenže ten není tím, který ukončuje MySQL. Ukázalo se nejjednodušší prostě využít pid souboru. MySQL ho naštěstí vytváří bez problémů. Napsal jsem run pro MySQL, jde o bashový skript, který spustí MySQL, a když obdrží od supervise TERM, provede kill podle pid souboru. Nepoddajných služeb je naštěstí málo.

Dan Bernstain je svérázný člověk. Qmail zůstal ve verzi 1.03 a nikdo ho nedonutí napsat pokračování. Podle něj je totiž dokonalý a jeho funkce jsou dostačující. Faktem zůstává, že dodnes nebyla v Qmailu objevena díra. To samé platí o daemontools.

Příště si ukážeme, jak úplně nahradit init runitem od Gerrita Papeho, který daemontools mírně přepracoval a využil.

Viz:
daemontoo/ls
Runit

Autor je lektorem OKsystem.

Našli jste v článku chybu?

7. 7. 2004 23:43

Martin Pala (neregistrovaný)

ad. 1) pokud proces umre a opet se nastartuje se stejnym pid (coz je malo pravdepodobne vzhledem k tomu ze pid se pro nove procesy roste) v okne kratsim nez je sonda schopna zjistit, nemusi to znamenat nutne problem - pokud by proces po takovem restartu nefungoval , sonda to stejne zjistit a provede akci, pokud by fungoval, neni treba nic podnikat.

Vyuziti pid ma take nektere vyhody - umoznuje to zacit monitorovat jiz bezici proces (sluzba nemusi byt nastartovana pod kontrolou monitu).

Sou…



7. 7. 2004 15:25

Michal Kubeček (neregistrovaný)

To je ovšem jen uživatelská nadstavba nad systémem SysV init skriptů, který byl v prvním dílu zkritizován coby naprosto nesmyslný, složitý a nepoužitelný. V dalších dílech sice zjistíme, že DJB varianta s sebou přináší zcela nové problémy, které vyžadují své vlastní berličky a workaroundy. To je navíc okořeněno faktem, že autor odmítá chyby považovat za chyby, takže je k jeho nástrojům třeba armáda dobrovolníků, kteří je doplní do jakž takž prakticky použitelné podoby. Ve výsledku je je pak syst…

Vitalia.cz: Říká amoleta - a myslí palačinka

Říká amoleta - a myslí palačinka

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Podnikatel.cz: Vládu obejde, kvůli EET rovnou do sněmovny

Vládu obejde, kvůli EET rovnou do sněmovny

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Lupa.cz: Není sleva jako sleva. Jak obchodům nenaletět?

Není sleva jako sleva. Jak obchodům nenaletět?

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

120na80.cz: Bojíte se encefalitidy?

Bojíte se encefalitidy?

120na80.cz: Jak oddálit Alzheimera?

Jak oddálit Alzheimera?

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

Podnikatel.cz: Prodává přes internet. Kdy platí zdravotko?

Prodává přes internet. Kdy platí zdravotko?

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET