Ero sivun ”Pacman” versioiden välillä

Linux.fista
Siirry navigaatioon Siirry hakuun
p (source->syntaxhighlight)
p (source->syntaxhighlight)
Rivi 1: Rivi 1:
{{Ohjelma
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]].
| nimi=Pacman
| kuva=
| kuvateksti=
| lisenssi=[[GPLv2+]]
| käyttöliittymä=teksti
| kotisivu=[https://www.archlinux.org/pacman/ archlinux.org/pacman]
| lähdekoodi=[git://git.archlinux.org/pacman.git git.archlinux.org/pacman.git]
}}


'''Pacman''' on [[Arch Linux]]in sekä siihen pohjautuvien jakeluiden kuten [[Manjaro]]n ja [[Parabola GNU/Linux-libre]]n kuten myös [[Slackware]]:n sukulaisjakelu [[Frugalware]]n käyttämä [[paketinhallinta]]ohjelma, jolla hallitaan järjestelmään asennettuja ohjelmapaketteja. Siinä on tuki riippuvuuksien hallintaan sekä kyky ottaa yhteys etäpalvelimeen ja automaattisesti päivittää, asentaa tai poistaa paketteja. Myös paikallisten pakettien asentaminen on mahdollista. Koska valitsimet ovat yhden kirjaimen mittaisia, pacmanilla on verrattaen nopea kirjoittaa, jopa monimutkaisia komentoja verrattuna esimerkiksi [[Debian]]-pohjaisten jakeluiden käyttämin [[Apt]]-paketinhallintaohjelmiin.
== Alkuun ==
Skripti aloitetaan rivillä
<syntaxhighlight lang="bash">
#!/bin/bash
</syntaxhighlight>
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.


Arch Linuxin paketit ovat [[gzip]]attuja [[tarball]]eja ja Frugalwaren paketit [[bzip2]]-pakattuja tarballeja. Tiedostopäätteenä Arch Linuxin paketeissa on <tt>.pkg.tar.gz</tt> ja Frugalwaren paketeissa <tt>.fpm</tt>. Pacmanin [[asetustiedostojen perusteet|asetustiedosto]] on <tt>[[pacman.conf|/etc/pacman.conf]]</tt>.
Skriptejä ei kuitenkaan ole pakko kirjoittaa erilliseen tiedostoon, vaan ne voi kirjoittaa myös suoraan komentoriville. Tällöin eri komentojen väliin laitetaan erottimeksi puolipiste (;).


