6. Átirányítások¶
Az eddigi példákban a parancsok a képernyőre írták a kimenetüket. Eddig nem volt fontos, hogy ezt a kérdést tisztázzuk, de ebben a fejezetben pontosítanunk kell, a kimenet valójában nem a képernyőre, hanem az ún. standard outputra kerül (ami alapértelmezésben az a képernyő, amit a bejelentkezésed során látsz). Ez a kimenet megváltoztatható, lehetőséged van arra, hogy azt átirányítsd egy fájlba, valamilyen eszközre vagy akár egy másik parancs bemenetére.
6.1. A kimenet átirányítása¶
Egy parancs kimenetének átirányításához a > karaktert kell használnod a parancs leírásának végén. Erre érdemes úgy gondolnod, mint egy nyílhegyre, ami az átirányítás céljára mutat. Első példáinkban ez a cél egy fájl, a /tmp/lista.txt
lesz.
feri@columbo:~/demo$ ls -l /etc/d*.conf >/tmp/lista.txt
A parancs lefutása során nem jelenik meg semmi a képernyőn, mert az, amit az ls kiírt volna, az a /tmp/lista.txt
fájlba került. Nézzük meg, így van-e, írjuk ki a képernyőre a fájl tartalmát! Ehhez a cat parancsot fogom használni.
feri@columbo:~/demo$ cat /tmp/lista.txt
-rw-r--r-- 1 root root 2969 márc 15 2012 /etc/debconf.conf
-rw-r--r-- 1 root root 604 okt 20 2011 /etc/deluser.conf
A kimeneti fájl a parancs hatására automatikusan létrejön, ha korábban létezett, a korábbi tartalmát a rendszer törli, a helyét az új tartalom váltja fel. Ha nem ezt szeretnéd, hanem a fájl eredeti tartalmához hozzá szeretnéd fűzni az új tartalmat, a > helyett a >> karaktereket kell használnod. Az előző példában létrehozott /tmp/lista.txt
tartalmát most az /etc
könyvtár s*.conf
fájljainak tartalomjegyzék soraival bővítem:
feri@columbo:~/demo$ ls -l /etc/s*.conf >>/tmp/lista.txt
feri@columbo:~/demo$ cat /tmp/lista.txt
-rw-r--r-- 1 root root 2969 márc 15 2012 /etc/debconf.conf
-rw-r--r-- 1 root root 604 okt 20 2011 /etc/deluser.conf
-rw-r--r-- 1 root root 10344 jan 15 2014 /etc/sensors3.conf
-rw-r--r-- 1 root root 7096 febr 28 2014 /etc/smartd.conf
-rw-r--r-- 1 root root 2084 ápr 1 2013 /etc/sysctl.conf
A >> használata miatt most a /tmp/lista.txt
tartalmát nem írta felül az újabb parancs kimenete.
6.2. A hibacsatorna¶
Végezzünk el egy kísérletet (már ha ebben az esetben lehet ezt a szót használni)! Létrehozok egy könyvtárat „kétszer”. A második esetben hibaüzenetet fogok kapni, amit szeretnék átirányítani azért, hogy ne csúfítsa el a képernyőt. Az átirányítás célja a /dev/null
lesz.
feri@columbo:~/demo$ mkdir teszt
feri@columbo:~/demo$ mkdir teszt
mkdir: nem lehet a következő könyvtárat létrehozni: ”teszt”: A fájl már létezik
feri@columbo:~/demo$ mkdir teszt >/dev/null
mkdir: nem lehet a következő könyvtárat létrehozni: ”teszt”: A fájl már létezik
Sajnos hiába alkalmaztam az átirányítást, ebben az esetben valamiért nem működik. Hogy lehet ez?
A programok megírásakor a hibaüzeneteket nem ugyanazzal a kiíró utasítással írják ki, mint amit a normál üzenetek esetén használnak. C#-ban a kiíró utasítás a Console.Writeline(), C++-ban a cout. Ha hibaüzenetet írnak ki, nem ezeket használják, hanem azokat, amelyek a hibacstornára írnak, ez a C#-ban Console.Error.WriteLine(), a C++-ban a cerr. Ez ad lehetőséget arra, hogy az operációs rendszer szintjén is szétválaszthasd a normál üzeneteket a hibaüzenetektől, mert az előbbiek a standard outputra, utóbbiak a standard errorra íródnak.
A hibacsatornára írt kimenetek átirányítására a 2> jelölést kell használni. A fenti példát most helyesen megírva, a hibaüzenet célja most a /dev/null
lesz, a képernyőn nem jelenik meg.
feri@columbo:~/demo$ mkdir teszt 2>/dev/null
A két átirányítást együtt is használhatod. Az alábbi parancsban a normál kimenet a /tmp/kimenet.txt
, a hibaüzenetek a /tmp/hibak.txt
fájlba kerül.
feri@columbo:~/demo$ command >/tmp/kimenet.txt 2>/tmp/hibak.txt
Ha a kimenetet és a hibákat is ugyanabba fájlba szeretnéd irányítani, egy rövidebb írásmódot is alkalmazhatsz. A >/tmp/uzenetek.txt 2>&1 azt jelenti, hogy a kimenet kerüljön a /tmp/uzenetek.txt
fájlba, a hiba pedig íródjon ugyanebbe.
feri@columbo:~/demo$ command >/tmp/uzenetek.txt 2>&1
Megjegyzés
Mi az a /dev/null
? Most nem szeretném még részletesen elmagyarázni, az eszkozfajlok-reference-label c. részben részletesen lesz róla szó. Most elégedj meg annyival, hogy ez egy speciális fájl, amelybe olyan kimeneteket szoktunk átirányítani, amire nincs szükség, a cél csak annyi, hogy az ne jelenjen meg.
6.3. A bemenet átirányítása¶
A bemenet átirányítása szintén hasznos lehetőség a gyakorlatban, nagy mennyiségű adat gyors bevitelét oldhatod meg, ha a billentyűzet helyett a bemenetet pl. egy fájlra cseréled. Ahhoz, hogy ezt meg tudjam mutatni neked, készítettem egy ketszeres nevű programot, amit a /usr/local/bin
könyvtárba másoltam. Ez a pársoros program a standard inputról számokat vár, és minden begépelt szám esetén kiírja annak kétszeresét. Próbáljuk ki!
feri@columbo:~/demo$
3
3*2=6
6
6*2=12
12
12*2=24
^C
Azokat a sorokat, amelyekben egy szám szerepel, én gépeltem be a billentyűzeten, a szorzatot tartalmazó sorok a program válaszai. Az utolsó sorban látható ^C
akkor jelent meg, amikor a program futtatását a Ctrl-c megnyomásával megszakítottam.
Tételezzük fel, hogy sok szám kétszeresét kell kiszámolnod, és ezek a számok egy fájlban rendelkezésedre állnak az adatok.txt
fájlban:
feri@columbo:~/demo$ cat adatok.txt
3
6
124
12
Végezzük el a kétszeresek kiszámolását minden számra, ami az adatok.txt
fájlban van! Ehhez a ketszeres program bemenetét át kell állítani a billentyűzet helyett az adatok.txt
fájlra, amihez a < karaktert, majd a forrás fájl nevét kell használni:
feri@columbo:~/demo$ ketszeres <adatok.txt
3*2=6
6*2=12
124*2=248
12*2=24
A parancs eredményként egy pillanat alatt minden szám kétszeresét kiszámolta a program anélkül, hogy egy gombot is le kellett volna nyomni a billentyűzeten. A standard input átállításával a program a adatok.txt
sorait úgy dolgozta fel, mint ha azokat normál esetben a billentyűzeten gépeltem volna be.
Megjegyzés
Felmerülhet a kérdés, hogy most miért csak a kiszámolt eredmények sorai látszanak. A billentyűzet használata esetén a terminál – úgy mondjuk – visszaechózza a begépelt karaktereket, ami a bemenet átirányítása esetén nem történik meg.
A ketszeres program forrása az alábbi, hamarosan te is könnyedén megírod majd te is.
#!/bin/bash while read I ; do echo "$I*2="$(expr $I \* 2) done
6.4. Átirányítás más programra¶
Az átirányítások legizgalmasabb területe az, amikor a kimenetet egy másik program bemenetére irányítjuk át. Ezzel olyan komplex feladatokat oldhasz meg, amelyekre más rendszerek esetén programokat kellene írnod. Ezzel a következő fejezet foglalkozik, Szűrők címmel.
Ha egy program kimenetét egy másik program bemenetére akarod irányítani, a | karaktert kell használnod. Az alábbi példában e logika mentén használom a ketszeres programot:
feri@columbo:~/demo$ cat adatok.txt | ketszeres
3*2=6
6*2=12
124*2=248
12*2=24
Bár az eredmény ugyanaz, mint amit a bemenet átirányításakor láttál, a működési mechanizmus más. Az első parancs, a cat adatok.txt kimenete 4 sor, amely egyenként a 3, 6, 124 és a 12 számokat tartalmazza. Ez a | karakter miatt nem a standard outputra kerül, hanem az azt követő parancsra, amely példánkban a ketszeres. Ez minden, a bemenetére érkező sort feldolgoz és a kimenetére küldi, ami egyéb rendelkezés híján a terminál képernyője lesz.
Gondolom, nem lepődsz meg, ha azt mondom, nem csak két programot köthetsz így össze, hanem többet is, ennek során az egyik kimenete az azt követő parancs bementére kerül, annak kimenet az őt követő bemenetére és így tovább, valahogy így:
feri@columbo:~/demo$ command1 | command2 | command3
Mivel ez a folyamat arra emlékeztet, mint ha egy csőben áramlanának az adatok, ezt ezt a struktúrát csőnek, angolul pipe-nak nevezik. Ugyanígy a | karakter neve is pipe.
A következő fejezetben olyan programokkal ismerkedünk meg, amelyeket tipikusan ilyen felhasználásra terveztek, az összefoglaló nevük: Szűrők.
6.5. Ellenőrző kérdések¶
Mi a standard input és standard output?
Mi az átirányítások módja, és mik a tipikus átirányítási célok?
Hogyan lehet a kimenetet átirányítani?
Mi a hibacsatorna és hogyan kezelhető?
Hogyan lehet a bemenetet átirányítani? Adjon példát a használatára!
Hogyan lehet a kimenetet más program bemenetére átirányítani?
6.6. Feladatok¶
Az ls parancs kimenetét irányítsd át a
/tmp/lista-<username>.txt
fájlba, ahol a <username> helyére helyettesítsd be a bejelentkezési nevedet!Az
/etc
könyvtár conf-ra végződő fájljainak tartalmát másold össze egyetlen fájlba, a/tmp/lista-<username>.txt
-be! Mi történt annak korábbi tartalmával?A
/tmp/lista-<username>.txt
fájlhoz fűzd hozzá az aktuális dátumot és időt!Hozd létre a
/tmp
könyvtárat! Az esetleges hibaüzeneteket irányítsd át ahiba.txt
fájlba!Hozd létre a
/tmp
könyvtárat! Gondoskodj róla, hogy az esetleges hibaüzenetek ne jelenjenek meg!