Existuje řada úloh, které samotný Perl vyřešit neumí a je třeba použít externí příkazy či programy.
Funkce system umožňuje provést externí příkaz a zjistit návratovou hodnotu z tohoto příkazu. Nejprve je pomocí funkce fork vytvořena kopie aktuálního procesu, funkcí exec je tato kopie přepsána kódem příkazu, který chceme spustit, skript pak čeká na ukončení tohoto procesu, vrátí jeho návratovou hodnotu a pak je řízení předáno zpět aktuálnímu skriptu. Nulová hodnota znamená úspěch, nenulová hodnota indikuje chybu při provádění tohoto příkazu.
system 'whodo';
Případná chyba vzniklá při spuštění tohoto příkazu nemá vliv na chod aktuálního skriptu v tom smyslu, že by způsobila jeho ukončení. Chceme-li zjistit, jak skončilo volání tohoto příkazu, můžeme zkontrolovat jeho návratovou hodnotu.
$navratova_hodnota = system 'whodo'; print "Volání whodo selhalo" if $navratova_hodnota; print "Volání whodo proběhlo v pořádku" unless $navratova_hodnota; # nebo system 'whodo' or die 'Není možné spustit příkaz whodo';
Příkaz spouštěný pomocí system samozřejmě nemusí být znám v době spouštění skriptu, ale může být znám až při běhu skriptu.
while (1) { # načteme jméno příkazu chomp ($prikaz = <>); # až bude zadán řetězec 'konec', skončíme last if $prikaz eq 'konec'; # provedeme externí příkaz system $prikaz; }
Proces spuštěný pomocí funkce system zdědí po aktuálním skriptu vlastnosti prostředí. To znamená, že zdědí standardní vstup, standardní výstup, standardní chybový výstup, proměnné prostředí, aktuální adresář či číslo uživatele.
Funkce system neumí získat výstup z takto spuštěného programu, ale je možné využít mechanismy příkazového řádku, pomocí kterých lze tohoto dosáhnout. Takovými mechanismy jsou např. přesměrování či použítí roury.
system 'whodo > whodo.txt'; # výsledek se uloží do souboru system 'whodo | lpr'; # výsledek se pošle na tiskárnu
Externí programy spouštené funkcí system mohou jako příkazy spouštěné z příkazového řádku dostávat argumenty, je možné spouštět několik procesů po sobě či spouštět procesy na pozadí.
# spuštění více příkazů system 'cd; echo "adresář změněn"; pwd'; # spuštení příkazu na pozadí system 'whodo &';
Chceme-li spustit program s argumenty, existují dva způsoby, jak toho dosáhnout. První způsob je předat funkci system v jednom řetězci jméno programu včetně argumentů.
system 'ls -la /home/darena/';
Druhým způsobem je předat funkci system seznam, kde prvním prvkem je jméno externího programu a dalšími prvky jsou argumenty, které budou v nezměněném pořadí předány příslušnému programu.
system 'ls', '-la', '/home/darena/';
Dalším způsobem, jakým dosáhnout spuštení externího programu, je místo funkce system použít funkci exec. Tato funkce je zahrnuta i v mechanismu spouštění programů funkcí system. Používá se k přepsání kódu aktuálního procesu kodém nového programu. Proto při použití této funkce je aktuální perlový skript přepsán a není mu možné předat zpět řízení. Je-li přece jenom řízení předáno zpět původnímu skriptu, došlo k chybě při volání tohoto příkazu.
Operátor obrácené apostrofy nebo qx// slouží k provedení externího příkazu pomocí příkazového interpretu a k zachycení jeho standardního výstupu. To bylo při použití funkcí system či exec nemožné.
Návratovou hodnotou tohoto operátoru je výstup ze spuštěného programu. Chybový výstup není zachytáván, ale je možné použít mechanismu shellu pro přesměrování chybového výstupu na standardní výstup.
$obsah = `ls /home/darena`; # zachytává se i chybový výstup $obsah = `ls /home/darena 2>&1`; # chybový výstup nás nezajímá $obsah = `ls /home/darena 2>/dev/nul`;
Při použití tohoto operátoru se načte celý výstup z externího programu, je pro něj alokována paměť a tento obsah je vrácen. Podle kontextu, ve kterém je operátor použit se vrátí buď jeden řetězec, který obsahuje celý výstup (obsahuje i případné znaky konce řádků), nebo seznam obsahující výstup rozdělený podle hodnoty obsažené v proměnné $/ (nejčastěji to bude znak konce řádku). V případě neúspěchu je vrácena nedefinovaná hodnota nebo prázdný seznam.
Proto není vhodné používat tento operátor pro spouštění programů, u kterých nás nezajímá jejich výstup -- např. kopírování či mazání souborů, změna aktuálního adresáře apod. Pro tyto případy je vhodnější použít funkci system.
Návratová hodnota z provedeného externího příkazu je uložena v proměnné $?. Proto pro zjištění, zda příkaz proběhl úspěšně, použijeme hodnotu této proměnné.
$obsah = `ls /home/darena/kniha`; print "Výsledek příkazu: $?"; # vytiskne '0' # $obsah obsahuje 'perl.tex perl.sty' $obsah = `ls /home/darena/knihaxxx`; print "Výsledek příkazu: $?"; # vytiskne '256'
Pomocí funkce fork můžeme vytvořit kopii aktuálního skriptu. V ten okamžik běží dva identické skripty. Abychom rozlišili, zda jsme skript rodičovský nebo potomek, využijeme návratovou hodnotu funkce fork. Nulová hodnota je vrácena pro potomka, nenulová pro rodiče.
my $cislo_procesu = fork; if ($cislo_procesu) { # jsme rodič } else { # jsme potomek }
Po vytvoření nového procesu může dojít k přepsání jiným procesem. K tomu slouží funkce exec s parametrem, kterým je jméno nového programu, kterým proces přepíšeme. V rodičovském procesu můžeme počkat na ukončení potomků pomocí funkce wait. Chceme-li čekat na ukončení konkrétního potomka, použijeme waitpid.
my $cislo_procesu = fork; if ($cislo_procesu) { # jsme rodič wait; # čekáme na ukončení potomka } else { # jsme potomek # spustíme externí příkaz exec 'externi prikaz'; # ukončíme tento proces, dál bude probíhat pouze rodič exit; }
© 2003, František
Dařena |