BASH: Skriptování: Porovnání verzí

Z Milan Kerslager
Přejít na: navigace, hledání
m (Styl)
m (Rozšíření)
Řádka 1: Řádka 1:
Shellové skripty jsou zápisem příkazů, které bychom jinak zadávali postupně na příkazovém řádku. Aby byl skript přímo spustitelný, musí být jméno interpretu uvedeno na prvním řádku skriptu (hned na začátku souboru). V našem případě bude na prvním řádku uvedeno:
+
Shellové skripty jsou zápisem příkazů, které bychom jinak zadávali postupně na příkazovém řádku.  
 +
 
 +
== Zápis skriptu ==
 +
 
 +
Aby byl skript přímo spustitelný, musí být jméno interpretu uvedeno na prvním řádku skriptu (hned na začátku souboru). V našem případě bude na prvním řádku uvedeno:
  
 
  #!/bin/bash
 
  #!/bin/bash
Řádka 11: Řádka 15:
 
  # spustíme skript z aktuálního adresáře
 
  # spustíme skript z aktuálního adresáře
 
  ./priklad.sh
 
  ./priklad.sh
 +
 +
== Ladění skriptu ==
  
 
Chceme-li vidět, jak se skript interpretuje, uvedeme na příslušném místě skriptu příkaz set -x a následně pak ladící výstup vypneme pomocí set +x. Také můžeme celý skript spustit s parametrem -x takto:
 
Chceme-li vidět, jak se skript interpretuje, uvedeme na příslušném místě skriptu příkaz set -x a následně pak ladící výstup vypneme pomocí set +x. Také můžeme celý skript spustit s parametrem -x takto:
Řádka 26: Řádka 32:
  
 
== Vložené příkazy ==
 
== Vložené příkazy ==
 +
 
Někdy je potřeba nejprve něco spočítat nebo zpracovat a teprve výsledek potřebujeme použít například jako parametr jiného příkazu. V tomto případě se používá buď zpětných apostrofů (na anglické klávesnici je zpětný apostrof vlevo vedle čísla 1 v horná řadě kláves) nebo nověji konstrukce $(...), kde na místo tří teček dosadíme příkaz nebo kolon příkazů. Výhodou tohoto způsobu je, že lze používat vnořené vyhodnocování.
 
Někdy je potřeba nejprve něco spočítat nebo zpracovat a teprve výsledek potřebujeme použít například jako parametr jiného příkazu. V tomto případě se používá buď zpětných apostrofů (na anglické klávesnici je zpětný apostrof vlevo vedle čísla 1 v horná řadě kláves) nebo nověji konstrukce $(...), kde na místo tří teček dosadíme příkaz nebo kolon příkazů. Výhodou tohoto způsobu je, že lze používat vnořené vyhodnocování.
  
Řádka 33: Řádka 40:
  
 
== Předávání parametrů ==
 
== Předávání parametrů ==
 +
 
Stejně jako ostatní programy mohou shellové skripty přebírat parametry, které byly zadány při spuštění na příkazovém řádku, např:
 
Stejně jako ostatní programy mohou shellové skripty přebírat parametry, které byly zadány při spuštění na příkazovém řádku, např:
  
Řádka 46: Řádka 54:
  
 
== Řídící konstrukce ==
 
== Řídící konstrukce ==
 +
 +
=== Podmínka if ===
  
 
;if výraz; then příkazy1; [ elif příkazy2; then příkazy3; ] ... [ else příkazy4; ] fi:
 
;if výraz; then příkazy1; [ elif příkazy2; then příkazy3; ] ... [ else příkazy4; ] fi:
Řádka 63: Řádka 73:
 
     echo jsem tu
 
     echo jsem tu
 
  fi
 
  fi
 +
 +
=== Cyklus while ===
  
 
;while výraz; do příkazy; done
 
;while výraz; do příkazy; done
Řádka 72: Řádka 84:
 
  done
 
  done
 
  echo "Už se odlásil"
 
  echo "Už se odlásil"
 +
 +
=== Cyklus until ===
  
 
;until výraz; do příkazy; done:
 
;until výraz; do příkazy; done:
Řádka 78: Řádka 92:
 
  until who | grep huzva > /dev/null; do sleep 20s; done
 
  until who | grep huzva > /dev/null; do sleep 20s; done
 
  echo "Už se přihlásil"
 
  echo "Už se přihlásil"
 +
 +
=== Smyčka for ===
  
 
;for jméno [ in slovo; ] do příkazy; done:
 
