HTML

Bagoj úr blogja

Kíváncsi Bagoj befigyel a Linux belsejébe, illetve különféle Linux terjesztéseket próbál ki. Ha jó napja van, scriptet ír Neked.

Friss topikok

Az elfelejtett világ - Linux parancssor és szkriptezés

2009.01.15. 12:14 bagoj ur

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 "^>*"
> imagemagick
> inkscape
> language-pack-gnome-hu
> language-pack-gnome-hu-base
> language-support-translations-hu
> libfaac0
...
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:

diff -a --suppress-common-lines alaprendszer.txt osszescsomag.txt | grep "^>*"|awk '{print $2}'
imagemagick
inkscape
language-pack-gnome-hu
language-pack-gnome-hu-base
language-support-translations-hu
libfaac0
...
Akkor ezzel meg is volnánk, csak irányítsuk be az egészet egy harmadik fájlba:

diff -a --suppress-common-lines alaprendszer.txt osszescsomag.txt | grep "^>*"|awk '{print $2}' > kulonbseg.txtNagyon 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.

 

4 komment

Címkék: linux ubuntu cat awk parancssor grep dpkg diff

A bejegyzés trackback címe:

https://bagojur.blog.hu/api/trackback/id/tr46879389

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Désiré · http://juhaszmarton.hu 2009.01.15. 14:48:55

Ilyet még, sokat,nagyon jó!
(bár egyenlőre jobban várom a gyors boot projekted leírását :D)

sala 2012.11.03. 08:39:56

Működne ez vajon egy paranccsal is a kettő helyett?

sudo apt-get install <( diff -a --suppress-common-lines alaprendszer.txt osszescsomag.txt | grep "^>*"|awk '{print $2}' )

Nem Debianom van, így nem tudom kipróbálni.

bagoj ur 2012.11.03. 12:11:41

@sala: Szia, igen elvileg működik, bár én így csinálnám:

sudo apt-get install $(diff -a --suppress-common-lines alaprendszer.txt osszescsomag.txt | grep "^>*"|awk '{print $2}')

...de tudod, jobb a békesség: előbb szeretem ellenőrizni, hogy mit csinál a parancsom, mi kerül bele a fájlba, és aztán kiadni az apt-get-et.

sala 2012.11.03. 17:27:09

@bagoj ur: Hülyeségeket írok, az én megoldásom nem menne, csak a tied. Néha összekeverem a két dolgot.
süti beállítások módosítása