A shell script, vagy magyarul parancsfájl, a Linux, Unix és macOS operációs rendszerek alapvető építőköve, egy rendkívül sokoldalú eszköz, amely lehetővé teszi a felhasználók és rendszergazdák számára, hogy automatizálják az ismétlődő feladatokat, összetett munkafolyamatokat hozzanak létre, és hatékonyabban kezeljék a rendszereket. Lényegében egy szöveges fájlról van szó, amely egy sor parancsot tartalmaz, amelyeket a shell (parancsértelmező) egymás után hajt végre, mintha azokat manuálisan írtuk volna be a terminálba. Ez a rugalmasság és az egyszerűség teszi a shell scripteket nélkülözhetetlenné a modern informatikai környezetben, a szerverek kezelésétől a szoftverfejlesztési folyamatok automatizálásáig.
Mi a shell script és miért van rá szükség?
A shell script egy olyan program, amelyet a shell futtat. A shell maga egy parancsértelmező, egy felhasználói felület, amely lehetővé teszi a felhasználó számára, hogy kommunikáljon az operációs rendszerrel. A leggyakrabban használt shell a Bash (Bourne Again SHell), de léteznek mások is, mint például a Zsh, Ksh, vagy a régi sh. Amikor parancsokat gépelünk be a terminálba, azokat a shell értelmezi és hajtja végre. A shell script lényegében ugyanezt teszi, de egy előre megírt fájlból olvassa be a parancsokat, és automatikusan hajtja végre azokat.
A shell scriptek fő célja az automatizálás. Képzeljük el, hogy minden nap el kell végeznünk ugyanazt a tíz lépésből álló feladatot: fájlok másolása, tömörítése, logfájlok elemzése, adatbázis-mentés indítása, majd az eredmények e-mailben való elküldése. Ha ezt manuálisan tennénk, sok időt és energiát emésztene fel, ráadásul könnyen hibázhatnánk. Egy shell script segítségével ezeket a lépéseket egyszer megírjuk, majd egyetlen paranccsal vagy akár ütemezetten (például cron segítségével) futtathatjuk. Ez nemcsak időt takarít meg, hanem növeli a pontosságot és a konzisztenciát is.
A shell scriptekre számos okból van szükség:
- Automatizálás: Ismétlődő, monoton feladatok automatizálása, mint például biztonsági mentések, rendszerkarbantartás, naplófájl elemzés.
- Rendszeradminisztráció: Felhasználók kezelése, szolgáltatások indítása/leállítása, hálózati konfiguráció, erőforrás-felhasználás monitorozása.
- Fejlesztői munkafolyamatok: Fordítás, tesztelés, telepítés, verziókezelési műveletek automatizálása.
- Adatfeldolgozás: Szöveges adatok manipulálása, szűrése, átalakítása olyan eszközökkel, mint a grep, sed, awk.
- Egyszerűség és gyorsaság: Gyorsan lehet velük prototípusokat készíteni, vagy ad-hoc problémákat megoldani anélkül, hogy komplex programozási nyelvre lenne szükség.
- Interakció az operációs rendszerrel: Közvetlenül hozzáférnek a rendszer parancsaihoz és segédprogramjaihoz.
A shell scriptek tehát hidat képeznek a felhasználó és az operációs rendszer mélyebb funkciói között, lehetővé téve a rendszer erőforrásainak hatékony kihasználását a parancssor erejével.
A shell script működésének alapjai
Egy shell script működése viszonylag egyszerű, de fontos megérteni a mögöttes mechanizmust. Amikor futtatunk egy shell scriptet, a shell (például Bash) elolvassa a fájl tartalmát sorról sorra, és minden sort parancsként értelmez és hajt végre. Ez a folyamat szekvenciális: az egyik parancs befejezése után lép át a következőre, hacsak valamilyen vezérlési szerkezet (pl. if, for) nem írja felül ezt a viselkedést.
Az első és talán legfontosabb elem egy shell scriptben a shebang (ejtsd: sí-bang vagy she-bang) sor. Ez a fájl legelső sora, ami így néz ki:
#!/bin/bash
vagy
#!/usr/bin/env bash
Ez a speciális sor (amely a #!
karakterekkel kezdődik, innen a név: hash + bang) tájékoztatja az operációs rendszert, hogy melyik értelmezővel kell futtatni a scriptet. A fenti példákban a /bin/bash
vagy a /usr/bin/env bash
azt jelzi, hogy a scriptet a Bash shellnek kell feldolgoznia. Ha a shebang sor hiányzik, a scriptet az aktuális felhasználó alapértelmezett shellje fogja megpróbálni futtatni, ami kompatibilitási problémákhoz vezethet, ha a script specifikus Bash (vagy más shell) funkciókat használ.
A script futtatásához általában végrehajtási jogot kell adni neki. Ezt a chmod +x script_neve.sh
paranccsal tehetjük meg. Ezután futtatható a ./script_neve.sh
paranccsal (a ./
jelzi, hogy az aktuális könyvtárból kell futtatni).
A shell script végrehajtási folyamata a következőképpen zajlik:
- Fájl megnyitása: Az operációs rendszer megnyitja a script fájlt.
- Shebang értelmezése: Az OS megnézi a shebang sort, és elindítja a megadott értelmezőt (pl. Bash).
- Parancsok olvasása és végrehajtása: A shell sorról sorra olvassa a script tartalmát. Minden sorban található parancsot végrehajt, mintha azt közvetlenül a terminálba írtuk volna.
- Változók és környezet: A shell script futása során saját környezetet hoz létre, amely tartalmazza a scriptben definiált változókat, függvényeket és az örökölt környezeti változókat.
- Kilépési státusz: Minden parancs végrehajtása után egy kilépési státusz (exit status) generálódik. A
0
általában sikeres végrehajtást jelent, míg a nem nulla érték hibát. A scriptekben gyakran ellenőrzik ezt a státuszt a hibakezeléshez.
A shell scriptek ereje abban rejlik, hogy képesek kombinálni a rendszer meglévő parancsait és segédprogramjait (pl. ls
, cp
, rm
, grep
, sed
, awk
) programozási konstrukciókkal, mint például változók, feltételes utasítások, ciklusok és függvények. Ez lehetővé teszi komplex logikák megvalósítását anélkül, hogy alacsonyabb szintű programozási nyelveket (C++, Java, Python) kellene használni.
A shell script felépítése: Alapvető elemek
Egy shell script felépítése egyszerű, de van néhány alapvető elem, amelyeket ismerni kell a hatékony íráshoz.
Shebang sor
Ahogy már említettük, ez a script legelső sora, amely megmondja az operációs rendszernek, melyik értelmezővel kell futtatni a fájlt. Például:
#!/bin/bash
Vagy ha a Bash nem a szokásos helyen van, vagy általánosabb megközelítést szeretnénk:
#!/usr/bin/env bash
Ez utóbbi megkeresi a Bash-t a rendszer PATH változójában, így rugalmasabb.
Kommentek
A kommentek kulcsfontosságúak a script olvashatóságának és karbantarthatóságának szempontjából. A shell scriptekben a #
karakterrel kezdődő sorok (a shebang kivételével) kommenteknek minősülnek, és a shell figyelmen kívül hagyja őket végrehajtáskor. Használjuk őket a kód magyarázatára, a célok dokumentálására és a script logikájának megértésének segítésére.
#!/bin/bash
# Ez egy komment. Ez a sor nem fut le.
echo "Hello, világ!" # Ez a parancs kiírja a "Hello, világ!" szöveget.
# Egy összetettebb feladat leírása:
# 1. Ellenőrizzük a fájl létezését.
# 2. Ha létezik, másoljuk egy biztonsági könyvtárba.
# 3. Értesítést küldünk a felhasználónak.
Parancsok
A shell scriptek lényege a parancsok végrehajtása. Bármilyen parancs, amit a terminálba beírhatunk, beírható egy scriptbe is. Ezek lehetnek egyszerű rendszerparancsok, mint az ls
, cp
, rm
, vagy komplexebb segédprogramok, mint a grep
, sed
, awk
, vagy akár más futtatható programok.
#!/bin/bash
# Fájlok listázása
ls -l
# Könyvtár létrehozása
mkdir uj_konyvtar
# Fájl másolása
cp forras.txt uj_konyvtar/cel.txt
# Üzenet kiírása
echo "A script befejeződött."
Sorvégek és többsoros parancsok
Alapértelmezés szerint minden új sor egy új parancsot jelent. Azonban néha szükség lehet arra, hogy egyetlen logikai parancs több fizikai soron keresztül fusson. Ezt a \
(backslash) karakterrel tehetjük meg, ami jelzi a shellnek, hogy a parancs a következő sorban folytatódik.
#!/bin/bash
# Hosszú parancs több sorban
find . -type f -name "*.log" \
-exec grep -l "hiba" {} \; \
-print
# Vagy olvashatóbb módon, ha a shell szintaxisa megengedi (pl. zárójelekkel)
if [ -f "valami.txt" ] && \
[ -s "valami.txt" ]; then
echo "A fájl létezik és nem üres."
fi
A parancsok pontos és egyértelmű megfogalmazása kulcsfontosságú. A hibásan megírt parancsok váratlan viselkedést okozhatnak, különösen olyan destruktív parancsok esetén, mint az rm
vagy mv
.
A shell scriptek az operációs rendszer parancssori eszközeinek és a programozási logika elemeinek zseniális ötvözete, amely páratlan rugalmasságot és hatékonyságot biztosít a rendszerfeladatok automatizálásában és az adatok manipulálásában.
Változók és adattípusok a shell scriptekben

A változók alapvető fontosságúak bármely programozási nyelvben, így a shell scriptekben is. Lehetővé teszik adatok tárolását és manipulálását a script futása során. A shell scriptekben a változók nem rendelkeznek explicit adattípussal (mint pl. integer, string), minden érték alapvetően stringként kezelődik, bár bizonyos műveletek (pl. matematikai számítások) során a shell megpróbálja számmá konvertálni őket.
Változó deklarálása és értékadás
Változót úgy deklarálunk és adunk neki értéket, hogy a változó nevét közvetlenül az =
jel elé írjuk, szóköz nélkül. Az érték lehet egy string, egy szám, vagy egy másik parancs kimenete.
#!/bin/bash
nev="Péter"
kor=30
uzenet="Hello, $nev! Te $kor éves vagy."
echo $uzenet
# Kimenet: Hello, Péter! Te 30 éves vagy.
Fontos: A változó neve és az =
jel között nem lehet szóköz! Az értékadásnál az idézőjelek használata javasolt, ha az érték szóközt tartalmaz, vagy speciális karaktereket (pl. *
, $
, !
) tartalmazhat, hogy elkerüljük a shell értelmezési hibáit.
Változók hivatkozása
Egy változó értékére a $
előtaggal hivatkozunk. A legjobb gyakorlat a változó nevének kapcsos zárójelekbe (${változó}
) tétele, különösen akkor, ha a változó közvetlenül más karakterekkel van körülvéve, és a shellnek egyértelműen meg kell különböztetnie a változó nevét.
#!/bin/bash
fajlnev="dokumentum"
kiterjesztes=".txt"
# Rossz: A shell nem tudja, hogy a fajlnev_backup egy változó, vagy a fajlnevhez tartozó része
# echo $fajlnev_backup
# Jó: Egyértelműen jelöli a változó végét
echo "A fájl neve: ${fajlnev}${kiterjesztes}"
# Kimenet: A fájl neve: dokumentum.txt
Környezeti változók
A környezeti változók olyan változók, amelyek a shell környezetében léteznek, és az összes alfolyamat számára elérhetők. Ezeket gyakran használják rendszerkonfigurációk, elérési útvonalak (PATH), felhasználói adatok (HOME, USER) tárolására. Az export
paranccsal tehetünk egy változót környezeti változóvá.
#!/bin/bash
# Helyi változó
my_var="Ez egy helyi változó"
echo "Helyi változó: $my_var"
# Környezeti változó
export MY_ENV_VAR="Ez egy környezeti változó"
echo "Környezeti változó: $MY_ENV_VAR"
# Egy alfolyamatban is elérhető lesz
bash -c 'echo "Alfolyamatban: $MY_ENV_VAR"'
Speciális változók
A shell számos speciális változót biztosít, amelyek információt tartalmaznak a script futásáról vagy a parancssori argumentumokról:
$0
: A script neve.$1
,$2
, …: Az első, második, stb. parancssori argumentum.$#
: A parancssori argumentumok száma.$*
: Az összes parancssori argumentum egyetlen stringként, szóközzel elválasztva.$@
: Az összes parancssori argumentum különálló stringekként. Ideális ciklusokhoz.$?
: Az utoljára végrehajtott parancs kilépési státusza (0
sikeres, nem0
hiba).$$
: A script folyamatazonosítója (PID).$!
: Az utoljára háttérben futtatott parancs PID-je.
#!/bin/bash
echo "A script neve: $0"
echo "Argumentumok száma: $#"
echo "Összes argumentum (*): $*"
echo "Összes argumentum (@): $@" # Fontos különbség a for ciklusnál!
echo "Első argumentum: $1"
echo "Második argumentum: $2"
ls /nemletezo_konyvtar
echo "Az 'ls' parancs kilépési státusza: $?"
A változók megfelelő használata elengedhetetlen a dinamikus és rugalmas scriptek írásához. Lehetővé teszi, hogy a scriptek interaktívak legyenek, felhasználói bemenetre reagáljanak, és különböző környezetekben is működjenek.
Bemenet és kimenet kezelése
A shell scriptek gyakran interakcióba lépnek a felhasználóval, vagy adatokat olvasnak be fájlokból, és eredményeket írnak ki a képernyőre vagy fájlokba. Ennek kezelésére szolgálnak a bemeneti és kimeneti parancsok, valamint az átirányítások.
Kimenet: echo
és printf
A leggyakoribb parancs a kimenet képernyőre írására az echo
. Egyszerű stringek, változók vagy parancsok kimenetének megjelenítésére szolgál.
#!/bin/bash
nev="Anna"
echo "Szia, $nev!"
echo "A mai dátum: $(date)" # Parancs kimenetének beillesztése
Az echo
alapértelmezetten új sort ad hozzá a végére. Az -n
opcióval elhagyható az új sor, az -e
opcióval pedig értelmezhetők az escape szekvenciák (pl. \n
új sor, \t
tabulátor).
#!/bin/bash
echo -n "Ez egy sor, "
echo "ez pedig a folytatása."
echo -e "Első sor.\nMásodik sor.\tTabulátor."
A printf
parancs fejlettebb kimeneti formázást tesz lehetővé, hasonlóan a C nyelv printf
függvényéhez. Különösen hasznos, ha pontosan formázott oszlopos kimenetre vagy számok formázására van szükség.
#!/bin/bash
termek="Laptop"
ar=1200.50
darab=3
printf "Termék: %s\nÁr: %.2f EUR\nDarab: %d\nÖsszesen: %.2f EUR\n" "$termek" "$ar" "$darab" "$(echo "$ar * $darab" | bc)"
A printf
nem ad hozzá új sort a végére alapértelmezetten, azt expliciten kell jelezni \n
-nel.
Bemenet: read
A read
parancs lehetővé teszi a felhasználói bemenet beolvasását a billentyűzetről. Az olvasott értéket egy változóba menti.
#!/bin/bash
echo "Kérlek add meg a neved:"
read felhasznalo_nev
echo "Szia, $felhasznalo_nev! Üdv a scriptben."
A read
parancsnak számos hasznos opciója van:
-p "Prompt szöveg"
: Kiír egy prompt üzenetet a bemenet előtt.-s
: Elrejti a beírt karaktereket (jelszavakhoz ideális).-t idő
: Időkorlátot állít be a bemenetre (másodpercben).-r
: Nyers bemenetet olvas be, figyelmen kívül hagyva a backslash escape-eket.
#!/bin/bash
read -p "Add meg a felhasználóneved: " username
read -s -p "Add meg a jelszavad: " password
echo # Új sor a jelszó beolvasása után
echo "Felhasználónév: $username"
echo "Jelszó (titkosítva): $password"
Bemeneti/Kimeneti átirányítás
A shell egyik legerősebb funkciója a bemeneti és kimeneti átirányítás. Ez lehetővé teszi a parancsok kimenetének fájlba írását, vagy egy fájl tartalmának bemenetként való használatát egy parancs számára.
>
: Kimenet átirányítása fájlba. Ha a fájl létezik, felülírja.>>
: Kimenet hozzáfűzése fájlhoz. Ha a fájl létezik, a végére ír, ha nem, létrehozza.<
: Bemenet átirányítása fájlból.2>
: Hibaüzenetek (stderr) átirányítása fájlba.&>
vagy>&
: Standard kimenet (stdout) és hibaüzenetek (stderr) együttes átirányítása fájlba.
#!/bin/bash
# Kimenet fájlba írása (felülírja)
ls -l > fajl_lista.txt
# Kimenet hozzáfűzése fájlhoz
echo "Ez egy új sor." >> fajl_lista.txt
# Fájl tartalmának beolvasása parancsba
wc -l < fajl_lista.txt # megszámolja a sorokat a fájlban
# Hibaüzenetek átirányítása
rm nem_letezo_fajl 2> hibalog.txt
# Standard kimenet és hibaüzenetek együttes átirányítása
find /etc -name "*.conf" &> osszes_kimenet.txt
Pipe-ok (|
)
A pipe (csővezeték) lehetővé teszi az egyik parancs standard kimenetének (stdout) közvetlen átirányítását egy másik parancs standard bemenetére (stdin). Ez rendkívül erőteljes, és lehetővé teszi a komplex adatfeldolgozási láncok felépítését.
#!/bin/bash
# Fájlok listázása, majd szűrés "log" szóra, majd sorok számlálása
ls -l | grep "log" | wc -l
# Rendszerfolyamatok listázása, szűrés "apache" szóra, majd a második oszlop (PID) kiírása
ps aux | grep apache | awk '{print $2}'
A bemeneti és kimeneti kezelés, valamint az átirányítások és pipe-ok ismerete alapvető a shell scriptek hatékony írásához. Ezek segítségével a scriptek interaktívvá válnak, képesek adatokat feldolgozni, és automatizált munkafolyamatokba illeszthetők.
Vezérlési szerkezetek: Döntések és elágazások
A shell scriptek nem lennének sokkal többet, mint egyszerű parancslisták, ha nem lennének bennük vezérlési szerkezetek. Ezek teszik lehetővé, hogy a scriptek döntéseket hozzanak, különböző útvonalakon haladjanak a feltételek alapján, és ismétlődő feladatokat végezzenek. A legfontosabb döntéshozatali szerkezetek az if
és a case
.
if
-elif
-else
szerkezet
Az if
utasítás a leggyakoribb módja a feltételes végrehajtásnak. Egy feltételt ellenőriz, és ha az igaz, végrehajt egy kódrészletet. Az elif
(else if) és az else
opcionális, és további feltételeket vagy egy alapértelmezett ágat biztosítanak.
#!/bin/bash
szam=10
if [ "$szam" -gt 5 ]; then
echo "A szám nagyobb, mint 5."
elif [ "$szam" -eq 5 ]; then
echo "A szám pontosan 5."
else
echo "A szám kisebb, mint 5."
fi
A feltételek ellenőrzésére a test
parancsot vagy annak rövidített formáját, a [ ]
-t használjuk. A Bash (és más modern shellek) emellett fejlettebb feltételeket is támogat a [[ ]]
és a (( ))
szintaxissal.
Gyakori feltételek ([ feltétel ]
vagy test feltétel
):
- Számok összehasonlítása:
-eq
: egyenlő (equal)-ne
: nem egyenlő (not equal)-gt
: nagyobb, mint (greater than)-ge
: nagyobb vagy egyenlő (greater than or equal)-lt
: kisebb, mint (less than)-le
: kisebb vagy egyenlő (less than or equal)
- Stringek összehasonlítása:
=
vagy==
: egyenlő!=
: nem egyenlő-z "string"
: string üres (zero length)-n "string"
: string nem üres (non-zero length)
- Fájlok ellenőrzése:
-e fájl
: fájl létezik-f fájl
: fájl létezik és reguláris fájl-d könyvtár
: könyvtár létezik és könyvtár-s fájl
: fájl létezik és nem üres (non-zero size)-r fájl
: fájl olvasható-w fájl
: fájl írható-x fájl
: fájl végrehajtható
Példa fájl ellenőrzésre:
#!/bin/bash
fajl="naplo.log"
if [ -f "$fajl" ]; then
echo "A $fajl létezik és reguláris fájl."
if [ -s "$fajl" ]; then
echo "A $fajl nem üres."
else
echo "A $fajl üres."
fi
else
echo "A $fajl nem létezik vagy nem reguláris fájl."
fi
Logikai operátorok:
A feltételeket kombinálhatjuk logikai operátorokkal:
-a
vagy&&
: ÉS (and)-o
vagy||
: VAGY (or)!
: NEM (not)
#!/bin/bash
kor=20
nem="férfi"
if [ "$kor" -ge 18 ] && [ "$nem" = "férfi" ]; then
echo "Felnőtt férfi."
fi
if [ "$kor" -lt 18 ] || [ "$nem" = "nő" ]; then
echo "Kiskorú vagy nő."
fi
case
szerkezet
A case
utasítás egy alternatíva az if-elif-else
láncolatra, ha több lehetséges értéket kell ellenőrizni egyetlen változó alapján. Különösen hasznos menürendszerek vagy argumentumok feldolgozásakor.
#!/bin/bash
read -p "Válassz egy opciót (a/b/c): " opcio
case "$opcio" in
a|A) # Több minta is megadható | jellel
echo "Az 'A' opciót választottad."
;; # Minden ágat ezzel zárjuk
b|B)
echo "A 'B' opciót választottad."
;;
c|C)
echo "A 'C' opciót választottad."
;;
*) # Alapértelmezett ág, ha egyik sem illeszkedik
echo "Érvénytelen opció."
;;
esac
A case
szerkezet mintákat (pattern) használ az összehasonlításhoz, ami rugalmasabbá teszi, mint a if
egyenlőségvizsgálata. Használhatók benne glob (wildcard) karakterek, mint a *
(bármilyen karakterek bármilyen száma) és a ?
(bármilyen egyetlen karakter).
#!/bin/bash
fajlnev="kep.jpg"
case "$fajlnev" in
*.txt)
echo "Ez egy szöveges fájl."
;;
*.jpg|*.png|*.gif)
echo "Ez egy képfájl."
;;
*)
echo "Ismeretlen fájltípus."
;;
esac
A vezérlési szerkezetek nélkülözhetetlenek a dinamikus és intelligens shell scriptek írásához, amelyek képesek alkalmazkodni a különböző körülményekhez és felhasználói bemenetekhez.
Ciklusok: Ismétlődő feladatok automatizálása
A ciklusok a programozás alapvető elemei, amelyek lehetővé teszik egy kódrészlet ismételt végrehajtását, amíg egy bizonyos feltétel teljesül, vagy egy elemek listáján végigmegyünk. A shell scriptekben a leggyakoribb ciklusok a for
, a while
és az until
.
for
ciklus
A for
ciklus a leggyakrabban használt ciklustípus, amikor egy ismert listán (fájlok, stringek, számok) szeretnénk végigmenni. Két fő szintaxisa van:
1. Lista alapú for
ciklus (Bash stílus)
Ez a leggyakoribb forma, amely egy elemek listáján iterál végig. Minden iterációban a lista következő eleme hozzárendelődik a ciklus változójához.
#!/bin/bash
# Fájlok feldolgozása
echo "Fájlok listázása az aktuális könyvtárban:"
for fajl in *.txt; do # Iterál a .txt kiterjesztésű fájlokon
echo "Feldolgozom: $fajl"
# Itt lehetne parancsokat végrehajtani a fájllal, pl. cat "$fajl"
done
# Stringek listáján iterálás
gyumolcsok="alma körte szilva"
echo "Kedvenc gyümölcseim:"
for gyumolcs in $gyumolcsok; do
echo "- $gyumolcs"
done
# Parancssori argumentumokon iterálás (fontos: "$@")
echo "Feldolgozom az argumentumokat:"
for arg in "$@"; do
echo "Argumentum: $arg"
done
Fontos: Amikor parancssori argumentumokon iterálunk, vagy változókat tartalmazó listán, mindig használjuk a duplá idézőjeleket ("$@"
vagy "$valtozo"
), hogy elkerüljük a szótagolási (word splitting) és glob (pathname expansion) problémákat, különösen, ha az elemek szóközt tartalmaznak.
2. C-stílusú for
ciklus (Bash)
Ez a forma ismerősebb lehet más programozási nyelvekből, ahol egy számláló változót használunk a ciklus szabályozására. A szintaxis: for (( inicializálás; feltétel; lépés )); do ... done
.
#!/bin/bash
echo "Számolás 1-től 5-ig:"
for (( i=1; i<=5; i++ )); do
echo "Szám: $i"
done
echo "Páros számok 10-től 2-ig:"
for (( i=10; i>=2; i-=2 )); do
echo "Páros szám: $i"
done
while
ciklus
A while
ciklus mindaddig fut, amíg a megadott feltétel igaz. Ez hasznos, ha nem tudjuk előre a ciklusok számát, például addig olvasunk egy fájlból, amíg van benne tartalom, vagy addig várunk, amíg egy szolgáltatás elindul.
#!/bin/bash
szamlalo=0
while [ "$szamlalo" -lt 5 ]; do
echo "Számláló: $szamlalo"
szamlalo=$((szamlalo + 1)) # Matematikai művelet
sleep 1 # Várakozás 1 másodpercet
done
echo "Ciklus vége."
Példa fájl sorainak olvasására:
#!/bin/bash
fajl="lista.txt"
# Hozzunk létre egy tesztfájlt
echo "Első sor" > "$fajl"
echo "Második sor" >> "$fajl"
echo "Harmadik sor" >> "$fajl"
echo "Fájl tartalmának soronkénti olvasása:"
while IFS= read -r sor; do
echo "Tartalom: $sor"
done < "$fajl" # A fájl átirányítása a while ciklus bemenetére
A IFS= read -r sor
egy gyakori és robusztus módja a fájlok soronkénti olvasásának. Az IFS=
megakadályozza a szótagolást, a -r
pedig a backslash escape-ek értelmezését.
until
ciklus
Az until
ciklus ellentétesen működik a while
ciklussal: mindaddig fut, amíg a feltétel hamis. Amint a feltétel igazzá válik, a ciklus leáll.
#!/bin/bash
# Várakozás, amíg egy fájl létezni nem kezd
fajl="figyelt_fajl.txt"
echo "Várakozás a '$fajl' fájlra..."
until [ -f "$fajl" ]; do
echo "A fájl még nem létezik. Várakozás..."
sleep 2
done
echo "A '$fajl' fájl létrejött! Folytatom."
break
és continue
break
: Azonnal kilép a legbelső ciklusból.continue
: Kihagyja a ciklus aktuális iterációjának hátralévő részét, és a következő iterációra lép.
#!/bin/bash
for i in {1..10}; do
if [ "$i" -eq 5 ]; then
echo "Megtaláltam az 5-öt, kilépek."
break
fi
echo "Aktuális szám: $i"
done
echo "---"
for i in {1..10}; do
if (( i % 2 == 0 )); then
echo "Páros szám ($i), kihagyom."
continue
fi
echo "Páratlan szám: $i"
done
A ciklusok elsajátítása kulcsfontosságú a shell scriptek írásakor, mivel ezek teszik lehetővé az ismétlődő és időigényes feladatok hatékony automatizálását, ezzel óriási időt és energiát takarítva meg a felhasználóknak és rendszergazdáknak.
Függvények: Kód újrafelhasználása és modularitás