Frugalware on nykyisin siirtynyt käyttämään alkuperäisen Arch Linuxin pacmanin sijaan uudelleenkirjoitettua pacman-versiota nimeltä pacman-G2. Pacman-G2 on syntaksiltaan käytännössä samanlainen kuin alkuperäinen pacman [http://frugalware.org/docs/stable/pacman-g2.html].
=== Ensimmäinen skripti ===
Tehdään aluksi yksinkertainen skripti, joka esittelee muutamia perustoimintoja:
<syntaxhighlight lang="bash">
#!/bin/bash
echo "Hei, $(whoami), mitä kuuluu"
echo "Olet hakemistossa $(pwd), tiedostolistaus:"
ls
</syntaxhighlight>
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.


== Historia ==
Tallenna skripti vaikka nimellä <tt>eka.sh</tt> (sh-päätettä käytetään yleensä skriptien kanssa), anna sille [[chmod|suoritusoikeudet]] ja aja skripti, jolloin tulostus on suunnilleen seuraavanlainen:
Hei, käyttäjä, mitä kuuluu
Olet hakemistossa /home/kayttaja/ohjelmointi/skriptit, tiedostolistaus:
eka.sh
Esimerkistä nähdään heti muutama perusasia. Ensinnäkin toisella rivillä käytetään ohjelmaa [[whoami]], joka tulostaa käyttäjänimen. Kun ohjelma on $()-merkinnän sisällä, kyseiseen kohtaan "kopioidaan" ajetun ohjelman tuloste.


* Versiossa 2.0 lisättiin mahdollisuus synkronoida paketteja (--sync valitsemilla) pääpalvelimen kanssa pakettitietokantojen kautta. Tätä aiemmin paketit piti manuaalisesti asentaa käyttämällä --add ja -upgrade toimintoja.
Toisella rivillä käytetään muuttujaa. Muuttujien edessä on dollarimerkki ($), ja niitä voidaan tunkea vaikka merkkijonojen (jotka erotetaan lainausmerkillä) sisälle. Muuttujia käsitellään tarkemmin myöhemmin. Esimerkissä käyttämämme muuttuja <tt>$PWD</tt> on [[ympäristömuuttuja]], jonka arvona on aina se hakemisto, jossa käyttäjä on. Voit kokeilla tätä esimerkiksi kirjoittamalla komentoriville komennon <tt>echo $PWD</tt>.


* Versiossa 3.0 siirryttiin kaksiosaiseen pacmaniin — taustaprosessiin nimeltä ''libalpm'' (Arch Linux paketinhallintakirjasto) ja tutumpaan ''pacman''-käyttöliittymään. Nopeus parantui monissa tapauksissa, samalla kun riippuvuus ja ristiriitojen ratkaiseminen pystyi käsittelemään yhä suuremman määrän tapauksia. Siirros kirjastopohjaiseen ohjelmaan helpottaisi tulevaisuudessa vaihtoehtoisten käyttöliittymien kehittämistä.
Viimeisellä rivillä ajetaan normaalisti komentoriviohjelma [[ls]]. Voit myös kokeilla korvata tämän rivin rivillä
<syntaxhighlight lang="bash">
echo "`ls`"
</syntaxhighlight>


* Versiossa 4.0 lisättiin paketin allekirjoitus ja varmennus mahdollisuudet koko makepgk/repo-add/pacman-työkaluketjuun GnuPGn ja GPGME:n avulla.
Merkintä $() voidaan kirjoittaa myös ``, kuten alla esimerkissä. Tällöin kuitenkaan ei voi käyttää sisäkkäisiä komentoja.


* Versio 5.0 toi tuen tapahtumia edeltäville sekä niiden jälkeisille koukuille ja tietokantatiedostoluettelon toimintojen synkronisoinnille.
Skripti voitaisiin myös kirjoittaa suoraan komentoriville muodossa
<syntaxhighlight lang="bash">
echo "Hei, `whoami`, mitä kuuluu"; echo "Olet hakemistossa $PWD, tiedostolistaus:"; ls;
</syntaxhighlight>


== Käyttö ==
== Muuttujat ==
===Päivittäminen===
Muuttujat määritellään syntaksilla
Päivitetään koko järjestelmä (valitsin <tt>-u</tt>) pakettitietokanta samalla kertaa synkronoiden:
<syntaxhighlight lang="bash">
# pacman -Syu
nimi=arvo
</syntaxhighlight>
ja niihin viitataan laittamalla muuttujan eteen $
<syntaxhighlight lang="bash">
$nimi
</syntaxhighlight>
Siinä tapauksessa mikäli halutaan, että komennon tulos on muuttuja asetetaan muuttuja tyyliin:
<syntaxhighlight lang="bash">
nimi=("komennon nimi ja parametrit")
</syntaxhighlight>
Tapauksia, joissa käyttäjän tarkoittama muuttuja on epäselvä, tulee käyttää aaltosulkuja muuttujan ympärillä
<syntaxhighlight lang="bash">
${foo}bar
</syntaxhighlight>
kun halutaan tulostaa teksti <tt>bar</tt> muuttujan <tt>foo</tt> jälkeen.


Päivitetään/asennetaan ennestään olemassaoleva, esimerkiksi vanhempi versio sovelluksesta tai itsetehty ohjelmapaketti:
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:
# pacman -U foobar-0.1.4-2.pkg.tar.gz
<syntaxhighlight lang="bash">
#!/bin/bash
HEI="Hei, `whoami`, mitä kuuluu?"
echo $HEI
</syntaxhighlight>
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.


===Asentaminen===
Huomaa, että yhtäsuuruusmerkin on oltava kiinni muuttujan nimessä ja arvossa, eli seuraavat muodot eivät käy:
Paketit asennetaan valitsemalla <tt>-s</tt> .
MUUTTUJA = "terve vaan"
Asennetaan paketti {{Pkg|zsh}}:
MUUTTUJA= "moi"
  # pacman -S {{Pkg|zsh}}
  MUUTTUJA ="moi"


Näytetään paketin {{Pkg|nginx}} ja sen riippuvaisuuksien suorat osoitteet. Tällöin käyttäjä voi kopioida paketit käsin vaikkapa hakemistoon <tt>/var/cache/pacman/pkg/</tt> ja käyttää tämän jälkeen normaalia pacman-syntaksia niiden asentamiseen.
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ä:
$ pacman -Sp {{Pkg|nginx}}
<syntaxhighlight lang="bash">
numero=43
</syntaxhighlight>


===Etsiminen===
== Ehtolauseet ==
Etsitään hakusanan "chess" sisältävät paketit pakettitietokannasta:
Ehdollisia rakenteita luodaan bashille if, then, else ja fi -avainsanoilla. Rakenteen syntaksi on seuraava:
$ pacman -Ss chess
<syntaxhighlight lang="bash">
if [ ehto ]
then
    lauseita
elif [ toinen ehto ]
then
    lauseita
else
    muita lauseita
fi
</syntaxhighlight>


Etsitään kaikki koneelle asennetut paketit, jotka sisältävät hakusanan "alsa":
Ehdot merkitään hakasulkeiden sisään esimerkiksi seuraavalla tavalla
$ pacman -Qs alsa
<syntaxhighlight lang="bash">
#!/bin/bash
if [ $PWD = "/" ]
then
    echo "Tämä skripti suoritetaan juurihakemistossa";
else
    echo "Skripti suoritetaan hakemistossa $PWD";
fi
</syntaxhighlight>


===Tietojen näyttäminen===
=== Yhden rivin ehtolauseet ===
Näytetään asentamattoman (pakettitietokannasta löytyvän) paketin {{Pkg|termite}} tiedot:
Lyhyiden skriptien kanssa.
$ pacman -Si {{Pkg|termite}}
<syntaxhighlight lang="bash">
[ ehto ] && lauseita || [ toinen ehto ] && lauseita || muita lauseita


Näytetään koneelle asennetun paketin {{Pkg|byobu}} tiedot:
[ $PWD = "/" ] && printf "Tämä skripti suoritetaan juurihakemistossa\n" || printf "Skripti suoritetaan hakemistossa %s\n" "$PWD"
$ pacman -Qi {{Pkg|byobu}}
</syntaxhighlight>


Näytetään mihin pakettiin tiedosto /usr/bin/ag kuuluu:
Tässä käytetään vertailuoperaattoria =, joka on tosi, jos merkkijonot ovat samat. Muita vertailuoperaattoreita ovat
$ pacman -Qo /usr/bin/ag
{|<!--taulukon määrite--> {{siistitaulukko}}
|-
! Operaattori
! Kuvaus
|-
<!-- taulukko alkaa tästä -->
| !  || Negaatio-operaattori, "Onko seuraava ehto epätosi?"
|-
| -n || Pituus ei ole 0
|-
| -z || Pituus on 0
|-
| -d || Hakemisto on olemassa
|-
| -f || Tavallinen tiedosto on olemassa
|-
| -r || Onko tiedostoon lukuoikeus
|-
| -w || Onko tiedostoon kirjoitusoikeus
|-
| -x || Onko tiedostoon ajo-oikeus
|-
| -eq || Kokonaisluvut ovat yhtäsuuret (a = b)
|-
| -ne || Kokonaisluvut eivät ole yhtä suuret (a != b)
|-
| = || Merkkijonot ovat samat (myös ==)
|-
| != || Merkkijonot eivät ole samat
|-
| -lt || Kokonaisluku on pienempi kuin toinen
|-
| -gt || Kokonaisluku on suurempi kuin toinen (a > b)
|-
| -le || Kokonaisluku on pienempi tai yhtäsuuri kuin toinen (a <= b)
|-
| -ge || Kokonaisluku on suurempi tai yhtäsuuri kuin toinen (a >= b)
|}


===Poistaminen===
Esimerkiksi seuraavat ehdot ovat tosia
Poistetaan paketti {{Pkg|cmus}}:
<syntaxhighlight lang="bash">
# pacman -R {{Pkg|cmus}}
[ 2 -lt 5 ]
[ "moi" != "linux" ]
[ 54 -ge 53 ]
[ -f "/etc/fstab" ]
</syntaxhighlight>


Poistetaan vain ja ainoastaan paketti {{Pkg|xorg-server}}.
== Silmukat ==
# pacman -Rdd {{Pkg|xorg-server}}
=== For ===
{{Huomautus|Tällöin ei tule huomautusta poistaa muita paketteja ja riippuvuuksia, jotka mahdollisesti ovat riippuvaisia poistetusta paketista, joka voi johtaa sovelluksien tai jopa järjestelmän rikkoutumiseen ellei poistettua pakettia, joko uudelleenasenneta tai sen riippuvuuksia poisteta. Useimmiten tämä komento tulee tarpeeseen asennettaessa vastaavaa pakettia, jolloin poistettava paketin poisto normaalisti voisi johtaa myös riippuvuuksien ja kyseisestä paketista riippuvaisten toisten pakettien poistamiseen. On siis vain nopeampaa poistaa vain ja ainoastaan ongelmallinen paketti.}}
For-silmukka on näppärä monessa tapauksessa, tässä esimerkkinä hakemiston kaikkien tiedostojen läpikäynti.


Poistetaan paketti {{Pkg|cantata}} riippuvuuksineen päivineen.
<syntaxhighlight lang="bash">
# pacman -Rns {{Pkg|cantata}}
for muuttuja in `ls`
do
    echo $muuttuja
done
</syntaxhighlight>
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">
echo "Lasketaan kymmeneen:"
for luku in $(seq 10)
do
    echo $luku
done
</syntaxhighlight>


Poistetaan paketti {{Pkg|cmus}} ja sen riippuvuudet, joita ei tarvita:
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
# pacman -Rs {{Pkg|cmus}}
<syntaxhighlight lang="bash">for muuttuja in {c..o}; { echo -n "$muuttuja "; sleep 1;}</syntaxhighlight>


==Pakettien aiheuttama tallennustilan täyttyminen ja sen puhdistaminen==
=== 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ä).
<syntaxhighlight lang="bash">
while [ ehto ]
do
    lauseita
