Muokataan sivua Bash-skriptaus

Siirry navigaatioon Siirry hakuun
Varoitus: Et ole kirjautunut sisään. IP-osoitteesi näkyy julkisesti kaikille, jos muokkaat. Jos kirjaudut sisään tai luot tunnuksen, muokkauksesi yhdistetään käyttäjänimeesi ja saat paremman käyttökokemuksen.

Kumoaminen voidaan suorittaa. Varmista alla olevasta vertailusta, että haluat saada aikaan tämän lopputuloksen, ja sen jälkeen julkaise alla näkyvät muutokset.

Nykyinen versio Oma tekstisi
Rivi 1: Rivi 1:
Komentorivi on jo yksinään [[Komentorivin perusteet|monipuolinen]] työkalu, mutta skriptien avulla on mahdollista toteuttaa huomattavasti monipuolisempia prosesseja pienellä vaivalla. Tässä oppaassa käsitellään skriptien kirjoittamista [[Bash]]-[[komentotulkki|komentotulkille]].
Komentorivi on jo yksinään [[Komentorivin perusteet|monipuolinen]] työkalu, mutta skriptien avulla on mahdollista toteuttaa huomattavasti monipuolisempia prosesseja pienellä vaivalla. Tässä oppaassa käsitellään skriptien kirjoittamista [[bash]]-[[komentotulkki|komentotulkille]].
 
Kirjoittaaksesi käyttöjärjestelmäriippumattomia skriptejä on syytä kirjoittaa skriptit [[POSIX]]-yhteensopivina [[POSIX-skriptaus|POSIX-skripteinä]].


== Alkuun ==
== Alkuun ==
Skripti aloitetaan rivillä
Skripti aloitetaan rivillä
<syntaxhighlight lang="bash">
<source lang="bash">
#!/bin/bash
#!/bin/bash
</syntaxhighlight>
</source>
Joka kertoo, että skripti suoritetaan käyttäen bashia riippumatta siitä, mitä komentotulkkia käyttäjä käyttää ajaessaan skriptin. Huomaa, että vaikka rivi alkaa #-merkillä, se ei ole kommentti. Muualla skriptissä #:llä alkavat rivit ovat kommentteja, eikä niitä huomioida.
Joka kertoo, että skripti suoritetaan käyttäen bashia riippumatta siitä, mitä komentotulkkia käyttäjä käyttää ajaessaan skriptin. Huomaa, että vaikka rivi alkaa #-merkillä, se ei ole kommentti. Muualla skriptissä #:llä alkavat rivit ovat kommentteja, eikä niitä huomioida.


Rivi 14: Rivi 12:
=== Ensimmäinen skripti ===
=== Ensimmäinen skripti ===
Tehdään aluksi yksinkertainen skripti, joka esittelee muutamia perustoimintoja:
Tehdään aluksi yksinkertainen skripti, joka esittelee muutamia perustoimintoja:
<syntaxhighlight lang="bash">
<source lang="bash">
#!/bin/bash
#!/bin/bash
echo "Hei, $(whoami), mitä kuuluu"
echo "Hei, $(whoami), mitä kuuluu"
echo "Olet hakemistossa $(pwd), tiedostolistaus:"
echo "Olet hakemistossa $(pwd), tiedostolistaus:"
ls
ls
</syntaxhighlight>
</source>
Kuten huomaat, skripteissä käytetään tavallisia komentorivikomentoja, jotka sitten suoritetaan järjestyksessä. Toisaalta kuten myöhemmin huomaamme, skriptit tarjoavat paljon enemmän mahdollisuuksia kuin pelkkä komentojen näpyttely konsoliin.
Kuten huomaat, skripteissä käytetään tavallisia komentorivikomentoja, jotka sitten suoritetaan järjestyksessä. Toisaalta kuten myöhemmin huomaamme, skriptit tarjoavat paljon enemmän mahdollisuuksia kuin pelkkä komentojen näpyttely konsoliin.


Rivi 31: Rivi 29:


Viimeisellä rivillä ajetaan normaalisti komentoriviohjelma [[ls]]. Voit myös kokeilla korvata tämän rivin rivillä
Viimeisellä rivillä ajetaan normaalisti komentoriviohjelma [[ls]]. Voit myös kokeilla korvata tämän rivin rivillä
<syntaxhighlight lang="bash">
<source lang="bash">
echo "`ls`"
echo "`ls`"
</syntaxhighlight>
</source>


