3.8. Démonok, jelzések és a futó programok leállítása

Amikor elindítunk egy szövegszerkesztőt, nem sok gondunk akad az irányításával, könnyen utasíthatjuk az állományok betöltésére és így tovább. Mindezt azért tehetjük meg, mert a szövegszerkesztő erre lehetőséget biztosít és mivel a szövegszerkesztő egy terminálhoz kapcsolódik. Egyes programok azonban nem úgy lettek kialakítva, hogy állandóan a felhasználó utasításaira támaszkodjanak, ezért az első adandó alkalommal lekapcsolódnak a terminálról. Például egy webszerver egész nap csak webes kéréseket válaszol meg, és általában semmi szüksége nincs a felhasználók utasításaira. A szerverek között leveleket közvetítő programok is ugyanezen osztályba tartoznak.

Ezeket a programokat démononoknak hívjuk. A démonok a görög mitológiában jelentek meg: sem a jót, sem pedig a gonoszt nem képviselték, egyszerű apró szellemecskék voltak, akik az emberiség javát szolgálták, pontosan úgy, ahogy ma teszik azt a különféle web- és levelező szerverek. Ezért is ábrázolták sokáig a BSD kabalafiguráját is egy tornacipős, vasvillás vidám démonként.

A démonként futó programok nevéhez a hagyományok szerint hozzá szokták fűzni a “d” betűt. A BIND a Berkeley Internet Name Domain (névfeloldó) szolgáltatása, azonban a hozzá tartozó program neve named, az Apache webszerver programját httpd-nek nevezik, a sornyomtató kezeléséért felelős démon pedig az lpd és így tovább. Ez csupán egy hagyomány, megszokás, nem pedig egy kőbe vésett szabály: például a Sendmail levelező démonának neve sendmail és nem pedig maild.

Néha azért szükségünk lehet arra, hogy felvegyük valahogy a kapcsolatot a démonként futó programokkal is. Ennek egyik lehetséges módja a jelzések (signal) küldése (de alapvetően bármilyen futó programnak küldhetünk). Több különféle jelzés küldhető — egyeseknek közülük megkülönböztetett jelentése van, másokat magukat az alkalmazások értelmeznek, amelyről a dokumentációjukban tájékozódhatunk. A kill(1) vagy kill(2) paranccsal más tulajdonában levő futó programoknak nem tudunk jelzéseket küldeni, ami alól egyedüli kivétel a root felhasználó.

Bizonyos esetekben a FreeBSD maga is küld néha jelzéseket. Amikor egy alkalmazást rosszul programoznak le és megpróbál egy számára tiltott memóriaterülethez hozzáférni, a FreeBSD küld neki egy Segmentation Violation (SIGSEGV, szegmentálási hiba) jelzést. Ha egy alkalmazás az alarm(3) rendszerhíváson keresztül kér egy adott idő utáni bekövetkező értesítést, akkor kap erről egy Alarm (SIGALRM) jelzést és így tovább.

A folyamatok leállítására két jelzés használható: a SIGTERM (befejeztetés) és a SIGKILL (leállítás). A SIGTERM a folyamatok leállításának illedelmes módja, mivel ekkor a futó program képes elkapni ezt a jelzést és észrevenni, hogy le akarjuk állítani. Ilyenkor a leállítás előtt lehetősége van szabályosan lezárni a naplóit és általánosságban véve befejezni mindent, amit éppen csinál. Előfordulhat azonban, hogy a folyamatok figyelmen kívül hagyják a SIGTERM jelzést, ha például éppen egy félbeszakíthatatlan feladat közepén tartanak.

A SIGKILL jelzést azonban egyetlen futó program sem hagyhatja figyelmen kívül. Ez lenne a “Nem érdekel, mivel foglalkozol, azonnal hagyd abba!” jelzés. Amikor SIGKILL jelzést küldünk egy folyamatnak, a FreeBSD leállítja a folyamatot ott és ahol tart [1].

További használható jelzések: SIGHUP, SIGUSR1 és SIGUSR2. Ezek általános célú jelzések, amelyeket az alkalmazások eltérő módokon kezelnek.

Tegyük fel, hogy megváltoztattuk a webszerverünk beállításait tartalmazó állományt — valamilyen módon szeretnénk tudatni a szerverrel, hogy olvassa be újra a beállításait. Ezt megtehetjük úgy, hogy leállítjuk és újraindítjuk a httpd démont, de ezzel kiesést okozhatunk a szerver működésében, amit viszont nem engedhetünk meg. A legtöbb démont úgy készítették el, hogy a SIGHUP jelzés hatására olvassa be újra a beállításait tartalmazó állományt. Így a httpd leállítása és újraindítása helyett egyszerűen elegendő egy SIGHUP jelzés küldése. Mivel azonban ez nem szabványosított, a különböző démonok ezt a jelzést többféleképpen is értelmezhetik. Ezért a használata előtt ennek mindenképpen járjunk utána a kérdéses démon dokumentációjában.