done


Poistetaan kaikki pacmanin lataamat paketit hakemistosta <tt>/var/cache/pacman/pkg</tt>. Mikäli valitsin annetaan muodossa -Sc, poistetaan vain vain vanhentuneet paketit. Mikäli paketteja ei poisteta tarpeeksi usein, kertyy niitä helposti useiden gigatavujen verran ja voi pahimmillaan täyttää <code>/var</code>-osion, oli sitten erillinen oma osionsa tai osa <code>/</code>juuri-osiota, joka johtaa siihen, että uusien päivitysten asentaminen ei onnistu ennen kuin ylimääräiset paketit poistetaan.
Esimerkki:
# pacman -Scc
while [ -f "testi" ]
do
    echo "Tiedosto on olemassa."
    sleep 1
done
</syntaxhighlight>
Edellä oleva skripti tarkistaa, onko samassa hakemistossa oleva tiedosto <tt>testi</tt> olemassa. Tätä jatketaan niin kauan kunnes tiedostoa ei enää ole.


[[Arch User Repository|AUR]]-sovellus {{AUR|pacleaner}} avulla on tosin mahdollista siivota pacman välimuistia niin, että kaikki muu, tarpeettomat paketit mukaanlukien poistetaan paitsi viimeksi ladatut, jolloin palaaminen aiempiin versioihin on mahdollista, mikäli viimeisimmät versiot omaavat esimerkiksi ohjelmavirheitä.
=== Until ===
Until on while:n vastakohta. Until-lauseke jatkaa suoritusta niin kauan kunnes ehto on tosi.  
<syntaxhighlight lang="bash">
until [ ehto ]
do
    lauseita