;for jméno [ in slovo; ] do příkazy; done:
Řádka 90: Řádka 106:
  
 
  for JMENO in *; do echo $JMENO; done        # ekvivalent příkazu ls
 
  for JMENO in *; do echo $JMENO; done        # ekvivalent příkazu ls
 +
 +
=== Větvení case ===
  
 
;case slovo in
 
;case slovo in
Řádka 117: Řádka 135:
 
     *)      echo Nerozumim
 
     *)      echo Nerozumim
 
  esac
 
  esac
 +
 +
=== Řízení cyklu break a continue ===
  
 
;break [n]:
 
;break [n]:
 
* ukončí n-tou úroveň cyklu for, while, until  
 
* ukončí n-tou úroveň cyklu for, while, until  
 +
 
;continue [n]:
 
;continue [n]:
 
* zahájí další iteraci cyklu  
 
* zahájí další iteraci cyklu  
;true:
 
* návratový kód vždy 0
 
;false:
 
* návratový kód vždy 1
 
  
while true; do
+
=== Posun parametrů shift ===
    echo y
 
done                # ekvivalent příkazu yes
 
  
 
;shift:
 
;shift:
Řádka 141: Řádka 156:
 
     echo $i
 
     echo $i
 
  done
 
  done
 +
 +
== Příkazy true, false ==
 +
 +
Příkaz true vrací pravdu (návratový kód nula) a příkaz false vrací nepravdu (nenulový návratový kód), což je možné použít v podmínkách a podobně.
 +
 +
;true:
 +
* návratový kód vždy 0
 +
;false:
 +
* návratový kód vždy 1
 +
 +
while true; do
 +
    echo y
 +
done                # ekvivalent příkazu yes
 +
 +
== Testování výrazu ==
  
 
;test výraz
 
;test výraz
Řádka 218: Řádka 248:
  
 
  [ ! -z $HOME ] && echo "Proměnná prostředí HOME existuje"
 
  [ ! -z $HOME ] && echo "Proměnná prostředí HOME existuje"
 +
 +
== Funkce ==
 +
 +
;[function] název() { ... }:
 +
* klíčové slovo ''function'' není nutné použít
 +
* parametry se předávají stejně, jako celému skriptu
 +
 +
function soucet() {
 +
  echo -n "$1 + $2 = "
 +
  expr $1 + $2
 +
}
 +
soucet 7 12

Verze z 19. 12. 2007, 11:54

Shellové skripty jsou zápisem příkazů, které bychom jinak zadávali postupně na příkazovém řádku.

Zápis skriptu

Aby byl skript přímo spustitelný, musí být jméno interpretu uvedeno na prvním řádku skriptu (hned na začátku souboru). V našem případě bude na prvním řádku uvedeno:

#!/bin/bash