A jelzéseket a kill(1) paranccsal tudjuk elküldeni, ahogy ezt a következő példában is láthatjuk.

Jelzés küldése egy futó programnak

Ebben a példában megmutatjuk, hogyan lehet jelzést küldeni az inetd(8) démonnak. Az inetd a beállításait az /etc/inetd.conf állományban tárolja, és az inetd a SIGHUP jelzés hatására képes újraolvasni ezt.

  1. Keressük meg annak a folyamatnak az azonosítóját, amelynek a jelzést kívánjuk küldeni. Ezt a ps(1) és a grep(1) használatával tehetjük meg. A grep(1) parancs segítségével más parancsok kimenetében tudunk megkeresni egy általunk megadott szöveget. Ezt a parancsot átlagos felhasználóként futtatjuk, azonban az inetd(8) démont a root birtokolja, ezért az ps(1) használata során meg kell adnunk az ax kapcsolókat is.

    % ps -ax | grep inetd
      198  ??  IWs    0:00.00 inetd -wW

    Innen kiderül, hogy az inetd(8) azonosítója 198. Előfordulhat, hogy az eredményben maga a grep inetd parancs is megjelenik. Ez a ps(1) listázási módszere miatt következhet be.

  2. A jelzés elküldésére használjuk a kill(1) parancsot. Mivel az inetd(8) démont a root felhasználó futtatja, ehhez először a su(1) parancs kiadásával nekünk is root felhasználóvá (rendszeradminisztrátorrá) kell válnunk.

    % su
    Password:
    # /bin/kill -s HUP 198

    Ahogy az a legtöbb UNIX® esetén elfogadott, a sikeres végrehajtás esetén a kill(1) sem válaszol semmit. Amikor viszont nem egy saját programunknak akarunk jelzést küldeni, akkor a “kill: PID: Operation not permitted” (a művelet nem engedélyezett) hibaüzenetet látunk. Ha véletlenül elgépeltük volna a futó program azonosítóját, akkor a küldendő jelzés nem a megfelelő folyamatnál fog kikötni (ami nem éppen jó), vagy ha szerencsénk van, akkor a jelzést egy éppen használaton kívüli azonosítóra küldtük. Az utóbbi esetben a következő láthatjuk: “kill: PID: No such process” (nincs ilyen folyamat).

    Miért /bin/kill?: A legtöbb parancsértelmező beépítetten tartalmazza a saját kill parancsát, tehát ilyenkor közvetlenül maga a parancsértelmező küldi a jelzést, nem pedig a /bin/kill programon keresztül. Ez gyakran a javunkra válhat, azonban a küldhető jelzések megadása parancsértelmezőnként eltérhet. Így, ahelyett, hogy egyenként ismernünk kellene mindegyiket, sokkal egyszerűbb közvetlenül a /bin/kill ... parancsot használni.

A többi jelzés küldése is nagyon hasonló módon történik, hiszen elegendő csupán a TERM vagy a KILL behelyettesítése a parancs megfelelő helyére.

Fontos: A rendszerünkben óvatosan bánjunk a futó programok leállítgatásával, és legyünk különös tekintettel az 1-es azonosítóval rendelkező, speciális feladattal bíró init(8) folyamatra. A /bin/kill -s KILL 1 parancs kiadásával ugyanis gyorsan le tudjuk állítani a rendszerünket. Mielőtt egy kill(1) parancsot lezárnánk az Enter billentyűvel, mindig győződjünk meg róla, hogy valóban tényleg a jó paramétereket adtuk meg.

Megjegyzések

[1]

Ez azért nem teljesen igaz. Van néhány olyan tevékenység, ami nem szakítható meg. Ilyen például az, amikor a program egy másik számítógépen található állományt próbál olvasni, miközben valamilyen ok (kikapcsolás, hálózati hiba) folytán elveszti vele a kapcsolatot. Ekkor a program futása “megszakíthatatlan”. Majd amikor a program feladja a próbálkozást (általában két perc után), akkor következik be a tényleges leállítása.

Ha kérdése van a FreeBSD-vel kapcsolatban, a következő címre írhat (angolul): <freebsd-questions@FreeBSD.org>.
Ha ezzel a dokumentummal kapcsolatban van kérdése, kérjük erre a címre írjon: <gabor@FreeBSD.org>.