Egy shell script nem más mint shell-parancsok sorozata, amelyeket az újrafelhasználás jegyében egy file-ba írunk. Mivel a shell programozható, shell scriptjeinkkel nagyon hasznos programokat írhatunk megdöbbentôen könnyen, ráadásul nem kell lefordítani ôket és könnyedén debuggolhatók!
Unixon van egy csomó shell, és ennek megfelelôen sokféle shell-ben írhatjuk meg scriptjeinket. Ennek ellenére nem kell zavarba jönnünk a bôségtôl, ugyanis sh-ban érdemes írni scriptjeinket, hogy olyan Unixokon is fussanak ahol esetleg csak ez van. A továbbiakban alapvetôen a Bourne shell programozását fogjuk taglalni, és minden script file elején a
#!/bin/shsorral jelezzük ezt. Megjegyzés: hallani olyasmiket, hogy a sh-család (sh, ksh, bash, zsh) alkalmasabb a scriptek írására mint a csh-család (csh, tcsh). Ez balga elôítélet. KIZÁRÓLAG azért érdemes sh-t használni, mert az mindenhol van. (Legtöbbször a ksh/bash/zsh nem nyújt lényeges elônyöket a Bourne-shellhez képest a script-programozáshoz, miként a tcsh sem a csh-hoz képest. Interaktív shellnek persze hülyeség volna sh/csh-t használni - erre valók a többiek. Az is elôfordulhat, hogy zsh-ban egy interaktív sorban meg tudod csinálni azt, amire sh-ban nemtriviális scriptet kellene írnod) Mellesleg Linuxon sh többnyire csak egy link a bash-ra, csh pedig a tcsh-ra. A bash egy kicsit másképp viselkedik, ha sh-ként hívod, de így is elfogad olyasmiket, amik az igazi sh-ban nincsenek meg. Linuxon ash-val lehet tesztelni, ha a kompatibilitás probléma (ash a legprimitívebb Bourne-kompatibilis shell). Ja, és a ksh-t pdksh néven lehet beszerezni.
A shell scriptek filozófiája általában az adatfolyam különbözô hasznos szûrôkön való átfolyatásan alapszik. Nézzük például, hogyan irathatjuk ki a nevünket (nem az júzert, az igazit):
#!/bin/sh
juzername=`whoami`
igaziname=`grep "^${juzername}:" /etc/passwd | cut -d: -f5 | cut -d, -f1`
echo A neved: $igaziname
A fenti példában megfigyelhettük a command substitution nevû pompás
mechanizmust, ami azt csinálja, hogy a ` jelek közé (nem egyszeres
idézôjel, nézz csak körül a billentyûzeteden!) tett parancs által
kiírt string lesz a megfelelô változó értéke.
Nem kell feltétlenül scripteket írni, ha a shell programozhatóságát
használni akarjuk. Tegyük fel például, hogy van egy rakás PostScript
fájlunk egy directoryban es sorra meg szeretnénk nézni ôket. Fárasztó
es unalmas lenne minden alkalommal File/Open-re kattintgatni es utána
kiválasztani a következôt vagy minden fájlra manuálisan
újraindítani
a gv-t.
Okos ember ilyenkor a következôt írhatja a zsh parancssorba:
$ for i in *.ps for > gv $ivagy:
for i (*.ps) gv $iAmikor lelövi az egyik gv-t (az egyszerû, csak egy q-t kell nyomni), automatikusan jön a következô. Sh/ksh/bash -ban kissé bonyolultabb:
$ for i in *.ps > do > gv $i > doneA fenti persze zsh-ban is mûködik. Csh/tcsh-ban:
$ foreach i (*.ps) foreach? gv $i foreach? end
A második módszer a legjobb általában: a script parancsként viselkedik és mivel külön process lesz, mindenféle dolgokat csinálhasz vele: a háttérben indíthatod (ha utána teszel egy & jelet), felfüggesztheted (Ctrl-Z), újraindíthatod a háttérben (bg) illetve az elôtérben (fg).
A futtattható scriptjeid legjobb helye a home directoryd bin/ konyvtárában van. Ellenôrizd, hogy a bin/ konyvtárad benne van-e a keresési útvonalban.(echo $PATH)
Egy változónak a következôképpen adhatsz érteket (sh, ksh, bash, zsh):
valtozo=ertekilletve (csh, tcsh):
set valtozo=ertekA változó értekét mindegyik shellben ugyanúgy nyerheted ki, mégpedig a dollárjellel:
echo $valtozo
#!/bin/sh echo a parancs neve: $0 echo az elsô argumentum: $1 echo a masodik argumentum: $2 echo a harmadik argumentum: $3 echo az argumentumok szama: $# echo az osszes argumentum: $*
#!/bin/sh echo -n 'filename: ' read filename echo filename will be $filename if test -e $filename then echo File $filename already exists. Exiting... exit 1 fi
Feltételes elágazást a következô módon csinálhatunk:
Például:
Az if-et értelemszerûen és a más programozási nyelvekben megszokott
módon ki lehet egészíteni else és elif szerkezetekkel (
az utóbbi az else if-nek felel meg). Az elôzô példa egy általánosított
változata:
Végül megjegyzem, hogy if-szerû viselkedést if nélkül is elérhetünk:
ha két parancs közé a && jelet tesszük, akkor a második csak akkor
hajtódik végre ha az elsô a 0 visszatérési értékkel jelzi sikeres
futását:
A for ciklus némiképp különbozik a Pascal es C nyelvek for ciklusától,
mégpedig abban, hogy csak egy rögzített lista elemein lehet végigmenni vele.
Tipikus felhasználása, hogy bizonyos kiterjesztésû file-okon vagy a
parancssor argumentumain megyünk végig.
Például a következô script azokat a txt kiterjesztésû file-okat,
amikben a "font" string szerepel egy directoryval feljebb mozgatja:
A while ciklus addig fut, amíg a hasában levô
feltétel igaz, az until
pedig pont fordítva: amíg a feltétele igaz nem lesz.
Mindkét esetben do és done közé kell zárni a ciklus parancsait.
Ha scripted parancssor-argumentumokat igényel, akkor
írhatsz egy "usage" függvényt (Ja, nem is mondtam, hogy
függvényeket is definiálhatsz, most figyeld meg a módjat!), például:
If-else
if feltétel
then
parancsok (statements)
fi
Az if az ôt követô parancsok közül az utolsónak az exit statusát
nézi, ha az nulla (vagyis a parancs sikeresen futott), akkor
"igaz"-nak veszi, különben "hamis"-nak. (Megjegyzés: a C programozási
nyelvben ez pont fordítva van: a nulla felel meg az "hamis"-nak, minden
más meg az "igaz"-nak).
#!/bin/sh
if who | grep haver > /dev/null
then
echo A haver be van jelentkezve
fi
A grep eredményét átirányítottuk a /dev/null -ba (vagyis átadtuk az
enyészetnek), mivel csak a grep exit statusa érdekel bennünket: szerepel
a "haver" string a who parancs által kiírt sorokban vagy nem.
#!/bin/sh
if test $# -eq 0
then
echo Használat: arguentumként egy juzernevet kérek.
exit 1
fi
haver=$1
if who | grep $haver > /dev/null
then
echo $haver be van jelentkezve
else
echo $haver nincs bejelentkezve
fi
A fenti példában láttunk egy igen hasznos paracsot, amelynek segítségével
különféle feltételek meglétét tesztelhetjük (ezert is hívják testnek...). Lásd még: man test.
latex szoveg.tex && xdvi szoveg.dvi
vagy:
gcc -o proba proba.c && proba
A || jel esetében pont fordítva, akkor hajtódik végre a második, ha az elsô
nem sikerül, például:
szukszavu_parancs || echo "Valami nem stimmel" >&2
For ciklus.
#!/bin/sh
for i in *.txt
do
if grep font $i > /dev/null
then
mv $i ..
fi
done
While és until.
A következô script addig irogatja ki
kétmásodpercenként üzenetét,
amíg le nem lövöd:
#!/bin/sh
while true
do
echo itt vagyok, ragyogok
sleep 2
done
Mellesleg a C nyelvhez hasonlóan, minden ciklusból break-al
törhetünk ki, és continue-val ugorhatunk a ciklus elejére.
Tippek és trükkök.
0. tipp.
Legtöbbet a profik altal gyártott scriptekbôl tanulhatunk.
Sok Unix parancs tulajdonképpen shell-script: a /bin vagy /usr/bin vagy /sbin/ vagy a /usr/sbin directorykban a
file * | grep script
parancsal szelektálhatjuk ki a scripteket.
1. Usage
#!/bin/sh
usage() {
cat << EOM
Ejnye-bejnye, ilyen meg ilyen paramétereket kellett volna adjál!
Használat: $0
-k kezdôknek
-h haladóknak
Olvasd el a man-paget is!
EOM
}
if test $# -eq 0
then
usage
fi
Visszajelzéseket
ezen a címen
várok türelmetlenül...