3.3 Lecke 1
Tanúsítvány: |
Linux Essentials |
---|---|
Verzió: |
1.6 |
Témakör: |
3 A Paranccsor Erősségei |
Fejezet: |
3.3 Parancsok Szkriptté Alakítása |
Lecke: |
1/2 |
Bevezetés
Azt már megtanultuk, hogy hogyan futtathatunk le parancsokat a shellben, de azt is megtehetjük, hogy a parancsokat egy fájlba írjuk és ezt a fájlt futtathatónak állítjuk be. Amikor lefuttatjuk a fájlt, ezek a parancsok egymás után fognak lefutni. Ezeknek a fájloknak a neve szkript, és minden Linux rendszergazda számára feltétlenül fontos eszközök. Lényegében a Bash-t programozási nyelvnek és shellnek is tekinthetjük.
Output Kiírása
Kezdjük egy olyan parancs bemutatásával, amit már használtunk az előző leckékben is: az echo
kiír egy értéket a standard kimenetre.
$ echo "Hello World!" Hello World!
Most a fájlátirányítást fogjuk használni, hogy átküldjük ezt a parancsot egy fájlba, aminek new_script
a neve.
$ echo 'echo "Hello World!"' > new_script $ cat new_script echo "Hello World!"
A new_script
fájl most az előző parancsot tartalmazza.
Szkript Futtathatóvá Tétele
Nézzük meg azokat a lépéseket, amelyek ahhoz szükségesek, hogy a fájl az elképzeléseinknek megfelelően fusson. Talán az lenne az első gondolatunk, hogy egyszerűen be kell írnunk a szkript nevét, mint bármely más parancs esetén:
$ new_script /bin/bash: new_script: command not found
Nyugodtan feltételezhetjük, hogy a new_script
létezik az aktuális helyen, de vegyük észre, hogy a hibaüzenet nem azt mondja, hogy a fájl nem létezik, hanem azt írja, hogy a parancs nem létezik. Hasznos lenne megbeszélni, hogyan kezeli a Linux a parancsokat és a futtatható fájlokat.
Parancsok és a PATH
Amikor beírjuk például az ls
parancsot a shellbe, egy ls
nevű fájlt futtatunk le, ami a fájlrendszerünkön van. Ezt a which
paranccsal bizonyíthatjuk:
$ which ls /bin/ls
Hamar fárasztó lenne, ha mindig be kellene írnunk az ls
abszolút elérési útját, amikor listázni akarjuk egy mappa tartalmát; így a Bash környezeti változó, ami tartalmazza az összes mappát, ahol azokat a parancsokat találhatjuk, amiket futtatni szeretnénk. Ennek a változónak a tartalmát az echo
paranccsal írathatjuk ki.
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Minden olyan lokáció, ahol a shell parancsot találhat, kettősponttal van elválasztva (:
). Láthatjuk, hogy a /bin
jelen van, de azt feltételezhetjük, hogy az aktuális mappa nincs. A shell minden itt megadott mappában keresni fogja a new_script
szkriptet, de mivel nem találja meg, a fenti hibaüzenetet adja vissza.
Három megoldás van a problémára: átmásolhatjuk a new_script
fájlt valamelyik PATH
mappába, hozzáadhatjuk az aktuális mappát a PATH
-hoz, vagy megváltoztathatjuk azt, hogy hogyan próbáljuk hívni a szkriptet. Utóbbi megoldás az egyszerűbb, egyszerűen csak arra van szükség, hogy megadjuk az aktuális mappát a ./
használatával.
$ ./new_script /bin/bash: ./new_script: Permission denied
A hibaüzenet megváltozott, ami jelzi, hogy elértünk valami haladást.
Futtatási Jogok
Az első lépés a nyomozásban, amit megtehetünk, hogy az ls -l
segítségével megnézzük a fájlt:
$ ls -l new_script -rw-rw-r-- 1 user user 20 Apr 30 12:12 new_script
Láthatjuk, hogy a fájl jogosultságai alapértelmezetten 664
-re vannak állítva. Még nem állítottuk be, hogy futtatási jog is legyen a fájlon.
$ chmod +x new_script $ ls -l new_script -rwxrwxr-x 1 user user 20 Apr 30 12:12 new_script
Ez a parancs minden felhasználónak jogot adott a futtatásra. Ez biztonsági kockázatot jelenthet, de egyelőre ez egy elfogadható szintű engedély.
$ ./new_script Hello World!
Most már képesek vagyunk futtatni a szkriptünket.
A Fordító Meghatározása
Ahogy azt bemutattuk, lehetséges beírni egy szöveget egy fájlba, futtathatóvá tenni és futtatni. A new_script
még mindig egy szöveges fájl, de Bash által fordíthatóvá tettük. De mi lenne a teendő, ha Perl vagy Python nyelven írtuk volna?
Nagyon jó megoldás meghatározni, hogy milyen fordítót akarunk használni már a szkriptünk első sorában. Ezt a sort bang line-nak vagy még inkább shebang-nek nevezzük. Ez jelzi a rendszer számára, hogyan akarjuk futtatni a fájlt. Mivel a Basht tanuljuk, a Bash abszolút útvonalát fogjuk használni, ismét a which
használatával:
$ which bash /bin/bash
A shebang ebben az esetben egy kettőskereszttel és egy felkiáltójellel kezdődik, amelyeket a fenti abszolút útvonal követ. Nyissuk meg a new_script
fájlt egy szövegszerkesztőben és szúrjuk be a shebanget. Ragadjuk meg a lehetőséget és szúrjunk be egy kommentet a szkriptünkbe. A kommenteket a fordító nem veszi figyelembe. Azoknak a felhasználóknak íródnak, akik meg akarják érteni a szkriptünket.
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. echo "Hello World!"
Egy további módosításra van szükségünk a fájl nevével: a fájl neve new_script.sh
legyen. Az ".sh" utótag semmilyen módon nem változtatja meg a fájl végrehajtását. Konvenció szerint a bash szkripteket .sh
vagy .bash
névvel látjuk el, hogy könnyebben azonosíthatóak legyenek, a Python szkriptek esetén ez a kiterjesztés a .py
.
Gyakori Szövegszerkesztők
Linux felhasználóként gyakran kell olyan környezetben dolgoznunk, ahol nem áll rendelkezésre grafikus szövegszerkesztő. Emiatt melegen ajánlott legalább kicsit megismerkednünk azzal, hogyan szerkeszthetünk szöveges fájlokat a parancssorból. A két legismertebb szövegszerkesztő a vi
és a nano
.
vi
A vi
egy nagy tiszteletnek örvendő szövegszerkesztő és alapértelmezés szerint szinte minden Linux rendszerre telepítve van. A vi
létrehozott egy vi IMproved vagy vim
nevű klónt, amely néhány pluszfunkciót ad hozzá, de megtartja a vi
kezelőfelületét. A vi
-al való munka ijesztő lehet egy új felhasználó számára, a szerkesztő népszerű és szeretett azon felhasználók körében, akik megtanulják a funkcióit.
A legnagyobb különbség a vi
és az olyan alkalmazások között, mint a Jegyzettömb, hogy a vi
-ban három különböző mód van. Az elindítás után a H, J, K és L billentyűk navigációra használhatók. Ez a navigációs mód, az I lenyomásával léphetünk az írási módba (insert mode). Itt lehetőségünk van a normális gépelésre. Az írási módból a Esc billentyű lenyomásával léphetünk vissza a navigációs módba. A navigációs módból, a : lenyomásával léphetünk a parancs módba (command mode). Itt menthetünk, törölhetünk, kiléphetünk és megváltoztathatjuk a beállításokat.
A vi
megtanulható, a különböző módok idővel lehetővé tehetik, hogy egy hozzáértő felhasználó hatékonyabb lehessen, mint más szerkesztőkkel.
nano
A nano
egy újabb eszköz, egyszerűbb és könnyebben használható, mint a vi
. A nano
-ban nincsenek különböző módok. Elindítás után a felhasználó azonnal elkezdhet gépelni és a Ctrl billentyűvel érheti el a képernyő alján látható eszközöket.
[ Welcome to nano. For basic help, type Ctrl+G. ] ^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos M-U Undo ^X Exit ^R Read File ^\ Replace ^U Uncut Text ^T To Spell ^_ Go To Line M-E Redo
Az, hogy melyik szövegszerkesztőt használjuk, saját döntés és bármelyiket is választjuk, nincs hatással erre a leckére. Egy vagy több szövegszerkesztő ismerete azonban biztosan kifizetődik majd.
Változók
A változók bármelyik programozási nyelvnek fontos részei és ez alól a Bash sem kivétel. Amikor egy új munkamenetet indítunk el a terminálból, a shell már néhány változót beállít. A PATH
változó például ilyen. Ezeket környezeti változónak nevezzük, mivel általában meghatározzák a shell környezeti jellemzőit. Módosíthatjuk őket és újakat is hozhatunk létre, de most a szkripten belüli változókra fogunk fókuszálni.
Az alábbira módosítjuk a szkriptünket:
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. username=Carol echo "Hello $username!"
Ebben az esetben létrehoztunk egy változót, aminek username
a neve és a Carol
értéket rendeltük hozzá. Vegyük észre, hogy nincsenek szóközök a változó neve, az egyenlőségjel és a hozzárendelt érték között.
A következő sorban az echo
parancsot használjuk a változóval, de van egy dollárjel ($
) a változó neve előtt. Ez azért fontos, mert ez jelzi a shellnek, hogy változóként akarjuk kezelni a username
-t, nem pedig egy sima szóként. A $username
beírásával jelezzük, hogy egy cserét hajtunk végre, a változó nevét a hozzárendelt értékre cseréljük.
A szkript lefuttatásával az alábbi kimenetet kapjuk:
$ ./new_script.sh Hello Carol!
-
VA változók csak alfanumerikus karaktereket vagy alulvonásokat tartalmazhatnak és kis/nagybetű érzékenyek. A
Username
és ausername
különböző változóként lesznek kezelve. -
A változók helyettesítésénél ismert a
${username}
formátum, a{ }
hozzáadásával. Ez is elfogadható. -
A változók Bashben implicit típusúak és sztringnek számítanak. Ez azt jelenti, hogy a matematikai műveletek végrehajtása sokkal nehezebb, mint más programozási nyelvekben, például C-ben vagy C++ esetén:
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. username=Carol x=2 y=4 z=$x+$y echo "Hello $username!" echo "$x + $y" echo "$z"
$ ./new_script.sh Hello Carol! 2 + 4 2+4
Idézőjelek Használata Változókkal
Hajtsuk végre az alábbi változtatást a username
változóval:
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. username=Carol Smith echo "Hello $username!"
A szkript futtatása során hibát kapunk:
$ ./new_script.sh ./new_script.sh: line 5: Smith: command not found Hello !
Jegyezzük meg, hogy a Bash egy fordító és így a szkriptünket sorról sorra fordítja. Ebben az esetben jól fordítja az username=Carol
részt úgy, hogy beállít egy username
nevű változót a Carol
értékkel. De ezután a szóközt úgy értelmezi, hogy az a rész végét jelzi, így a Smith
egy parancs neve lesz. Annak érdekében, hogy szóközt írhassunk és a Smith
is a változó értéke legyen, dupla idézőjeleket ("
) írunk a név köré.
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. username="Carol Smith" echo "Hello $username!"
$ ./new_script.sh Hello Carol Smith!
Még egy fontos dolog, amit meg kell jegyeznünk: a dupla és a szimpla ('
) idézőjelek máshogy viselkednek. A dupla idézőjeleket gyakran “gyengének” tekintik, mivel lehetővé teszik, hogy a fordító behelyettesítsen az idézőjeleken belül. A szimpla idézőjeleket “erősnek” tekintik, mivel megakadályozzák a behelyettesítést. Nézzük az alábbi példát:
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. username="Carol Smith" echo "Hello $username!" echo 'Hello $username!'
$ ./new_script.sh Hello Carol Smith! Hello $username!
A második echo
parancsban a fordító megakadályozta, hogy a $username
szót a Carol Smith
helyettesítse, ezért szó szerint ez lett a kimenet.
Argumentumok
Már megismerkedtünk az argumentumok használatával a Linux alapvető segédprogramjaiban. Az rm testfile
tartalmazza mind az rm
parancsot és a testfile
argumentumot. Az argumentumok a futtatáskor átadhatók a szkriptnek és módosítják a szkript viselkedését. Könnyen implementálhatók.
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. username=$1 echo "Hello $username!"
Ahelyett, hogy értéket adnánk a username
változónak közvetlenül a szkriptben, helyette egy új változó ($1
) értékét adjuk át. Ez az első argumentum értéke.
$ ./new_script.sh Carol Hello Carol!
Az első kilenc argumentumot így kezeljük. Természetesen van lehetőség kilencnél több argumentum kezelésére is, de az túlmutat ezen a leckén. Az alábbi példában két argumentumot használunk:
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. username1=$1 username2=$2 echo "Hello $username1 and $username2!"
$ ./new_script.sh Carol Dave Hello Carol and Dave!
Figyelembe kell vennünk az argumentumok használata során: A fenti példában két argumentum van, Carol
és Dave
, az $1
és $2
értékhez hozzárendelve. Ha a második argumentum hiányzik, a shell nem fog hibát dobni. A $2
értéke egyszerűen null lesz vagy semmi.
$ ./new_script.sh Carol Hello Carol and !
Jó ötlet lenne, ha bevezetnénk némi logikát a szkriptünkbe, hogy a különböző feltételek befolyásolják a kimenetet, amit ki szeretnénk íratni. Kezdjük egy másik hasznos változó bevezetésével, majd folytassuk az if utasítással.
Argumentumok Számának Visszaadása
Míg a változók, mint a $1
és $2
a helyzeti argumentumok értékét tárolják, a $#
változó az argumentumok számát.
#!/bin/bash # Ez az első kommentünk. Jó, ha az összes szkriptünket dokumentáljuk. username=$1 echo "Hello $username!" echo "Az argumentumok száma: $#."
$ ./new_script.sh Carol Dave Hello Carol! Az argumentumok száma: 2.
Feltételes Logika
A feltételes logika használata a programozásban hatalmas témakör és nem foglalkozunk vele mélyrehatóan ebben a leckében. A Bash feltételeinek szintaxisára fókuszálunk, amely eltér a legtöbb programozási nyelvtől.
Kezdjük azzal, hogy áttekintjük, mit is szeretnénk elérni. Van egy egyszerű szkriptünk, aminek képesnek kell lennie üdvözölni egy felhasználót. Ha nem egy felhasználó van, egy hibaüzenetet kell kiírni.
-
A feltétel , amit tesztelünk, a felhasználók száma, ami a
$#
változóban van tárolva. Szeretnénk tudni, ha a$#
értéke1
. -
Ha a feltétel igaz, az utasítás az, hogy köszöntjük a felhasználót.
-
Ha a feltétel hamis, hibaüzenetet íratunk ki.
Most, hogy a logika világos, a megvalósításához szükséges szintaxisra fogunk fókuszálni.
#!/bin/bash # Egy egyszerű szkript a felhasználó üdvözléséhez. if [ $# -eq 1 ] then username=$1 echo "Hello $username!" else echo "Egy argumentumot adjon meg!" fi echo "Argumentumok száma: $#."
A feltételes logika az if
és a fi
között található meg. A tesztelendő feltétel a szögletes zárójelek [ ]
között van, és a feltétel teljesülése esetén végrehajtandó utasítás a then
után található. Vegyük észre a szóközöket a szögletes zárójelek között és az utasítás előtt. A szóköz elhagyása hibákhoz vezet.
A szkript a köszönést írja ki, vagy a hibaüzenet. Mindig ki fogja írni az Argumentumok száma
sort.
$ ./new_script.sh Csak egy argumentumot adjon meg! Argumentumok száma: 0. $ ./new_script.sh Carol Hello Carol! Argumentumok száma: 1.
Nézzük meg az if
állítást. A -eq
használatával egy numerikus összehasonlítást végeztünk. Ebben az esetben azt vizsgáljuk, hogy a $#
egyenlő-e eggyel. Egyéb összehasonlítások még:
-ne
-
Nem egyenlő
-gt
-
Nagyobb, mint
-ge
-
Nagyobb vagy egyenlő
-lt
-
Kisebb, mint
-le
-
Kisebb vagy egyenlő
Gyakorló Feladatok
-
A felhasználó az alábbiakat írja be a shellbe:
$ PATH=~/scripts $ ls Command 'ls' is available in '/bin/ls' The command could not be located because '/bin' is not included in the PATH environment variable. ls: command not found
-
Mit tett a felhasználó?
-
Melyik parancs kombinálja a
PATH
aktuális értékét az új~/scripts
mappával?
-
-
Nézzük meg az alábbi szkriptet! Vegyük észre, hogy az
elif
használatával vizsgálja a második feltételt:> /!bin/bash > fruit1 = Alma > fruit2 = Narancs if [ $1 -lt $# ] then echo "Ez olyan, mint a $fruit1 és a $fruit2 összehasonlítása!" > elif [$1 -gt $2 ] then > echo '$fruit1 győzött!' else > echo "Fruit2 győzött!" > done
-
A
>
-al jelölt sorok hibákat tartalmaznak. Javítsuk ki a hibákat!
-
-
Mi lesz a következő esetekben a kimenet?
$ ./guided1.sh 3 0
$ ./guided1.sh 2 4
$ ./guided1.sh 0 1
Gondolkodtató feladatok
-
Írjunk egy egyszerű szkriptet, amely ellenőrzi, hogy pontosan két argumentumot kap-e! Ha igen, fordított sorrendben írassuk ki az argumentumokat. Nézzük meg az alábbi példát (megjegyzés: a kód ettől eltérően nézhet ki, de ugyanaz kell, hogy legyen a kimenete):
if [ $1 == $number ] then echo "True!" fi
-
Ez a kód korrekt, de nem numerikus összehasonlítás. Keressünk rá az interneten, miben különbözik ez a kód az
-eq
használatától. -
Van egy környezeti változó, amely megadja az aktuális mappát. Az
env
segítségével keressük meg ezt a változót! -
A 2. és 3. kérdésben tanultak segítségével írjunk egy rövid szkriptet, amely egy argumentumot kap. Ha megkapta, ellenőrizze, hogy az argumentum megegyezik-e az aktuális mappa nevével. Ha igen, írassuk ki, hogy
igen
, ellenkező esetben azt, hogynem
.
Összefoglalás
Ebben a leckében megtanultuk:
-
Hogyan hozzunk létre és futtassunk egyszerű szkripteket
-
Hogyan használjuk a shebanget a fordító meghatározásához
-
Hogyan állítsunk be és használjuk változókat a szkriptekben
-
Hogyan kezeljük az argumentumokat a szkriptekben
-
Hogyan hozzunk létre
if
utasításokat -
Hogyan hasonlítsunk össze számokat a numerikus operátorok segítségével
A gyakorlatok során használt parancsok:
echo
-
Sztring kiírása a standard outputra.
env
-
Az összes környezeti változó kiírása a standard outputra.
which
-
A parancs abszolút elérési útjának kiírása.
chmod
-
Egy fájl jogosultságainak megváltoztatása.
Speciális változók, amit használtunk a gyakorlatban:
$1, $2, … $9
-
Pozicionális argumentumok, amiket átadunk a szkriptnek.
$#
-
A szkriptnek átadott argumentumok száma.
$PATH
-
Azokat a könyvtárakat tartalmazza, amelyben a rendszer által használt, futtatható fájlok vannak.
A gyakorlatban használt operátorok:
-ne
-
Nem egyenlő
-gt
-
Nagyobb, mint
-ge
-
Nagyobb vagy egyenlő
-lt
-
Kisebb, mint
-le
-
Kisebb vagy egyenlő
Válaszok a Gyakorló Feladatokra
-
A felhasználó az alábbiakat írja be a shellbe:
$ PATH=~/scripts $ ls Command 'ls' is available in '/bin/ls' The command could not be located because '/bin' is not included in the PATH environment variable. ls: command not found
-
Mit tett a felhasználó?
A felhasználó felülírta a PATH tartalmát a
~/scripts
mappával. Azls
parancs nem található, mivel már nincs a PATH-ban tárolva. Ne feledjük, hogy ez a változtatás csak az aktuális munkamenetre vonatkozik, egy ki- és bejelentkezés visszaállítja az eredeti állapotot. -
Melyik parancs kombinálja a
PATH
aktuális értékét az új~/scripts
mappával?PATH=$PATH:~/scripts
-
-
Nézzük meg az alábbi szkriptet! Vegyük észre, hogy az
elif
használatával vizsgálja a második feltételt:> /!bin/bash > fruit1 = Alma > fruit2 = Narancs if [ $1 -lt $# ] then echo "Ez olyan, mint a $fruit1 és $fruit2 összehasonlítása!" > elif [$1 -gt $2 ] then > echo '$fruit1 győzött!' else > echo "Fruit2 győzött!" > done
-
A
>
-al jelölt sorok hibákat tartalmaznak. Javítsuk ki a hibákat!#!/bin/bash fruit1=Alma fruit2=Narancs if [ $1 -lt $# ] then echo "Ez olyan, mint a $fruit1 és $fruit2 összehasonlítása!" elif [ $1 -gt $2 ] then echo "$fruit1 győzött!" else echo "$fruit2 győzött!" fi
-
-
Mi lesz a kimenet a következő esetekben?
$ ./guided1.sh 3 0
Alma győzött!
$ ./guided1.sh 2 4
Narancs győzött!
$ ./guided1.sh 0 1
Ez olyan, mint az Alma és a Narancs összehasonlítása!
Válaszok a Gondolkodtató Feladatokra
-
Írjunk egy egyszerű szkriptet, amely ellenőrzi, hogy pontosan két argumentumot kap-e! Ha igen, fordított sorrendben írassuk ki az argumentumokat. Nézzük meg az alábbi példát (megjegyzés: a kód ettől eltérően nézhet ki, de ugyanaz kell, hogy legyen a kimenete):
if [ $1 == $number ] then echo "True!" fi
#!/bin/bash if [ $# -ne 2 ] then echo "Error" else echo "$2 $1" fi
-
Ez a kód korrekt, de nem numerikus összehasonlítás. Keressünk rá az interneten, miben különbözik ez a kód az
-eq
használatától.A
==
segítségével sztringeket hasonlíthatunk össze. Ha a karakterek mindkét változóban pontosan megegyeznek, a feltétel igaz lesz.abc == abc
true
abc == ABC
false
1 == 1
true
1+1 == 2
false
A sztringek összehasonlítása számok esetén váratlan viselkedéshez vezethet.
-
Van egy környezeti változó, amely megadja az aktuális mappát. Az
env
segítségével keressük meg ezt a változót!PWD
-
A 2. és 3. kérdésben tanultak segítségével írjunk egy rövid szkriptet, amely egy argumentumot kap. Ha megkapta, ellenőrizze, hogy az argumentum megegyezik-e az aktuális mappa nevével! Ha igen, írassuk ki, hogy
igen
, ellenkező esetben azt, hogynem
!#!/bin/bash if [ "$1" == "$PWD" ] then echo "yes" else echo "no" fi