Merkintä $() voidaan kirjoittaa myös ``, kuten alla esimerkissä. Tällöin kuitenkaan ei voi käyttää sisäkkäisiä komentoja.
Merkintä $() voidaan kirjoittaa myös ``, kuten alla esimerkissä. Tällöin kuitenkaan ei voi käyttää sisäkkäisiä komentoja.


Skripti voitaisiin myös kirjoittaa suoraan komentoriville muodossa
Skripti voitaisiin myös kirjoittaa suoraan komentoriville muodossa
<syntaxhighlight lang="bash">
<source lang="bash">
echo "Hei, `whoami`, mitä kuuluu"; echo "Olet hakemistossa $PWD, tiedostolistaus:"; ls;
echo "Hei, `whoami`, mitä kuuluu"; echo "Olet hakemistossa $PWD, tiedostolistaus:"; ls;
</syntaxhighlight>
</source>


== Muuttujat ==
== Muuttujat ==
Muuttujat määritellään syntaksilla
Muuttujat määritellään syntaksilla
<syntaxhighlight lang="bash">
<source lang="bash">
nimi=arvo
nimi=arvo
</syntaxhighlight>
</source>
ja niihin viitataan laittamalla muuttujan eteen $
ja niihin viitataan laittamalla muuttujan eteen $
<syntaxhighlight lang="bash">
<source lang="bash">
$nimi
$nimi
</syntaxhighlight>
</source>
Siinä tapauksessa mikäli halutaan, että komennon tulos on muuttuja asetetaan muuttuja tyyliin:
Siinä tapauksessa mikäli halutaan, että komennon tulos on muuttuja asetetaan muuttuja tyyliin:
<syntaxhighlight lang="bash">
<source lang="bash">
nimi=("komennon nimi ja parametrit")
nimi=("komennon nimi ja parametrit")
</syntaxhighlight>
</source>
Tapauksia, joissa käyttäjän tarkoittama muuttuja on epäselvä, tulee käyttää aaltosulkuja muuttujan ympärillä
Tapauksia, joissa käyttäjän tarkoittama muuttuja on epäselvä, tulee käyttää aaltosulkuja muuttujan ympärillä
<syntaxhighlight lang="bash">
<source lang="bash">
${foo}bar
${foo}bar
</syntaxhighlight>
</source>
kun halutaan tulostaa teksti <tt>bar</tt> muuttujan <tt>foo</tt> jälkeen.
kun halutaan tulostaa teksti <tt>bar</tt> muuttujan <tt>foo</tt> jälkeen.


Ensimmäisen skriptimme tapauksessa käytimme jo ympäristömuuttujaa $PWD echo:n kanssa. Tehdäänpä samantyyppinen skripti nyt käyttäen itse määrittelemäämme muuttujaa:
Ensimmäisen skriptimme tapauksessa käytimme jo ympäristömuuttujaa $PWD echo:n kanssa. Tehdäänpä samantyyppinen skripti nyt käyttäen itse määrittelemäämme muuttujaa:
<syntaxhighlight lang="bash">
<source lang="bash">
#!/bin/bash
#!/bin/bash
HEI="Hei, `whoami`, mitä kuuluu?"
HEI="Hei, `whoami`, mitä kuuluu?"
echo $HEI
echo $HEI
</syntaxhighlight>
</source>
Kuten huomaat, kun muuttujaan sijoitetaan arvo, voidaan käyttää samoja "kikkoja" kuin muuallakin skriptissä, esimerkiksi tässä tapauksessa sijoitamme muuttujaan merkkijonon jonka sisällä on ohjelman <tt>whoami</tt> tuloste.
Kuten huomaat, kun muuttujaan sijoitetaan arvo, voidaan käyttää samoja "kikkoja" kuin muuallakin skriptissä, esimerkiksi tässä tapauksessa sijoitamme muuttujaan merkkijonon jonka sisällä on ohjelman <tt>whoami</tt> tuloste.


Rivi 75: Rivi 73:


Lisäksi muuttujaan sijoitettavan arvon on oltava lainausmerkkien sisällä, jos siihen kuuluu välilyönti. Yksittäisen sanan tai numeron voi sijoittaa ilman lainausmerkkejä:
Lisäksi muuttujaan sijoitettavan arvon on oltava lainausmerkkien sisällä, jos siihen kuuluu välilyönti. Yksittäisen sanan tai numeron voi sijoittaa ilman lainausmerkkejä:
<syntaxhighlight lang="bash">
<source lang="bash">
numero=43
numero=43
</syntaxhighlight>
</source>


== Ehtolauseet ==
== Ehtolauseet ==
Ehdollisia rakenteita luodaan bashille if, then, else ja fi -avainsanoilla. Rakenteen syntaksi on seuraava:
Ehdollisia rakenteita luodaan bashille if, then, else ja fi -avainsanoilla. Rakenteen syntaksi on seuraava:
<syntaxhighlight lang="bash">
<source lang="bash">
if [ ehto ]
if [ ehto ]
then
then
Rivi 91: Rivi 89:
     muita lauseita
     muita lauseita
fi
fi
</syntaxhighlight>
</source>


Ehdot merkitään hakasulkeiden sisään esimerkiksi seuraavalla tavalla
Ehdot merkitään hakasulkeiden sisään esimerkiksi seuraavalla tavalla
<syntaxhighlight lang="bash">
<source lang="bash">
#!/bin/bash
#!/bin/bash
if [ $PWD = "/" ]
if [ $PWD = "/" ]
Rivi 102: Rivi 100:
     echo "Skripti suoritetaan hakemistossa $PWD";
     echo "Skripti suoritetaan hakemistossa $PWD";
fi
fi
</syntaxhighlight>
</source>


=== Yhden rivin ehtolauseet ===
=== Yhden rivin ehtolauseet ===
Lyhyiden skriptien kanssa.
Lyhyiden skriptien kanssa.
<syntaxhighlight lang="bash">
<source lang="bash">
[ ehto ] && lauseita || [ toinen ehto ] && lauseita || muita lauseita
[ ehto ] && lauseita || [ toinen ehto ] && lauseita || muita lauseita


[ $PWD = "/" ] && printf "\nTämä skripti suoritetaan juurihakemistossa\n" || printf "\nSkripti suoritetaan hakemistossa %s\n" "$PWD"
[ $PWD = "/" ] && printf "Tämä skripti suoritetaan juurihakemistossa\n" || printf "Skripti suoritetaan hakemistossa %s\n" "$PWD"
</syntaxhighlight>
</source>


Tässä käytetään vertailuoperaattoria =, joka on tosi, jos merkkijonot ovat samat. Muita vertailuoperaattoreita ovat
Tässä käytetään vertailuoperaattoria =, joka on tosi, jos merkkijonot ovat samat. Muita vertailuoperaattoreita ovat
Rivi 153: Rivi 151:


Esimerkiksi seuraavat ehdot ovat tosia
Esimerkiksi seuraavat ehdot ovat tosia
<syntaxhighlight lang="bash">
<source lang="bash">
[ 2 -lt 5 ]
[ 2 -lt 5 ]
[ "moi" != "linux" ]
[ "moi" != "linux" ]
[ 54 -ge 53 ]
[ 54 -ge 53 ]
[ -f "/etc/fstab" ]
[ -f "/etc/fstab" ]
</syntaxhighlight>
</source>


== Silmukat ==
== Silmukat ==
Rivi 164: Rivi 162:
For-silmukka on näppärä monessa tapauksessa, tässä esimerkkinä hakemiston kaikkien tiedostojen läpikäynti.
For-silmukka on näppärä monessa tapauksessa, tässä esimerkkinä hakemiston kaikkien tiedostojen läpikäynti.


<syntaxhighlight lang="bash">
<source lang="bash">
for muuttuja in `ls`  
for muuttuja in `ls`  
do
do
     echo $muuttuja
     echo $muuttuja
done
done
</syntaxhighlight>
</source>
Silmukassa suoritettavat rivit laitetaan siis sanojen <tt>do</tt> ja <tt>done</tt> väliin. Laskurimuuttujaan sijoitetaan vuorotellen <tt>in</tt>:n jälkeen olevat sanat, esimerkiksi tässä tapauksessa komennon [[ls]] tuloste (eli hakemistossa olevien tiedostojen nimet). Ohjelman tuloste voidaan merkitä myös seuraavasti: <tt>$(komento)</tt>. Jos silmukalla on käytävä läpi kaikki kokonaisluvut tietyltä väliltä, voi käyttää komentoa [[seq]], joka tulostaa kokonaisluvut väliltä 1-annettu parametri. Esimerkiksi
Silmukassa suoritettavat rivit laitetaan siis sanojen <tt>do</tt> ja <tt>done</tt> väliin. Laskurimuuttujaan sijoitetaan vuorotellen <tt>in</tt>:n jälkeen olevat sanat, esimerkiksi tässä tapauksessa komennon [[ls]] tuloste (eli hakemistossa olevien tiedostojen nimet). Ohjelman tuloste voidaan merkitä myös seuraavasti: <tt>$(komento)</tt>. Jos silmukalla on käytävä läpi kaikki kokonaisluvut tietyltä väliltä, voi käyttää komentoa [[seq]], joka tulostaa kokonaisluvut väliltä 1-annettu parametri. Esimerkiksi
<syntaxhighlight lang="bash">
<source lang="bash">
echo "Lasketaan kymmeneen:"
echo "Lasketaan kymmeneen:"
for luku in $(seq 10)
for luku in $(seq 10)
Rivi 177: Rivi 175:
     echo $luku
     echo $luku
done
done
</syntaxhighlight>
</source>


Läpi käytävä joukko voidaan merkitä myös syntaksilla <tt>{alku..loppu}</tt>. Jos esimerkiksi halutaan käydä läpi kaikki merkit c-o, kokeile vaikka kirjoittaa
Läpi käytävä joukko voidaan merkitä myös syntaksilla <tt>{alku..loppu}</tt>. Jos esimerkiksi halutaan käydä läpi kaikki merkit c-o, kokeile vaikka kirjoittaa
<syntaxhighlight lang="bash">for muuttuja in {c..o}; { echo -n "$muuttuja "; sleep 1;}</syntaxhighlight>
<source lang="bash">for muuttuja in {c..o}; { echo -n "$muuttuja "; sleep 1;}</source>


=== While ===
=== While ===
While suorittaa lausekkeita niin kauan kuin ehto on tosi. Kun ehto on epätosi poistutaan loopista jolloin skriptin suoritus jatkuu seuraavalta loogiselta riviltä (while-lausekkeen jälkeiseltä riviltä).
While suorittaa lausekkeita niin kauan kuin ehto on tosi. Kun ehto on epätosi poistutaan loopista jolloin skriptin suoritus jatkuu seuraavalta loogiselta riviltä (while-lausekkeen jälkeiseltä riviltä).
<syntaxhighlight lang="bash">
<source lang="bash">
while [ ehto ]
while [ ehto ]
do
do
Rivi 196: Rivi 194:
     sleep 1
     sleep 1
done
done
</syntaxhighlight>
</source>
Edellä oleva skripti tarkistaa, onko samassa hakemistossa oleva tiedosto <tt>testi</tt> olemassa. Tätä jatketaan niin kauan kunnes tiedostoa ei enää ole.
Edellä oleva skripti tarkistaa, onko samassa hakemistossa oleva tiedosto <tt>testi</tt> olemassa. Tätä jatketaan niin kauan kunnes tiedostoa ei enää ole.


=== Until ===
=== Until ===
Until on while:n vastakohta. Until-lauseke jatkaa suoritusta niin kauan kunnes ehto on tosi.  
Until on while:n vastakohta. Until-lauseke jatkaa suoritusta niin kauan kunnes ehto on tosi.  
<syntaxhighlight lang="bash">
<source lang="bash">
until [ ehto ]
until [ ehto ]
do
do
     lauseita
     lauseita
done
done
</syntaxhighlight>
</source>


== Funktiot ==
== Funktiot ==
Kuten "oikeissa" ohjelmointikielissä, myös bash-skripteissä on mahdollista käyttää funktioita seuraavalla tavalla
Kuten "oikeissa" ohjelmointikielissä, myös bash-skripteissä on mahdollista käyttää funktioita seuraavalla tavalla


