FreeBSD kézikönyv
Előző | Fejezet 3. A UNIX alapjai | Következő

# 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.

Előző | Tartalom | Következő
Folyamatok | Fel | Parancsértelmezők

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>.