Hrátky z řádky: tenký led - skripty generují skripty

Ondřej Bojar 21. 4. 2008

Opět se setkáváme u pravidelné pondělní dávky tipů a triků z černé řádky. Ve většině stávajících dílů jsme se snažili omezit rizika chyb v shellových skriptech. Dnes zmíníme možnosti, jak si naopak efektivně na problém náhodnými překlepy naběhnout. Skripty totiž samozřejmě mohou generovat skripty.

Spusť příkaz – eval

Jsou situace, kdy potřebujete „vypočítat“ název programu, který budete spouštět. (Například při hodně nebezpečné situaci, kdy uživatel zadává vašemu skriptu přímo nějakou výkonnou komponentu.) V některých verzích bashe navíc expanze proměnných neprobíhala v prvním slově příkazové řádky, takže název programu nešlo přímo brát z proměnné. Dnes už bash proměnné expanduje a název programu z proměnné brát můžete, dokonce i s předpřipra­venými počátečními argumenty:

moje_razeni="sort -nr"
$moje_razeni < in > out
# příklad je jen ilustrativní, konkrétně v tomhle případě by
# jistě bylo lepší zadefinovat a užít alias

V souladu s gramatikou bash ale expanduje proměnné až po částečném rozboru příkazové řádky, kdy jsou identifikovány jednotlivé příkazy oddělené středníkem, rourou ap. Když tedy výsledek „výpočtu“ programů (nebo ten vstup od uživatele), který chcete spustit, zahrnuje složitejší konstrukce, nezbývá, než použít explicitní prosbu o vyhodnocení, tj. eval:

moje_razeni="sort -n | tac"
# neznám parametr -r, znám jen tac, opak catu
cat in | $moje_razeni
# nezabere! bash zkouší spustit sort s parametry "-n", "|" a "tac"
cat in | eval $moje_razeni
# zabere, eval obsah proměnné $moje_razeni nechá vyhodnotit na místě,
# tj. stejně, jako kdybyste rovnou napsali
cat in | sort -n | tac

Samozřejmě použití evalu zesiluje vaši povinnost myslet na správné uvozovkování a ochraňování speciálních znaků. Plejáda problémů, na něž můžete narazit, je příliš široká, takže mohu poradit jediné: postupujte po malých krůčcích a testujte každý krok a eval izolovaně, než se přesvědčíte, že na požadovaných vstupech dělá, co má.

Spusť skript v aktuálním shellu – source, tečka

Už dříve jsme vyráběli jednoduché skripty. Ty se spouštěly v samostatném procesu (tj. ekvivalent „/bin/bash nazev_skriptu“), takže nemohly např. nastavit adresář nebo proměnné prostředí tak, aby nastavení zůstalo platné pro náš shell. Pak jsme zmínili aliasy jako prostředek pro spuštění předpřipravené konstrukce v aktuálním shellu.

Kombinaci obojího představuje spuštění skriptu v aktuálním shellu, tzv. sourcnutí. Provedeme jej pomocí příkazu „source“, který se pro zpestření a z historických důvodů dá zkráceně také zapsat jako „.“ (tečka). Nejspíš proto, aby se vám v manuálových stránkách hůře hledalo, co ta tečka dělá…

source muj_skript
# stejně jako
. muj_skript
# spustí muj_skript přímo v aktuálním shellu

Kdy sourcování potřebujete? Kdykoli má skript ovlivnit vaše aktuální prostředí. (Nastavení adresáře, proměnných, aliasů… V tomto smyslu je např. ~/.bashrc také „sourcován“.) Jaká jsou rizika? Velká, sourcnutý skript může omylem poničit vaše (exportované i neexportované) proměnné, zanechat vás v adresáři, se kterým nepočítáte, nebo vám rovnou uzavřít spojení! (Rozhodně neradím napsat „exit“ do vašeho .bashrc.)

Jsem spuštěn, nebo sourcnut?

Právě konfigurační skripty, kterými si má uživatel nastavit nějaké proměnné ve svém prostředí ap., potřebují nutně, aby byly načteny přímo aktuálním bashem, nikoli spuštěny. Vhodné je uživatele o této časté chybě informovat. O detekci se postará následující magická formulka:

if [ -z $BASH_ARGV ]; then
    cat >&2 <<-KONEC
    Tento inicializační skript musíte pro správný běh spustit takto:
      . $0
    tj. v aktuálním shellu a nikoli jako samostatný proces.
    KONEC
    # pozor na to, aby před slovem KONEC byly jen tabulátory, ne mezery
    exit 1
fi

Generuj-kopíruj-vlož

Dnešní celkem stručný díl uzavřu svým oblíbeným tipem pro spouštění mnoha příkazů s různými argumenty najednou. Program xargs v našem seriálu určitě spatříte. Je dobrý, když jste si jisti a chcete všechny příkazy hned spustit (nebo ručně každý potvrzovat, použijete-li „ xargs -p“). Občas se ale hodí hromadu příkazů automaticky připravit a pak spouštět víceméně naráz, jen s lehkou optickou kontrolou, jestli nedělají blbosti, nebo s lehkými pauzami, aby se nějaký systém nezahltil.

V takovém případě často vyrobím např. jednoduchý for-cyklus, který zamýšlené příkazy vypíše na konzoli. Prohlédnu si je a zkusím první zkopírovat a hned vložit, čímž se příkaz spustí. Pokud jsem s výsledkem spokojen, zkopíruju dalších pár příkazů a zas je vložím (možná do jiné konzole, aby mi tahle neodrolovávala). A když vidím, že systém dávku vstřebal, vezmu další.

Když je příkazů prostě moc na ruční copy-paste přes konzoli, použiju generovací for cyklus, ale přesměruji jej do souboru:

(for args in ...; do echo cmd $args; done) > rychloskript.sh

Rychloskript si pak prohlédnu, případně tu a tam vložím „ sleep 5“, aby se prostředí mohlo vzpamatovat, a nakonec spustím „ sh rychloskript.sh“ nebo „ source rychloskript.sh“, podle toho, co potřebuji.

Ohodnoťte jako ve škole:

Průměrná známka 2,93

Našli jste v článku chybu?
Zasílat nově přidané názory e-mailem
Lupa.cz: Zaplatíme ti, když ti seženeme práci

Zaplatíme ti, když ti seženeme práci

Vitalia.cz: Tři sta kilogramů tuňáka obsahovalo histamin

Tři sta kilogramů tuňáka obsahovalo histamin

120na80.cz: Tady se vaří padělané léky

Tady se vaří padělané léky

Podnikatel.cz: Miliony hodin nad hlášením k DPH. K vzteku

Miliony hodin nad hlášením k DPH. K vzteku

Vitalia.cz: Syndrom počítačového vidění: stačí dvě hodiny denně

Syndrom počítačového vidění: stačí dvě hodiny denně

Lupa.cz: Přenos hokeje padal kvůli útoku, tvrdí O2

Přenos hokeje padal kvůli útoku, tvrdí O2

DigiZone.cz: Šlágr TV: pokuta 100 tisíc za on-line

Šlágr TV: pokuta 100 tisíc za on-line

Podnikatel.cz: Přechod z OSVČ na firmu? Totální šok!

Přechod z OSVČ na firmu? Totální šok!

Vitalia.cz: Taky ji kupujete? Je šizená

Taky ji kupujete? Je šizená

120na80.cz: Jak si udržet zdravou vaginu

Jak si udržet zdravou vaginu

Vitalia.cz: 7 nemocí očí, které musíte léčit včas

7 nemocí očí, které musíte léčit včas

Podnikatel.cz: Když už je sexy, tak ať taky funguje

Když už je sexy, tak ať taky funguje

DigiZone.cz: Konec geoblokace online médií?

Konec geoblokace online médií?

Vitalia.cz: Před, nebo po snídani? Kdy je lepší čistit si zuby

Před, nebo po snídani? Kdy je lepší čistit si zuby

DigiZone.cz: Mafra varuje před stíháním za pomluvu

Mafra varuje před stíháním za pomluvu

120na80.cz: Co jí dělá? Sklerotizaci

Co jí dělá? Sklerotizaci

Vitalia.cz: Proč máme prasklý chléb nejraději?

Proč máme prasklý chléb nejraději?

Vitalia.cz: Sója a rakovina

Sója a rakovina

Podnikatel.cz: Alza radí e-shopům, jak opustit Heureku

Alza radí e-shopům, jak opustit Heureku

Podnikatel.cz: Různé podoby lahve Coca–Coly. Úchvatné

Různé podoby lahve Coca–Coly. Úchvatné