Erinevus lehekülje "Bash" redaktsioonide vahel
Allikas: Kuutõrvaja
(→Bash ja internet) |
|||
1. rida: | 1. rida: | ||
===Bash kooriku skript=== | ===Bash kooriku skript=== | ||
+ | |||
+ | <source lang=bash> | ||
Kooriku skript on tekstifail, millesse on kirjutatud üksteise järele programmi nimed või kooriku sisekäsud. Lisaks saab kasutada programmeerimisele iseloomulikke konstruktsioone, nagu tingimus, kordus- ja valiklause jne. Koorik on interpreteeritav keel. | Kooriku skript on tekstifail, millesse on kirjutatud üksteise järele programmi nimed või kooriku sisekäsud. Lisaks saab kasutada programmeerimisele iseloomulikke konstruktsioone, nagu tingimus, kordus- ja valiklause jne. Koorik on interpreteeritav keel. | ||
473. rida: | 475. rida: | ||
exec 3>&- | exec 3>&- | ||
+ | </source> | ||
===Kasulikud lisamaterjalid=== | ===Kasulikud lisamaterjalid=== | ||
http://www.tinker.ncsu.edu/LEGO/shell_help.html | http://www.tinker.ncsu.edu/LEGO/shell_help.html |
Redaktsioon: 9. juuni 2010, kell 20:25
Bash kooriku skript
Kooriku skript on tekstifail, millesse on kirjutatud üksteise järele programmi nimed või kooriku sisekäsud. Lisaks saab kasutada programmeerimisele iseloomulikke konstruktsioone, nagu tingimus, kordus- ja valiklause jne. Koorik on interpreteeritav keel.
Paljud süsteemi utiliidid on kooriku skriptid.
===Skripti kirjutamine ja käivitamine===
Kooriku skript kirjutatakse tekstiredaktoris, kusjuures failil peab olema lugemis- ja käivitamisõigus.
Näiteks toome skpriti, mis kirjutab ekraanile "Näe, poolkuu".
#!/bin/sh
echo "Näe, poolkuu"
Selgituseks märgime, et
* #!/bin/sh näitab interpretaatori nime
* echo on sisekäsk, mis väljastab ekraanile oma argumendi
===Skript käivitakse käsurealt===
Esmalt tuleb skript teha käivitatavaks öeldes
$ chmod 0755 skript.sh
ja käivitada
$ ./skript.sh
Heaks kombeks on skripti nimi lõpetada mõnetähelise kombinatsiooniga, mis viitab interpretaatorile - '.sh'.
Skripti käivitamisel käivitatakse uus koorik, milles skripti käsud täidetakse.
===Muutuja ja väärtuse omistamine===
Muutuja nimi peab algama tähe või alakriipsuga, kusjuures võib sisaldada neid ja ka numbreid. Muutuja tüüpi pole tarvis deklareerida.
Muutujale väärtuse omistamisel märgitakse teda vaid nimega (a_1), kuid talle viidates peab alustama muutuja nime dollar ($a_1). Näites omistatakse võrdusmärgi abil muutujale väärtus ja kasutatakse seda
#!/bin/sh
a_1=5
b_1=$a_1
c_1=Tere
echo $a_1
echo $b_1
echo $c_1
Tühikute olemasolu ja puudumine on oluline.
Kui muutujale väärtust omistades on vaja vältida metasümbolite erilist käsitlust, siis tuleb avaldis kirjutada ülakomade vahele, näiteks
#!/bin/sh
echo 'Ei asenda keskkonnamuutujat $OSTYPE tema väärtusega'
Kui on tarvis, et keskkonnamuutujad asenduksid oma väärtustega ning toimuks muutuja väärtustamine, siis kasutatakse jutumärke, näiteks
#!/bin/sh
echo "Keskkonnamuutujate asemele tekivad nende väärtused: $OSTYPE"
echo "Muutujad väärtustatakse: $(date)"
echo "Käsud väärtustatakse: `date`"
echo "Aritmeetiline väärtustamine: 11 + 11 = $((11+11))"
===Aritmeetilised tehted===
Esitame näited aritmeetiliste tehete kohta
* "+, -" - liitmine ja lahutamine
* "*, /, %" - korrutamine, jagamine ja jääk
* "<<, >>" - bitinihe
#!/bin/sh
a=255
b=1
c=5
d=50
a_miinus_c=$(($a - $b))
a_jaak_d=$(($a % $d))
a_bitinihe_paremale_b=$(($a >> $b))
echo "$a - $b = $a_miinus_c"
echo "$a % $d = $a_jaak_d"
echo "$a >> $b = $a_bitinihe_paremale_b"
===Tingimused ja valikulause===
Valikulause võimaldab vastavalt seatud tingimustele programmi edasist käiku suunata.
Arvulisi suurusi võrreldakse järgmiste loogiliste operaatoritega
* -eq - võrdne (ingl. k. equal)
* -ne - mittevõrdne (ingl. k. not equal)
* -lt - väiksem (ingl. k. less than)
* -le - väiksemvõrdne (ingl. k. less equal)
* -gt - suurem (ingl. k. greater than)
* -ge - suuremvõrdne (ingl. k. greater equal)
Näiteks tingimus
[ 5 < 6 ]
on tõene kuna "viis on väiksem kuuest".
===If-elif-else valikulause===
Skript genereerib juhusliku arvu vahemikus 0 kuni 32 767 (2^15) ja teatab, milline see on
#!/bin/sh
a=$RANDOM
if [ $a -lt 10000 ]; then
echo "Juhuslik arv $a < 10 000"
elif [ $a -ge 10000 -a $a -lt 20000 ]; then
echo "Juhuslik arv on 10 000 <= $a < 20 000"
else [ $a -ge 20000 -a $a -lt 32767 ]
echo "Juhuslik arv on 20 000 <= $a < 32767"
fi
Näites esitatakse tingimused, kusjuures
* -a (AND) nõuab mõlema tingimuse samaaegset täidetust
* -o (OR) väljendab, et täidetud võib olla üks või teine või mõlemad.
* ! (NOT) alustades tingimust hüüumärgiga märgitakse eitust
Näiteks tingimus
[ ! 5 < 6 ]
on väär kuna "viis on väiksem kuuest", aga kasutatakse loogilist eitust (!).
Kantsulgude asemel võib tingimuse esitamisel kasutada suvalist programmi. Sel juhul tõlgendatakse programmi lõppkoodi väärtust tõeväärtusena, so 0 on tõene ja muu väär. Näites saadab õppejõud igale praktikumist puudujale kirja, milles ta vabandab, et viib õppetööd läbi ilma tegelase osavõtuta
#!/bin/sh
for i in priit miima peeter mart liibu
do
if ! who | grep $i ; then
echo -e "Subject: Ma vabandan, et Teid polnud kohal\n\n." | \
/usr/sbin/sendmail $i
fi
done
Nagu ikka, peab rida jätkav kaigas olema viimane sümbol real.
Tihti kasutatakse tingimuste esitamisel spetsiaalset sisekäsku test. Esitame näite selle käsu kasutamisest
#!/bin/sh
a=$RANDOM
if test $a -lt 10000; then
echo "Juhuslik arv $a < 10 000"
elif test $a -ge 10000 -a $a -lt 20000; then
echo "Juhuslik arv on 10 000 <= $a < 20 000"
else test $a -ge 20000 -a $a -lt 32767
echo "Juhuslik arv on 20 000 <= $a < 32767"
fi
If-else tingimust saab esitada ka && (AND) ja || (OR) abil
#!/bin/sh
a=$RANDOM
(test $a -lt 15000 && echo "$a < 15 000" ) || echo "$a >= 15 000"
&& -le järgnev käsk täidetakse, kui eelnenud käsu lõppkood oli null (tõene).
|| -le järgnev käsk täidetakse, kui eelnenud käsu lõppkood oli üks (väär).
Loogiliste tehetega mängimiseks on otstarbekas kasutada spetsiaalseid programme true ja false, mis ei tee muud, kui tagastavad vastava lõppkoodi
bash~$ (true && echo "õige" ) || echo "väär"
õige
bash~$ (false && echo "õige" ) || echo "väär"
väär
Tavaline on skriptides kontrollida mingite muutujate seadistust, näiteks kontrollime kas ssl kataloog on seadistatud
if [ "$MOD_SSL_DIR" = "" ]
then
echo "MOD_SSL_DIR seadmata"
exit 1
fi
Leksikograafilisi tingimusi esitatakse järgmiste loogiliste operaatorite abil
* = võrdne
* != mittevõrdne
Esitame näite, kus skript ootab vastust küsimusele, "Kes on Kuutõrvaja üks peategelaskujusid?"
#!/bin/sh
echo "Kes on Kuutõrvaja üks peategelaskujusid?\n"
read vastus
if [ $vastus = "Priit" ]; then
echo "Õige"
else
echo "Vale"
fi
Rida 'read vastus' ootab klaviatuurilt sisestust ning omistab selle muutuja $vastus väärtuseks.
===Case valikulause===
Case valik võimaldab valida mitme tegevuse vahel. Näide teatab, kas sisestatud sõna algustäht oli vahemikust A-K, L-Z või midagi muud
#!/bin/sh
echo "Sisestage klaviatuurilt sõna:"
read a
case $a in
[a-k]*|[A-K]*) echo "Sisestatud sõna algab tähega vahemikust A kuni K";;
[l-z]*|[L-Z]*) echo "Sisestatud sõna algab tähega vahemikust L kuni Z";;
*) echo "Midagi muud";;
esac
Valikut määrav regulaaravaldise stiilis avaldis [a-k]*|[A-K]* tähendab, et klapivad stringid, mis algavad väikese vahemikku a kuni k jääva tähega või samasse vahemikku jääva suure tähega.
===Select valikulause===
See on väga sarnane Case valikule olles interaktiivsem
#!/bin/sh
select i in "Tartu" "Valga" "Paide" "Ahja" "Ots"
do
case $i in
Tartu) echo "Tartu" ;;
Valga) echo "Valga" ;;
Paide) echo "Paide" ;;
Ahja) echo "Ahja" ;;
Ots) exit ;;
*) echo "midagi muud" ;;
esac
done
===Korduslaused===
Kordus võimaldab teatud arv kordi korrata tegevust.
====For korduslause====
For korduses seatakse tavaliselt otseselt paika korduste arv. Toome näite
#!/bin/sh
a="Tartu Elva Puhja Polva"
for i in $a
do
echo $i
done
Iga järgmise kordusega omandab muutuja $i uue väärtuse nimekirjast, milleks on muutuja $a tühikuga eraldatud alamstringid. Muutujale $a võib väärtust omistada ka kasutades käsu väärtustamist, näiteks jätame muutuja $a enda kasutamata
#!/bin/sh
for i in `ls r*`
do
echo $i
done
Näites kuvatakse kõik r tähega algavad failinimed.
====While korduslause====
While kordust korratakse kuni tingimus on tõene. Näites sooritatakse kordus kuni muutuja $a on väiksem kümnest
#!/bin/sh
a=0
while [ $a -lt 10 ]
do
echo $a
a=$(($a+1))
done
====Until korduslause====
Kordust sooritatakse kuni tingimus saab tõeseks.
#!/bin/sh
a=20
while [ $a -lt 10 ]
do
echo $a
a=$(($a-1))
done
====Kordusest väljumine====
Kasutades korduse sees lisatingimust, on võimalik kordusest väljuda käsuga exit. Skripti täitmine jätkub kordusele järgnevast käsust. Näites sooritatakse kordus kuni muutuja $i saab võrdseks stringiga "teie"
#!/bin/sh
a="mina sina tema meie teie nemad"
for i in $a
do
if test $i = "teie"; then
exit
else
echo $i
fi
echo "Skripti lõpp"
done
===Sisend, väljund ja käsurea argumendid===
Skripti sisendi vastuvõtmist korraldab käsk read. Loeme näites sisendit kuni andmete lõppemiseni ning trükime välja vastavad suured tähed.
#!/bin/sh
while read a
do
echo $a | tr "a-z" "A-Z"
done
Suuname programmi df väljundi skripti sisendisse
bash~$ df | skript.sh
Skripti väljund tekitatakse tavaliselt käsuga echo.
Skripti käivitamisel saab anda ka argumente, kusjuures nende väärtused on skriptis muutujates $1, $2 jne.
#!/bin/sh
echo $1 $2 $3
Lisaks on olulised sellised muutujad
* * - "$*" väärtustub stringiks, kus on kõik argumendid tühikutega eraldatud
* @ - "$@" väärtustub mitmeks stringiks, mis on vastavalt käsurea argumendid
* # - "$#" käsurea argumentide arv
* ? - "$?" eelmise esiplaanil käivitatud programmi väljundkood
* $ - "$$" skripti enda PID
* ! - "!$" viimati tagaplaanil käivitatud programmi nimi
* 0 - "$0" skripti enda nimi
===Failitestid===
Sisekäsk test võimaldab kontrollida faili tüüpi. Näiteks eristame kataloogis olevad lingid, tavalised faili ja kataloogid
#!/bin/sh
for i in `ls -a`
do
if test -f $i; then
echo $i: fail
elif test -L $i; then
echo $i: link
elif test -d $i; then
echo $i: kataloog
fi
done
===Sisestus märgini===
Märgini sisestamine võimaldab vältida mitmete järjestikuste käskude echo kasutamist.
cat >> /home/kasutaja/fail <<EOT
esimene rida
teine rida
kolmas rida
EOT
Toome näite CGI valdkonnast
#!/bin/sh
echo -e "Content-type: text/html\n\n"
a=`df`
cat <<mark
< HTML >< BODY >
< p >Tere, masina failisüsteemiga on sellised lood:< p >
< pre >
$a
< /pre >
< pre >
$(hostname -f)
$(date)
< /pre >
< /BODY >< /HTML >
mark
Kusjuures, kui 'cat <<mark' rida asendada 'cat <<\mark', siis muutujaid ei asendata ega väärtustata.
===Funktsioonid===
Tihti esinevaid järgnevusi on mõistlik kirjeldada kord funktsioonina ning hiljem kasutada nende poole pöördumiseks seda funktsiooni. Näideks loome funktsiooni, mis paneb teksti < pre > ja < /pre > märkide vahele.
#!/bin/sh
function pre () {
echo -e "< pre >$1< /pre >"
}
echo -e "Content-type: text/html\n\n< HTML >< BODY >"
pre "`df`"
pre "`uptime`"
echo "< /BODY >< /HTML >"
Funktsioonis kirjeldatu käivitamiseks ei tekitata uut koorikut. Argumente saab kasutada sarnaselt skriptile endale.
Teise näitena küsime kinnitust kasutajalt mingi tegevuse toestamise kohta
kinnitus(){
echo
echo
echo -n "$1 (y/n) [n] "
read VASTUS
if [ "$VASTUS" != "y" ]
then
exit
fi
}
Kasutamine järgnev
kinnitus "installime vajalikud komponendid ?"
Üks shelliskriptis suisa häda vajalik funktsioon oleks kontrollida kas eelmine käsk on väljastanud mingi veateate
ehk siis lõpetanud enda tegevuse ebaviisakalt
kas_korras(){
RET=$?
if [ "$RET" != '0' ]
then
echo
echo "eelmine käsk väljastas: $RET"
exit $RET
fi
}
Ning seejärel võib lisada näiteks make käsu järele kontrollfuntskiooni
kas_korras
===Lock faili kasutamine skriptis===
Vahel on vajalik saavutada olukord kus skripti selle
töötamise ajal uuesti enam käivitada ei saa, siin tuleb appi lockf
abil tekitatav /var/run/skript.lock nimeline fail
skripti idee lihtsalt tuhat sekundit passida
#!/bin/sh
if [ -f /var/run/skript.lock ]; then
echo "eelmine programm ikka veel toimib."
return
else
lockf -t 0 /var/run/skript.lock '''sleep 1000'''
fi
Paneme skripti toimima taustal
# ./skript.sh &
[1] 80562
proovime veelkord startida
# ./skript.sh
eelmine programm ikka veel toimib.
Lockfaili võib muidugi käsu lockf puudumisel tekitada ka lihtsalt touch käsuga ja hiljem eemaldada
===Bash ja internet===
Bash võimaldab tegeleda ka võrgusocketitega. Viimaste kaudu on võimalik avada võrguühendus
teatava serveri pordini ja vahetada sellega infot.
See käib läbi socketi mis kujul '''/dev/tcp/SERVER/PORT'''
Näiteks saadame maili serverile postfix pordile ühe käsu
#avame socketi
exec 3<>/dev/tcp/zoo.edu.ee/25
# saadame HELO käsu
echo -e "HELO mail.edu.ee" >&3
# loeme tulemust
while read line <&3
do
echo -n $line >&1
done
# saadame QUIT käsu
echo -e "QUIT" >&3
# sulgeme sisendi
exec 3<&-
# sulgeme väljundi
exec 3>&-