đĄ Gallium
Osaat jo ajaa Hello World -skriptin, ja olet lukenut oikeaa tuotantokoodia. TÀssÀ luvussa harjoittelemme yksinkertaisia skriptejÀ, jotka eivÀt odota argumentteja tai kÀyttÀjÀn syötettÀ. Ne eivÀt myöskÀÀn luo tai tuohoa tiedostoja. Seuraavassa luvussa siirrymme ajamaan skriptejÀ Docker-kontissa, jolloin voimme kÀyttÀÀ hitusen riskialttiimpia skriptejÀ.
Olet kasannut itsellesi oppimateriaaleja, joten tÀmÀ paketti ei keskity esittelemÀÀn teoriaa. Alla on kuitenkin muutama tÀrppi, joista voi olla hyötyÀ. Varsinkin debug-taidot kannattaa ottaa haltuun.
Muuttujanimet
Muuttujien nimet voivat olla mitÀ tahansa, mutta niiden tulee alkaa kirjaimella tai alaviivalla ja niissÀ voi olla kirjaimia, numeroita ja alaviivoja. Muuttujanimet ovat case-sensitiivisiÀ, eli muuttuja
ja Muuttuja
ovat kaksi eri muuttujaa.
Bashissa kÀytetÀÀn usein kokonaan pienillÀ kirjoitettuja muuttujia ja eri sanat irrotetaan toisistaan snake_case
-tyylillÀ. Esimerkiksi max_length
on hyvÀ muuttujanimi.
Kussakin kielessÀ on varattuja avainsanoja (engl. reserved keyword). NiitÀ ei voi kÀyttÀÀ muuttujien niminÀ. NÀmÀ on listatuna alla.
Klikkaa auki skripti, jolla lista muodostettiin
#!/bin/bash
# Get all reserved keywords
keywords=($(compgen -k))
# Define the number of columns
columns=4
# Loop through and print in formatted columns
for ((i = 0; i < ${#keywords[@]}; i++)); do
printf "%-12s" "${keywords[i]}"
# Print a newline after every nth column
if (( (i + 1) % columns == 0 )); then
echo
fi
done
# End the output with a newline
echo
Warning
Varattujen avainsanojen lisÀksi on lista Bashin sisÀÀnrakennettuja komentoja, jotka voit ylikirjoittaa, mutta tÀmÀ ei luonnollisesti kannata. Esimerkiksi cd ..
-komennon pitÀisi vaihtaa hakemistopuussa yksi hakemisto ylöspÀin. Katso alta skripti, jossa kyseinen komento tulostaa vain .. by cd()
, koska se on korvattu samannimisellÀ funktiolla kyseisen skriptin sisÀllÀ.
TÀmÀ ei riko skriptin ulkopuolista cd
-komennon toimintaa, paitsi jos sen tuo kyseiseen namespaceen source
-komennolla. TÀmÀn jÀlkeen hakemiston muuttuminen muuttuu merkittÀvÀn hankalaksi:
Muuttujan asettaminen
Muuttujan asettaminen tapahtuu seuraavasti:
# â
Oikein
muuttuja="arvo"
muuttuja='arvo'
muuttuja=arvo
muuttuja="moni sanainen arvo"
muuttuja=5 # Merkkijono "5", ei varsinainen numero
# âïž VÀÀrin
muuttuja = "arvo"
muuttuja=moni sanainen arvo
LisÀksi on mahdollista kÀyttÀÀ declare
-komentoa, joka on Bashin sisÀÀnrakennettu komento muuttujien mÀÀrittelyyn. declare
-komento on hyödyllinen, jos haluat mÀÀrittÀÀ muuttujan tyypin.
# Kokonaisluku
declare -i muuttuja=5
# Joukko (array)
declare -a my_array=("eka" "toka" "kolmas")
# Joukko (assoasiative array)
declare -A my_dictionary=([key1]="value1" [key2]="value2")
Jos haluat tulostaa kaikki kÀyttÀmÀsi muuttujat, kirjoita declare -p
.
Saavutettuja hyötyjÀ declare -<tyyppi>
-kÀytöstÀ ovat mm. virheiden vÀlttÀminen ja koodin selkeyttÀminen. Vahvasti tyyppimÀÀriteltyÀ kieltÀ BashistÀ ei nÀin tule, mutta declare
-komento auttaa hieman.
Aritmeettiset operaatiot?
Voit suorittaa kokonaislukumuuttujien avulla laskuoperaatioita esimerkiksi nÀin:
Vaihtoehtoinen tapa on let
, joka kÀsittelee kaikkia =
-merkin oikealla puolella olevia muuttujia lukuina.
Warning
Huomaa, ettÀ luvut ovat kokonaislukuja, mikÀ aiheuttaa sen, ettÀ esimerkiksi 5 / 3
palauttaa luvun 1
. Jos jostain syystÀ haluat kÀyttÀÀ liukulukuja, sinun tulee kutsua jotakin ulkoista ohjelmaa, kuten bc
-ohjelmaa. LÀhtökohtaisesti Bash ei kuitenkaan ole matemaattinen ohjelmointikieli vaan skriptikieli, joten jÀtÀmme nÀmÀ operaatiot muiden kielien ongelmaksi tÀllÀ kurssilla.
VianetsintÀ
Virheiden etsiminen on tÀrkeÀ osa ohjelmointia. Bashissa on muutamia tapoja, joilla voit helpottaa vianetsintÀÀ.
Set Builtin
Jos haluat debugata skriptiÀsi, voit kÀyttÀÀ set -x
ja set -u
-komentoja. EnsimmÀinen tulostaa jokaisen komennon ennen sen suorittamista ja jÀlkimmÀinen kaataa skriptin, jos kÀytÀt mÀÀrittelemÀtöntÀ muuttujaa. JÀlkimmÀinen kaatuu myös silloin, jos yritÀt esimerkiksi sijoittaa merkkijonon kokonaislukumuuttujaan. Tutustu myös muihin The Set Builtin optioihin. NÀistÀ varsinkin -e
on hyödyllinen, joka kaataa skriptin, jos jokin komento palauttaa virheen.
Tip
Samat optiot voi antaa myös skriptiÀ ajaessa nÀin: bash -u muuttuja_set_u.sh
.
Echo
Yksi luonnollinen tapa debugata lÀhes mitÀ tahansa ohjelmointikieltÀ on kÀyttÀÀ echo
-komennon tulostusta. Voit tulostaa muuttujien arvoja ja tarkistaa, ettÀ ne ovat oikein.
Interaktiivinen
Huomaa, ettÀ BashiÀ voi ajaa skriptin lisÀksi myös interaktiivisesti komentoriviltÀ. TÀmÀ voi kuulostaa itsestÀÀnselvÀltÀ, mutta on helppoa unohtaa, ettÀ keskellÀ 200-rivistÀ skriptiÀ olevan rivin voi myös ajaa erikseen ihan vain kopioimalla sen ja liittÀmÀllÀ terminaaliin.
Declare
Ajoittain on tarpeellista katsoa, mitÀ muuttujia on mÀÀritelty ja mitÀ niiden arvot ovat. TÀmÀ onnistuu declare -p
-komennolla. Se tulostaa kaikki mÀÀritellyt muuttujat ja niiden arvot - myös sellaiset, jotka Bash on mÀÀritellyt jossain sinun skriptin ulkopuolella. Sinun mÀÀrittelemÀt muuttuja-arvot ovat onneksi helposti listan lopussa.
#!/bin/bash
declare -A my_dictionary=([key1]="value1" [key2]="value2")
my_dictionary[key3]="kissa"
declare -p
# Komentoa lyhennetty - ks. runbash.sh alemmasta tehtÀvÀstÀ.
docker container run ... declare_p.sh
# ...
declare -x TERM="xterm"
declare -ir UID="0"
declare -- _=""
declare -A my_dictionary=([key2]="value2" [key3]="kissa" [key1]="value1" )
Tip
Jos haluat tulostaa tietyt muuttujat, sinun tulee antaa ne argumentteina.
TehtÀvÀt
TehtÀvÀ: DevausympÀristö ja runbash.sh
EnsimmÀisenÀ tehtÀvÀnÀ luot itsellesi devausympÀristön. KÀytÀnnössÀ luot:
- Hakemistorakenteen tehtÀvien vastauksia varten
- Skriptin
runbash.sh
, joka joko:- Ajaa valitun skriptin kontissa
- KÀynnistÀÀ interaktiivisen Bashin kontissa
- Varmistat, ettÀ kaikki on versionhallinnassa
Opettaja on antanut sinulle tyhjÀn repositorion tÀtÀ kurssia varten, ja se on esimerkiksi osoitteessa https://repo.kamit.fi/skriptiohjelmointi-2054/johnanderton
. TyhjÀ repositorio sisÀltÀÀ ohjeet, kuinka voit luoda lokaalin repositorion ja alustaa sen main
-haaralla sekÀ tyhjÀllÀ README.md
-tiedostolla. Noudata GitLabin ohjeita. Kloonaa repositorio lokaatioon:
- âïž win:
C:\Users\uname\Code\skriptiohjelmointi-2054\johnanderton
- đ§ linux:
/home/uname/Code/skriptiohjelmointi-2054/johnanderton
Korvaa 2054 kuluvalla vuodella. Korvaa johnanderton omalla nimellÀsi, jossa kirjoitusa on sÀhköpostisi alku: xxxxxx@kamk.fi
)
Miksi 2054?
Minority Report -elokuvan John Anderton seikkailee vuodessa 2054. KÀytÀn fiktionaalista vuotta, jotta tÀtÀ materiaalia ei tarvitse pÀivittÀÀ joka toteutuksen yhteydessÀ.
Luo repositorion sisÀllle seuraava rakenne:
johnanderton
âââ README.md
âââ bash
â âââ README.md
â âââ runbash.sh
â âââ scripts
â âââ kaikki.sh
â âââ skriptit.sh
â âââ tanne.sh
âââ pwsh
â âââ .gitkeep
âââ python
âââ .gitkeep
Tiedosto runbash.sh
:n luominen olisi hyvÀ tehtÀvÀ viikon pÀÀstÀ, mutta tarvitset sitÀ jo nyt, joten tarjoan sen valmiina. Voit ladata sen Githubista osoitteesta gh:sourander/skriptiohjelmointi/exercise-assets/scripts/runbash.sh. Lataa tiedosto ja sijoita se oikeaan hakemistoon.
TehtÀvÀ: Bash Hello World
Luo skripti hello.sh
, joka tulostaa tekstin "Hello World".
Huomaa, ettÀ sijoita se oikeaan hakemistoon, kuten ~/Code/skriptiohjelmointi-2054/johnanderton/bash/scripts/hello.sh
. Voit ajaa tiedoston Àsken lataamallasi apuri-skriptillÀ.
TehtÀvÀ: Turboahdettu Bash Hello World
Luo skripti, joka tulostaa absoluuttisen polun työhakemistoon ja siihen hakemistoon, missÀ skripti sijaitsee. Skriptin runko on alla:
#!/bin/bash
source /etc/os-release
distro_version=${VERSION:-"Unknown distribution"}
cwd_path='' # IMPLEMENT
scr_path='' # IMPLEMENT
printf "========= Turbo Hello World! =========\n"
printf "%-30s %s\n" "Current working directory:" "$cwd_path"
printf "%-30s %s\n" "Script directory:" "$scr_path"
printf "%-30s %s\n" "Kernel name:" "$distro_version"
Rivit, joiden perÀssÀ on kommentti # IMPLEMENT
, vaativat sinulta toimia. LisÀÀ nÀihin toiminnallisuus. Testaa yllÀ olevan tehtÀvÀn neuvoilla. Kutsu skriptiÀ hello_turbo.sh
ja katso, ettÀ se tulostaa oikeat tiedot.
HUOM! PelkkÀ src_path=$0
sattuu toimimaan, koska skripti ajetaan absoluuttisella polulla. TÀmÀn tulet kuitenkin huomaamaan vÀÀrÀksi vastaukseksi viimeistÀÀn seuraavaa tehtÀvÀÀ tehdessÀ. SelvitÀ, kuinka saat kÀÀnnettyÀ relatiivisen polun absoluuttiseksi.
TehtÀvÀ: Interaktiivinen Bash
Harjoittele tÀssÀ tehtÀvÀssÀ interaktiivista Bashin kÀyttöÀ. TÀmÀ on tarpeellista, jos haluat luoda kontin sisÀlle esimerkiksi testitiedostoja, tai haluat tarkkailla, mitÀ ajettu skripti oikeastaan tekikÀÀn. Tarvitset tÀssÀ tehtÀvÀssÀ ylempÀnÀ mainitun runbash.sh
-skriptin. Huomaa, ettÀ se löytyy /app/
-hakemistosta kontin sisÀllÀ. TÀmÀ johtuu runbash.sh
-skriptin rivistÀ: --mount type=bind,source="$(pwd)/${SCRIPT_DIR}",target=/app,readonly
.
Jos muokkaat hello_turbo.sh
-tiedostoa Host-koneella, sinun ei tarvitse poistua kontista ja kÀynnistÀÀ sitÀ uudelleen, koska polku on bindattu kontin sisÀÀn. Tallenna tiedosto ja aja se uudelleen kontissa - tiedosto on pÀivittynyt! Myös alla komennoissa luotava tiedosto /root/a/b/c/hello_turbo.sh
-pÀivittyy samalla kertaa, koska se on symbolinen linkki eli pointteri alkuperÀiseen tiedostoon.
KÀynnistÀ istunto alla olevalla komennolla. Pois pÀÀset komennolla exit
tai pikanÀppÀimellÀ Ctrl+D.
# Ilman parametriÀ skripti ajaa kontin vakio CMD:n, joka on
# haluamamme: /bin/bash
./runbash.sh
Vaihe 1: Aja missÀ oletkin
========= Turbo Hello World! =========
Current working directory: /
Script directory: /app/hello_turbo.sh
Kernel name: 24.04.1 LTS (Noble Numbat)
Huomaa, ettÀ vakiona työhakemisto on /
eli juurihakemisto.
Vaihe 2: Aja toisaalla ja toisaalta
mkdir -p /root/a/b/c
ln -s /app/hello_turbo.sh /root/a/b/c/hello_turbo.sh
cd /root/a
./b/c/hello_turbo.sh
Huomaa, ettÀ hello_turbo.sh
-skripti tulostaa nyt oikeat tiedot. Symbolinen linkki tosiaan sijaitsee hakemistossa /root/a/b/c/
, eli src_path
-muuttuja on mÀÀritelty oikein. Samaten cwd_path
-muuttuja on mÀÀritelty oikein, koska kun ajoit skritin, olit hakemistossa /root/a
.
========= Turbo Hello World! =========
Current working directory: /root/a
Script directory: /root/a/b/c/hello_turbo.sh
Kernel name: 24.04.1 LTS (Noble Numbat)
Tip
TehtÀvÀ: Bash vianetsintÀ
Luo yllÀ esitellyt kolme skriptiÀ: muuttuja_set_{none,u,ux}.sh
.
- Tarkastele, kuinka optiot vaikuttavat outputtiin.
- Kokeile myös vaihtoehtoista tapaa. Aja
bash -ux muuttuja_set_none.sh
.
Ajathan nÀmÀ kontissa aiempien tehtÀvien oppien avulla.