done
</syntaxhighlight>


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


==Listaa asennetut paketit==
<syntaxhighlight lang="bash">
Muokkaamalla käytössä olevan [[komentotulkki|komentotulkin]] asetustiedostoa, voidaan lisätä funktio, joka oletuksena listaa saman päivän aikana asennetut paketit, valitsin <tt>-a</tt> listaa kaikki asennetut paketit järjestelmän alkuperäisestä asennuksesta lähtien tai numeron lisäämällä tietyn määrän asennettuja paketteja. Esim. [[bash]]-komentotulkin [[.bashrc]]-tiedostoon:
#!/bin/bash
function Käyttis {
        os="Linux"
}
os="Windows"
#Kutsutaan funktiota
Käyttis
echo $os
</syntaxhighlight>


''Vaatimukset:'' {{pkg|expac}}
Tulostaisi "Linux".


<syntaxhighlight="bash">
Funktio määritellään siis syntaksilla
# pacman updates history
<syntaxhighlight lang="bash">
# requirements: expac


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


  local first_package=$(expac --timefmt='%Y-%m-%d %T' '%l\t%n'|sort -r|tail -n1|awk '{print $1}');
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>:
  local latest_update=$(expac --timefmt='%Y-%m-%d %T' '%l\t%n'|sort -n|tail -n1|awk '{print $1}');


  case $1 in
<syntaxhighlight lang="bash">
      -a)  expac --timefmt='%Y-%m-%d %T' '%l\t%n'|sort -n; printf "\n Ensimmäinen paketti asennettu: %s\n\n" $first_package; ;;
#!/bin/bash
      -h)  pachis_help; ;;
function Käyttis {
      ''|*[!0-9]*) expac --timefmt='%Y-%m-%d %T' '%l\t%n'|sort -n |grep "$latest_update";printf "\n Päivitetty viimeksi %s\n\n" $latest_update; ;;
        local os        # os paikallinen muuttuja
      ''|*[0-9]*) expac --timefmt='%Y-%m-%d %T' '%l\t%n'|sort -n|tail -n"$1";printf "\n $1 viimeisintä päivitystä lueteltuna.\n\n"; ;;
        os="Gentoo"
      *)  printf "\n pachis\n\n Tulostaa päivitykset aikajärjestyksessä.\n" ;;
  esac
}
}
os="Debian"
#Kutsutaan funktiota
Käyttis
echo $os
</syntaxhighlight>
Tulostaisi "Debian".


