Harmadik lecke

"Természetes párhuzam él a nők és a Unix shellek között. Mindkét csoportban vannak egyszerű, csunyácska tipusok (sh) és érettebb, minden igényt kielégítő tipusok (tcsh). (-: Egy igazi buherátor természetesen az sh-val és az sh-tipusú nőkkel is megtalálja a nyelvet! :-)"
(Csáky István)
Verzió: 1.0

A Unix shell

A cím rém rövid, de e nélkül a program nélkül (a shell valójában csak egy program Unix alatt, de a funkciója kiemeli a többi program közül) a munka elképzelhetetlen. Ugyanis ez a program az amelyik elindul mikor beszállunk egy Unixos rendszerbe, ennek adjuk ki a parancsokat és ez válaszol nekünk. (Funkciója hasonló a DOS command.com-jáéhoz). Shellből több fajta létezik, mivel a Unix lehetőséget ad belső érzületünk kifejezésére és nem köt egy megadott shellhez. Két fő kategória van: az un. "Bourne shell" és a "C shell", ezek neve sh és csh. Nevükön kívül szintaxisukban különböznek: a csh a C programoknál használatos szintaktikát követi. ( Én a csh egy kibővített változatát a tcsh-t használom, természetesen az sh-nak is vannak bővített változatai: a ksh, a bash és a zsh). Hogy ki mit használ teljesen vallás kérdése - a különféle shellek szolgáltatásaikban egyenrangúak!*

Mint már korábban olvashattuk, a Unix parancsok nem, vagy nagyon ritkán jelzik, ha jól működnek. Természetesen ez első látásra furcsán hat, azonban nagyon is értelmes magyarázata van. (Sokan szidják a Unixot bonyolultsága miatt, azonban Unixban minden az összehangoltságon alapul). Az, hogy a Unix nem jelzi a hiba nélkül futást, azért van, hogy a parancsok be- és kimenetei más parancsoknak átadhatóak legyenek. A legtöbb program a bemenetről (standard input - stdin) veszi az adatait és a kimenetre (standard output - stdout) küldi az eredményt. Rendszerint a bemenet a billentyűzet és a kimenet és a hibacsatorna a képernyő.

Például: a sort program rendezi a bemenetről beérkező sorokat:

woland> sort
gyufa
izzok
csoko
<Ctrl-d>
csoko
gyufa
izzok
woland>
Megjegyzés: a <Ctrl-d> a control (Ctrl) és a d billentyűk együttes leütését jelenti!

Így máris abc sorrendbe raktuk a bevásárlólistát. Az élet kis dolgaiban is nyugodtan számíthatunk a Unixra.

A bemenet és a kimenet átirányítása

Mi történik azonban akkor, ha mindig csak ezt a pár dolgot vesszük, ezért szeretnénk megtartani a listánkat? A shell lehetőséget ad arra, hogy az kimenetet átirányítsuk (redirection), és ehhez csupán a ">" jelet kell hogy használjuk. Nézzük, hogy is működik ez.
woland> sort > mit_vegyek
gyufa
izzok
csoko
<Ctrl-d>
woland>
Ugyanezzel a módszerrel - átirányítás - hoztunk létre fájlt az első leckében (ott a cat parancs kimenetét irányítottuk át). Az eredmény nem látható, hanem a mit_vegyek nevű fájlba került. Nézzük meg, hogy valóban ez történt-e?
woland> cat mit_vegyek
csoko
gyufa
izzok
woland>
A kimenet átirányítása csupán ennyi munkánkba kerül. Ugyanez vonatkozik a bemenet átirányítására is, ennek jele "<".

Például: csináljunk egy aruk nevű fájlt, aminek tartalmát rendezzük:

woland> cat > aruk
izzok
gyufa
csoko
<Ctrl-d>
woland>
woland> sort < aruk
csoko
gyufa
izzok
woland>
Fontos jel még a ">>", ami szintén a kimenet átirányítását jelenti; különbség közte és a szimpla átirányítójel között annyi, hogy ha ezt használjuk, a fájl amibe a kimenetet átirányítjuk, nem íródik felül. Ezzel a jellel a fájl tartalmához tudunk hozzáfűzni.

Megjegyzés: Természetesen a hibacsatornát is át lehet irányítani, erről bővebben az ötödik leckében olvashatunk majd!

Csövek

