Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
Alapfogalmak a héj (shell) használatához 1. A shell - definíció és típusok.......................................................................................................1 Alias-ok (helyettesítő nevek)..................................................................................................4 2. A parancsvégrehajtás ..................................................................................................................4 3. A shell változói ...........................................................................................................................5 A {} jelölés ............................................................................................................................6 Az echo parancs .....................................................................................................................7 Az export parancs ..................................................................................................................9 5. Átirányítások és csővezetékek ....................................................................................................9 6. A parancs behelyettesítés...........................................................................................................12 7. A parancssor átírása...................................................................................................................13
1. A shell - definíció és típusok 1.1 A shell A shell egy időben egy interaktív parancs végrehajtó és egy programozási nyelv (interpretált szkript nyelv). Az interpretált (értelmezett) nyelvek olyan programozási nyelvek, amelyeknél a futtatás előtt nem állítanak elő gépi kódot. Magát a programszöveget értelmezi egy "értelmező" program, a mi esetünkben ez maga a shell. A UNIX parancsértelmezőjét magyarul héj-nak vagy burok-nak is nevezzük (mert a felhasználó szempontjából "körülveszi" az operációs rendszer magját. A tanfolyam folyamanán mi a héj vagy shell megnevezéseket fogjuk használni. Több változata létezik, ezek a UNIX fejlődésének különböző szakaszaiban jelentek meg. Bourne (a programot tartalmazó bináris kód neve a rendszeren: sh) shell A UNIX első éveiben a shell "programozási nyelv" jellege nem volt annyira hangsúlyos, elsősorban a parancsok futtatását oldotta meg. A Bourne shell volt az első parancsértelmező amelyiket kimondottan arra fejlesztették, hogy szkript nyelv is legyen egyben. 1977-ben fejlesztettét az AT&T-nél (első fejlesztő Stephen Bourne). Ezzel vezettek be sok új lehetőséget először, mint a parancssor behelyettesítése, a 2-es jel használata a standard hibakimenet jelölésére. A későbbi években is az AT&T-nél fejlesztették. Korn (ksh) shell Ezt a változatot ugyancsak az AT&T-nél fejlesztették tovább (David Korn), és a legfontosabb fejlesztési cél a shell programozási nyelvvé való átalakítása volt. Visszafelé kompatibilis maradt a Bourne shell-el. Sok új lehetőséget vezettek be, így az asszociatív tömböket, és a valós számokkal való számítást. A POSIX standard "Shell Language Standard" nevű előírásait pontosan betartja, ezért leginkább ezt használják ipari standard shell-ként a UNIX variánsokban. Eleinte az AT&T tulajdonában volt a fejlesztése, 2000-ben nyílt forráskódúvá tették és jelenleg Common Public Licence licenc alatt fejlesztik. Annak ellenére, hogy a mindennapi munkában sokan ennek modernebb változatait vagy a Bash-t használjuk, UNIX karbantartó vagy installáló szkriptekben legtöbben ma is a Bourne vagy a Korn régi változatait futtatják. C shell (csh) 1
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
A C Shell-t a BSD fejlesztés során fejlesztették (Bill Joy, a későbbi Sun Microsystems alapító). Amint nevéből kiderül, szerkezetei hasonlítanak a C-re. Ebben fejlesztették tovább a feladatok (jobs) felügyeletét biztosító szerkezeteket. Nem annyira használt mint a Bournera épülő változatok. Jelenleg tcsh nevű modern változatát használják, és leginkább a BSD alapú rendszereken felhasználóinál gyakori a használata. Bash (bash) A Bash (Bourne again shell) változatot eleve nyílt forráskódúnak kezdték fejleszteni. A kompatibilitás szempontjából mind a Bourne, mind Korn shell-t követi, és sok ezekre írt szkript lefut módosítás nélkül a bash-en is. Mindhárom előzőleg említett shell-ből vett át megoldásokat, de fejlesztett saját nyelvi lehetőségeket is. Modern Linux-okon általában ez az alapértelmezett shell, és valószínű, hogy a leggazdagabb programozási lehetőségeket ez nyújtja. A bibliográfiában említett "Learning the bash shell" című könyv részletesen bemutatja nyelvi lehetőségeit. Azt, hogy egy rendszeren melyiket lehet használni, a /etc/shells állomány tartalmából tudhatjuk meg. Ez pl. Fedora disztribúció alatt az alábbi módon nézhet ki: $cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/zsh /bin/tcsh /bin/csh /bin/ksh
Látható, hogy a rendszeren egyszerre több shell lehet. A Linux alatt többnyire a Bash shell-t használjuk, de a többi is ott szokott lenni a gépen. A legtöbb programhoz viszont a Bourne shell alá írják a telepítő, indító, stb. szkripteket. Az iparban nagyon sok helyen a Korn shell-t használják mint standardot, ezt standardizálja a POSIX is. A felhasználó által használt alapértelmezett shell-t a rendszer a /etc/passwd állomány felhasználót leíró sorában találja meg. A tanfolyam során igyekszünk klasszikus elemeket használni, amelyek a Bourne és Korn héjakra épülnek. Megemlítjük, ha egy-egy jellegzetességet csak a Korn vagy Bash nyújt.
1.2 Shell programok Egy héjprogram állomány (vagy shell szkript) egyszerű szöveges állomány, amelyet a shell soronként értelmez. Minden egyes sort külön parancsnak vesz (mintha a parancssorról ütöttük volna be), és egyenként végrehajtja őket. A parancssor formátumát láttuk már a terminál használatakor: a parancs nevéből, kapcsolókból és argumentumokból áll. A shell számára a megjegyzést deklaráló karakter a # (kettős kereszt, angol: hash mark). Azokat a sorokat amelyekben megjelenik a kettős kereszt karaktertől a sor végéig megjegyzésnek tekinti a shell (az alábbi példában a shell készenléti jele a $). $ #itt rendezzük az állományt $ sort szoveg.txt
A shell program első sora speciális lehet. Itt adhatunk meg információt arról, hogy a szöveges állományt milyen értelmezővel szeretnénk végrehajtani. Ez úgy történik, hogy ez a sor egy olyan megjegyzést tartalmaz, amelyben a kettős keresztet azonnal egy felkiáltójel követ (tehát: #!áll ott), utána pedig a kívánt értelmező teljes elérési útja. 2
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
Így egy egyszerű szkript (hello.sh) így néz ki: #!/bin/bash echo hello echo vege
(a #! szimbólumok és az elérési út a modern előírások szerint szorosan követik egymást, régi héjakben használatos volt a szünet is köztük. A hivatkozott értelmező program teljes elérési útját meg kell adni, mint: /bin/bash vagy /bin/sh ) Végrehajtva az alábbit látjuk: $ bash hello.sh hello vege $
A végrehajtás tehát azt jelenti, hogy elindítjuk a shell-t (és ez egy új shell lesz) úgy, hogy argumentumként (amelyet ő bemenetnek használ) megadjuk a programot tartalmazó állományt. Amennyiben a bash-t megjelölő sor hiányzik, a shell megpróbálja a szöveget a felhasználó számára beállított alapértelmezett shell-el végrehajtani (ennek nevét a $SHELL környezeti változó tartalmazza). A két echo helyén bármilyen hosszú szöveg állhat, egymás utáni parancssorok amelyeket a shell egymás után: mindig az előző lefutását megvárva hajt végre.
1.3 Shell parancsok Amikor a shell megkap egy parancsnevet, az alábbi kategóriákban kezdi keresni: -beépített parancsok - a nagyon gyakran használt parancsokat beépítik a shellbe. Így ezeket sokkal gyorsabban lehet végrehajtani. Ilyen például az echo, pwd, history, test. Ugyanakkor ezek léteznek önálló parancsként is (bináris program). -függvények - a shell nyelvén függvényeket lehet meghatározni az olyan feladatokra amelyeket többször hívunk meg. Ezekkel később foglalkozunk. -külső parancsok - azok a parancsok amelyek programok formájában valahol az állományrendszerben találhatóak. -alias-ok: helyettesítő nevek vagy pszeudo parancsok (lásd alább) A héjba épített parancsokra leírást a Linux rendszerekben a help paranccsal kapunk. A help argumentum nélkül a beépített parancsokat, argumentummal egy parancs segédletét listázza. Tehát a man echo a UNIX külső echo-jának, a help echo pedig a belső echo segédletét írja ki. Bash alatti futtatásnál az ugyanolyan nevű beépített parancs fut a külső helyett (ha nem hivatkozunk a külsőre speciálisan). A külső parancsok programokat jelentenek, amelyeket a shell meg tud keresni az állományrendszerben, és a shell-t futtató felhasználónak végrehajtási joga van reájuk. Ezeket a $PATH környezeti változóban leírt útvonalakon keresi a shell. 3
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
Alias-ok (helyettesítő nevek)
Az alias-ok vagy helyettesítő nevek arra szolgálnak, hogy a gyakran használt, több kapcsolóval meghívott programoknak egy helyettesítő nevet adjunk, és gyorsabban, egyszerűbben hivatkozzunk rájuk. Jellegzetes példa a Linuxon az ls parancsot helyettesítő alias, amely színes kiírással hívja meg az ls-t. Létrehozása az alias paranccsal történik: $ alias ls='ls --color=tty'
Amint látható, az alias létrehozás tulajdonképpen a névnek egy karakterláncot feleltet meg, és meghívásakor ez helyettesítődik a parancssorra. A helyettesítő neveknek elsőbbségük van az ugyanolyan nevű parancsokhoz képest amikor meghívjuk őket. Törlésük az unalias , listázásuk egyszerűen az alias paranccsal történik. $ unalias ls
2. A parancsvégrehajtás Hogyan fut le egy egyszerű parancsvégrehajtás? Beépített parancsok esetében a futó shell végzi ezt. Külső parancsok, azaz programok futtatása során az alábbi történik:
Amikor a shell elfogadja a parancsot és elindítja, azt mondjuk, hogy egy új folyamat jön létre: a futó shell fiú folyamata. Amikor a program kódja betöltődik, a kódon kívül az operációs rendszer több információt létrehoz illetve követ: ezeket együtt folyamatnak nevezzük. Tehát egy futó programot mindig folyamatként fogunk emlegetni. A parancsvégrehajtásnál új folyamat keletkezik, amelyben a shell végrehajtja a parancsot. Ugyanakkor a futó shell maga is egy folyamat. Egy parancssoron (az új sor elválasztó karakterig tartó karakterlánc) általában egy programot indítunk el. Megtehetjük, hogy többet indítsunk el egyszerre, ha köztük a ; -t használjuk mint elválasztó jelet. $ echo "rendezes indul" ; sort szoveg.txt;
echo "vege"
Ilyenkor a második parancs megvárja az elsőt, tehát nem párhuzamosan hajtódnak végre. A parancssoron elindított programról azt mondjuk, hogy "előtérben fut"; mivel a terminálra ír, és ilyenkor a shell nem adja vissza a készenléti jelet (prompter): azt jelzi ezzel, hogy nem fogad el új parancsot az előző befejezéséig. Megtehetjük, hogy a parancsot "háttérben" futtassuk; ilyenkor a shell visszaadja a készenléti jelet, 4
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
és új parancsot üthetünk be. A háttérben futtatást kétféleképpen válthatjuk ki: 1) a parancssort a parancs indításakor az & jellel zárjuk, ilyenkor a folyamat azonnal a háttérben indul; 2) az előtérben futó folyamatot felfüggesztjük a suspend jelzéssel (^Z kombináció a terminálról), majd a bg (background) paranccsal háttérben indítjuk. A jelzések tulajdonképpen szoftver útján küldött megszakítások: a felfüggesztés tipikus példa erre. Lenyomunk egy billentyűt amely valamilyen megszakítás közvetítésére használunk, és azt a shell rendszert vezérlő kernel-en keresztül eljuttatja a folyamathoz. Mindkét esetben a shell 2 számot, egy feladat (job) azonosítót illetve egy folyamat azonosítót ír ki számunkra. $ sort rendezetlen.txt > rendezett.txt & [1] 4467 $
Ezek segítségével hivatkozhatunk később az elindított munkára, például az előtérbe hívhatjuk az fg (foreground) paranccsal. A munkák illetve folyamatok kezelésével, valamint ezek különböző indítási módjával később, a Folyamatok kezelése c. fejezetben foglalkozunk, itt csak röviden adtuk meg az elindításukhoz szükséges szintaxist. Egyelőre az alábbit kell megjegyezni: parancs indításkor mindig egy új shell indul el. Ez futtatja a megadott parancsot, és átveszi a futtató shell tulajdonságait: ugyanarra a standard kimentre ír, ugyanarról a bemenetről olvas, ugyanabban a munkakönyvtárban dolgozik és megkapja az indító shell környezeti változóit. A fenti példaprogramot (hello.sh) egyszerűbben is indíthatjuk. Mivel a shell elindít bármely szöveges állományt ha az végrehajtható és megadtuk az értelmező programját, egyszerűen végrehajtási jogot adunk rá, és az állomány nevével - mint parancsnévvel indítjuk. Természetesen ilyenkor is elindul egy új shell, a program szöveget értelmezve: $ chmod u+x hello.sh $ ./hello.sh hello vege $
3. A shell változói 3.1 Az általános shell változók A shell az adatok, információk tárolására változókat használ. Mivel a shell parancsai szövegekből épülnek fel, a változók nevét és értékét is egyaránt sztringekben tárolja. A név-érték hozzárendelést egyszerűen az = jel segítségével adjuk meg. Például a $ szin=piros
sor végrehajtása során létrejön az a szin változó piros értékkel. Látható, hogy a változó létrehozása dinamikus: akkor jön létre amikor deklarálom, nincs szükség előzetes definícióra. Amikor a létrejött változót később shell parancsok argumentumaiban használjuk, egy $ jellel és a változó nevével hivatkozunk rá. Tehát $szin lesz a hivatkozott változó, és ezt így használjuk: 5
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás $ echo $szin piros
A változók tehát sztringeket tartalmaznak, így megtörténhet az is, hogy nincs értékük (üres sztringet tartalmaznak). A változók értékét idézőjelek közé is tehetjük, sőt, ha a változó értéke olyan sztring amelyik elválasztó karaktert is tartalmaz, akkor kötelezően ezt kell tennünk. Például, ha egy változó értéke a piros alma karaktersor, akkor ezt így kell megadni: $valt="piros alma"
Egyébként a shell csak a piros sztringet rendelné a változóhoz és úgy értelmezné, hogy az alma egy következő parancs része. A változók neve az angol Abc betűiből (kis és nagybetű közti eltérés számít) valamint a számjegyekből és a _ aláhúzásjel karakterből állhatnak.
3.2 Az idézőjelek használata és az echo parancs Háromféle idézőjelet használhatunk a shell programokban: " (idézőjel, double quote), ' (aposztróf, single quote vagy forward tick) és ` (vissza idézőjel, backtick). A ' egyes idézőjel vagy aposztróf segítségével olyan sztringeket deklarálunk, amelyekben minden egyes karakter elveszti a shell szerinti metakarakter jelentést, és betű szerint lesz értelmezve. Tehát az alábbi kiíráskor: $ $ echo -e 'ez itt egy $ jel' ez itt egy $ jel valódi $ kerül a kimenetre. A shell nem ír át semmit a sztring belsejében, úgy dolgozik vele ahogy
leírtuk. A " kettős idéző jelet is sztringek deklarálására használjuk. Amikor egy sztringet kettős idézőjellel veszünk körül, akkor a shell a sztring belsejében a változók nevét átírja, és úgy használja fel őket a továbbiakban. $ szin=piros $ echo "$szin alma" piros alma
A harmadik idéző jelet, a vissza-idézőjelet az un. parancs behelyettesítés végrehajtására használjuk, lásd alább. A {} jelölés
Mivel ilyen esetekben előfordul, hogy a shell nem tudja a változó nevét meghatározni, például alábbi esetben, ha a "pirosalma" szöveget akarjuk kiírni: $ echo "$szinalma"
(meddig tart a változónév? a shell úgy fogja értelmezni, hogy egy új változó nevet használunk, a $szinalma nevűt), létezik egy jelölési mód ami ezt egyértelművé teszi. Ilyenkor a változó nevét jelentő karakterekláncot {} zárójelekkel vesszük körül. Így már egyszerű kifejezni a változót: $ echo "${szin}alma"
A jelölés még néhany további kiértékelést is lehetővé tesz a kapcsos zárójelek között: ${szin:-piros} ha a változó nem létezik, nem ad értéket a változónak, de visszatéríti a "piros"-at ${szin:=piros}
ha a változó nem létezik, értéket a változónak és visszatéríti a "piros"6
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
at ${szin:?hibas szin}
ha a változó nem létezik a shell program hibaüzenettel leáll
Az alábbi kis programban (szin.sh) nem adunk értéket a $szin változónak, így első használatkor automatikusan felveszi azt: #!/bin/sh echo ${szin:=piros} echo $szin exit 0
Elindítva a program kétszer fogja a "piros" sztringet kiírni: $bash szin.sh piros piros $
Az echo parancs
Az echo parancs kiírja saját argumentumainak listáját és utána automatikusan egy új sor karaktert. echo argumentum_lista $ echo ez egy üzenet ez egy üzenet
Két kapcsolója van: -n nem ír új sor karaktert -e engedélyezi a következő speciális karakterek értelmezését a karakterlánc okban: \a riadó (csengő) \b egy karakter törlése visszafelé \c nem ír ki újsor karaktert \f lapdobás \n új sor \r kocsi vissza \t vízszintes tabulátor \v függőleges tab \\ backslash \nnn a karakter ASCII kódja nnn (oktálisan) \xnn a karakterkódot hexadecimálisan lehet megadni, pl. \x32
Az echo a leggyakrabban használt parancs a héjprogramokból való kiírásra. A shell rendelkezik ugyanakkor egy printf paranccsal is, amelyet ritkábban, abban az esetben használunk, ha bonyolultabban kell formatálnunk a kimenetet. Meghívása az alábbi: printf formatáló_sztring argumentumlista A formatáló sztring megegyezik a C nyelvből ismert printf szintaxisával, a kiírt argumentumokat pedig a formátum után, egy listában kell felsorolni, elválasztójelek nélkül. A printf nem ír ki automatikusan új sort, ezt meg kell adnunk egy \n karakterrel, akár a C nyelvben.
7
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás $ printf "Ez egy %s alma\n" $szin Ez egy piros alma
3.2 A környezeti változók Egy folyamat környezete mindazt az információt jelenti, amit a folyamat az őt futtató operációs rendszerről, gépről, beállításokról megtudhat. Ezeket az információkat többnyire változókban tároljuk (név-érték párok). Ezek a változók létrejönnek a shell indításakor, és úgy fér hozzájuk mint saját változóihoz. Többnyire nagy betűs változó nevekkel ábrázoljuk ezeket, különbséget téve így (a programozó számára) a saját, illetve az operációs rendszertől kapott változók közt. Ilyen változót már láttunk: például a végrehajtható állományok elérési útja, a PATH változó. $ echo $PATH /usr/local/bin:/bin:/usr/bin:/home/lszabo/bin:.
Néhány környezeti változót az alább sorolunk fel. A beállított változókat a printenv paranccsal lehet kilistázni. Például az alábbi változók szinte minden gépen be vannak állítva: HOSTNAME=eowyn.maros.emte.ro TERM=xterm SHELL=/bin/bash USER=lszabo MAIL=/var/spool/mail/lszabo PATH=/bin:/usr/local/bin:/bin:/usr/bin:/home/lszabo/bin:./ PWD=/home/lszabo EDITOR=/usr/bin/vim LANG=en_US.UTF-8 HOME=/home/lszabo LOGNAME=lszabo
3.3 A shell indítása Indításkor a shell végigolvas néhány konfigurációs állományt, ezek változókat állíthatnak be illetve programokat indíthatnak, amelyek meghatározzák azt a környezetet amelyben a shell indul. Ezek közt vannak olyan állományok amelyek közösek, tehát bármely felhasználó belépésekor értelmeződnek (/etc/profile, /etc/bashrc). Ezen kívül minden felhasználónak saját indító állományai vannak a home könyvtárában (.profile, .bash_profile, .bashrc). Ezeket szabadon szerkesztheti, és amennyiben indításkor automata módon akar változókat, alias definíciókat, stb. beállítani, azt innen teheti meg. A a .profile és .bash_profile állományok minden egyes belépésnél értelmezve lesznek (a megadott sorrendben). Így lehet például a PATH változó értékét megváltoztatni. Amennyiben azt szeretném, hogy a munka könyvtáram (./) is legyen a keresett könyvtárak közt a parancsok elindításánál, az alábbit kell beírnom a .bash_profile állományba: PATH=$PATH:./ export PATH
Az első sor átállítja (újra deklarálja) a PATH változót: a régi mögé odailleszti az elválasztó karaktert (:) és utána a pillanatnyi munkakönyvtár nevét, majd az export shell utasítással beírja a környezeti változók közé, úgy, hogy azt az általam indított folyamatok is örököljék. A bash esetében kilépéskor egy .bash_logout nevű állomány tartalma értelmeződik, ebbe írhatunk be rutin feladatokat, amelyeket kilépéskor kell végrehajtani.
8
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
Megjegyezés: a fenti konfigurációs állomány nevek a Bash-re érvényesek. Az export parancs
Amikor egy változót létrehozunk (pl. a fenti példában az új PATH változót), ez csak a héj számára lesz látható, a héjból induló parancsok számára nem. Az export beírja a héjváltozót azok közé a környezeti változók közé, amelyeket minden más általam indított parancs is megkap.
3.4 Nyelvi karakterkészlet beállítása (LANG, LC_ ) A shell karakterkészletének beállítása fontos, amennyiben például a magyar nyelv karaktereit akarjuk használni. Ezt a LANG illetve az LC_ kezdőbetűket tartalmazó shell változókkal tehetjük. Két paramétert kell ilyenkor beállítani: a karakterkódolást (encoding) és a nyelvet, esetleg országot amelyben az illető nyelvet beszélik. Az LC_ nevű változókkal (LC_ALL, LC_TIME, LC_NUMERIC) a nyelven kívül különböző helyi beállításokat lehet megadni (idő, számok formatálása). A nyelvi beállítást, amennyiben nincsenek LC_változók megadva, elsődlegesen a LANG változó adja meg, ennek lehetséges értékeit (ami függ attól, hogy fel vannak-e telepítve a szükséges szoftverek a rendszerre), a locale -a paranccsal lehet kilistázni. Ez például egy fedora Linux rendszeren a magyar nyelvi beállításokra az alábbi lehetőségeket listázza: hu_HU hu_HU.iso88592 hu_HU.utf8 hungarian
Az UTF-8 kódolás használata ma már jelentősen megkönnyíti ezeket a beállításokat.
4. A shell speciális változói A shell több speciális változót tartalmaz, amelyek minden esetben automatikusan létrejönnek. Többnyire olyan információkat fognak tartalmazni amelyek minden programra jellemzőek és gyakran használjuk őket. Néhányat megemlítünk itt részletesen, a többit ahogy haladunk az anyaggal. Ezeknek a változóknak a nevét többnyire úgy alakították ki, hogy a $ karakter után felhasználtak még egy speciális karaktert. Így például a parancssor argumentumait a $1, $2, ... $9 változókkal lehet elérni egy shell programból. Ezek a kapcsos zárójeles szintaxissal is használhatóak. Az alábbi szkript például kiírja első és harmadik argumentumát. #!/bin/bash echo $1 echo ${3}
A többi speciális változót később vezetjük majd be, ahogy használatra kerülnek. Listájukat megtalálhatjuk a Függelék 2. pontjánál.
5. Átirányítások és csővezetékek Emlékeztetünk a standard bemenet, kimenet és hibakimenet fogalmára egy futó programnál. Mindhármat állományként kezeli a shell (akárcsak a C nyelv). Jelölésükre egész számot tartalmazó azonosítókat használ a C nyelv akkor, amikor első szintű állománykezelő függvényeket használ. 9
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
0 - standard bemenet 1 - standard kimenet 2 - standard hibakimenet. Ezeket az azonosítókat a héj is használja.
5.1 Átirányítások Az átirányítások példáinál a sort , cat , head, tail parancsokat használjuk. Ezeket laboron vesszük át, leírásuk megtalálható az előadás honlapján. A héj szintaktikailag néhány szimbólumot használ a standard bemenet és kimenet illetve hibakimenet átirányítására. Ezek használata és jelentése az alábbi: A standard bemenet megváltoztatása a < jellel: az alábbi példában a sort program bemenete nem a standard bemenetről jön, ahogy az a sort egyszerű futtatásánál tenné, hanem a lista.txt nevű állományból. sort < lista.txt
A standard kimenet állományba irányítása a > jellel: az alábbi példában a sort program nem a terminálra, hanem a rendezett.txt nevű állományba ír, de a standard bemenetről olvas: $ sort > rendezett.txt b a $ cat rendezett.txt a
Megjegyzendő, hogy a > állományba irányítás törli a régi állományt ha ilyen nevű már létezik. A két típusú átirányítást akár egyszerre is használhatjuk: sort < lista.txt > rendezett.txt
A kimenet hozzáfűzése egy állományhoz a >> jellel: ezzel az átirányítással hozzáfűzés módban írunk a kimeneti állományba, tehát az állomány tartalma amennyiben létezik megmarad, és az új sorok az állomány végérekerülnek. $ echo elso > f $ echo masodik >> f $ echo harmadik >> f $ cat f elso masodik harmadik
5.2 Csővezetékek A csővezetékek az operációs rendszer által létrehozott kommunikációs csatornák, amelyeken keresztül egy folyamat kimenete egy másik bemenetére irányítható egy rendkívül egyszerű szintaxissal a parancssoron. A deklaráláshoz használt jel a | elválasztójel. Az alábbi példában a cat kimenetét a sort-ba irányítjuk (a sort parancs egyszerűen rendezi a bemenetére kerülő szöveges állomány sorait és átírja a kimenetre - részletes használatával később foglalkozunk): $ cat lista.txt | sort
10
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
A két folyamat adatai közti szinkronizációról az operációs rendszer gondoskodik. Az említett átirányítások többször is alkalmazhatóak ugyanazon a parancssoron. Az alábbi parancssoron a lista.txt állomány a cat-ből a sort-ra, onnan pedig a head parancs bemenetére kerül, és végső kimenetként csak a rendezett lista első sorát látjuk (csak ez érdekel minket): $ cat lista.txt | sort | head -1
Ebben az esetben a sort teljes kimenete nem kerül lementésre, csak a kívánt végeredményt kapjuk meg. Itt említjük meg a tee parancsot, amely sorozatos feldolgozás esetén biztosíthatja egy köztes kimenet elmentését, ha arra később szükség lehet. A tee használata az alábbi: tee [-a] állománynév
amelynek hatására a bemenetet a kimenetre és az adott nevű állományba írja. Az alábbi esetben elvégződik ugyanaz a feldolgozás mint a fenti példában, de ezúttal a sort által előállított teljes rendezett lista is elmenésre kerül: $ cat lista.txt | sort |tee rendezett.txt | head -1
5.3 Speciális eszközök Bizonyos esetekben hasznos ha állományokon kívül eszközöket is használhatunk a ki-és bemenetek átirányításakor. Ilyen például a /dev/null eszköz, amely végtelen sok karaktert teljesen elnyelő kimenetként viselkedik. Erre lehet minden olyan kimenetet irányítani, amelyre nincs szükség: jelenléte felesleges vagy zavaró. Például az alábbi parancs esetében az abc könyvtár tartalma listázódik ha van ilyen. Amennyiben nincs, az ls hibaüzenetét elnyeli a null periféria és nem látunk semmit. $ ls abc 2 > /dev/null $
5.4 A 2>&1 átirányítás és a naplózás Vannak esetek, amikor mindkét programkimenetet (kimenet és hibakimenet) ugyanabba az állományba akarjuk irányítani. Ilyenkor az egyik megoldás a feladatra az alábbi: -a kimenetet egy állományba irányítjuk -utána a hibakimenetet a kimenetre $ sort rendezetlen.txt $
>
naplo.txt
2>&1
Ilyenkor nyílván semmit sem látunk a terminálon, minden kiírt szöveg (akár eredmény, akár hiba) a naplo.txt nevű állományba kerül, és onnan olvashatjuk el később. A parancs lefutását pedig nyilván meg kell várnunk (nincs készenléti jel csak ha a sort lefutott). Ilyenkor megtehetjük, hogy a feladatot a háttérben futtatjuk (hiszen amúgy sem látunk semmit), az alábbi parancsindítással: $ sort rendezetlen.txt > naplo.txt 2>&1 & [1] 5039 $ Így azonnal új paranccsal foglalkozhatunk, nem kell a sort végére várnunk. A parancs lefutásának
eredménye, hibái pedig egy állományban lesznek rögzítve: az ilyen állományokat amelyeket későbbi felhasználásra rögzítünk nevezünk naplónak (log file). Van olyan eset, amikor a két kimenetet ugyanabba a csővezetékbe szeretnénk irányítani, ezt az alábbi megoldással érjük el: $ sort rendezetlen.txt 2>&1 $
|
cat
> eredmeny.txt
11
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
Először a hibakimenetet a standard kimenetre irányítjuk, majd a standard kimenetet vezetjük egy csővezetékbe. Utána a csővezetékéket egy másik program, jelen esetben a cat bemenetére.
5.4 Here document ("itt dokumentum") A következő átirányítás már nem a parancssorra, hanem a shell programokra jellemző. Segítségével a shell program bemenete átirányítható arra az állományra amelyben a shell program van. Használati módját az alábbi több soros szöveg adja meg: parancs << VEGE itt bármilyen szöveg állhat VEGE
A parancs végrehajtása után (ez bármilyen UNIX parancssor lehet), a shell a parancs bemenetét a saját programszövegére irányítja (az "itt bármilyen szöveg állhat" sorra vagy sorokra), és a parancs addig olvas innen, amíg egy sor elején ugyanarra a karakterláncra akad, amely a << jel után áll. Itt abbahagyja az olvasást, és a shell végrehajtja a következő soron levő parancsot. Az alábbi shell program (phone.sh) egyszerűen kiír egy telefonszám listát: 1 2 3 4 5 6 7 8 9
#!/bin/bash cat << VEGE Laci 0756-453-675 Peter 0744-456-436 Johanna 0722-567-890 VEGE echo ez mar nem "here document" kiiras
Végrehajtásakor az alábbit látjuk: $ bash phone.sh Laci 0756-453-675 Peter 0744-456-436 Johanna 0722-567-890 ez mar nem here document kiiras $
Miközben a szöveg átkerül az őt olvasó programhoz (a cat-hez ebben a példában), a shell ugyanúgy átírja, mintha "" kettős idézőjellel körülvett sorok lennének: tehát amennyiben a szövegben változók is vannak, azok átírásra kerülnek. Fontos: a VEGE jelet tartalmazó lezáró sorban akármilyen szócska állhat, de a sornak csak ezt az egyetlen szót kell tartalmaznia a sor elején.
6. A parancs behelyettesítés Parancs behelyettesítésnek azt a műveletet nevezzük, amely során a shell lefuttat egy parancsot, és a parancs kimenetét (standard kimenet) mint egyetlen karaktersort egy változóhoz rendel. Két jelölést használunk erre, egy hagyományosat és egy modernebbet. Hagyományos jelölés: változó=`parancsor`
tehát ilyenkor a két vissza idézőjel (back tick) veszi körül azt a parancssort, amelyet futtatunk.
12
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
A modernebb jelölés: változó=$(parancssor)
Mindkét jelöléssel lefuttatott hozzárendelés ugyanazt az eredményt idézi elő. Amint azt tapasztalni fogjuk, a $() jelölés jobban olvasható, ezért ezt ajánlott használni, de a gyakorlatban mindkettővel ugyanolyan mértékben találkozunk. Az alábbi példában az első parancssor echo kimenete nem a kimenetre kerül, hanem az üzenet változóba: $ uzenet=` echo "ez a kiirni valo" ` $ echo $uzenet ez a kiirni valo
Ugyanazt érjük el az alábbi jelöléssel: $ uzenet=$( echo "ez a kiirni valo" ) $ echo $uzenet ez a kiirni valo
A fenti példában az echo kimenete egy egy soros karakterlánc volt. Amennyiben nem így van, és a kimenet több sorból áll, a shell átírja az új sor karakter elválasztót egy szóköz karakterré. Ilyenkor egy karakterláncokból álló, szóközzel ellátott listát rendel a változóhoz. Például az ls -1 (ez úgy listáz, hogy minden egyes állománynév külön sorba kerül) parancs kimenetét változóba írva egy állománynév listát kapunk: $ ls -1 alma.sh hello.sh phone.sh $ lista=$( ls -1 ) $ echo $lista alma.sh hello.sh phone.sh $
7. A parancssor átírása A shell a parancssort végrehajtás előtt "átírja": ha vannak benne olyan szerkezetek vagy metakarakterek amelyeket a végrehajtás előtt behelyettesíthet, akkor megteszi azt. A metakarakterek olyan karakterek, amelyek mást jelentenek a shell számára mint betű szerinti jelentésük. Egyelőre az alábbiakkal találkoztunk: *
a munkakönyvtárban levő állomány neveket írja be helyette
~
a home könyvtár elérési útját jelenti (pl. /home/lszabo/ , ezt írja be a tilda helyett)
$
a közvetlenül utána következő karakterláncot változónévnek tekinti
A metakaraktereket lehet literális értelemben is használni a parancssoron, de ekkor backslash 13
Operációs rendszerek I. - UNIX felhasználói ismeretek és héjprogramozás
jelöléssel kell megadni vagy aposztróf közé kell zárni őket (így karakterláncot adunk meg). Egy * ot így írunk ki a terminálra: $ echo \* * $ #vagy: $ echo '*' *
A héj bonyolultabb folyamatok közti összefüggéseket is létrehoz amikor a parancssort kiértékeli, ezért később még visszatérünk a parancssor átírására.
14