Máma má annyira fejlettek és oly grafikussak a Linugzok, hogy a felhasználói lassan el is felejtik, hogy létezik olyan, hogy parancssor. Sokan a Windowsról áttérők közül boldogan pörgetik a kockát, aztán ha esetleg át kell nevezniük 100 fájlt, akkor
a) Nekiállnak egyesével
b) Keresnek a neten valami grafikus programot
c) Fórumokon sírnak.Még többen ezek közül, amikor egy veterántól azt hallják, hogy "usgyi parancssorba", akkor elborzadnak és inkább azt mondják, hogy "köszi de nem, jó lesz nekem ha egyesével átnevezgetem, majd csak végzek vele a héten". Pedig már a Windows 9x/2k/XP parancssorában is rengeteget meg lehetett tenni, a szabad OSS rendszerek parancssora pedig összehasonlíthatatlanul jobb. Van mostanában ez a Powershell, én nem foglalkoztam vele, mert az "objektumok kezelése parancssorból" gondolat nekem perverz. :)
A neten természetesen 1000 helyen lehet howto-kat meg example-ket találni, de úgy gondoltam, erről a témáról sem lehet eleget írni. Hiszen nagyban megkönnyíti az életünket pár szkript, aminek aztán készíthetünk egy parancsikont és futtathatjuk a grafikus felületről is; nem kell látni hogy a fogaskerekek mit csinálnak lent a mélyben.
Elhatároztam hát, hogy pár egyszerű példán keresztül én is indítok egy sorozatot. Ebben leírom, mi volt a feladat, hogyan oldottam meg és el is magyarázom, hogy mi miért működik. Ez talán több annál, mint amit szerete a neten megtalálhatunk. És persze tudjátok, a bagoj ragadozó, úgyhogy pizzáért bárkinek rittyentek szkripteket. :-)
Megjegyzés: Nem a nagyon kezdő szinttől indulok (bár onnan kellene), mert azt elvárom, hogy egy kézikönyvet vagy a Fullcircle magazint végig tudja böngészni a nyájas olvasóm. Ettől függetlenül próbálok mindent apróra elmagyarázni; aztán ha valakit érdekel a téma, úgy gondolom úgyis utánanéz. Ha nem jól sikerült a szintet belőnöm, írjatok egy kommentet.
Első példa
Tegyük fel, hogy egy ismerős meglátja csodálatos Linux rendszerünket, és mély meggyőződéssel közli, hogy ilyen kell neki is. Ez mint tudjuk, rengeteg munkával jár - az alaprendszer telepítése csak az első lépés. Utána le kell tölteni a csomagkezelővel minden alkalmazást, ami nincs az alaprendszerben, esetleg le kell tölteni skineket, a beállításokat úgy megrajzolni hogy jók legyenek stb. Most vegyük csak az első lépést; a plusz csomagok telepítésének fáradtságos munkáját. A példa kedvéért (és mert ez így történt meg a valóságban is) képzeljük el, hogy 250 km-re vagyunk saját gépünktől, de el tudjuk érni SSH-n keresztül.
Megfejtés
Mint az közismert, a Linux csomagokba szervezi az egyes programokat és az őket kiszolgáló lib-eket, azaz függvénykönyvtárakat. Ez lehetővé teszi, hogy ugyanabban a csomagban lévő kódot több másik csomag is használhassa. Az alaprendszer és a már szénné telepítgetett rendszer tehát csak a csomagnevek listájában különbözik. Szedjük le hát a telepített csomagok listáját! Először a távoli gépen (ez a miénk; ezen van az elérendő állapot):
dpkg-query -W -f='${Package}\n' > osszescsomag.txt
Illetve a frissen telepített gépen:
dpkg-query -W -f='${Package}\n' > alaprendszer.txt
A nevezett parancs a Debian-alapú rendszerek része. Alapértelmezésben kiírja mindegyik csomag nevét, verzióját és rövid leírását - ez minket perpillanat nem érdekel, ezért megkértük, hogy csak a csomagneveket írja ki, mindegyiket külön sorba (a ${Package} jelenti a csomagnevet, a \n a sortörést értelemszerűen, mindezt beleirányítjuk egy-egy fájlba a "kacsacsőr" nevű népszerű átirányító karakter segítségével. Vigyázzunk, hogy a kacsa balra néz, ha éppen szembe áll velünk! :-)
A távoli gépről a fájl eljuttatását a helyi gépre feladnám házi feladatnak... :-)
Az összehasonlításhoz van nekünk egy szép, diff nevű parancsunk. Futtassuk is:
diff -a --suppress-common-lines alaprendszer.txt osszescsomag.txt
0a1,4
> imagemagick
> inkscape
> language-pack-gnome-hu
> language-pack-gnome-hu-base
> language-support-translations-hu
> libfaac0
...
Tehát a diff nevű csoda két vagy több fájl tartalmát tudja összehasonlítani. Eredetileg forráskódok összehasonlítására szakosodott, a foltok (patch-ek) előállítását végzik vele. De természetesen mi is tudjuk alkalmazni saját céljainkra. Tehát jobbra kacsacsőrrel látjuk, ami az osszecsomag.txt (a másodiknak megadott fájl) pluszban tartalmaz. Először is vágjuk ki a minket nem érdeklő részeket (ez a "0a1,4" a fájlban elfoglalt helyet mutatja; de ez arra kell, ha patch-et gyártunk ahogy írtam; a patch nevű program majd ezek alapján tudja hogy a forráskódot hol kell patch-elni, de ez most nem tartozik ide), tartsuk meg csak a jobbra kacsacsőrös részeket:
diff -a --suppress-common-lines alaprendszer.txt osszescsomag.txt | grep "^>*"
Hurrá, most már van egy rakás kacsacsőrös sorunk, de a kacsacsőr nekünk nem kell. Számos módszer lehetséges, ahogyan ki lehet vágni a "> " karaktersorozatot, szerintem a legegyszerűbb az awk használata; ami képes egy-egy sort szétvágni megadott karakterek mentén oszlopokra - figyeljük meg, hogy felfoghatjuk úgy is, mint egy táblázatot: Az első oszlop csak kacsacsőröket tartalmaz, a szóköz az elválasztójel, és a nekünk szükséges csomagnevek a második oszlop. Az awk - rengeteg más funkciója mellett - képes kiírni a megadott oszlopokat. Ráadásul alapértelmezetten a szóközt tartja elválasztónak. Irányítsuk át tehát az awk-ba az egészet és írassuk ki a második oszlopot:
> imagemagick
> inkscape
> language-pack-gnome-hu
> language-pack-gnome-hu-base
> language-support-translations-hu
> libfaac0
...
diff -a --suppress-common-lines alaprendszer.txt osszescsomag.txt | grep "^>*"|awk '{print $2}'
Akkor ezzel meg is volnánk, csak irányítsuk be az egészet egy harmadik fájlba:
imagemagick
inkscape
language-pack-gnome-hu
language-pack-gnome-hu-base
language-support-translations-hu
libfaac0
...
diff -a --suppress-common-lines alaprendszer.txt osszescsomag.txt | grep "^>*"|awk '{print $2}' > kulonbseg.txt
Nagyon jó, most már van egy fájlunk, ami tartalmazza, hogy mit kell pluszban telepítenünk. Akkor zúzzuk:
sudo apt-get install `cat kulonbseg.txt`
Figyelem! Az aposztrófok valójában visszafelé mutató aposztrófok; magyar billentyűzeten "AltGr + 7"-tel lehet őket elérni! Azt jelenti, hogy az ezek között lévő parancsot futtassa le, majd az eredményt másolja oda.
Mit tanultunk ma?
- A dpkg-query parancs tudja Debian rendszerek alatt lekérdezni a csomagokat.
- A diff két vagy több fájlt hasonlít össze, eredetileg programfejlesztéshez fejlesztették ki
- A grep parancs csak a paraméterben megadott szöveget tartalmazó sorokat tartja meg. Megadható neki regexp, azaz regular expression, a caret (^) a sor elejét jelzi, a mi példánkban azt fogalmaztuk meg: "Mi csak azokat a sorokat kérjük, ahol a sor eleje után következik egy kacsacsőr, majd tetszőleges karakterek a sor végéig."
- Az awk egy programozható, bár nehéz szintaktikájú univerzális szövegfeldolgozó program. Mi a tudása töredékét használva kiírattuk a második oszlopot. Csak a példa kedvéért, több oszlopot is ki lehet íratni, a '{print $3 $2 $1}' segítségével például megcseréltük oszlopaink sorrendjét. Majd szerintem erről külön írok egy kisebb szösszenetet
- A normál esetben konzolra kiírt üzeneteket a jobbra kacsacsőr ">" segítségével fájlba irányíthatjuk (megadandó a fájl neve, nyilván).
- A cat parancs egy fájl teljes tartalmát írja ki a konzolra.
- A feldolgozó parancsok kimenete egymásba átirányítható a pipe "|" segítségével.
Bónusz játék
Ha nem Ubuntunk van, és a csomagkezelő nem paraméterezhető az elmesélt módon, akkor is használhatjuk az awk-t hogy kinyerjük a szükséges infókat. Megint a dpkg-query-ből kiindulva, bemutatom az analógiát - ez alapján már menni fog bármilyen Linux alól.
dpkg-query -l
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Cfg-files/Unpacked/Failed-cfg/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Név Verzió Leírás
+++-============-==============-================================
acl 2.2.47-2 Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
acpi 1.1-1ubuntu1 Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
acpi-support 0.114 Ubuntu Core developers <ubuntu-devel-discuss@lists.ubuntu.com>
...
dpkg-query -l | awk '{print $2}'
Status=Not/Inst/Cfg-files/Unpacked/Failed-cfg/Half-inst/trig-aWait/Trig-pend
Err?=(none)/Hold/Reinst-required/X=both-problems
Név
acl
acpi
acpi-support
acpid
...
Na, értitek.