Arról már tudunk, hogy egy-egy program eredményét hogy lehet fájlba irányítani, azonban a lehetőség van arra, hogy egy program bemenetét egy másik programtól vegye. Erre találták ki Unixban a cső (pipe) fogalmát. Azt, hogy egy program kimenetét egy másik bemenetére szeretnénk átirányítani a "|" jellel jelezzük.

Vegyünk egy konkrét példát - szeretnénk a munkakönyvtárunkat fordított abc-sorrendben kinyomtatni. Eddigi tudásunkkal hogyan tudjuk ezt megvalósítani?

woland> ls -l >file_list
(Az igazi buherátor csak "bő" könyvtárlistát szeret olvasni.)
woland> cat file_list
total 8                                                 
drwxr-xr-x  2 csaky       1024 Jul 21  1992 Apps        
drwxr-xr-x  8 csaky       1024 Oct 19 13:35 Library     
drwxr-xr-x  3 csaky       1024 Jul 25  1992 Mailboxes   
drwxr-xr-x  2 csaky       1024 Nov  9 19:05 NewFolder   
-rw-------  1 csaky          5 Dec  6 16:46 dead.letter 
drwx------  2 csaky       1024 Jan 12 11:39 mail        
drwxr-xr-x  2 csaky       1024 Jan 17 17:23 pin-ups     
drwxr-xr-x  2 csaky       1024 Oct  5 09:02 tabla.draw~ 
woland> sort +7r < file_list

total 8
drwxr-xr-x  2 csaky       1024 Oct  5 09:02 tabla.draw~
drwxr-xr-x  2 csaky       1024 Jan 17 17:23 pin-ups
drwx------  2 csaky       1024 Jan 12 11:39 mail
-rw-------  1 csaky          5 Dec  6 16:46 dead.letter
drwxr-xr-x  2 csaky       1024 Nov  9 19:05 NewFolder
drwxr-xr-x  3 csaky       1024 Jul 25  1992 Mailboxes
drwxr-xr-x  8 csaky       1024 Oct 19 13:35 Library
drwxr-xr-x  2 csaky       1024 Jul 21  1992 Apps
woland>
A sort kapcsolói csak azt jelentik, hogy a 8. mezőtől kezdjen rendezni (egyet ki kell vonni a mező sorszámából!), és hogy fordítva (r - reverse). A mező definicióját a második leckében találhatjuk meg!

Ezt a cső használatával egy sorban is el lehet intézni, és az eredmény ugyanaz:

woland> ls -l | sort +7r
Nagyon jó szolgálatot tesznek a csövek a hosszú könyvtárlisták nézegetésénél is. Az ls -l | more paranccsal oldalanként nézegethetjük a listát, így az nem fut le a képernyőről.

Processzek

A Unix egyik fő jellemzője amellett, hogy többfelhasználós, az, hogy egyszerre több program futtatására képes (multitasking). Ezt a lehetőségét már a shell használata során is élvezhetjük, tehát az igazi Unix buherátor nem éli át azt a lealacsonyító érzést, hogy várnia kell egy program lefutására ahhoz, hogy egy másikat indíthasson. (Hahó MS-DOS).

A ps paranccsal meg tudjuk nézni, hogy milyen processzeink (programjaink) futnak.

woland> ps
  PID TT STAT  TIME COMMAND   
 3902 p0 S     0:01 -csh (tcsh)
woland>
Amint látjuk, most a felhasználónak csak egy processze fut, mégpedig a shell (tcsh). A listán még egy nagyon fontos dolog szerepel, a processz egyedi azonosítója (PID - process ID), esetünkben 3902.

A futó processzet a shell job néven ismeri (a processz és a job ugyanazt jelentik!). A shell lehetőséget ad a jobok manipulálására, ezt job controlnak hívjuk; ami azt jelenti, hogy egyszerre több egymástól különböző dolgot csinálhatunk, és váltogathatjuk, hogy éppen melyik futását akarjuk figyelemmel kísérni. Például éppen szerkesztünk egy programot, de eszünkbe jut, hogy már meg kellett volna írni egy E-mailt; erre kínál megoldást a job control.

Előtérben (foreground) és háttérben (background) való futtatás

A jobok futhatnak előterben és háttérben, előterben azonban egyszerre csak egy job lehet. Az előtérben lévő job kapja a bemenetet a billentyűzetről és küldi a kimenetét a képernyőre (hacsak át nem irányítottuk). A háttérben futó jobok azonban semmilyen billentyűzetről jövő bemenetet sem kapnak meg. (Vigyázat, mert a képernyőre attól még írhatnak!)

