Erinevus lehekülje "Bash" redaktsioonide vahel

Allikas: Kuutõrvaja
(Lock faili kasutamine skriptis)
391. rida: 391. rida:
 
  # ./skript.sh
 
  # ./skript.sh
 
  eelmine programm ikka veel toimib.
 
  eelmine programm ikka veel toimib.
 +
 +
===Skripti pid===
 +
 +
Sageli on vaja ,et skript teataks enda pid'i kuna
 +
vaja on ehk seda mingi teise skriptiga stopida. Selleks on
 +
skriptil muutuja $$
 +
 +
#!/bin/sh
 +
echo $$
 +
  
 
===Kasulikud lisamaterjalid===
 
===Kasulikud lisamaterjalid===

Redaktsioon: 28. jaanuar 2009, kell 13:57

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

bash~$ 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

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 test $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. Toome näite CGI valdkonnast

#!/bin/sh
echo -e "Content-type: text/html\n\n"
a=`df`
cat <<mark
<HTML><BODY>

Tere, masina failisüsteemiga on sellised lood:

 $a
 
 $(hostname -f)
 $(date)
 
</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.


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.

Skripti pid

Sageli on vaja ,et skript teataks enda pid'i kuna vaja on ehk seda mingi teise skriptiga stopida. Selleks on skriptil muutuja $$

#!/bin/sh
echo $$


Kasulikud lisamaterjalid

http://www.tinker.ncsu.edu/LEGO/shell_help.html

Bashi koorik

© EENet 2000