Skriptimine Linuxis
Praktikum annab ülevaate käsurea skriptide loomisest Linuxis. Tihti on keerulisemate käsurea toimingute jaoks palju mugavam teha ette valmis skriptid, mida saab tulevikus perioodiliselt kasutada.
Sissejuhatus
Skript on sisuliselt tekstifail, kus sees on käsud. Skriptide koostamisel tuleb kasutada tekstiredaktorit, valikuid on Linuxis mitmeid. Vali see redaktor, mis sulle enim meeldib, kuid soovitame installeerida Kate
, kuna see teeb skriptide kirjutamise lihtsamaks.
sudo apt update
sudo apt install kate
- Otsige programmide loendist installeeritud programm
kate
ja käivitage see. - Alternatiivsed terminalis töötavad editorid:
nano
,vim
. Alternatiivne GUI editor:gedit
.
Skriptide loomine ja käivitamine
Kui tahad skripti käivitada sarnaselt tavalise Linuxi programmiga, siis peab sellel olema korrektne päis (esimene faili rida) ning failile tuleb lisada käivitamisõigus. Skriptifaili päis määrab ära, millist käsureinterpretaatorit kasutatakse skripti käivitamisel.
- Pannes skripti päiseks, ehk esimeseks reaks
#!/bin/sh
, määratakse skripti interpretaatoriks standardne POSIX-ühilduv käsuintepretaator (Bourne Shell).- Algselt kasutati Linuxis sh'na bash'i (Bourne-again shell), Ubuntus ning seega ka meie süsteemis on see alates versioonist 6.10 dash (Debian Almquist shell), mõnedes teistes süsteemides aga endiselt bash.
- Soovitav on kasutada skriptide jaoks tavalist Bourne Shelli /bin/sh, kui ekstra muid laiendusi tarvis pole - niisugused skriptid on kasutatavad ka muudes Unixi baasil operatsioonisüsteemides, kus puudub
/bin/bash
. Bash on sobiv interaktiivseks tööks terminalis ning mõnikord skriptide loomisel (juhul, kui Bashi laiendusi väga vaja on).
- Käsureaskriptide kokkuleppeline failide laiend on .sh, aga palju kasutatakse ka lihtsalt ilma laiendita failinimesid - oluline on, et fail oleks käivitatav.
- Silumisvahendina on kasulik -x lipp sh käivitamisel, näiteks sh -x skriptinimi.sh või esimesel real
#!/bin/sh -x
- see näitab ridahaaval välja, mida täidetakse.
Ülesanne 1
- Loo uus skriptifail esimene.sh, pane paika selle päis ning skripti sisuks lisa rida:
echo "Tere, tali!!"
- echo on käsuinterpretaatori käsk, mis väljastab ekraanile (standardväljundisse) oma argumendid
- Käivitamiseks on vajalik anda skriptile käivitamisõigus:
chmod 700 esimene.sh
- Käivita skript käsurealt nii:
./esimene.sh
Muutujad ja käsurea parameetrid
Skriptides on võimalik kasutada mitut erinevat tüüpi muutujaid:
- Protsessilt protsessile päranduvad keskkonnamuutujad
$PATH
- kust otsida käivitatavaid programme, kui nende asukoht pole täisteega määratud$USER
- kasutajanimi$PWD
- protsessi hetkel aktiivne töökataloog
- Skripti sisendi muutujad, mille kaudu saab ligi skripti argumentidele ja muule skriptiga seotud informatsioonile
$0
- skripti nimi$1 $2 .. $9
- skripti käsurea argumendid$$
- käesoleva interpretaatori (shell'i) PID
- Skripti sisesed lokaalsed kasutaja poolt määratud muutujad
- Muutuja väärtustamisel piisab vaid nime määramisest:
nimi=Juku
(NB! Võrdusmärgi ees ja järel ei tohi olla tühikuid!)
- Muutuja väärtuse kasutamisel tuleb nime ette panna $ märk:
echo $nimi
- Kasutades ülakomasid (') teksti ümber, ei asendata seal sees muutujate väärtusi (ehk märk $ ei oma mõju, kui see on ülakomade vahel)
-
echo 'Ei asenda muutujat $1 tema väärtusega'
-
- Kui aga kasutada juttumärke ("), toimub asendus ilusti.
echo "Asendatakse muutuja $1 tema väärtusega"
- Muutuja väärtustamisel piisab vaid nime määramisest:
Ülesanne 2
- Skripti käivitamisel lisa argumendina oma nimi:
./esimene.sh "Juku Mets"
- Pane skript väljastama tervitust argumendis nimetatud isikule.
- Proovi, mis juhtub siis, kui argumendi määramisel jutumärke ei kasuta?
Interaktiivne sisend
Selleks, et küsida kasutaja käest täiendavat informatsiooni (näiteks failinime), saab kasutada read
käsku nii:
echo "Sisesta väärtus:" read sisse echo "Sisestati: $sisse"
Ülesanne 3
- Muuda oma esimene.sh skripti nii, et küsitakse kasutaja käest ükshaaval tema
nimi
,eriala
ningmatrikli number
. - Sisestatud vastused tuleb väljastada ekraanile.
Juhtvood
Sarnaselt muudele programmeerimiskeeltele on võimalik skriptides kasutada erinevaid tingimusi ja juhtvoogusid.
IF-ELSE
Teistest programmeerimiskeeltest juba hästi tuntud IF-ELSE konstruktsioon:
NB! Pöörake tähelepanu [] sulgude juures enne ja pärast tühikute kasutamisele!
#!/bin/sh a=$1 if [ $a -lt 1000 ] then echo "Sisestatud arv on vaiksem kui 1000" elif [ $a -ge 1000 -a $a -le 5000 ] then echo "Sisestatud arv on vahemikus 1000 kuni 5000" else echo "Sisestatud arv on suurem kui 5000" fi
- Operaatorid teksti (stringide - kõik muutujad on siin stringitüüpi) võrdlemisel:
- = - võrdne
- != - mittevõrdne
- -z - On tühi
- -n - Ei ole tühi
- Operaatorid arvude võrdlemisel (stringide intepreteerimine tekstina esitatud arvudena):
- -eq - võrdne (ingl. k. equal)
- -ne - mittevõrdne (ingl. k. not equal)
- -lt - väiksem (ingl. k. less than)
- -le - väiksem või võrdne (ingl. k. less or equal)
- -gt - suurem (ingl. k. greater than)
- -ge - suurem või võrdne (ingl. k. greater or equal)
- Ning loogikaavaldised:
- -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
While
While tsükli sisu korratakse seni, kuni tingimus on tõene. Näites sooritatakse järgnev sisu, kuni muutuja $a on väiksem kümnest:
#!/bin/sh a=0 while [ $a -lt 10 ] do echo $a a=$(($a+1)) done
For
For kordus on kasulik mingi nimekirja või listi läbi vaatamiseks:
#!/bin/sh a="Martin Janar Tiit Juku" for i in $a do echo "$i" done
NB! Kui tegemist on teksti sisaldavate muutujatega, siis on soovitav muutuja kasutamisel ümbritseda see " märkidega nii: echo "$i"
Ülesanne 4
- Loo skript, mis nimetab kõik etteantud kaustas asuvad
.txt
laiendiga failid ümber.csv
laiendiga failideks. - Seda ja järgnevaid skripte soovitame käivitada
bash
is (faili alguses rida#!/bin/bash
), sestbash
i laiendused teevad tekstiasendusi lihtsamaks.- Vaata tsükli abil läbi aktiivses kataloogis leiduvad failid.
- Mingi käsu väljundi saab avaldisse asendada, ümbritsedes selle
$(...)
konstruktsiooniga. Näiteks käsuls
puhul:valjund=$(ls)
- Sarnsaselt saab käsu väljundit läbi vaadata ka for tsüklis (
for i in $(ls)
)
- Mingi käsu väljundi saab avaldisse asendada, ümbritsedes selle
- Kontrolli laiendit.
if [ ${i##*.} = txt ]; then
- Siin
${muutuja_nimi_ilma_dollarita##tekst}
asendab pikima võimaliku prefiksi (kõik enne "." oleva teksti)tühja stringiga
, seejärel kontrollime (=
) kas allesjäänud osa võrdub soovitud laiendiga (txt). Niisuguseid teisendusi on veel, vt. man sh seest "Parameter Expansion" jaotist.
- Siin
- Kui kontroll läheb läbi, nimeta fail ümber.
- Ümber saab faili nimetada
mv
abil - Nime saab asendada näiteks
sed
abil:
echo "failinimi.txt" | sed -e s/asendatav_text/asendus_text/
ja selle programmi tulemus tuleks siis$(...)
konstruktsiooni abilmv
argumendi sisse asendada. - Võime kasutada ka **Parameter Expansion** funktsionaalsust
${muudetav_text/mida_muudame/milleks_muudame}
rohkem infot siin
- Ümber saab faili nimetada
- Vaata tsükli abil läbi aktiivses kataloogis leiduvad failid.
$ fail=failinimi.txt; mv $fail $(echo $fail | sed -e s/.txt/.csv/g) $ fail=failinimi.txt;laiend1=.txt;laiend2=.csv; mv $fail ${fail/$laiend1/$laiend2}
- Täienda programmi nii, et nii
muudetav
kui kaasendatav
faili laiend loetaks sisse argumendina kasutaja käest.
- Täienda programmi nii, et nii
Ülesanne 5
- Loo skript, mis võtab argumendiks protsessi nime ning väljastab selle process ID ja nime.
- Otsi protsessi käsu
ps -A
väljundist. - Otsida võid kohe
ps-A
väljundis käsugrep
abil või siis iga rea puhul võrrelda kas programmi nimi on õige. - Vaata kõik käsu väljundi read ükshaaval läbi. Seda on võimalik teha näiteks nii:
- Otsi protsessi käsu
#!/bin/bash IFS=$'\n' # Eraldaja ümber muutmine tühikust reavahetuseks for line in $(ls) do echo "$line" done
- Selles näites muudetakse shelli muutuja
IFS
väärtus ajutiselt ümber reavahetuseks, et saaks käsu väljundit läbi vaadata ühe rea kaupa.
- Selles näites muudetakse shelli muutuja
- Vihjed: Väljasta protsessi nimi ja PID iga leitud protsessi kohta.
- Selleks, et leida esimest "sõna" tühikutega eraldatud "lauses" on võimalik kasutada
echo $line | cut -d ' ' -f1
kus-fn
määrab ära mitmes sõna ning-d
määrab ära eraldaja. - Probleeme tekib siis, kui eraldajaks on rohkem kui üks tühik!
- Selle vältimiseks on võimalik lisada
echo
jacut
vahele käsk:tr -s ' '
, mis eemaldab korduvad tühikud.
- Selle vältimiseks on võimalik lisada
- Probleeme tekitab (ajab tulbad nihkesse) ka esimene tühik, mis osadel ridadel on ja teistel pole.
- Selle probleemi saab kergesti lahendada lisades kõigile ridade algusesse ühe tühiku lisaks, ning siis kõik korduvad tühikud ära eemaldada (näiteks
echo " "$line | tr -s ' ' | cut -d ' ' -f2
kus" "$line
lisab tühiku rea ette.
- Selle probleemi saab kergesti lahendada lisades kõigile ridade algusesse ühe tühiku lisaks, ning siis kõik korduvad tühikud ära eemaldada (näiteks
- Selleks, et leida esimest "sõna" tühikutega eraldatud "lauses" on võimalik kasutada
Funktsioonid
Tihtiesinevaid tegevusi skriptides on mõistlik kirjeldada funktsioonina, mida saab hiljem mitmeid kordi välja kutsuda.
- Funktsiooni saab sama skripti piires välja kutsuda nagu teist skripti või Linuxi käsku.
- Selleks, et funktsiooni (või ükskõik millise käsu) väljund avaldise sisse asendataks (näiteks muutuja väärtuse seadmisel), tuleb kasutada "`" märke või $() konstruktsiooni nii:
echo "Funktsioonid väärtustatakse nii: $(minu_funktsioon 3 4 5)"
- Kasutage $(()) kui soovite, et teie kood lisaks muutuja asendustele arvutaks ka sulgude sees oleva tehte väärtuse (näites
a=$(($1 + $2))
, kusjuures siin$1
ja$2
on väljakutsumisel antud meetodi sisendparameetrid, mitte skripti käivitamisel sisestatud väärtused.)
Näiteks loome funktsiooni, mis arvutab summat:
#!/bin/bash summa () { a=$(($1 + $2)) echo $a } a=$(summa 23 11) b=$(summa $a 1) echo $b
Ülesanne 6
- Loo funktsioon astendamiseks, kasutades korrutamistehet.
- Kasuta kas rekursiooni (9^5 == 9*(9^4))
- Või näiteks WHILE/FOR tsüklit.
- Väljasta oma skriptis 9^5 väärtus, kasutades loodud funktsiooni
Viki
Oma viki leheküljele lisa:
- Kõigi siniste ülesannete (3-6) lahendamiseks loodud skripti(de) sisu.
- Ei tohi olla ekraanivaatena lisatud.
- Soovitame kasutada [@ ja @] koodi küljendamiseks vikis.
- Kõigi siniste ülesannete (3-6) lahendamiseks loodud skripti(de) väljundid.
- Peavad olema ekraanivaatena lisatud.
Tulemuse esitamine
Kui teil on viki lehekülg valmis, siis lisage meile kommentaar (koos mingi tühja failiga).
10. Praktikum 10 - Skriptimine Linuxis(Tähtaeg 2 nädalat)