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>&-

Kasulikud lisamaterjalid

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