Dále musí mít skript nastaven příznak spuštění (eXecutable). Na příponě souboru nezáleží, ale obvykle se uvádí .sh (příponu je možné i vynechat). Pokud chceme skript spouštět pouhým zadáním jeho jména, je potřeba ho umístit do adresáře uvedeného v proměnné PATH. Takovým adresářem je obvykle automaticky adresář bin v domácím adresáři přihlášeného uživatele. Je-li umístěn skript jinde, musíme k němu uvést cestu, protože shell z bezpečnostních důvodů aktuální adresář neprohledává. Komentáře se ve skriptech označují křížkem neboli znakem hash (#). Je-li komentář započat na začátku řádku, ignoruje shell celý řádek. Jinak ignoruje pouze text umístěný za ním.

# použijeme oblíbený editor
mcedit priklad.sh
# nastavíme právo spuštění
chmod +x priklad.sh
# spustíme skript z aktuálního adresáře
./priklad.sh

Ladění skriptu

Chceme-li vidět, jak se skript interpretuje, uvedeme na příslušném místě skriptu příkaz set -x a následně pak ladící výstup vypneme pomocí set +x. Také můžeme celý skript spustit s parametrem -x takto:

bash -x priklad.sh

Návratový kód

Každý příkaz v Unixu vrací návratový kód. V případě úspěchu (resp. "pravdy") vrací ukončený program (nebo skritpt) podle dohody nulu (0). Jsou-li při provádění příkazu zjištěny problémy, je návratový kód nenulový (nejčastěji 1). Větší hodnoty mohou blíže specifikovat situaci, kvůli které je vrácena chyba. Tím pádem je potřeba ve skriptech při kontrole výstupního kódu příkazu testovat jeho nenulovost (tj. netestovat, jestli vrací 1, ale jestli vrací 0 nebo cokoliv jiného). Pro ukonční skriptu a předání návratového kódu slouží příkaz exit.

# návratový kód je 1 (tj. chyba, nepravda)
exit 1

Návratový kód využívají i kontrukce podmínek a smyček, kdy se vyhodnocuje, je-li výraz pravdivý (tj. použitý příkaz vrací nulu) nebo nepravdivý (vrací číslo různé od nuly). V případě, že je použita ve výrazu kolona (pipe, trubka), vyhodnocuje se pouze návratový kód posledního příkazu v koloně.

Vložené příkazy

Někdy je potřeba nejprve něco spočítat nebo zpracovat a teprve výsledek potřebujeme použít například jako parametr jiného příkazu. V tomto případě se používá buď zpětných apostrofů (na anglické klávesnici je zpětný apostrof vlevo vedle čísla 1 v horná řadě kláves) nebo nověji konstrukce $(...), kde na místo tří teček dosadíme příkaz nebo kolon příkazů. Výhodou tohoto způsobu je, že lze používat vnořené vyhodnocování.

echo Písmeno x má ve jméně právě přihlášený $(who | grep x)

Ve výše uvedeném příkladu je nejprve vyhodnocen příkaz v závorkách, jeho výstup je dosazen na původní místo příkladu a pak je teprve proveden příkaz echo.

Předávání parametrů

Stejně jako ostatní programy mohou shellové skripty přebírat parametry, které byly zadány při spuštění na příkazovém řádku, např:

./mujskript.sh jedna 2

Předané parametry jsou ve skriptu dostupné pomocí speciálních konstrukcí:

$# - počet předaných parametrů
$* - všechny předané parametry
$0 - jméno skriptu (jak byl volán - nultá část z příkazového řádku)
$1 - první parametr zadaný za názvem programu
$2 - druhý parametr atd.

Řídící konstrukce

Podmínka if

if výraz; then příkazy1; [ elif příkazy2; then příkazy3; ] ... [ else příkazy4; ] fi
  • pokud je návratový kód výrazu nulový (příkaz byl úspěšný, nenastala chyba), bude provedena část příkazy1
  • jinak je provedena část příkazy2 nebo příkazy4 (pokud část elif nepoužijeme)
  • návratový kód vrací poslední provedený proces nebo 0, pokud se ještě neprovedl žádný příkaz
  • pokud použijeme kolonu příkazů, bude použita návratová hodnota posledního příkazu v koloně
if grep -q huzva /etc/passwd; then
   echo yes
else
   echo no
fi
if [ -f /tmp/IAmHere ]; then
   echo jsem tu
fi

Cyklus while

while výraz; do příkazy; done
  • úsek do příkazy; je prováděn tak dlouho, dokud je návratový kód výrazu nulový (pravda)
while who | grep huzva > /dev/null
do
   sleep 20s
done
echo "Už se odlásil"

Cyklus until

until výraz; do příkazy; done
  • úsek do příkazy; je prováděn tak dlouho, dokud je návratový kód výrazu NEnulový (NEpravda)
until who | grep huzva > /dev/null; do sleep 20s; done
echo "Už se přihlásil"

Smyčka for

for jméno [ in slovo; ] do příkazy; done
  • příkaz expanduje slovo a postupně vytvářené položky přiřazuje proměnné jméno a provádí posloupnost příkazů příkazy
  • není-li in slovo; zadáno, potom se příkazy provede pro každý poziční parametr (viz dále)
for POLOZKA in a b c d
do
    echo $POLOZKA
done
for JMENO in *; do echo $JMENO; done        # ekvivalent příkazu ls

Větvení case

case slovo in
vzorek [ | vzorek ... ]) příkazy;;
...
esac
  • příkaz expanduje slovo a hledá je mezi zadanými vzorky i s použitím žolíkových znaků (používají se také pro expanzi jmen souborů)
  • jakmile se shoduje, provede se úsek příkazy
  • po nalezení první shody se dále už nehledá
echo Zadej akci a soubor:
read AKCE SOUBOR
case $AKCE in
   smaz|remove|delete) rm $SOUBOR;;
   vytvor|create)      touch $SOUBOR;
                       chmod 777 $SOUBOR;;
esac
echo Zadej odpoved
read VSTUP
case $VSTUP in
   [aAyY]*) echo ANO
            ;;
   n*|N*)   echo NE
            ;;
   *)       echo Nerozumim
esac

Řízení cyklu break a continue

break [n]
  • ukončí n-tou úroveň cyklu for, while, until
continue [n]
  • zahájí další iteraci cyklu

Posun parametrů shift

shift
  • příkaz způsobí posun zadaných parametrů vlevo, tj. první parametr je zahozen a na jeho místo je posunut druhý parametr, na pozici druhého je posunut třetí atd.
