BASH (programmeerimise alused)

Смотри: Руководство по Bash для начинающихИскусство программирования на языке сценариев командной оболочки
Lühiülevaate programmeerimis võimalustest shellis (BASH)
Kasuks tuleb ka Bash prompt HOWTO,   Bash Guide for Beginners

Tähistused

Programmeerida saab:

Shell scripting lubab:

Skripti käivitamiseks on vaja:

  1. Hankida või luua skriptifail:
  2. Muuta skriptifaili õigusi nii, et fail oleks käivitatav:
  3. Käivitada skript:

NÄIDE SKRIPTIST

Traditsiooniline Hello World skript
#!/bin/bash
echo Hello World
Esimene rida ütleb mis programmi kasutada skripti käivitamiseks
Teine rida väljastab lause terminalile.
loome tühja skript faili hello.sh kodukatalogis näiteks /home/kasutaja.
# touch hello.sh
Lisame/redigeerime ülalpool olevat sisu
# nano hello.sh
Lisame failile käivitus õigused.
# chmod +x hello.sh
Käivitame skripti olles samas katalogis
# ./hello.sh
olles programmi asukohast alamkatalogis
# ../hello.sh
või kui oled mitte kodukatalogis
# /home/kasutaja/hello.sh

Lihtne backup skripti näide
#!/bin/bash
tar -cZf /var/tmp/my-backup.tgz /home/kasutaja/

KÄSUREA ERI SÜMBOLID

BASH interpretaator käsitleb järgmiseid sümboleid eriliselt.
& ; | * ? ' " ` [ ] ( ) $ < > { } ^ # / \ % ! ~
Kui on vajadus need neid sümboleid kasutada stringides tuleb sümboli ette paigutada backslash \ sümbol
# echo " \& \; \* \"Tere\" "

MUUTUJAD
muutuja nimi peab algama alakriipsust või inglise tähest ja peab koosnema alakriipsudest , inglise tähtedest ja numbritest.
nimi=väärtus
# määrata muutujale FRUIT väärtus "peach"
# FRUIT=peach
# trükime muutuja FRUIT väärtuse ekraanile
Muutuja kasutamisel, väärtuse saamiseks tuleb panna tema ette $ märk
# echo $FRUIT
!!!VALE: # $FRUIT=peach; echo FRUIT;

Muutujate deaktiviseerimine
unset nimi
# unset FRUIT

MASSIIVID
nimi[index]=väärtus
# FRUIT[0]=apple; FRUIT[1]=banana; FRUIT[2]=orange; FRUIT[10]=plum;
# FRUIT[apple]=10

Mitme elemendi väärtustamine:
# määrata massiivi elemendid
# band=(peeter mari kaja indrek)
# trükime välja
# echo ${band[0]}; echo ${band[1]}; echo ${band[2]}; echo ${band[3]}
# trükida välja ühes reas
# echo ${band[*]}
või teine versioon
# echo ${band[@]}

KESKKONNA MUUTUJAD
export nimi - eksportida ta jooksvasse keskkonda
export nimi=väärtus - luua muutuja väärtusega kui pole olemas ja eksportida ta jooksvasse keskkonda
# PATH=/sbin:/bin ; export PATH
# export FMHOME=/usr/frame CLEARHOME=/usr/atria PATH
# loome mitu muutujat ja expordime nad keskkonda
# set | less # näidata less programmis kõik jooksva keskkonna muutujad

Mõningad keskkonna muutujate näited:
PWD - jooksev katalog
UID - kasutaja identifikaator süsteemis
SHLVL - keskkonna(shelli) tase - iga bashi käivitamisel suureneb ühevõrra
PATH - käskude katalogide nimistu
HOME - kodukatalog

TORUD/KANALID

Pipes - kanalid, ühe käsu väljund suunatakse järgmise käsu sisendisse
mitu järjest ümber suunatud käsku nimetatakse konveieriks
käsk1 | käsk2 | käsk3
# ps -ael | grep "$UID" | less

List - nimistud, käskude ja konveierite hulgad.
käsk1-1 | käsk1-2; käsk2; käsk3-1 | käsk3-2 | käsk3-3 ....
# ps -ael | head -1; ps -ael | grep "$UID"

ÜMBERSUUNAMINE

Kõik protsessid sisestavad ja väljastavad infot läbi kanalite. Igal kanalil on määratud number. Kanaleid on võimalik ümbersuunata.
Kanalid on:

Ümbersuunamiseks kasutatakse erisymboleid:

Väljundi suunamine faili
käsk > fail või list > fail

