Arvutiteaduse instituut
  1. Kursused
  2. 2022/23 sügis
  3. Operatsioonisüsteemid (LTAT.06.001)
EN
Logi sisse

Operatsioonisüsteemid 2022/23 sügis

  • Pealeht
  • Loengud
  • Praktikumid
  • Kodutööd

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
  • Otsi programmide loendist installeeritud programm kate ja käivita 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-põhistes 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 lipp -x, 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:

  1. 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
  2. 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
  3. Skriptisisesed 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 jutumärke ("), toimub asendus ilusti:
      • echo "Asendatakse muutuja $1 tema väärtusega"

Ülesanne 2

  1. Skripti käivitamisel lisa argumendina oma nimi:
    • ./esimene.sh "Juku Mets"
  2. 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 ning matriklinumber.
  • Sisestatud vastused tuleb väljastada ekraanile.

Juhtvood

Sarnaselt muude programmeerimiskeeltega on võimalik skriptides kasutada erinevaid tingimusi ja juhtvoogusid.

IF-ELSE

Teistest programmeerimiskeeltest juba hästi tuntud IF-ELSE konstruktsioon:
NB! Pööra tähelepanu nurksulgude ees ja järel 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 (sõnede – kõik muutujad on siin sõnetüüpi) võrdlemisel:
    • = – võrdne
    • != – mittevõrdne
    • -z – On tühi
    • -n – Ei ole tühi
  • Operaatorid arvude võrdlemisel (sõnede interpreteerimine 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 jutumärkidega nii: echo "$i".

Ülesanne 4

  • Esita skript, mis nimetab kõik etteantud kaustas asuvad laiendiga A (nt .txt) failid ümber laiendiks B (nt .csv), kus A ja B loetakse sisse argumentidena kasutajalt.
  • Seda ja järgnevaid skripte soovitame käivitada bashis (faili alguses rida #!/bin/bash), sest bashi 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äsu ls puhul: valjund=$(ls).
      • Sarnaselt saab käsu väljundit läbi vaadata ka for-tsükliga (for i in $(ls)).
    • Soovitatav on esialgu kirjutada kood, mis muudab kindla laiendi, näiteks txti laiendiks csv.
    • 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 jaotist "Parameter Expansion".
    • Kui kontroll läheb läbi, nimeta fail ümber.
      • Ümber saab faili nimetada käsu mv abil
      • Nime saab asendada näiteks käsu sed abil:
        echo "failinimi.txt" | sed -e s/asendatav_text/asendus_text/, ja selle programmi tulemus tuleks siis $(...)-konstruktsiooni abil mv-käsu argumendi sisse asendada.
      • Võime kasutada ka Parameter Expansion-funktsionaalsust. ${muudetav_text/mida_muudame/milleks_muudame} Rohkem infot siin.
$ 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}
  • Esita skript, mis nimetab kõik etteantud kaustas asuvad laiendiga A (nt .txt) failid ümber laiendiks B (nt .csv), kus A ja B loetakse sisse argumentidena kasutajalt..

Ülesanne 5

  1. Loo skript, mis võtab argumendiks protsessi nime ning väljastab selle protsessi-ID (PID) ja nime.
    • Otsi protsessi käsu ps -A väljundist.
    • Otsida võid kohe ps -A väljundis käsu grep 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:
#!/bin/bash
IFS=$'\n'
# Eraldaja 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.
  • 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 ja cuti vahele käsk tr -s ' ', mis eemaldab korduvad tühikud.
    • 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 eemaldades (näiteks echo " "$line | tr -s ' ' | cut -d ' ' -f2, kus " "$line lisab tühiku rea ette).

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 arvutaks lisaks muutuja asendustele 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

  1. Loo funktsioon astendamiseks, kasutades korrutamistehet.
    • Kasuta kas rekursiooni (9^5 == 9*(9^4))
    • või näiteks WHILE/FOR-tsüklit.
  2. Väljasta oma skriptis 9^5 väärtus, kasutades loodud funktsiooni.

Tulemuse esitamine

Oma Githubi/vikilehele/failiesitusse lisa:

  1. Kõigi siniste ülesannete (3-6) lahendamiseks loodud skripti(de) sisu tekstina (hindaja peab saama skripti mugavalt kopeerida).
    • Ei tohi olla ekraanivaatena lisatud.
    • Vikis soovitame kasutada küljendamiseks [@ ja @].
  2. Kõigi siniste ülesannete (3-6) lahendamiseks loodud skripti(de) käsurea väljundid.
    • Peavad olema ekraanivaatena lisatud.

Kui teil on Github/vikileht valmis, siis lisage meile kommentaar, kust me teie lahenduse leiame.

10. Praktikum 10 - Skriptimine Linuxis
Sellele ülesandele ei saa enam lahendusi esitada.

(Tähtaeg 2 nädalat)

  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused