A shell az operációs rendszer parancsértelmezője. A Bash a kedvenc shell-em, de minden Linux shell a felhasználó vagy rendszergazda által begépelt parancsokat értelmezi olyan formába, amit az operációs rendszer használni tud. Amikor a shell program visszakapja az eredményeket, elküldi azokat az STDOUT-ra, amely alapértelmezés szerint megjeleníti azokat a terminálban. Az összes általam ismert héj egyben programozási nyelv is.

Az olyan funkciók, mint a tabulátor-kiegészítés, a parancssor visszahívása és szerkesztése, valamint a gyorsbillentyűk, mint például az aliasok, mind hozzájárulnak a nagy teljesítményű héj értékéhez. Az alapértelmezett parancssori szerkesztési mód az Emacsot használja, de az egyik kedvenc Bash funkcióm az, hogy átállíthatom Vi módra, hogy olyan szerkesztési parancsokat használhassak, amelyek már az izommemóriám részei.

Ha azonban a Bashre kizárólag shellként gondolunk, akkor a valódi erejéből sokat kihagyunk. A háromkötetes Linux önképző tanfolyamom (amelyen ez a cikksorozat alapul) kutatása során olyan dolgokat tudtam meg a Bash-ről, amelyeket a Linux-szal való több mint 20 éves munka során soha nem tudtam. Ezen új ismeretek némelyike a programozási nyelvként való használatához kapcsolódik. A Bash egy nagy teljesítményű programozási nyelv, amelyet tökéletesen a parancssorban és a shell szkriptekben való használatra terveztek.

Ez a háromrészes sorozat a Bash parancssori felületű (CLI) programozási nyelvként való használatát vizsgálja. Ez az első cikk néhány egyszerű parancssori programozást vizsgál meg a Bash segítségével, a változókat és a vezérlőoperátorokat. A további cikkek a Bash-fájlok típusait; a végrehajtás-áramlás vezérlési logikáját biztosító string-, numerikus és különféle logikai operátorokat; a különböző típusú shell-kiterjesztéseket; valamint az ismétlődő műveleteket lehetővé tevő for-, while- és until-hurkokat vizsgálják. Megvizsgálnak néhány olyan parancsot is, amelyek egyszerűsítik és támogatják ezen eszközök használatát.

A shell

A shell az operációs rendszer parancsértelmezője. A Bash a kedvenc shell-em, de minden Linux shell a felhasználó vagy rendszergazda által begépelt parancsokat értelmezi az operációs rendszer által használható formába. Amikor az eredmények visszakerülnek a shell programhoz, az megjeleníti azokat a terminálban. Az összes általam ismert héj egyben programozási nyelv is.

A Bash a Bourne Again Shell rövidítése, mivel a Bash héj a régebbi Bourne héjon alapul, amelyet Steven Bourne írt 1977-ben. Sok más héj is elérhető, de ez az a négy, amellyel a leggyakrabban találkozom:

  • csh: A C shell azoknak a programozóknak, akik szeretik a C nyelv szintaxisát
  • ksh: A Korn shell, amelyet David Korn írt és a Unix felhasználók körében népszerű
  • tcsh: A csh egy változata több egyszerűbb használati funkcióval
  • zsh: A Z héj, amely más népszerű héjak számos funkcióját egyesíti

Minden héjnak vannak beépített parancsai, amelyek kiegészítik vagy helyettesítik az alapvető segédprogramok által nyújtottakat. Nyisd meg a shell man oldalát, és keresd meg a “BUILT-INS” részt, hogy lásd az általa biztosított parancsokat.

Minden shellnek saját személyisége és szintaxisa van. Némelyik jobban fog működni az Ön számára, mint mások. Én használtam a C shell-t, a Korn shell-t és a Z shell-t. Még mindig jobban szeretem a Bash shell-t, mint bármelyiket. Használd azt, amelyik a legjobban működik neked, bár lehet, hogy ehhez ki kell próbálnod néhányat a többiek közül. Szerencsére elég könnyű héjat váltani.

A felsorolt héjak mindegyike programozási nyelv, valamint parancsértelmező. Íme egy gyors áttekintés néhány programozási konstrukcióról és eszközről, amelyek a Bash szerves részét képezik.

A Bash mint programozási nyelv

A legtöbb rendszergazda a Bash-t olyan parancsok kiadására használja, amelyek általában meglehetősen egyszerűek és egyszerűek. A Bash azonban túlmutat az egyes parancsok megadásán, és sok rendszergazda egyszerű parancssori programokat hoz létre egy sor feladat elvégzésére. Ezek a programok olyan általános eszközök, amelyekkel időt és energiát takaríthatunk meg.