# programm date väljastab tänase kuupäeva ja kellaaja
# suuname programmi töö väljundi faili "now.txt", kui faili polnud olemas, fail luuakse, kui oli olemas, sisu kustutatakse
# date > now.txt
# cat trükib faili sisu terminali ekraanile
# cat now.txt
Mon Sep 12 16:58:13 EEST 2011

# programm uptime näitab kui kaua on süsteem üleval peale viimast rebuuti või sisselülitamist
# who näitab aktiivseid kasutajaid
# suuname käskude listi väljundid faili "mylog"
# (date; uptime; who; ) > mylog
# cat mylog
Mon Sep 12 16:59:26 EEST 2011
16:59:26 up 3 min, 2 users, load average: 0.62, 0.94, 0.44
kasutaja tty7 2011-09-12 16:56 (:0)
kasutaja pts/0 2011-09-12 16:58 (:0.0)


Faili andmete lisamine

käsk >> fail
# date >> now.txt
# suuname programmi töö väljundi faili "now.txt", kui faili polnud olemas, fail luuakse, kui oli olemas, lisatakse väljund faili lõppu
list >> fail
# {date; uptime; who; } >> mylog
# suuname lisades käskude listi väljundid faili "mylog"

Vigade ümbersuunamine

käsk 2> fail; list 2> fail # suunata veateated faili
käsk > fail 2>&1; list > fail 2>&1
# suunata väljund ja veateated faili

# kustutada katalog, kõik teated ja veateated käsutäitmisel suunata /dev/null-i ja luua uus katalog
# rm -rf /tmp/my_tmp_dir > /dev/null 2>&1 ; mkdir /tmp/my_tmp_dir

Andmete sisestamine käsku

käsk < fail
Näiteks (juhul kui meilindus on väljahäälestatud ja internet olemas) saada peetri meilile eksami vastused olemasolevast vastus failist :
# mail peeter@hot.ee < Eksami_Vastused.txt

Sisestada käsku andmevoog. eraldaja on sümbolite jada mis ei kohtu sisestatavas textis.
käsk << eraldaja
dokument
eraldaja


# saadetakse printerile kõik read mis algavad peale eraldajat "MYURLS" kuni kohtub see sama eraldaja "MYURLS"
# lpr << MYURLS
http://www.pa08a.com
http://www.facebook.com
http://www.youtube.com
http://www.myspace.com
MYURLS

ALAMSHELLID
{ list; } täidetakse jooksvas shellis
( list; ) täidetakse alamshellis

# alamshellis tekitatakse muutuja FRUIT ja trükitakse ekraanile peale seda shell panakse kinni
# FRUIT="banana"; ( FRUIT="watermelon"; echo $FRUIT;) ; echo $FRUIT ;
# olles näiteks kodukatalogis vaatame kus oleme, seejärel käivitame alamshellis kaks käsku liikudes /tmp katalogi
# ja vaadates kus oleme, peale subshelli töö lõpetamist tuleme tagasi põhi shelli ja vaatame kus me nüüd oleme.
# pwd; ( cd /tmp; pwd; ) ; pwd;

Väärtuste omistamine käskudest:
# DATE=`date`; echo $DATE; # date käsu väljund suunata muutujasse DATE ja printida välja
# USERS=`who | wc -l`; echo $USERS; # arvutada välja mitu kasutajat on systeemis, resultaat väärtustada muutujale USERS ja trükida välja

read - lugeda kasutaja sisend muutujasse/tesse
# echo "Month and Day of birth?"
# read mon day rubbish # loetakse sistatud sonad mutujatesse $mon $day ja koik muu muutujasse $rubbish
kasutaja sisestab uhes reas: 09 16 mingi_muu_info
# echo kuu=$mon, paev=$day, muu=$rubbish

FUNKTSIOONID

Saame deklareerida funktsiooni käsureast
# function clist {
> cd $1
> ls
> }
ja käivitada funktsiooni käsureast
# clist /home
Väljund:
isa kasutaja mati sasa sass tiina

ARITMEETIKA
Reegel:
$((väljend))
let väljend

Näited:
# echo $(( ((5 + 3*2) -4) / 2 ))
# let x=5; let x=$x*4; echo $x
# echo korrutame; read x y; let z=$x*$y; echo $z

JUHTKONSTRUKTSIOONID

OPERAATOR IF
Käskude voo juhtimine.
Reegel:
if statement_list_1 ; then
statement_list_2
elif statement_list_3 ; then
statement_list_4
else
statement_list_5
fi
Näited:
# if uname -a | grep "GNU/Linux" > /dev/null; then echo "You are in Linux"; fi

#!/bin/bash
#myvar="abcd"
if [ -z "$myvar" ] then echo "myvar is not defined" fi
Need kaks võrdlus näidet on samaväärsed
#!/bin/bash if [ "$myvar" -eq 3 ] then echo "myvar equals 3" fi if [ "$myvar" = "3" ] then echo "myvar equals 3" fi

#!/bin/bash
echo "Sisesta number kontrolliks"
read count # sisestame numbri muutujasse count # kui see number on võrdne 100-ga if [ $count -eq 100 ] then echo "Count is 100" # vastasel juhul kui on suurem kui 100 elif [ $count -gt 100 ] then echo "Count is greater than 100" # vastasel juhul else echo "Count is less than 100" fi
Stringide võrdlus.
PS! IF lauses muutuja peab kindlasti olema jutumärkides
if [ "$myvar" = "foo bar oni" ]
then
    echo "yes"
fi

KIIRE IF
käskude tingimuslik täitmine
käsk1 && käsk2 - käsk2 täidetakse ainult siis kui käsk1 täitmise status on 0(vigu ei ole) -on samaväärne if !käsk1; then käsk2; fi
käsk1 || käsk2 - käsk2 täidetakse ainult siis kui käsk1 täitmise status ei ole 0(oli viga) - on samaväärne if käsk1; then käsk2; fi
# mkdir docs && cd docs # liikuda katalogi docs kui see sai olla loodud
# grep root /etc/passwd || echo 'Help! No one in charge' # kui root kasutaja on puudu antud failis siis prindib lause

OPERAATOR CASE
Reegel:
case value in
pattern) statement_list ;;
{pattern) statement_list ;; }
esac

Naited:

Nädalapäevale vastava lause väljstsmine

# !/bin/bash
#dow=`date '+%w'` # get day of the week PS Vananenud meetod
dow=$(date '+%w') # get day of the week
wd=$(date '+%A') # get name of the weekday
case "$dow" in
1|2|3|4) echo $wd - Another working day ;;
5) echo $wd - TGIF! ;;
0|6) echo $wd - I live for the weekend;;
*) echo $wd - What day is $dow
esac

Failide lajendite kontroll katalogis
Loo uus katalog mingi nimega ja mine sinna sisse.
Loo seal tühjad failid kõikide lajenditega mida kontrollitakse selles skriptis
Loo skript fail fext.sh ja anna talle käivitus õigused.
Pane järgnev skripti sisu sellesse fext.sh faili.
Käivita ja kontrolli kas kõikide failide jaoks saad õiged teavitused lajendite kohta.

#! /bin/bash
# Iga faili jaoks jooksvas katalogis
for filename in $(ls)
# toimeta järgmist
do
# Take extension available in a filename
ext=${filename##*\.}
# kui faili lajend langeb kokku ette antud variantidega
# trüki faili nimi ja lajendi seletus
case "$ext" in
c) echo "$filename : C source file"
;;
h) echo "$filename : C source file"
;;
o) echo "$filename : Object file"
;;
sh) echo "$filename : Shell script"
;;
txt) echo "$filename : Text file"
;;
conf) echo "$filename : Text file"
;;
*) echo " $filename : Not processed"
;;
esac
done

TSÜKLID

OPERAATOR FOR
Reegel:
for var [ in list ]
do
statement_list
done

Naite kood on failis for1.sh, koodi käivitamisel lisada parameetrid:
-----------------------------
# !/bin/bash
# trükida välja kõik argumendid
for arg
do
echo $arg
done

Näide for2.sh
-----------------------------
# !/bin/bash
# trükida välja valemi väärtused kõikide muutuja i=1->9 väärtuste jaoks
for i in 1 2 3 4 5 6 7 8 9
do
echo \$i=$i f\(i\)=$(($i*10+5 ))
done

# sama tsükkel aga ühes reas:
# for i in 1 2 3 4 5 6 7 8 9; do echo \$i=$i f\(i\)=$(($i*10+5 )); done;

Katalogi list

# for i in $( ls ); do echo item: $i; done

cycles1.sh
# !/bin/bash
for i in $( ls ); do
echo item: $i
done

C-tüüpi kood:

# for i in `seq 1 10`; do echo $i; done;

cycles2.sh
# !/bin/bash
for i in `seq 1 10`; do
echo $i;
done

OPERAATOR WHILE
harilikult kasutatakse juhul kui korduste arv on määramatu
Reegel: korrata nii kaua kui while statement ei ole null
while
statement_list
do
statement_list
done
Käsureast iga sekundi tagant trükkida kellaaeg, lõpetamiseks Ctl-C
# while (true); do sleep 1; date +%T; done

