23Kapitola

Bash 23: Tvorba funkcí

Již po třiadvacáté se setkáváme na stránkách LinuxEXPRESu nad tématem Bash - nejrozšířenější textový příkazový interpretr v Linuxu. Probrali jsme všechna důležitá témata a dnes si představíme poslední - tvorbu vlastních funkcí.

Funkce

Jak jsme si předvedli, Bash má vlastních (interních) funkcí celkem dostatek. Navíc se můžeme ve skriptech odkazovat na jakýkoli linuxový program (ls, ps, awk, wc, cut, ...), jakých jsou v systému běžně nainstalovány stovky. Proč tedy definovat další funkce?

Vlastní funkce se hodí v případě, kdy potřebujeme ve skriptu na více místech provést tutéž (resp. velmi podobnou) posloupnost příkazů. Ukažme si to na příkladu. Píšeme skript, který bude ukazovat různé informace o běžícím systému (třeba je bude číst z /proc nebo pomocí uname, uptime, who apod.)

Na začátku každého výpisu chceme zobrazit hlavičku identifikující daný počítač. Např. seznam běžících procesů (ps a) začíná

  PID TTY      STAT   TIME COMMAND
4244 tty1     Ss+    0:00 /sbin/mingetty tty1
4245 tty2     Ss+    0:00 /sbin/mingetty tty2

My ale chceme, aby se před hlavičkou tohoto výpisu zobrazilo ještě

Počítač: Muj_Comp, čas: Pá lis  3 08:19:21 CET 2006

Toho dosáhneme např. trojicí příkazů:

echo -n "Počítač: $HOSTNAME, čas: "
date
echo

Pro potřeby našeho příkladu tedy uzavřeme tyto dva příkazy do funkce nazvané např. tento_pocitac a použijeme ji před každým výpisem. Definici funkce provedeme zápisem jejího jména následovaným prázdnou kulatou závorkou, otevřením složené závorky, posloupností příkazů na dalších řádcích a uzavřením složené závorky:

tento_pocitac()
{
echo -n "Počítač: $HOSTNAME, čas: "
date
echo
}



Definice funkcí dáváme zpravidla na začátek skriptu. Potom je můžeme v rámci tohoto skriptu volat prostým uvedením jejich jména jako příkazu. Takto by vypadal skript, ve kterém danou funkci nadefinujeme a potom ji použijeme před výpisem volného místa na discích (df) a seznamem přihlášených uživatelů (who):

!#/bin/bash
tento_pocitac()
{
echo -n "Počítač: $HOSTNAME, čas: "
date
}
echo "Obsazenost disků:"
tento_pocitac
df
echo
echo "Přihlášení uživatelé:"
tento_pocitac
who

Takto samozřejmě vypadá skript dost primitivně. Pokud mu ale vytvoříte nějaké textové menu a příkazem read (14. díl) budete hlídat stisknutou klávesu, můžeme (např. pomocí case - viz 15. díl) vypisovat různé informace o systému, uvozené vždy jménem počítače a aktuálním časem.

Posloupnost příkazů, které takto vytvořená funkce popisuje, je Bashem zařazena do skriptu na místo, kde bylo uvedeno jméno funkce. Z toho vyplývá, že (na rozdíl od mnoha programovacích jazyků) zde není nutné předávat funkci nějaké proměnné či jiné parametry a očekávat od ní návratové kódy nebo něco podobného. Návratovou hodnotou je jednoduše návratová hodnota posledního provedeného příkazu ve funkci.

Tečka

Symbolickou tečku za výčtem možností Bashe v tomto seriálu udělá příkaz tečka. Představme si situaci, že jsme zkušenými skriptéry a časem jsme si vytvořili několik vlastních funkcí, které ve svých skriptech často používáme. Bylo by jistě nepohodlné tento zdrojový text vkládat na začátek každého našeho skriptu. Např. by bylo dost pracné opravit nějakou chybu nebo vylepšit některou z již déle používaných funkcí. Toho se naštěstí bát nemusíme. Bash umožňuje na libovolné místo skriptu vložit posloupnost příkazů definovaných v jiném souboru. K tomu právě slouží příkaz tečka (.). Své oblíbené funkce si tak mohu vyčlenit a udržovat ve zvláštním souboru (třeba funkce.sh). Kdykoli pak chci do svého nového skriptu tyto funkce zařadit, zapíšu někam na jeho začátek . funkce.sh . Pokud by uvedený soubor neležel v aktuálním adresáři, bude hledán (jakožto soubor spustitelný) ve všech adresářích definovaných proměnnou PATH. Místo tečky lze použít také slovo source. Jde však o zcela jiný příkaz než exec (viz 3. díl)! Tečka (resp. source) pouze provede obsah zadaného souboru, jako by šlo o příkazy obsažené ve stávajícím skriptu.

Závěr

Tím jsme probrali vše, co jsem vám chtěl v Bashi předvést. On toho samozřejmě umí ještě mnohem více. Další podrobnosti najdete v manuálové stránce a jiné dokumentaci. Ve dvou zbývajících dílech si ukážeme probranou látku v praxi - na konkrétních (systémových) skriptech.