A célom a CLI-programok írásakor az, hogy időt és energiát takarítsak meg (azaz, hogy én legyek a lusta rendszergazda). A CLI-programok ezt úgy támogatják, hogy több parancsot sorolnak fel egy meghatározott sorrendben, amelyek egymás után hajtódnak végre, így nem kell figyelni az egyik parancs előrehaladását, és nem kell beírni a következő parancsot, amikor az első befejeződik. Elmehet más dolgokat csinálni, és nem kell folyamatosan figyelnie az egyes parancsok előrehaladását.

Mi az a “program”?

A Free On-line Dictionary of Computing (FOLDOC) meghatározása szerint a program a következő: “A számítógép által végrehajtott utasítások, szemben a fizikai eszközzel, amelyen futnak”. A Princeton University’s WordNet a programot a következőképpen definiálja: “…utasítások olyan sorozata, amelyet a számítógép értelmezni és végrehajtani képes…”. A Wikipédiának is van egy jó bejegyzése a számítógépes programokról.

Ezért egy program egy vagy több utasításból állhat, amelyek egy adott, összefüggő feladatot hajtanak végre. A számítógépes program utasítását program utasításnak is nevezik. A rendszergazdák számára egy program általában shell-parancsok sorozata. A Linuxhoz elérhető összes shell, legalábbis az általam ismertek, legalább egy alapvető programozási képességgel rendelkeznek, és ez alól a legtöbb Linux-disztribúció alapértelmezett shellje, a Bash sem kivétel.

Míg ez a sorozat a Bash-t használja (mivel az annyira mindenütt jelen van), ha más shell-t használ, az általános programozási koncepciók ugyanazok lesznek, bár a konstrukciók és a szintaxis némileg eltérhetnek. Egyes shell-ek támogathatnak olyan funkciókat, amelyeket mások nem, de valamilyen programozási lehetőséget mindegyik biztosít. A héjprogramok tárolhatók egy fájlban ismételt használatra, vagy szükség esetén a parancssoron is létrehozhatók.

Egyszerű CLI-programok

A legegyszerűbb parancssori programok egy vagy két egymást követő programutasítás, amelyek lehetnek összefüggőek vagy nem, és amelyeket az Enter billentyű lenyomása előtt írunk be a parancssorba. A program második utasítása, ha van ilyen, függhet az első utasítás műveleteitől, de nem feltétlenül kell, hogy függjön.

Még egy kis szintaktikai írásjel, amit világosan ki kell mondani. Amikor egyetlen parancsot írunk be a parancssorba, az Enter billentyű lenyomása egy implicit pontosvesszővel (;) zárja le a parancsot. A parancssoron egyetlen sorban beírt CLI shell programban történő használatakor a pontosvesszőt minden egyes utasítás befejezésére és a következő utasítástól való elválasztására kell használni. A CLI shell program utolsó utasítása használhat explicit vagy implicit pontosvesszőt.

Egy kis alapszintaktika

A következő példák tisztázzák a szintaxist. Ez a program egyetlen parancsból áll, explicit terminátorral:

$ echo "Hello world." ;
Hello world.

Ez talán nem tűnik nagy programnak, de ez az első program, amivel minden új programozási nyelven, amit megtanulok, találkozom. Lehet, hogy a szintaxis minden nyelvnél kicsit más, de az eredmény ugyanaz.

Bővítsük egy kicsit ezt a triviális, de mindenütt jelenlévő programot. A te eredményeid különbözni fognak az enyémektől, mert én más kísérleteket végeztem, míg neked lehet, hogy csak az alapértelmezett könyvtárak és fájlok vannak meg, amelyek a fiók home könyvtárában jönnek létre, amikor először jelentkezel be egy fiókba a GUI desktopon keresztül.

$ echo "My home directory." ; ls ;
My home directory.
chapter25 TestFile1.Linux dmesg2.txt Downloads newfile.txt softlink1 testdir6
chapter26 TestFile1.mac dmesg3.txt file005 Pictures Templates testdir
TestFile1 Desktop dmesg.txt link3 Public testdir Videos
TestFile1.dos dmesg1.txt Documents Music random.txt testdir1

Ez már egy kicsit értelmesebb. Az eredmények összefüggnek, de az egyes programutasítások függetlenek egymástól. Vegye észre, hogy a pontosvessző előtt és után szeretem a szóközöket, mert így kicsit könnyebben olvasható a kód. Próbáljuk meg újra ezt a kis CLI-programot explicit pontosvessző nélkül a végén:

$ echo "My home directory." ; ls 

Nincs különbség a kimenetben.

Mit a változókról

Mint minden programozási nyelv, a Bash shell is tud változókkal bánni. A változó egy szimbolikus név, amely a memória egy adott helyére utal, amely valamilyen értéket tartalmaz. A változó értéke megváltoztatható, azaz változó.

A Bash nem tipizálja a változókat, mint a C és a rokon nyelvek, egész számokként, lebegőpontos vagy karakterlánc típusokként definiálva azokat. A Bashben minden változó karakterlánc. Egy string, amely egész szám, használható egész számok aritmetikájában, ami az egyetlen olyan matematikai típus, amelyre a Bash képes. Ha bonyolultabb matematikára van szükség, a CLI programokban és szkriptekben a bc parancs használható.

A változókhoz értékeket rendelnek, és a CLI programokban és szkriptekben ezekre az értékekre lehet hivatkozni. Egy változó értékét a nevével adjuk meg, de nem előzi meg a $ jel. A VAR=10 hozzárendelés a VAR változó értékét 10-re állítja be. A változó értékének kiírásához használhatja az echo $VAR utasítást. Kezdjük a szöveges (azaz nem numerikus) változókkal.

A Bash-változók a shell környezet részévé válnak, amíg vissza nem vonjuk a beállításukat.

Vizsgáljuk meg a ki nem rendelt változó kezdeti értékét; annak nullának kell lennie. Ezután rendelj hozzá egy értéket a változóhoz, és írd ki, hogy ellenőrizd az értékét. Mindezt egyetlen CLI-programban is elvégezheti:

$ echo $MyVar ; MyVar="Hello World" ; echo $MyVar ;
Hello World
$

Figyelem: A változó hozzárendelésének szintaxisa nagyon szigorú. A hozzárendelési utasításban az egyenlőségjel (=) mindkét oldalán nem lehet szóköz.

Az üres sor azt jelzi, hogy a MyVar kezdeti értéke null. Egy változó értékének megváltoztatása és beállítása ugyanígy történik. Ez a példa az eredeti és az új értéket is mutatja.

Mint említettük, a Bash képes egészértékű aritmetikai számításokat végezni, ami hasznos egy tömbben lévő elem helyére való hivatkozás kiszámításához vagy egyszerű matematikai feladatok elvégzéséhez. Nem alkalmas tudományos számításokhoz vagy bármihez, ami tizedesjegyeket igényel, például pénzügyi számításokhoz. Az ilyen típusú számításokhoz sokkal jobb eszközök léteznek.

Itt egy egyszerű számítás:

$ Var1="7" ; Var2="9" ; echo "Result = $((Var1*Var2))"
Result = 63

Mi történik, ha olyan matematikai műveletet hajtunk végre, amelynek eredménye egy lebegőpontos szám?

Az eredmény a legközelebbi egész szám. Vegyük észre, hogy a számítást a visszhang utasítás részeként végeztük el. A matematikai művelet a Bash rangsor miatt a körülvevő echo parancs előtt történik. A részletekért lásd a Bash man oldalát, és keress rá a “precedence” kifejezésre.”

Vezérlőoperátorok

A shell vezérlőoperátorok egyike azon szintaktikai operátoroknak, amelyekkel könnyen létrehozhatunk néhány érdekes parancssori programot. A CLI-program legegyszerűbb formája nem más, mint több parancs egymás utáni sorba fűzése a parancssorban:

command1 ; command2 ; command3 ; command4 ; . . . ; etc. ;

Ezek a parancsok mind gond nélkül futnak, amíg nem lép fel hiba. De mi történik, ha hiba lép fel? A beépített && és || Bash vezérlőoperátorok segítségével előre láthatjuk és figyelembe vehetjük a hibákat. Ez a két vezérlőoperátor némi folyamatkezelést biztosít, és lehetővé teszi a kódvégrehajtás sorrendjének megváltoztatását. A pontosvessző is Bash vezérlőoperátornak számít, akárcsak az újsor karakter.

A && operátor egyszerűen azt mondja, hogy “ha a parancs1 sikeres, akkor futtasd a parancs2-t. Ha a parancs1 bármilyen okból sikertelen, akkor a parancs2-t kihagyod”. Ez a szintaxis így néz ki:

command1 && command2