echo Pocet zadanych parametru: $#
echo Prvni parametr: $1
shift
echo dalsi parametry:
for i in $*; do
    echo $i
done

Příkazy true, false

Příkaz true vrací pravdu (návratový kód nula) a příkaz false vrací nepravdu (nenulový návratový kód), což je možné použít v podmínkách a podobně.

true
  • návratový kód vždy 0
false
  • návratový kód vždy 1
while true; do
    echo y
done                # ekvivalent příkazu yes

Testování výrazu

test výraz
[ výraz ]
  • obě uvedené formy jsou ekvivalentní (tj. chovají se naprosto stejně), [ je linka na příkaz test
  • příkaz vyhodnotí výraz a nastaví návratový kód 0 (true) nebo 1 (false)
  • místo příkazu if lze s výhodou použít zkrácenou formu:
[ výraz ] && příkaz
  • příkaz je proveden, pokud výraz vrátí pravdu
[ výraz ] || příkaz
  • příkaz je proveden, pokud výraz vrátí nepravdu
  • Testování typu souboru
    • -f soubor soubor existuje a je normálním souborem
    • -d soubor soubor existuje a je adresářem
    • -h soubor nebo -L soubor soubor existuje a je symbolickým odkazem
    • -b soubor soubor existuje a je blokovým speciálním souborem
    • -c soubor soubor existuje a je znakovým speciálním souborem
    • -e soubor soubor existuje (pouze vestavěný příkaz test)
    • -p soubor soubor existuje a je pojmenovanou rourou
    • -S soubor soubor existuje a je socket
    • -t [fd] fd je otevřeno na terminál, vynecháme-li fd, potom se použije hodnota 1 (standardní výstup)
if [ -f /etc/shadow ]; then
   echo "V systému je nainstalováno shadow password"
fi
  • Testování přístupových práv
    • -r soubor soubor existuje a lze jej číst
    • -w soubor soubor existuje a lze do něj zapisovat
    • -x soubor soubor existuje a je proveditelný
    • -u soubor soubor existuje a má nastaven SUID bit
    • -g soubor soubor existuje a má nastaven SGID bit
    • -k soubor soubor existuje a má nastaven sticky bit
  • Testování charakteristik souborů
    • -e soubor soubor existuje
    • -s soubor soubor existuje a má velikost větší než nula
    • soubor1 -nt soubor2 soubor1 je novější (podle času poslední modifikace obsahu) než soubor2
    • soubor1 -ot soubor2 soubor1 je starší (podle času poslední modifikace obsahu) než soubor2
    • soubor1 -ef soubor2 soubor1 a soubor2 jsou na stejném zařízení a mají stejné číslo i-uzlu (tzn. jde o dva tvrdé odkazy na tentýž soubor)
  • Testování řetězců
    • -z řetězec délka řetězce je nulová
    • -n řetězec nebo řetězec délka řetězce je nenulová
    • řetězec1 = řetězec2 řetězce jsou shodné
    • řetězec1 != řetězec2 řetězce se neshodují
[ -z $HOME ] && echo "Proměnná prostředí HOME neexistuje"
  • Numerické testy
    • na místě numerického argumentu se smí vyskytovat buď číslo (může být i záporné), nebo speciální výraz
    • -l řetězec výraz je nahrazen délkou řetězce
    • číslo1 -eq číslo2 číslo1 je rovno číslo2
    • číslo1 -ne číslo2 číslo1 se nerovná číslo2
    • číslo1 -lt číslo2 číslo1 je menší než číslo2
    • číslo1 -le číslo2 číslo1 je menší nebo rovno číslo2
    • číslo1 -gt číslo2 číslo1 je větší než číslo2
    • číslo1 -ge číslo2 číslo1 je větší nebo rovno číslo2
i=1
while [ $i -le 10 ]; do
    echo $i
    i=`expr $i + 1`
done
RETEZEC="abc"
test -l $RETEZEC -gt 1 && echo "Řetězec je delší"
  • Logické výrazy
    • priority lze upravovat závorkami ( )
    • Pozor: nezapomenout zrušit speciální význam závorky v shellu - např. pomocí zpětného lomítka \( \)
    • ! výraz výraz je nepravdivý
    • výraz1 -a výraz2 výraz1 a výraz2 jsou pravdivé
    • výraz1 -o výraz2 výraz1 nebo výraz2 je pravdivý
[ ! -z $HOME ] && echo "Proměnná prostředí HOME existuje"

Funkce

[function] název() { ... }
  • klíčové slovo function není nutné použít
  • parametry se předávají stejně, jako celému skriptu
function soucet() {
  echo -n "$1 + $2 = "
  expr $1 + $2
}
soucet 7 12