pachis_help(){
== Vinkkejä ==
cat >&2 << EOF
=== Joukot ===
Käytimme jo aiemmin merkintätapaa <tt>{1..4}</tt> merkitsemään joukkoa, johon kuuluu kaikki välin merkit (esimerkissä 1,2,3,4). Tämä ominaisuus on kuitenkin monipuolisempi. Esimerkiksi jos haluamme luoda Matille, Martalle ja Jormalle työ- ja kotihakemistot, voisimme kirjoittaa lyhyesti näin
mkdir {ma{ti,rta},jorma}n_{työ,koti}hakemisto
Jolloin luotaisiin hakemistot matin_työhakemisto, matin_kotihakemisto, martan_työhakemisto, martan_kotihakemisto, jorman_työhakemisto ja jorman_kotihakemisto.


  pachis() - pacman history-function 2020-10-27
Puretaanpa hieman tuota komentoa. <tt>ma{ti,rta}</tt> tuottaa sanat mati ja marta. Kun joukon merkinnän ulkopuolella on n, liitetään jokaisen joukon sisällä olevan alkion perään n, jolloin alaviivaa edellä oleva osuus tuottaa sanat matin, martan ja jorman. Jälkimmäinen osuus toimii samalla tavalla, sanojen työ ja koti perään liitetään sana hakemisto. Näin saamme lyhyellä komennolla aikaan paljon.


  Oletuksena tulostaa kaikki päivitysten viimeisimmän päivitysten asennuspäivän aikana asennetut päivitykset.
Tärkeä huomio on, että <tt>{}</tt>-joukon tulkitsee bash-komentotulkki eikä ohjelma, jonka yhteydessä <tt>{}</tt>-joukkoa käytetään. Käytännössä tämä tarkoittaa, että ensin bash ikään kuin avaa joukon ja vasta sen jälkeen suorittaa komentorivin. Tässä esimerkissä <tt>mkdir</tt>-ohjelma saa parametreikseen vain listan luotavista hakemistoista eikä <tt>mkdir</tt> edes tiedä, että käytettiin <tt>{}</tt>-joukkoa:
mkdir matin_työhakemisto matin_kotihakemisto martan_työhakemisto martan_kotihakemisto jorman_työhakemisto jorman_kotihakemisto


  -h
Tässä huomataan myös, että komentoja voi käyttää aivan normaalien [[Komentorivikomennot|komentoriviohjelmien]] kanssa, sillä bash käsittelee syötteen, ja suorittaa skriptit antaen ohjelmalle syötteenä skriptin tulosteen.
    Näyttää tämän viestin.


  -a
=== Hyödyllisiä ohjelmia ===
    Tulostaa kaikki asennetut paketit järjestelmän asennuksesta lähtien.
Unixin filosofian mukaisesti Linuxissa on lukuisia ohjelmia, jotka hoitavat jonkin yksittäisen tehtävän ja tekevät sen hyvin. Näitä pikkuohjelmia käytetäänkin usein skripteissä hoitamaan erilaisia tehtäviä.
 
  [0-9]+
    Tulostaa määritellyn määrän viimeisempinä asennettuja/päivitettyjä paketteja.


EOF
Kaikista Linux-järjestelmistä löytyviä ohjelmia on listattu luokkaan [[:Luokka:Komentorivin perustyökalut|Komentorivin perustyökalut]]. Näitä ohjelmia kannattaa selailla. Komentoriviohjelmia on listattu käyttötarkoituksen mukaan myös artikkelissa [[komentorivikomennot]].


}
Esimerkkinä ladataan kaikki [[LinuCast]]-podcastin [[ogg]]-muotoiset jaksot käyttämällä jokaisesta järjestelmästä löytyviä peruskomentoja [[seq]] ja [[wget]]:
 
(esimerkin sivusto on kuollut ja kuopattu, joten koodi ei toimi)
 
<syntaxhighlight lang="bash">
#!/bin/bash
for  i in `seq -f"%03g" 1 104`
do
    wget -c "http://koskisuomi.pp.fi/linucast/LinuCast$i.ogg"
done
</syntaxhighlight>
 
Esimerkkiohjelma voidaan tallentaa vaikka nimelle <tt>linuxcast.sh</tt> ja sille voidaan antaa [[chmod|suoritusoikeudet]] komennolla
chmod u+rx linucast.sh
Tämän jälkeen komentojono ajettaisiin komennolla
./linucast.sh
 
*1 tarkoittaa että mistä numerosta aloitetaan
*104 tarkoittaa kuinka monta jaksoa haetaan, lukua voi kasvattaa jaksojen lisääntyessä.
 
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">
#!/bin/bash
 
# Tyhjennetään ruutu
clear
 
# Haetaan kaikki Full Circle artikkelit numeroon 1-55 asti.
 
for luku in $(seq 55)
do
  FILE="issue"$luku"_en.pdf"
 
# Tarkistetaan onko tiedosto jo olemassa, ennen kuin ladataan se. 
if [ -f $FILE ]; then
  echo " '$FILE' tiedosto on olemassa."