Most nézzünk meg néhány olyan parancsot, amely új könyvtárat hoz létre, és – ha sikerül – a jelenlegi munkakönyvtárrá (PWD) teszi. Győződjünk meg róla, hogy az otthoni könyvtárunk (~) a PWD. Próbáld ki először a /root könyvtárban, amelyhez nincs hozzáférésed:

A hibát az mkdir parancs adta ki. Nem kapott hibaüzenetet arról, hogy a fájlt nem lehetett létrehozni, mert a könyvtár létrehozása sikertelen volt. A && vezérlő operátor érzékelte a nem nulla visszatérési kódot, ezért a touch parancsot kihagyta. A && vezérlőoperátor használata megakadályozza a touch parancs futtatását, mivel a könyvtár létrehozása hibás volt. Az ilyen típusú parancssori programáramlás-szabályozás megakadályozhatja, hogy a hibák összeadódjanak és valódi zűrzavart okozzanak. De itt az ideje, hogy egy kicsit bonyolultabbá váljon.

A || vezérlőoperátor lehetővé teszi egy másik programutasítás hozzáadását, amely akkor hajtódik végre, ha az eredeti programutasítás nullánál nagyobb kódot ad vissza. Az alapvető szintaxis így néz ki:

command1 || command2 

Ez a szintaxis így szól: “Ha a parancs1 sikertelen, hajtsa végre a parancs2-t”. Ez azt jelenti, hogy ha a parancs1 sikeres, a parancs2 kihagyásra kerül. Próbálja ki ezt úgy, hogy megpróbál létrehozni egy új könyvtárat:

Ez pontosan az, amire számíthat. Mivel az új könyvtárat nem sikerült létrehozni, az első parancs sikertelen volt, ami a második parancs végrehajtását eredményezte.

A két operátor kombinálása mindkettőből a legjobbat nyújtja. A valamilyen folyamatkezelést használó vezérlőoperátor szintaxis a && és a || vezérlőoperátorok használata esetén a következő általános formát ölti:

preceding commands ; command1 && command2 || command3 ; following commands

Ezt a szintaxist a következőképpen lehet megfogalmazni: “Ha a parancs1 0 visszatérési kóddal lép ki, akkor hajtsa végre a parancs2-t, ellenkező esetben hajtsa végre a parancs3-at”. Próbáld ki:

Most próbáld meg újra az utolsó parancsot a /root könyvtár helyett az otthoni könyvtáraddal. Engedélyed lesz ennek a könyvtárnak a létrehozására:

$ Dir=~/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
$

A vezérlőoperátor szintaxis, mint a command1 && command2, azért működik, mert minden parancs küld egy visszatérési kódot (RC) a héjnak, amely jelzi, hogy sikeresen befejeződött-e, vagy valamilyen hiba történt a végrehajtás során. A konvenció szerint a nulla (0) RC a sikert jelzi, és minden pozitív szám valamilyen hibát jelez. A rendszergazdák által használt eszközök némelyike csak egy egyest (1) küld vissza a hiba jelzésére, de sokan más kódokat használnak a bekövetkezett hiba típusának jelzésére.

A Bash shell $? változója tartalmazza az utolsó parancs RC-jét. Ezt az RC-t nagyon könnyen ellenőrizheti egy szkript, a következő parancs a parancsok listájában, vagy akár közvetlenül a rendszergazda. Kezdjük egy egyszerű parancs futtatásával, és azonnal ellenőrizzük az RC-t. Az RC mindig az utolsó parancsra vonatkozik, amely lefutott, mielőtt megnézted.

Az RC ebben az esetben nulla, ami azt jelenti, hogy a parancs sikeresen befejeződött. Most próbálja meg ugyanezt a parancsot a root home könyvtárában, egy olyan könyvtárban, amelyhez nincs jogosultsága:

Az RC ebben az esetben kettő; ez azt jelenti, hogy a nem root felhasználó számára megtagadták az engedélyt egy olyan könyvtárhoz való hozzáférésre, amelyhez a felhasználónak nincs jogosultsága. A vezérlőoperátorok ezeket az RC-ket arra használják, hogy lehetővé tegyék a programvégrehajtás sorrendjének megváltoztatását.

Összefoglaló

Ez a cikk a Bash-t, mint programozási nyelvet vizsgálta, és feltárta annak alapvető szintaxisát, valamint néhány alapvető eszközt. Megmutatta, hogyan nyomtathatunk adatokat az STDOUT-ra, és hogyan használhatunk változókat és vezérlőoperátorokat. A sorozat következő cikke a Bash számos logikai operátora közül néhányat vizsgál meg, amelyek az utasítások végrehajtásának folyamatát irányítják.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.