cycles3.sh loendur 0-st 10-ni
# !/bin/bash
COUNTER=0;
while [ $COUNTER -lt 10 ]; do
echo The counter is $COUNTER
let COUNTER=COUNTER+1
done

factorial.sh arvutab faktoriaali
#!/bin/bash
counter=$1
factorial=1
while [ $counter -gt 0 ]
do
factorial=$(( $factorial * $counter ))
counter=$(( $counter - 1 ))
done
echo $factorial

Skripti käivitamiseks trüki:
$ ./factorial.sh 5

While tsükli kasutamine käsureast:

# while
> (( x-=1 ))
> do
> foo=$(( ((5 + 3*2) -4) / 2 ))
> done
#

OPERAATOR UNTIL

until1.sh
# !/bin/bash
COUNTER=20
until [ $COUNTER -lt 10 ]; do
echo COUNTER $COUNTER
let COUNTER-=1
done


#!/bin/bash
END_CONDITION=end
until [ "$var1" = "$END_CONDITION" ]
# Tests condition here, at top of loop.
do
echo "Input variable #1 "
echo "($END_CONDITION to exit)"
read var1
echo "variable #1 = $var1"
echo
done

OPERAATOR SELECT, CONTINUE ja BREAK
Reegel:
select item in itemlist
do
Statements
done

Näide:
#!/bin/bash
echo "Tee oma valik"
select item in Continue Finish More
do
if [ $item = "Continue" ]; then
echo "Se ei sobi"
fi
if [ $item = "Finish" ]; then
break
fi
if [ $item = "More" ]; then
echo "Se kaa ei sobi"
fi
done

 

 

 

 

 

 

 

Kontrolltöö

PA-09B

Ülesanne. Luua shell skript uue kasutaja kodukatalogis.
Loo uus kasutaja sinu nimega mis kuuluks grupi users, shelliks peab olema /bin/bash. Uue kasutaja kodukatalog peaks asuma home katalogis. (näiteks /home/vasja)
Lisa kodukatalogile grupi õigused lugemiseks ja käivitamiseks.
Logi loodud kasutaja all süsteemi.
Kodukatalogis luua omanimeline skript .sh laiendiga. (näiteks vasja.sh)
Lisa scriptile käivitus õigused. Esimene rida peab ütlema süsteemile et on vaja käivitada see skript shellis.
Teine rida peaks olema kommentaar sinu nime ja perekonnanimega.
Kolmas rida kommentaar rühmanimega.
NB! Skript tuleks käivitada käsureast mitme numbrilise parameetriga (argumediga)
NB! Kogu info mida sa väljastad ekraanile pead suunama ka sinunimelisse log faili.(näiteks vasja.log)
Skript peaks tegema järgmist:

  1. Luua muutuja BEGIN ja väärtustada ta antud aja momendi timestamp-iga(sekundite arvuga unix ajastust), selleks et hiljem saaks arvutada skripti tööaega.
  2. Väljasta kellaeg formaadis hh<<mm<<ss ja jäta kellaaeg meelde.
  3. Viivis 1 sekund
  4. Tervita kasutajat nime järgi, nimed võta keskkonna muutujast
  5. Näita jooksva kasutaja gruppi ID
  6. Viivis 1 sekund
  7. Väljasta käivitatud skripti nimi
  8. Kontrolli kas loodud kasutaja on passwd failis ja väljasta resultaat
  9. Kui jookasvas ajas sekundite arv on suurem kui 30 siis väljasta nädalapäev sõnadega(inglise) vastasel juhul numbriga.
  10. Väljasta jooksev kuupäev formaadis dd>>kuunimi>>yy
  11. Palu sisestada 2 arvu 2-st kuni 20-ni, sisesta arvud. Leia kõikide vahearvude summa väiksemast suuremani, trüki välja.
  12. Trüki välja skripti ridade arv
  13. Loo muutuja END ja väärtusta ta jooksva aja timestamp-iga ja kirjuta
  14. Trüki välja BEGIN väärtus järgmises reas END väärtus ja järgmises reas aeg mis kulus selle skripti tööks
  15. Viivis 2 sekundit
  16. Trüki välja skripti sisu

PA-09A

Ülesanne. Luua shell skript uue kasutaja kodukatalogis.
Loo uus kasutaja sinu nimega mis kuuluks grupi users, shelliks peab olema /bin/bash. Uue kasutaja kodukatalog peaks asuma home katalogis. (näiteks /home/vasja)
Lisa kodukatalogile grupi õigused lugemiseks ja käivitamiseks. Teised kasutajad ei peaks juurdepääsema.
Logi loodud kasutaja all süsteemi.
Kodukatalogis luua omanimeline skript .sh laiendiga. (näiteks vasja.sh)
NB! Skript tuleks käivitada käsureast mitme numbrilise parameetriga (argumediga)
NB! Kogu info mida sa väljastad ekraanile pead suunama ka sinunimelisse log faili.(näiteks vasja.log)
Skript peaks tegema järgmist:

  1. Luua muutuja START ja väärtustada ta antud aja momendi timestamp-iga(sekundite arvuga unix ajastust), selleks et hiljem saaks arvutada skripti tööaega.
  2. Väljasta kellaeg formaadis hh::mm::ss
  3. Kirjutada selle muutuja väärtus log faili.
  4. Tervita jooksvat kasutajat tema login nime järgi kasutades keskkonna muutujat (näiteks vasja)
  5. Kontrolli kas kasutaja nimega "kasutaja" on passwd failis ja näita resultaat ekraanile
  6. Arvuta käsureas sisestatud parameetrite keskväärtus ja trüki see välja.
  7. Loo massiiv MONTHS mis koosneb kuu nimedest inglise keeles.
  8. Päri operaatorilt(klaviatuurist) ja sisesta oma sünnipäev ja sünnikuu numbriliselt muutujatesse BDAY ja BMONTH
  9. Trüki välja ja lisa omanimelisse log faili oma sünnipäeva päev ja kuunimi saades kätte ta indekseerides massiivi BMONTH
  10. Tekita viivis 1 sekund
  11. Kui sünnipäev on paaris arv teavita sellest operaatorit ja kirjuta see info log faili vastasel juhul teavita et see arv on paaritu ja kirjuta see info log faili.
  12. Loe mitu faili on /bin katalogis ja trüki see info välja ning lisa ka log faili
  13. Trüki välja loodud/töötava skripti ridade arv suune see ka logi faili
  14. Loo muutuja STOP ja väärtusta ta jooksva aja timestamp-iga ja kirjuta ta log faili
  15. Trüki välja START väärtus järgmises reas STOP väärtus ja järgmises reas aeg mis kulus selle skripti tööks
  16. Tekita viivis 3 sekundit
  17. Trüki välja sinu log faili sisu

PV-09

Задача. Создать скрипт под новым пользователем в домашнем каталоге.
Создать нового пользователя со своим именем в группе users , с shell /bin/bash и с домашним каталогом в директории /home ( например /home/petra)
Установить права доступа к домашнему каталогу этого пользователя так, чтобы пользователи группы users могли зайти к нему в домашний каталог, остальные доступа к этому каталогу иметь не должны.
Зайти в систему под этим именем.
В домашнем каталоге создать скрипт с именем своего пользователя и расширением .sh (например petra.sh )
Скрипт должен запускаться с 2-мя числовыми параметрами
Скрипт должен сделать следующие действия:

  1. Создать переменную с именем твоей фамилиии и присвоить ей значение текущего времени, распечатать на экран значение созданной переменной.
  2. Задержка на 1 секунды
  3. Создать переменные DAY , MON , YEAR и WEEKDAY ; присвоить им соответствующие значения дня рождения, название месяца рождения на английском , года рождения и дня недели на английском.
  4. Распечатать значения созданных переменных на экран.
  5. Вывести переменные в файл с твоим именем и расширением .txt (например petra.txt )
  6. Задержка на 1 секунды
  7. Создать массив WEEKDAYS с текстовыми значениями дней недели и распечатать его содержимое на экран.
  8. Добавить распечатку содержимого массива в файл с твоим именем и расширением .txt (например petra.txt )
  9. Найти в массиве день недели указанный в переменной WEEKDAY и вывести на экран номер элемента в массиве.
  10. Задержка на 1 секунды
  11. Распечатать содержимое работающего скрипт файла на экран. (например petra.sh )
  12. Задержка на 1 секунды
  13. Распечатать содержимое созданного текстового файла на экран. (например petra.txt )
  14. Задержка на 1 секунды
  15. Вычислить и распечатать сумму чисел находящихся между аргументами - первым и вторым параметрами командной строки (например если при запуске скрипта ввели параметры 4 и 8, требуется программно сложить 4+5+6+7+8)
  16. Распечатать количество строк в твоём скрипт файле (например petra.sh )
  17. Распечатать текущее время, и время потраченное на работу скрипта.