A háttérben futtatás nagyon jól használható abban az esetben ha egy olyan programot futtatunk ami sokáig fut és semmi érdekeset nem produkál (pl. nagy fájlok tömörítése az előtérben - csak megrögzött DOS felhasználóknak ajánlott). Ebben az esetben nincs értelme arra várni, hogy a job lefusson, mikor közben valami mást is tudnánk csinálni (a számítógéppel). Futtassuk a háttérben!

A jobok lehetnek felfüggesztett állapotban (suspended); ez azt jelenti, hogy a jobot egy kis időre megállítjuk. Az ilyen job se az előtérben sem pedig a háttérben nem fut. Miután felfüggesztettünk egy jobot, a futtatását lehet folytatni tetszés szerint az előtérben, vagy akár a háttérben. A job ott folytatja a munkát, ahol előzőleg abbahagyta.

Figyelem! Egy job felfüggesztése nem ugyanaz, mint a megszakítása; ugyanis megszakítás esetén (Ctrl-c) a job már nem tudja a munkáját folytatni!

Vegyünk egy példát:

(A yes parancs y karakterek végtelen sorozatát küldi a kimenetére.)

woland> yes
y
y
y
y
y
Ez így menne a végtelenségig, ha meg nem szakítanánk. Ha csak nem az y-ok végtelen sorát akarjuk látni (márpedig mi mást szeretnénk csinálni) irányítsuk át egy alkalmas helyre: /dev/null - egy un. fekete lyuk: a beleirányított összes információt elnyeli.
woland> yes > /dev/null
Megy ez, de a job még mindig az előtérben fut. Hogy a háttérbe tegyük, a "&" jelet kell alkalmaznunk, ugyanis ez jelzi a Unix számára azt a vágyunkat, hogy a jobot a háttérben akarjuk futtani.
woland> yes > /dev/null &
[1] 3954
woland>
Amint látjuk, a shell promptját visszakaptuk, két furcsa számmal együtt. Mik ezek, és a yes fut-e egyáltalán?

Az [1] a yes processz job számát jelenti a shell számára. A shell minden futó jobhoz rendel egy számot. Mivel még csak a yes-t futtatjuk, ezért annak száma 1. A másik szám a processz azonosítója (PID mező a ps-ben) - a processzre mindkét számmal utalhatunk.

Nézzük meg, hogy valóban fut-e a processzünk?

woland> jobs
[1]  + Running              yes > /dev/null 
woland>
Igen, a processzünk fut. A ps paranccsal is megbizonyosodhatunk efelől.
woland> ps
  PID TT STAT  TIME COMMAND   
 3902 p0 S     0:01 -tcsh (tcsh)
 3954 p0 R     6:00 yes       
woland>

Most már tudunk jobot a háttérbe tenni, de valahogy le is kéne állítani, ha esetleg magától nem áll le (a yes-nél ez nagyon valószínű). Erre való a kill parancs, paramétere lehet a job száma vagy pedig a processz azonosítója. Használjuk:

woland> kill %1
vagy
woland> kill 3954
A % jellel jelezzük azt, hogy job számot adunk meg. Ha processz azonosítót adunk, akkor nincs szükség másra csak a processz azonosítójára. Lássuk, mi történt.
woland> jobs
[1]  + Terminated           yes > /dev/null
woland>
Mint látható, a jobot kilőttük, a következő job listában már nem is fog szerepelni.

Megjegyzés: Előfordulhat, hogy egy háttérben futó processzt sehogyan sem tudunk megállítani. Használjuk ilyenkor a "kill -KILL processz száma (vagy job száma)", vagy "kill -9 processz száma (vagy job száma)" parancsot (a két parancs ekvivalens)! Ez a Unix számára azt jelenti, hogy mindenképp lője ki a processzt.

Van egy másik lehetőség is arra, hogy egy jobot a háttérben futtassunk, mégpedig az, hogy futását felfüggesztjük, majd a háttérbe téve futtatjuk tovább.

Indítsuk el:

woland> yes > /dev/null
Majd nyomjuk meg a <Ctrl-z>-t , amivel a job futását felfüggesztjük.
woland> yes > /dev/null
<Ctrl-z>
Stopped
woland>
A program futását ezután mind az előtérben, mind a háttérben folytathatjuk. Az előtérben való folytatásra az fg parancs szolgál, a háttérben futtatásra pedig a bg.
woland> fg
yes > /dev/null
<Ctrl-c>
woland> bg
[1]    yes > /dev/null &
woland>
Természetesen mind az fg mind a bg parancsnak is megadhatunk job számot és így akár háttérben futó jobokat is vissza lehet hozni az előtérbe és fordítva.
woland> fg %2
vagy az egyszerübb formát is használhatjuk:
woland> %2

Egyéb job vezérlő (control) parancsok

Még két parancsról kell ebben a fejezetben beszélnünk: ezek a nohup és az at. A nohup (jelentése no-hangup) arra szolgál, hogy egy processz azután is fusson, miután mi kiszálltunk a rendszerből; különben a háttérben futó processzek megállnak.
szintaxisa: nohup <parancs>
Például:
nohup compress nagyon_nagy_program &
Ezután nyugodtan hazamehetünk, a processz le fog futni és mire másnap bejövünk, az eredmény látható lesz.

Megjegyzés: egyes Unix változatokban nincs nohup; az &-el indított processzek akkor is tovább futnak, ha kilépünk.

Az at paranccsal egy programot egy meghatározott időpontban futtathatunk (igazi Unix buherátorok nem használják; úgyis mindig ott vannak a gép mellett, úgyhogy a kellő időben ők maguk tudják futtatni az ilyen programokat). Az at parancsot úgy használjuk, hogy megadjuk az időpontot, amikor el akarjuk indítani a kérdéses programot, majd leütjük az entert. Erre (a legtöbb gépen) megjelenik az at> prompt, ahova be kell gépelnünk az elindítandó programok neveit. A listát a <Ctrl-d> leütésével zárjuk. Ha a program(ok) futtatásakor nem vagyunk bejelentkezve, akkor a program által generált kimenetet a rendszer E-mailben elküldi nekünk.

Például:

at 8:00am jan 24
at> csenget
<Ctrl-d>
Ennek eredményeképp a gép január 24.-én reggel 8-kor csengetni fog (feltéve ha a csenget program valójában csenget, nem pedig perverz leveleket küld a bejelentkezve levő felhasználóknak).

Feladatok

  1. Nézzük meg milyen shellünk van (ps).

  2. Próbáljuk meg kilőni az aktuális shellünket (kill -KILL). Mi történt? Miért?

  3. Nézzük meg az aktuális dátumot és időt (date) és tegyük fel az at várólistájára a következő parancsot: echo "Haho" | Mail -s "greeting" orlando@mars.sztaki.hu úgy, hogy az öt perc múlva induljon!

  4. Nehéz! Fűzzük össze a /etc könyvtárban lévő fájlokat (cat) és ennek kimenetét adjuk át a szabványos Unix tömörítő programnak (compress), az eredményt irányítsuk egy fájlba (különben nagyon érdekes Unix élményben lesz részünk, mindenféle absztrakt karakterek jelennek meg a képernyőn)! Nézzuk meg milyen tömörítési arányt sikerült elérnünk. (A du és az ls -l parancsok segítenek ebben!)

    Most ismételjük meg a feladatot a háttérben. Nézzük meg, hogy fut-e, és ha igen, akkor lőjük ki!

  5. Nézzük meg, hogy eddigi munkánkkal mennyi helyet foglalunk!


*************************************************************************
*=                                                                     =*
*=                           SZERZOI JOGOK                             =*
*=                                                                     =*
*=   Ez  a dokumentum a Unix  operacios  rendszer  es a szamitogepes   =*
*=   halozatok elterjedeset  kivanja  elosegiteni, ezert dijmentesen   =*
*=   terjesztheto.  Nem szabad azonban a terjesztes soran a szoveget   =*
*=   megvaltoztatni,  barmilyen  modon  megcsonkitani  es a  szerzoi   =*
*=   jogokra vonatkozo megjegyzest eltavolitani!  Sem  a dokumentum,   =*
*=   sem annak barmely resze nem hasznalhato fel segedanyagkent vagy   =*
*=   tankonyvkent profitorientalt intezmenyekben vagy tanfolyamokon,   =*
*=   a szerzok elozetes irasbeli engedelye nelkul!                     =*
*=                                                                     =*
*=   (C) Csaky Istvan es Mork Peter         Miskolc, 1994. januar 19   =*
*=                                                                     =*
*************************************************************************