else
  echo " '$FILE' tiedostoa ei ole olemassa. Ladataan se..."
  wget "https://dl.fullcirclemagazine.org/$FILE"
 
# Pidetään 5 sekunnin tauko latausten välissä, mukana laskuri
 
for (( i=5; i>0; i--)); do
    sleep 1 &
    printf "\b\b$i"   
    wait
done
fi
done
echo "Lataus valmis"
</syntaxhighlight>
</syntaxhighlight>


==Katso myös==
Esimerkkiohjelma voidaan tallentaa vaikka nimelle <tt>issueLataaja.sh</tt> ja sille voidaan antaa [[chmod|suoritusoikeudet]] komennolla
* [[Rosetta]], eri jakeluiden paketinhallintaohjelmistojen käskyjen tulkinta ja käyttö.
chmod u+rx issueLataaja.sh
Tämän jälkeen komentojono ajettaisiin komennolla
./issueLataaja.sh
 
== Katso myös ==
*[[Komentorivin perusteet]]
*[[Komentorivivinkkejä]]
 
==Aiheesta muualla==
*[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://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 parannus ehdotukset.
*[https://explainshell.com/ ExplainShell] on www-ohjelma, joka antaa ohjetekstin annetuille komennoille.
*[https://mywiki.wooledge.org/BashPitfalls Bash Pitfalls] yleisimmät bash-skriptauksen sudenkuopat.
 


[[Luokka:Paketinhallinta]]
[[Luokka:Komentorivin erikoisohjelmat]]


[[pl:pacman]]
[[Luokka:Komentorivi]]
[[Luokka:Ohjeet]]

Versio 19. maaliskuuta 2021 kello 11.04

Komentorivi on jo yksinään monipuolinen työkalu, mutta skriptien avulla on mahdollista toteuttaa huomattavasti monipuolisempia prosesseja pienellä vaivalla. Tässä oppaassa käsitellään skriptien kirjoittamista bash-komentotulkille.

Alkuun

Skripti aloitetaan rivillä

#!/bin/bash

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.

Skriptejä ei kuitenkaan ole pakko kirjoittaa erilliseen tiedostoon, vaan ne voi kirjoittaa myös suoraan komentoriville. Tällöin eri komentojen väliin laitetaan erottimeksi puolipiste (;).

Ensimmäinen skripti

Tehdään aluksi yksinkertainen skripti, joka esittelee muutamia perustoimintoja:

#!/bin/bash
echo "Hei, $(whoami), mitä kuuluu"
echo "Olet hakemistossa $(pwd), tiedostolistaus:"
ls

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.

Tallenna skripti vaikka nimellä eka.sh (sh-päätettä käytetään yleensä skriptien kanssa), anna sille suoritusoikeudet ja aja skripti, jolloin tulostus on suunnilleen seuraavanlainen:

Hei, käyttäjä, mitä kuuluu
Olet hakemistossa /home/kayttaja/ohjelmointi/skriptit, tiedostolistaus:
eka.sh

Esimerkistä nähdään heti muutama perusasia. Ensinnäkin toisella rivillä käytetään ohjelmaa whoami, joka tulostaa käyttäjänimen. Kun ohjelma on $()-merkinnän sisällä, kyseiseen kohtaan "kopioidaan" ajetun ohjelman tuloste.

Toisella rivillä käytetään muuttujaa. Muuttujien edessä on dollarimerkki ($), ja niitä voidaan tunkea vaikka merkkijonojen (jotka erotetaan lainausmerkillä) sisälle. Muuttujia käsitellään tarkemmin myöhemmin. Esimerkissä käyttämämme muuttuja $PWD on ympäristömuuttuja, jonka arvona on aina se hakemisto, jossa käyttäjä on. Voit kokeilla tätä esimerkiksi kirjoittamalla komentoriville komennon echo $PWD.

Viimeisellä rivillä ajetaan normaalisti komentoriviohjelma ls. Voit myös kokeilla korvata tämän rivin rivillä

echo "`ls`"

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

echo "Hei, `whoami`, mitä kuuluu"; echo "Olet hakemistossa $PWD, tiedostolistaus:"; ls;

Muuttujat

Muuttujat määritellään syntaksilla

nimi=arvo

ja niihin viitataan laittamalla muuttujan eteen $

$nimi

Siinä tapauksessa mikäli halutaan, että komennon tulos on muuttuja asetetaan muuttuja tyyliin:

nimi=("komennon nimi ja parametrit")

Tapauksia, joissa käyttäjän tarkoittama muuttuja on epäselvä, tulee käyttää aaltosulkuja muuttujan ympärillä

${foo}bar

kun halutaan tulostaa teksti bar muuttujan foo 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:

#!/bin/bash
HEI="Hei, `whoami`, mitä kuuluu?"
echo $HEI

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 whoami tuloste.

Huomaa, että yhtäsuuruusmerkin on oltava kiinni muuttujan nimessä ja arvossa, eli seuraavat muodot eivät käy:

MUUTTUJA = "terve vaan"
MUUTTUJA= "moi"
MUUTTUJA ="moi"

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ä:

numero=43

Ehtolauseet

Ehdollisia rakenteita luodaan bashille if, then, else ja fi -avainsanoilla. Rakenteen syntaksi on seuraava:

if [ ehto ]
then
    lauseita
elif [ toinen ehto ]
then
    lauseita
else
    muita lauseita
fi

Ehdot merkitään hakasulkeiden sisään esimerkiksi seuraavalla tavalla

#!/bin/bash
if [ $PWD = "/" ]
then
    echo "Tämä skripti suoritetaan juurihakemistossa";
else
    echo "Skripti suoritetaan hakemistossa $PWD";
fi

Yhden rivin ehtolauseet

Lyhyiden skriptien kanssa.

[ ehto ] && lauseita || [ toinen ehto ] && lauseita || muita lauseita

[ $PWD = "/" ] && printf "Tämä skripti suoritetaan juurihakemistossa\n" || printf "Skripti suoritetaan hakemistossa %s\n" "$PWD"

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

Operaattori Kuvaus
! Negaatio-operaattori, "Onko seuraava ehto epätosi?"
-n Pituus ei ole 0
-z Pituus on 0
-d Hakemisto on olemassa
-f Tavallinen tiedosto on olemassa
-r Onko tiedostoon lukuoikeus
-w Onko tiedostoon kirjoitusoikeus
-x Onko tiedostoon ajo-oikeus
-eq Kokonaisluvut ovat yhtäsuuret (a = b)
-ne Kokonaisluvut eivät ole yhtä suuret (a != b)
= Merkkijonot ovat samat (myös ==)
!= Merkkijonot eivät ole samat
-lt Kokonaisluku on pienempi kuin toinen
-gt Kokonaisluku on suurempi kuin toinen (a > b)
-le Kokonaisluku on pienempi tai yhtäsuuri kuin toinen (a <= b)
-ge Kokonaisluku on suurempi tai yhtäsuuri kuin toinen (a >= b)

Esimerkiksi seuraavat ehdot ovat tosia

[ 2 -lt 5 ]
[ "moi" != "linux" ]
[ 54 -ge 53 ]
[ -f "/etc/fstab" ]

Silmukat

For

For-silmukka on näppärä monessa tapauksessa, tässä esimerkkinä hakemiston kaikkien tiedostojen läpikäynti.

for muuttuja in `ls` 
do
    echo $muuttuja
done

Silmukassa suoritettavat rivit laitetaan siis sanojen do ja done väliin. Laskurimuuttujaan sijoitetaan vuorotellen in:n jälkeen olevat sanat, esimerkiksi tässä tapauksessa komennon ls tuloste (eli hakemistossa olevien tiedostojen nimet). Ohjelman tuloste voidaan merkitä myös seuraavasti: $(komento). 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

echo "Lasketaan kymmeneen:"
for luku in $(seq 10)
do
    echo $luku
done

Läpi käytävä joukko voidaan merkitä myös syntaksilla {alku..loppu}. Jos esimerkiksi halutaan käydä läpi kaikki merkit c-o, kokeile vaikka kirjoittaa

for muuttuja in {c..o}; { echo -n "$muuttuja "; sleep 1;}

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 [ ehto ]
do
    lauseita
done

Esimerkki:
while [ -f "testi" ]
do
    echo "Tiedosto on olemassa."
    sleep 1
done

Edellä oleva skripti tarkistaa, onko samassa hakemistossa oleva tiedosto testi olemassa. Tätä jatketaan niin kauan kunnes tiedostoa ei enää ole.

Until

Until on while:n vastakohta. Until-lauseke jatkaa suoritusta niin kauan kunnes ehto on tosi.

until [ ehto ]
do
    lauseita
done

Funktiot

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

#!/bin/bash
function Käyttis {
        os="Linux"
}
os="Windows"
#Kutsutaan funktiota
Käyttis
echo $os

Tulostaisi "Linux".

Funktio määritellään siis syntaksilla

function Funktio {
 #koodi
}

Jos halutaan skriptin toimivan myös Sh-komentotulkkia käytettäessä, funktion kanssa on käytettävä syntaksia

Funktio() { ... }

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 local:

#!/bin/bash
function Käyttis {
        local os        # os paikallinen muuttuja
        os="Gentoo"
}
os="Debian"
#Kutsutaan funktiota
Käyttis
echo $os

Tulostaisi "Debian".

Vinkkejä

Joukot

Käytimme jo aiemmin merkintätapaa {1..4} merkitsemään joukkoa, johon kuuluu kaikki välin merkit (esimerkissä 1,2,3,4). Tämä ominaisuus on kuitenkin monipuolisempi. Esimerkiksi jos haluamme luoda Matille, Martalle ja Jormalle työ- ja kotihakemistot, voisimme kirjoittaa lyhyesti näin

mkdir {ma{ti,rta},jorma}n_{työ,koti}hakemisto

Jolloin luotaisiin hakemistot matin_työhakemisto, matin_kotihakemisto, martan_työhakemisto, martan_kotihakemisto, jorman_työhakemisto ja jorman_kotihakemisto.

Puretaanpa hieman tuota komentoa. ma{ti,rta} tuottaa sanat mati ja marta. Kun joukon merkinnän ulkopuolella on n, liitetään jokaisen joukon sisällä olevan alkion perään n, jolloin alaviivaa edellä oleva osuus tuottaa sanat matin, martan ja jorman. Jälkimmäinen osuus toimii samalla tavalla, sanojen työ ja koti perään liitetään sana hakemisto. Näin saamme lyhyellä komennolla aikaan paljon.

Tärkeä huomio on, että {}-joukon tulkitsee bash-komentotulkki eikä ohjelma, jonka yhteydessä {}-joukkoa käytetään. Käytännössä tämä tarkoittaa, että ensin bash ikään kuin avaa joukon ja vasta sen jälkeen suorittaa komentorivin. Tässä esimerkissä mkdir-ohjelma saa parametreikseen vain listan luotavista hakemistoista eikä mkdir edes tiedä, että käytettiin {}-joukkoa:

mkdir matin_työhakemisto matin_kotihakemisto martan_työhakemisto martan_kotihakemisto jorman_työhakemisto jorman_kotihakemisto

Tässä huomataan myös, että komentoja voi käyttää aivan normaalien komentoriviohjelmien kanssa, sillä bash käsittelee syötteen, ja suorittaa skriptit antaen ohjelmalle syötteenä skriptin tulosteen.

Hyödyllisiä ohjelmia

Unixin filosofian mukaisesti Linuxissa on lukuisia ohjelmia, jotka hoitavat jonkin yksittäisen tehtävän ja tekevät sen hyvin. Näitä pikkuohjelmia käytetäänkin usein skripteissä hoitamaan erilaisia tehtäviä.

Kaikista Linux-järjestelmistä löytyviä ohjelmia on listattu luokkaan Komentorivin perustyökalut. Näitä ohjelmia kannattaa selailla. Komentoriviohjelmia on listattu käyttötarkoituksen mukaan myös artikkelissa komentorivikomennot.

Esimerkkinä ladataan kaikki LinuCast-podcastin ogg-muotoiset jaksot käyttämällä jokaisesta järjestelmästä löytyviä peruskomentoja seq ja wget:

(esimerkin sivusto on kuollut ja kuopattu, joten koodi ei toimi)
#!/bin/bash
for  i in `seq -f"%03g" 1 104`
do
    wget -c "http://koskisuomi.pp.fi/linucast/LinuCast$i.ogg"
done

Esimerkkiohjelma voidaan tallentaa vaikka nimelle linuxcast.sh ja sille voidaan antaa suoritusoikeudet komennolla

chmod u+rx linucast.sh

Tämän jälkeen komentojono ajettaisiin komennolla

./linucast.sh
  • 1 tarkoittaa että mistä numerosta aloitetaan
  • 104 tarkoittaa kuinka monta jaksoa haetaan, lukua voi kasvattaa jaksojen lisääntyessä.

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.

#!/bin/bash

# Tyhjennetään ruutu
clear

# Haetaan kaikki Full Circle artikkelit numeroon 1-55 asti.

for luku in $(seq 55)
do
  FILE="issue"$luku"_en.pdf"

# Tarkistetaan onko tiedosto jo olemassa, ennen kuin ladataan se.  
if [ -f $FILE ]; then
   echo " '$FILE' tiedosto on olemassa."
else
   echo " '$FILE' tiedostoa ei ole olemassa. Ladataan se..."
   wget "https://dl.fullcirclemagazine.org/$FILE"

# Pidetään 5 sekunnin tauko latausten välissä, mukana laskuri

for (( i=5; i>0; i--)); do
    sleep 1 &
    printf "\b\b$i"    
    wait
done
fi
done
echo "Lataus valmis"

Esimerkkiohjelma voidaan tallentaa vaikka nimelle issueLataaja.sh ja sille voidaan antaa suoritusoikeudet komennolla

chmod u+rx issueLataaja.sh

Tämän jälkeen komentojono ajettaisiin komennolla

./issueLataaja.sh

Katso myös

Aiheesta muualla