<syntaxhighlight lang="bash">
<source lang="bash">
#!/bin/bash
#!/bin/bash
function Käyttis {
function Käyttis {
Rivi 220: Rivi 218:
Käyttis
Käyttis
echo $os
echo $os
</syntaxhighlight>
</source>


Tulostaisi "Linux".  
Tulostaisi "Linux".  


Funktio määritellään siis syntaksilla
Funktio määritellään siis syntaksilla
<syntaxhighlight lang="bash">
<source lang="bash">


function Funktio {
function Funktio {
  #koodi
  #koodi
}
}
</syntaxhighlight>
</source>
Jos halutaan skriptin toimivan myös [[Sh]]-komentotulkkia käytettäessä, funktion kanssa on käytettävä syntaksia
Jos halutaan skriptin toimivan myös [[Sh]]-komentotulkkia käytettäessä, funktion kanssa on käytettävä syntaksia
<syntaxhighlight lang="bash">
<source lang="bash">
Funktio() { ... }
Funktio() { ... }
</syntaxhighlight>
</source>


Jos muuttujia ei funktiossa erikseen määritellä yksityisiksi, ne ovat julkisia. Eli kun esimerkkiskriptissämme muutimme muuttujan $os arvoa funktiossa, tämä muutos näkyi myös funktion ulkopuolella. Muuttuja voidaan määritellä yksityiseksi avainsanalla <tt>local</tt>:
Jos muuttujia ei funktiossa erikseen määritellä yksityisiksi, ne ovat julkisia. Eli kun esimerkkiskriptissämme muutimme muuttujan $os arvoa funktiossa, tämä muutos näkyi myös funktion ulkopuolella. Muuttuja voidaan määritellä yksityiseksi avainsanalla <tt>local</tt>:


<syntaxhighlight lang="bash">
<source lang="bash">
#!/bin/bash
#!/bin/bash
function Käyttis {
function Käyttis {
Rivi 248: Rivi 246:
Käyttis
Käyttis
echo $os
echo $os
</syntaxhighlight>
</source>


Tulostaisi "Debian".
Tulostaisi "Debian".
Rivi 274: Rivi 272:
  (esimerkin sivusto on kuollut ja kuopattu, joten koodi ei toimi)
  (esimerkin sivusto on kuollut ja kuopattu, joten koodi ei toimi)


<syntaxhighlight lang="bash">
<source lang="bash">
#!/bin/bash
#!/bin/bash
# linucast.sh - LinuCast-podcastin latausskripti
for  i in `seq -f"%03g" 1 104`
for  i in `seq -f"%03g" 1 104`
do
do
     wget -c "http://koskisuomi.pp.fi/linucast/LinuCast$i.ogg"
     wget -c "http://koskisuomi.pp.fi/linucast/LinuCast$i.ogg"
done
done
</syntaxhighlight>
</source>


Esimerkkiohjelma voidaan tallentaa vaikka nimelle <tt>linuxcast.sh</tt> ja sille voidaan antaa [[chmod|suoritusoikeudet]] komennolla
Esimerkkiohjelma voidaan tallentaa vaikka nimelle <tt>linuxcast.sh</tt> ja sille voidaan antaa [[chmod|suoritusoikeudet]] komennolla
Rivi 293: Rivi 290:
Esimerkki ohjelmana 2. Ladataan kaikki Full Circle magazinen englanninkieliset pdf-tiedostot palvelimelta. Esimerkissä on käytetty Bash skriptaus koodeja joita löytyy esimerkiksi tältä sivulta.
Esimerkki ohjelmana 2. Ladataan kaikki Full Circle magazinen englanninkieliset pdf-tiedostot palvelimelta. Esimerkissä on käytetty Bash skriptaus koodeja joita löytyy esimerkiksi tältä sivulta.


<syntaxhighlight lang="bash">
<source lang="bash">
#!/bin/bash
#!/bin/bash
# issueLataaja.sh - Ubuntu-aiheisen verkkojulkaisu Full Circle:n artikkelilataaja, kerää ne kaikki!


# Tyhjennetään ruutu
# Tyhjennetään ruutu
clear
clear


# Haetaan kaikki Full Circlen artikkelit ensimmäisestä beta-julkaisusta (0) kaikkein uusimpaan asti.
# Haetaan kaikki Full Circle artikkelit numeroon 1-55 asti.
 
# Listataan julkaisut verkkosivulta, joista viimeisin tallennetaan muuttujaksi.
viimeisin_julkaisu=$(curl -s https://fullcirclemagazine.org/downloads/ | grep -oP '(?<=Issue )[0-9]+' | tail -1);


for luku in $(seq 0 $viimeisin_julkaisu)
for luku in $(seq 55)
do
do
   FILE="issue"$luku"_en.pdf"
   FILE="issue"$luku"_en.pdf"
Rivi 326: Rivi 319:
done
done
echo "Lataus valmis"
echo "Lataus valmis"
</syntaxhighlight>
</source>


Esimerkkiohjelma voidaan tallentaa vaikka nimelle <tt>issueLataaja.sh</tt> ja sille voidaan antaa [[chmod|suoritusoikeudet]] komennolla
Esimerkkiohjelma voidaan tallentaa vaikka nimelle <tt>issueLataaja.sh</tt> ja sille voidaan antaa [[chmod|suoritusoikeudet]] komennolla
Rivi 336: Rivi 329:
*[[Komentorivin perusteet]]
*[[Komentorivin perusteet]]
*[[Komentorivivinkkejä]]
*[[Komentorivivinkkejä]]
*[[ShellCheck]] on ohjelma, joka havaitsee kaikki [[sh]] ja [[bash]]-skriptien ongelmat ja antaa niille parannusehdotukset.


==Aiheesta muualla==
==Aiheesta muualla==
*[https://tldp.org/LDP/abs/html/ Advanced Bash-Scripting Guide] - laaja englanninkielinen opas bash-skriptaukseen
*[https://tldp.org/LDP/abs/html/ Advanced Bash-Scripting Guide] - laaja englanninkielinen opas bash-skriptaukseen
*[https://www.panix.com/~elflord/unix/bash-tute.html Pikaopas bash-skriptaukseen] (englanniksi)
*[https://www.panix.com/~elflord/unix/bash-tute.html Pikaopas bash-skriptaukseen] (englanniksi)
*[https://web.archive.org/web/20170610153335/https://gd.tuwien.ac.at/linuxcommand.org/writing_shell_scripts.php Writing shell scripts] - toinen laaja englanninkielinen opas bash-skriptaukseen - {{InternetArchive}}
*[https://web.archive.org/web/20170610153335/https://gd.tuwien.ac.at/linuxcommand.org/writing_shell_scripts.php Writing shell scripts] - toinen laaja englanninkielinen opas bash-skriptaukseen - archive.org tallenne 10.6.2017
*[https://www.shellcheck.net/ ShellCheck] on www-ohjelma, joka havaitsee kaikki [[sh]] ja [[bash]]-skriptien ongelmat ja antaa niille parannusehdotukset.
*[https://www.shellcheck.net/ ShellCheck] on www-ohjelma, joka havaitsee kaikki [[sh]] ja [[bash]]-skriptien ongelmat ja antaa niille parannus ehdotukset.
*[https://explainshell.com/ ExplainShell] on www-ohjelma, joka antaa ohjetekstin annetuille komennoille.
*[https://explainshell.com/ ExplainShell] on www-ohjelma, joka antaa ohjetekstin annetuille komennoille.
*[https://mywiki.wooledge.org/BashPitfalls Bash Pitfalls] yleisimmät bash-skriptauksen sudenkuopat.
*[https://mywiki.wooledge.org/BashPitfalls Bash Pitfalls] yleisimmät bash-skriptauksen sudenkuopat.
Wikin materiaali on kaikkien vapaasti käytettävissä Creative Commons 3.0 - nimi mainittava -lisenssin alaisuudessa. TEKIJÄNOIKEUDEN ALAISEN MATERIAALIN KÄYTTÄMINEN ILMAN LUPAA ON EHDOTTOMASTI KIELLETTYÄ!

Muokataksesi tätä sivua vastaa alla olevaan kysymykseen (lisätietoja):

Peruuta Muokkausohjeet (avautuu uuteen ikkunaan)