Ahogy a scriptek egyre hosszabbak és komplexebbek lesznek, fontos, hogy a kódot modulárisan és újrafelhasználhatóan szervezzük. Erre szolgálnak a függvények. Egy függvény egy elnevezett kódrészlet, amelyet többször is meghívhatunk a scripten belül, elkerülve a kódismétlést és javítva az olvashatóságot.
Függvény deklarálása és hívása
A függvényeket kétféleképpen deklarálhatjuk Bash-ben:
#!/bin/bash
# 1. Szintaxis (a preferált, POSIX-kompatibilis)
function udvozles {
echo "Szia, $1!" # $1 az első argumentum
}
# 2. Szintaxis (Bash-specifikus)
koszontes() {
echo "Üdvözöllek, $1!"
}
# Függvény hívása
udvozles "Péter"
koszontes "Anna"
A függvényeket a nevükkel hívhatjuk meg, akárcsak egy parancsot. Az argumentumokat szóközzel elválasztva adhatjuk át, és a függvényen belül a $1
, $2
, stb. speciális változókkal érhetjük el őket, akárcsak a script parancssori argumentumait. A $#
a függvénynek átadott argumentumok számát, a $@
pedig az összes argumentumot jelöli.
Függvények argumentumai és visszatérési értékei
A függvények a return
paranccsal adhatnak vissza egy kilépési státuszt (0-255 közötti számot), akárcsak a normál parancsok. A 0
általában sikert, a nem nulla érték hibát jelez. A visszatérési értékre a $?
változóval hivatkozhatunk a függvény hívása után.
Ha egy függvényből szöveges kimenetet szeretnénk kapni, azt általában a echo
paranccsal tesszük, majd a függvény hívását egy parancssubstitúcióban ($(függvény)
) használjuk.
#!/bin/bash
# Függvény kilépési státusszal
ellenoriz_fajl() {
local fajl="$1" # local kulcsszó: változó a függvényen belül marad
if [ -f "$fajl" ]; then
echo "A '$fajl' létezik."
return 0 # Sikeres
else
echo "A '$fajl' nem létezik."
return 1 # Hiba
fi
}
# Függvény szöveges kimenettel
get_current_time() {
date +"%Y-%m-%d %H:%M:%S"
}
# Függvények hívása és visszatérési értékek kezelése
ellenoriz_fajl "nemletezo.txt"
if [ $? -eq 0 ]; then
echo "Ellenőrzés sikeres."
else
echo "Ellenőrzés sikertelen."
fi
aktualis_ido=$(get_current_time)
echo "Aktuális idő: $aktualis_ido"
Fontos: A local
kulcsszó használata javasolt a függvényen belüli változók deklarálásakor, hogy elkerüljük a globális változók véletlen felülírását és a névütközéseket. Ez hozzájárul a függvények reusability-jéhez.
Függvények előnyei
- Kód újrafelhasználása: Ugyanazt a kódot többször is felhasználhatjuk anélkül, hogy újraírnánk.
- Modularitás: A kódot logikai egységekre bonthatjuk, ami javítja az olvashatóságot és a karbantarthatóságot.
- Hibakeresés: Könnyebb megtalálni és javítani a hibákat, ha a kód kisebb, jól definiált egységekre van bontva.
- Absztrakció: Elrejthetjük a komplex részleteket egy egyszerű függvényhívás mögé.
A függvények elengedhetetlenek a komplex shell scriptek strukturálásához és kezeléséhez. Segítségükkel a scriptek tisztábbá, hatékonyabbá és könnyebben fejleszthetővé válnak.
Parancssori argumentumok és paraméterek kezelése
A shell scriptek gyakran igénylik, hogy a felhasználó adatokat adjon meg a futtatáskor, vagy hogy különböző opciókkal indíthatók legyenek. Erre szolgálnak a parancssori argumentumok. Ezeket a script neve után, szóközzel elválasztva adjuk meg a terminálban.
Alapvető argumentumok kezelése
Ahogy a speciális változóknál már említettük, a parancssori argumentumokat a $1
, $2
, $3
, stb. változókkal érhetjük el, ahol $1
az első argumentum, $2
a második, és így tovább. A $0
a script nevét tartalmazza.
#!/bin/bash
# script_nev.sh
echo "A script neve: $0"
echo "Az első argumentum: $1"
echo "A második argumentum: $2"
echo "A harmadik argumentum: $3"
# Példa futtatás: ./script_nev.sh alma körte szilva
# Kimenet:
# A script neve: ./script_nev.sh
# Az első argumentum: alma
# A második argumentum: körte
# A harmadik argumentum: szilva
A $#
változó tartalmazza az átadott argumentumok számát, ami hasznos lehet annak ellenőrzésére, hogy a felhasználó megadott-e elegendő argumentumot.
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Használat: $0 <forrás_fájl> <cél_könyvtár>"
exit 1 # Kilépés hibával
fi
forras_fajl="$1"
cel_konyvtar="$2"
if [ ! -f "$forras_fajl" ]; then
echo "Hiba: A forrásfájl '$forras_fajl' nem létezik."
exit 1
fi
if [ ! -d "$cel_konyvtar" ]; then
echo "Hiba: A célkönyvtár '$cel_konyvtar' nem létezik."
exit 1
fi
cp "$forras_fajl" "$cel_konyvtar"
echo "A '$forras_fajl' sikeresen átmásolva ide: '$cel_konyvtar'."
A $*
és $@
speciális változók az összes argumentumot tartalmazzák. Bár hasonlóak, van egy fontos különbség, amikor idézőjelek közé tesszük őket:
"$*"
: Az összes argumentumot egyetlen stringként kezeli, szóközzel elválasztva."$@"
: Az összes argumentumot különálló stringekként kezeli. Ez a preferált forma, ha argumentumokon szeretnénk iterálni, különösen, ha azok szóközt tartalmaznak.
#!/bin/bash
echo "Futtatás: $0 \"alma körte\" szilva"
echo "--- \$* példa ---"
for arg in "$*"; do
echo "Arg: $arg"
done
# Kimenet: Arg: alma körte szilva (egy sorban)
echo "--- \$@ példa ---"
for arg in "$@"; do
echo "Arg: $arg"
done
# Kimenet:
# Arg: alma körte
# Arg: szilva (külön sorban)
Opciók (flags) kezelése: getopts
Komplexebb scriptek esetén gyakran szükség van opciók (pl. -v
a verbose módhoz, -f
a fájlnévhez) kezelésére. Erre a célra a getopts
beépített parancs a legrobosztusabb megoldás.
#!/bin/bash
VERBOSE=false
OUTPUT_FILE=""
while getopts "vf:" opt; do
case ${opt} in
v )
VERBOSE=true
;;
f )
OUTPUT_FILE="$OPTARG"
;;
\? ) # Érvénytelen opció
echo "Használat: $0 [-v] [-f <fájlnév>] <argumentumok...>"
exit 1
;;
esac
done
# Shifteljük el a feldolgozott opciókat, hogy a maradék argumentumok elérhetők legyenek $1, $2, stb.
shift $((OPTIND -1))
echo "Részletes mód: $VERBOSE"
echo "Kimeneti fájl: ${OUTPUT_FILE:-\"Nincs megadva\"}" # Ha üres, írja ki "Nincs megadva"
echo "Feldolgozandó argumentumok:"
for arg in "$@"; do
echo "- $arg"
done
# Példa futtatás: ./script.sh -v -f log.txt arg1 "második arg"
A getopts
használata:
- Az első argumentum egy string, amely tartalmazza az összes elfogadott opciót. Ha egy opció után kettőspont (
:
) van, az azt jelenti, hogy az adott opcióhoz argumentum is tartozik. - A
while
ciklus mindaddig fut, amíg agetopts
további opciókat talál. - A feldolgozott opció a
$opt
változóban található. - Az opcióhoz tartozó argumentum (ha van) az
$OPTARG
változóban található. - Az
$OPTIND
változó a következő feldolgozandó argumentum indexét tárolja. Ashift $((OPTIND -1))
paranccsal eltávolítjuk a már feldolgozott opciókat, így a fennmaradó argumentumok a$1
,$2
, stb. helyekre kerülnek.
A parancssori argumentumok és opciók kezelése kulcsfontosságú ahhoz, hogy a scriptek rugalmasak és felhasználóbarátok legyenek, lehetővé téve a testreszabott viselkedést a különböző futtatások során.
Hibakezelés és hibakeresés a shell scriptekben
A robusztus shell scriptek írásának elengedhetetlen része a hibák megfelelő kezelése és a problémák hatékony felderítése. Egy jól megírt script nemcsak azt teszi, amit elvárnak tőle, hanem azt is kezeli, ha valami rosszul sül el.
Hibakezelés
Kilépési státusz ellenőrzése ($?
)
Minden parancs végrehajtása után egy kilépési státuszt (exit status) ad vissza. A 0
érték általában sikert jelez, míg a nem nulla érték (1-255) valamilyen hibát. Ezt a státuszt a $?
speciális változóban tárolja a shell.
#!/bin/bash
cp nemletezo_fajl.txt uj_hely.txt
if [ $? -ne 0 ]; then
echo "Hiba: A fájl másolása sikertelen volt."
exit 1 # Kilépés hibakóddal
fi
echo "Fájl másolása sikeres."
set -e
: Kilépés hibára
Ez az egyik leghasznosabb opció a shell scriptekben. Ha a set -e
(vagy set -o errexit
) opciót beállítjuk a script elején, a script azonnal kilép, ha bármelyik parancs hibával (nem nulla kilépési státusszal) tér vissza. Ez megakadályozza, hogy a script hibás állapotban tovább fusson, és további problémákat okozzon.
#!/bin/bash
set -e # Ha bármely parancs hibával tér vissza, a script azonnal kilép
echo "Ez az első parancs."
cp nemletezo_fajl.txt /tmp/cel.txt # Ez a parancs hibát okoz
echo "Ez a sor sosem fog megjelenni, ha a másolás sikertelen volt."
Fontos: A set -e
nem reagál a pipe-okban lévő hibákra, csak az utolsó parancs hibájára. A set -o pipefail
opcióval orvosolható ez a probléma, így a pipe bármelyik parancsának hibája esetén az egész pipe hibával tér vissza.
#!/bin/bash
set -e
set -o pipefail # A pipe-okban lévő hibák is kilépést okoznak
echo "Ez egy teszt" | grep "nemlétező_szó"
echo "Ez a sor sem fog megjelenni."
trap
parancs
A trap
parancs lehetővé teszi, hogy bizonyos események (jelek) bekövetkeztekor (pl. script leállítása, hiba) egy adott parancsot vagy függvényt futtassunk. Gyakori használata a tisztítási feladatok (ideiglenes fájlok törlése) végrehajtása kilépéskor.
#!/bin/bash
# Függvény, ami lefut, ha a script kilép (akár hibával, akár sikerrel)
cleanup() {
echo "Tisztítás végrehajtása..."
rm -f /tmp/temp_file_*.txt
}
# A cleanup függvény futtatása EXIT jel esetén (kilépéskor)
trap cleanup EXIT
# A cleanup függvény futtatása ERR jel esetén (hiba esetén)
trap 'echo "Hiba történt a(z) $LINENO sorban!"; cleanup; exit 1' ERR
echo "Ideiglenes fájl létrehozása..."
touch /tmp/temp_file_1.txt
touch /tmp/temp_file_2.txt
echo "Valamilyen művelet..."
ls -l /nemletezo_konyvtar # Ez hibát okoz, és elindítja az ERR trap-et
echo "Ez a sor nem fog lefutni hiba esetén."
Hibakeresés (Debugging)
set -x
: Parancsok kiírása
A set -x
(vagy set -o xtrace
) opció bekapcsolja a "trace" módot, ami minden végrehajtott parancsot kiír a terminálra, mielőtt az lefutna. Ez rendkívül hasznos a script futásának követésére és a problémás sorok azonosítására.
#!/bin/bash
# set -x # Bekapcsolhatjuk itt, vagy futtathatjuk bash -x script.sh formában
nev="János"
echo "Szia, $nev!"
if [ -d "/tmp" ]; then
echo "A /tmp könyvtár létezik."
else
echo "A /tmp könyvtár nem létezik."
fi
A kimenet minden egyes parancs előtt egy +
jellel jelzi a végrehajtást, és kiírja a parancsot a változók feloldott értékeivel.
set -v
: Bemeneti sorok kiírása
A set -v
(vagy set -o verbose
) opció kiírja a script minden sorát, ahogy azt a shell olvassa, még a kommenteket is. Kevésbé hasznos, mint a set -x
, de segíthet a szintaktikai hibák felderítésében.
Részleges hibakeresés
A hibakeresési opciókat be- és kikapcsolhatjuk a script különböző részein, hogy csak a problémás területekre fókuszáljunk:
#!/bin/bash
echo "Ez a rész normálisan fut."
set -x # Hibakeresés bekapcsolása
echo "Ez a rész trace módban fut."
ls -l /tmp
set +x # Hibakeresés kikapcsolása
echo "Ez a rész ismét normálisan fut."
echo
és printf
a hibakereséshez
A legegyszerűbb, de gyakran leghatékonyabb hibakeresési módszer az echo
vagy printf
parancsok beillesztése a scriptbe, hogy kiírjuk a változók értékeit, vagy jelezzük, melyik kódrészlet futott le.
#!/bin/bash
fajl="adataim.txt"
echo "DEBUG: A fájlnév változó értéke: '$fajl'"
if [ -f "$fajl" ]; then
echo "DEBUG: A fájl létezik, feldolgozás indítása..."
# ... feldolgozási logika ...
else
echo "DEBUG: A fájl nem létezik, kilépés."
exit 1
fi
A hibakezelés és hibakeresés integrálása a shell script fejlesztési folyamatába elengedhetetlen a megbízható és fenntartható scriptek létrehozásához. Segítenek azonosítani és orvosolni a problémákat, mielőtt azok komolyabb károkat okoznának.
Gyakori és haladó parancsok a shell scriptekben
A shell scriptek ereje abban rejlik, hogy képesek integrálni és automatizálni a Linux/Unix rendszerekben elérhető parancsok és segédprogramok széles skáláját. Néhány parancs különösen gyakran és hatékonyan használható scriptekben az adatfeldolgozásra, fájlkezelésre és rendszerinterakcióra.
grep
: Szöveges minták keresése
A grep
(Global Regular Expression Print) parancs egy sorban keres egy adott mintát, és kiírja azokat a sorokat, amelyek tartalmazzák a mintát. Rendkívül hasznos naplófájlok elemzésére, konfigurációs fájlok szűrésére stb.
#!/bin/bash
# Keresés a "hiba" szó után egy naplófájlban
grep "hiba" /var/log/syslog
# Esetérzéketlen keresés és sorok számlálása
grep -i "error" /var/log/messages | wc -l
# Sorok kiírása, amelyek NEM tartalmazzák a mintát
grep -v "info" /var/log/auth.log
# Rekurzív keresés fájlokban
grep -r "TODO" .
Gyakori opciók: -i
(esetérzéketlen), -v
(invertálja a találatokat), -c
(csak a sorok számát adja vissza), -n
(sorok számát is kiírja), -r
(rekurzív keresés könyvtárakban), -l
(csak a fájlneveket írja ki, ahol talált).
sed
: Szövegstream szerkesztő
A sed
(Stream EDitor) egy rendkívül erőteljes parancs szöveges fájlok vagy bemeneti streamek manipulálására. Gyakran használják szöveg cseréjére, sorok törlésére, beszúrására vagy kinyerésére.
#!/bin/bash
# Szöveg cseréje (első előfordulás soronként)
echo "Hello World" | sed 's/World/Universe/'
# Kimenet: Hello Universe
# Szöveg cseréje (összes előfordulás soronként)
echo "alma, körte, alma" | sed 's/alma/banán/g'
# Kimenet: banán, körte, banán
# Sor törlése, ami tartalmazza a mintát
sed '/hiba/d' /var/log/alkalmazas.log
# Sor beszúrása az 5. sor elé
sed '5i\--- EZ EGY ÚJ SOR ---' bemenet.txt
# In-place szerkesztés (vigyázat!)
# sed -i 's/régi/új/g' fajl.txt
A sed
a reguláris kifejezések széles skáláját támogatja, ami rendkívül rugalmassá teszi a mintakeresésben és cserében.
awk
: Mintakereső és feldolgozó nyelv
Az awk
egy programozási nyelv, amelyet kifejezetten szöveges adatok feldolgozására terveztek. Soronként dolgozza fel a bemenetet, és minden sort mezőkre (alapértelmezés szerint szóközzel elválasztva) bont. Nagyon hasznos táblázatos adatok elemzésére.
#!/bin/bash
# Teszt adatfájl létrehozása
echo "Név Kor Város" > adatok.txt
echo "Péter 30 Budapest" >> adatok.txt
echo "Anna 25 Szeged" >> adatok.txt
echo "Gábor 35 Debrecen" >> adatok.txt
# Kiírja a második oszlopot (Kor)
awk '{print $2}' adatok.txt
# Kimenet:
# Kor
# 30
# 25
# 35
# Kiírja azokat a sorokat, ahol a kor > 30
awk '$2 > 30 {print $1, $2}' adatok.txt
# Kimenet:
# Gábor 35
# Összegzés
ls -l | awk '{sum += $5} END {print "Összes méret: " sum " byte"}'
Az awk
a BEGIN
és END
blokkokkal is rendelkezik, amelyek a feldolgozás előtt, illetve után futnak le, lehetővé téve az inicializálást és az összegzést.
find
és xargs
: Fájlok keresése és parancsok futtatása
A find
parancs fájlokat és könyvtárakat keres a fájlrendszerben a megadott kritériumok alapján. A xargs
pedig egy segédprogram, amely a standard bemenetéről olvas listát, és minden elemen futtat egy parancsot.
#!/bin/bash
# Összes .log fájl törlése az aktuális könyvtárból és alkönyvtáraiból
# find . -name "*.log" -delete # Biztonságosabb, ha a find támogatja a -delete-et
# Alternatíva xargs-szal (biztonságosabb, ha sok fájl van)
find . -name "*.log" -print0 | xargs -0 rm
# Keresés és jogosultságok módosítása
find . -type f -name "*.sh" -exec chmod +x {} \;
# Fájlok keresése méret alapján és listázása
find . -type f -size +10M -ls
A -print0
és xargs -0
kombinációja fontos, mert ez kezeli a fájlnevekben lévő szóközöket és speciális karaktereket, null karakterrel elválasztva az elemeket.
sort
, uniq
, cut
, head
, tail
, wc
sort
: Sorok rendezése.uniq
: Ismétlődő sorok eltávolítása (csak egymás melletti duplikátumokat távolít el, ezért gyakransort
után használják).cut
: Oszlopok kivágása szöveges fájlokból.head
: Fájl elejének kiírása.tail
: Fájl végének kiírása (-f
opcióval valós idejű figyelés).wc
: Sorok, szavak, karakterek számlálása.
#!/bin/bash
# IP címek rendezése és egyedi listázása egy logfájlból
cat access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -n 10
# Ez a parancs kiírja a top 10 leggyakoribb IP címet az access.log-ból.
Ezeknek a parancsoknak a kombinálása pipe-ok és átirányítások segítségével adja a shell scriptek rendkívüli erejét az adatok hatékony feldolgozásában és manipulálásában.
Shell scriptek a gyakorlatban: Példák és felhasználási területek

A shell scriptek alkalmazási területe rendkívül széles. Alább néhány valós példa és felhasználási terület, amelyek bemutatják a parancsfájlok sokoldalúságát.
Rendszeradminisztráció és karbantartás
1. Rendszerinformációk gyűjtése
Egy script, ami alapvető rendszerinformációkat gyűjt és kiír:
#!/bin/bash
# system_info.sh
echo "--- Rendszerinformációk: $(date) ---"
echo "Hostnév: $(hostname)"
echo "Operációs rendszer: $(uname -a)"
echo "Futtató felhasználó: $(whoami)"
echo "Aktuális könyvtár: $(pwd)"
echo ""
echo "--- Lemezhasználat ---"
df -h /
echo ""
echo "--- Memóriahasználat ---"
free -h
echo ""
echo "--- Top 5 CPU-t használó folyamat ---"
ps aux --sort=-%cpu | head -n 6
Ez a script gyors áttekintést nyújt a rendszer állapotáról, és könnyen bővíthető további ellenőrzésekkel.
2. Biztonsági mentés automatizálása
Egy egyszerű biztonsági mentés script, ami egy könyvtárat tömörít és időbélyeggel ellátva ment el:
#!/bin/bash
# backup_script.sh
SOURCE_DIR="/home/felhasznalo/dokumentumok"
BACKUP_DIR="/mnt/backup/dokumentumok_mentesek"
DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="$BACKUP_DIR/dokumentumok_backup_$DATE.tar.gz"
LOG_FILE="/var/log/backup_script.log"
mkdir -p "$BACKUP_DIR"
echo "[$(date)] Indul a biztonsági mentés a '$SOURCE_DIR' könyvtárból..." | tee -a "$LOG_FILE"
tar -czvf "$BACKUP_FILE" "$SOURCE_DIR" >> "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
echo "[$(date)] Sikeres mentés: '$BACKUP_FILE'" | tee -a "$LOG_FILE"
# Régi mentések törlése (pl. 7 napnál régebbiek)
find "$BACKUP_DIR" -type f -name "dokumentumok_backup_*.tar.gz" -mtime +7 -delete
echo "[$(date)] Régi mentések törölve." | tee -a "$LOG_FILE"
else
echo "[$(date)] Hiba a mentés során!" | tee -a "$LOG_FILE"
# Hiba esetén értesítés küldése (pl. e-mailben)
# echo "Hiba a mentés során!" | mail -s "Mentési hiba" admin@example.com
exit 1
fi
Ez a script futtatható cron jobként, így automatikusan elvégzi a mentéseket.
Fejlesztői munkafolyamatok
3. Projekt buildelése és tesztelése
Egy script, ami egy szoftverprojektet fordít, majd futtatja a teszteket:
#!/bin/bash
# build_and_test.sh
PROJECT_DIR="/home/felhasznalo/my_project"
BUILD_LOG="$PROJECT_DIR/build.log"
TEST_LOG="$PROJECT_DIR/test.log"
cd "$PROJECT_DIR" || { echo "Hiba: Nem található a projekt könyvtár!"; exit 1; }
echo "--- Projekt fordítása ---" | tee "$BUILD_LOG"
make clean && make all >> "$BUILD_LOG" 2>&1
if [ $? -eq 0 ]; then
echo "Fordítás sikeres." | tee -a "$BUILD_LOG"
echo "--- Tesztek futtatása ---" | tee "$TEST_LOG"
./run_tests.sh >> "$TEST_LOG" 2>&1
if [ $? -eq 0 ]; then
echo "Tesztek sikeresen lefutottak." | tee -a "$TEST_LOG"
else
echo "Hiba: Tesztek sikertelenek!" | tee -a "$TEST_LOG"
exit 1
fi
else
echo "Hiba: Fordítás sikertelen!" | tee -a "$BUILD_LOG"
exit 1
fi
echo "Build és teszt folyamat befejeződött."
Ez a script integrálható Continuous Integration (CI) rendszerekbe.
Adatfeldolgozás és elemzés
4. Naplófájl elemzés
Egy script, ami egy webkiszolgáló hozzáférési naplójából kinyeri a legtöbb kérést küldő IP-címeket:
#!/bin/bash
# analyze_access_log.sh
LOG_FILE="/var/log/apache2/access.log"
OUTPUT_FILE="top_ips.txt"
if [ ! -f "$LOG_FILE" ]; then
echo "Hiba: A naplófájl '$LOG_FILE' nem található."
exit 1
fi
echo "--- Top 10 IP-cím a '$LOG_FILE' fájlból ---"
awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -nr | head -n 10 > "$OUTPUT_FILE"
echo "Az eredmények elmentve ide: '$OUTPUT_FILE'"
cat "$OUTPUT_FILE"
Ez egy tipikus példa a pipe-ok és az alapvető Linux segédprogramok erejére az adatfeldolgozásban.
5. Fájlok átnevezése
Egy script, ami fájlokat nevez át egy adott minta alapján, például hozzáad egy előtagot:
#!/bin/bash
# rename_files.sh
PREFIX="uj_elotag_"
DIR="." # Az aktuális könyvtár
if [ "$#" -eq 1 ]; then
DIR="$1"
fi
if [ ! -d "$DIR" ]; then
echo "Hiba: A könyvtár '$DIR' nem létezik."
exit 1
fi
echo "Fájlok átnevezése a(z) '$DIR' könyvtárban a '$PREFIX' előtaggal..."
for file in "$DIR"/*; do
if [ -f "$file" ]; then # Csak reguláris fájlokat dolgozunk fel
filename=$(basename "$file")
dirname=$(dirname "$file")
new_filename="${dirname}/${PREFIX}${filename}"
mv "$file" "$new_filename"
echo "Átnevezve: '$filename' -> '${PREFIX}${filename}'"
fi
done
echo "Átnevezés befejezve."
Ezek a példák csak ízelítőt adnak a shell scriptek hatalmas potenciáljából. A képzelet és a rendelkezésre álló parancsok ismerete szabja meg a határokat, hogy milyen feladatokat automatizálhatunk velük.
Biztonsági megfontolások és legjobb gyakorlatok
A shell scriptek rendkívül erősek, de ez az erő felelősséggel jár. A rosszul megírt vagy nem kellően átgondolt scriptek biztonsági réseket okozhatnak, adatvesztést eredményezhetnek, vagy instabil rendszereket hozhatnak létre. Fontos, hogy tisztában legyünk a biztonsági kockázatokkal és a legjobb gyakorlatokkal.
Biztonsági megfontolások
1. Felhasználói bemenet ellenőrzése
Soha ne bízzunk a felhasználói bemenetben! A felhasználó által megadott adatok (parancssori argumentumok, read
-del beolvasott értékek) potenciálisan rosszindulatú kódokat tartalmazhatnak (pl. parancsinjekció). Mindig ellenőrizzük és szűrjük a bemenetet, mielőtt felhasználnánk azt parancsokban.
#!/bin/bash
# ROSSZ PÉLDA (parancsinjekcióra hajlamos)
# echo "Add meg a fájlnevet:"
# read FILENAME
# rm $FILENAME # Ha a felhasználó beírja "alma.txt; rm -rf /", az katasztrófa
# JÓ PÉLDA (ellenőrzés)
echo "Add meg a fájlnevet:"
read FILENAME
# Ellenőrizzük, hogy csak alfanumerikus karaktereket, pontot és kötőjelet tartalmaz-e
if [[ ! "$FILENAME" =~ ^[a-zA-Z0-9._-]+$ ]]; then
echo "Hiba: Érvénytelen fájlnév karakterek."
exit 1
fi
# Ellenőrizzük, hogy a fájl létezik-e és az aktuális könyvtárban van-e
if [[ ! -f "./$FILENAME" ]]; then
echo "Hiba: A fájl nem létezik vagy nem elérhető."
exit 1
fi
rm "./$FILENAME" # Most már biztonságosabb
Kerüljük az eval
parancs használatát, hacsak nem vagyunk 100%-ig biztosak a forrásban, mivel ez futtathat tetszőleges kódot.
2. Jogosultságok
Futtassuk a scripteket a legkevesebb jogosultsággal, amennyi a feladat elvégzéséhez szükséges. Ha egy scriptnek root jogosultságokra van szüksége, használjuk a sudo
-t, és győződjünk meg róla, hogy csak a feltétlenül szükséges parancsokat futtatja rootként.
#!/bin/bash
# Néhány parancs, ami nem igényel root jogot
echo "Helyi könyvtár tartalma:"
ls -l
# Egy parancs, ami root jogot igényel
if [ "$(id -u)" -ne 0 ]; then
echo "Ez a rész root jogosultságot igényel. Kérjük, futtassa sudo-val."
exit 1
fi
echo "Rendszerfrissítés indítása (root):"
apt update
3. Fájlútvonalak és szóközök
Mindig használjunk idézőjeleket ("..."
) a változók körül, amelyek fájlútvonalakat vagy szóközt tartalmazó stringeket tárolhatnak. Ez megakadályozza a szótagolási (word splitting) problémákat és a glob (pathname expansion) értelmezést.
#!/bin/bash
MY_FILE="Ez egy fájl név szóközzel.txt"
# ROSSZ: rm $MY_FILE # A shell három külön argumentumként látná: "Ez", "egy", "fájl..."
# JÓ: rm "$MY_FILE"
# ROSSZ: for f in *.txt; do echo $f; done # Ha van "fájl név.txt", akkor hibásan kezelheti
# JÓ: for f in *.txt; do echo "$f"; done
Legjobb gyakorlatok
1. Shebang használata
Mindig kezdjük a scriptet egy shebang sorral (pl. #!/bin/bash
), hogy biztosítsuk a megfelelő shell használatát.
2. Kommentek
Dokumentáljuk a kódot kommentekkel (#
), magyarázva a komplex logikát, a változók célját és a script általános működését.
3. Hibakezelés és kilépési státuszok
Használjuk a set -e
és set -o pipefail
opciókat a script elején. Ellenőrizzük a parancsok kilépési státuszát a $?
segítségével, és lépjünk ki megfelelő hibakóddal (exit 1
) hiba esetén.
4. Változók és függvények
- Használjuk a
local
kulcsszót a függvényen belüli változók deklarálásakor. - Használjunk értelmes változó- és függvényleveket.
- Kerüljük a globális változók túlzott használatát.
5. Szabványos kimeneti és hibaüzenetek
A felhasználóval való kommunikációhoz használjuk a standard kimenetet (stdout
) és a hibaüzenetekhez a standard hiba kimenetet (stderr
). Ez lehetővé teszi a kimenetek átirányítását és a hibák elkülönítését.
#!/bin/bash
echo "Ez egy normál üzenet." >&1
echo "Ez egy hibaüzenet." >&2
6. Idiglenes fájlok kezelése
Ha ideiglenes fájlokat használunk, mindig gondoskodjunk a törlésükről, még hiba esetén is. A trap EXIT
vagy trap ERR
parancsok ideálisak erre a célra.
#!/bin/bash
TEMP_FILE=$(mktemp) # Biztonságos ideiglenes fájl létrehozása
trap "rm -f $TEMP_FILE" EXIT # Törlés kilépéskor
echo "Valami ideiglenes tartalom" > "$TEMP_FILE"
cat "$TEMP_FILE"
# ... script további része ...
7. Idézési konvenciók
Mindig idézőjelezzük a változókat, különösen, ha azok felhasználói bemenetből származnak, vagy szóközt tartalmazhatnak. Ez megakadályozza a shell szótagolási és globálási problémáit.
8. Tesztelés
Alaposan teszteljük a scripteket különböző bemenetekkel és körülmények között, beleértve a hibás eseteket is.
A biztonság és a legjobb gyakorlatok betartása nem csak a scriptek megbízhatóságát növeli, hanem hozzájárul a rendszer általános stabilitásához és biztonságához is. Egy jól megírt shell script értékes eszköz, egy rosszul megírt viszont komoly kockázatot jelenthet.
Különböző shell típusok és kompatibilitás
Bár a Bash (Bourne Again SHell) a legelterjedtebb shell a Linux és macOS rendszereken, fontos tudni, hogy számos más shell is létezik, és mindegyiknek megvannak a maga sajátosságai és előnyei. A script kompatibilitása attól függ, hogy milyen shell-specifikus funkciókat használunk, és melyik shebang sort adjuk meg.
A leggyakoribb shell típusok
- sh (Bourne Shell): Az eredeti Unix shell, a legkevésbé funkciókban gazdag, de a legkompatibilisebb. Számos rendszeren a
/bin/sh
egy szimbolikus link a Bash-re (vagy Debian/Ubuntu esetén a Dash-re). - Bash (Bourne Again SHell): A legnépszerűbb és alapértelmezett shell a legtöbb Linux disztribúcióban és macOS-ben (régebbi verziókban). Számos kiegészítő funkcióval rendelkezik az
sh
-hoz képest (pl. C-stílusú for ciklus,[[ ]]
feltételek, parancskiegészítés). - Zsh (Z Shell): Egy modern, rendkívül funkciókban gazdag shell, amely számos Bash funkciót tartalmaz, és ezen felül további fejlesztésekkel rendelkezik (pl. jobb parancskiegészítés, globális aliasok, téma-támogatás). Népszerű a fejlesztők körében.
- Ksh (Korn Shell): Egy másik népszerű shell, amely számos funkciót vezetett be, amelyeket később a Bash is átvett. Jó teljesítmény és POSIX kompatibilitás jellemzi.
- Fish (Friendly Interactive SHell): Egy felhasználóbarát shell, amely a könnyű használhatóságra és a "out-of-the-box" funkciókra összpontosít, mint például a szintaxis kiemelés és az automatikus javaslatok. Nem POSIX-kompatibilis, így a scriptek általában nem átvihetők más shellekbe.
- Dash (Debian Almquist Shell): Egy minimális, gyors és POSIX-kompatibilis shell, amelyet gyakran használnak a Debian/Ubuntu rendszereken a
/bin/sh
szimbolikus link céljaként, a rendszerindítási scriptek felgyorsítása érdekében.
Kompatibilitás és a shebang szerepe
Amikor shell scriptet írunk, a shebang sor (pl. #!/bin/bash
) az elsődleges módja annak, hogy jelezzük, melyik értelmezővel kell futtatni a scriptet. Ez kritikus a kompatibilitás szempontjából:
- Ha egy script Bash-specifikus funkciókat használ (pl. asszociatív tömbök,
(( ))
aritmetikai kifejezések,[[ ]]
feltételes kifejezések), akkor a shebang-nek#!/bin/bash
-nak kell lennie. Ha#!/bin/sh
-t használunk, és a/bin/sh
egy POSIX-kompatibilis, de nem Bash shellre (pl. Dash) mutat, a script hibát fog dobni. - Ha a scriptet úgy írjuk, hogy csak a POSIX szabványos funkciókat használja (azaz kompatibilis az
sh
-val), akkor a#!/bin/sh
shebang biztosítja a legszélesebb kompatibilitást. Ez jó gyakorlat lehet, ha a scriptnek sokféle Unix-szerű rendszeren kell futnia. - Ha Zsh-specifikus funkciókat használunk (pl. tömbök indexelése 1-től, globális aliasok), akkor a
#!/bin/zsh
shebang szükséges.
Kompatibilitási tippek:
- Legyen tudatos a shell választásban: Mielőtt elkezdenénk írni, döntsük el, melyik shellre optimalizáljuk a scriptet. Ha széles kompatibilitásra van szükség, maradjunk a POSIX
sh
funkcióknál. Ha Bash-specifikus funkciók kényelmesebbek, használjuk a Bash-t, de ezt jelezzük a shebang-ben. - Kerüljük a nem szabványos funkciókat: Ha nem feltétlenül szükséges, kerüljük a shell-specifikus bővítményeket. Például, a
[ ]
feltételvizsgálat általában hordozhatóbb, mint a[[ ]]
. - Teszteljünk különböző környezetekben: Ha a scriptnek különböző rendszereken kell futnia, teszteljük azokat.
#!/bin/sh
# Ez a script POSIX sh kompatibilis
nev="Világ"
echo "Hello, $nev!"
if test -f "/tmp/testfile"; then
echo "A tesztfájl létezik."
fi
# Ez a Bash-specifikus kód hibát okozna sh-ban:
# if [[ -v BASH_VERSION ]]; then
# echo "Bash-ben futok."
# fi
A shell típusok és a kompatibilitás megértése alapvető fontosságú, különösen, ha olyan scripteket írunk, amelyeknek különböző rendszereken vagy megosztott környezetekben kell megbízhatóan működniük. A shebang megfelelő beállítása és a használt funkciók tudatos megválasztása biztosítja, hogy a scriptünk a várt módon fusson.