Unix - kolik jsme toho zapomněli? (2) Kontrola a přizpůsobení proměnných prostředí Unixové příkazové interpretery spolupracují s proměnnými, které používají buďto jednotlivé příkazové interpretery, nebo odpovídající programy či instrukce. Výhod proměnných, které jsou pro interpretery definovány, využívá i samotný interpreter (shell). Jestliže se přihlásíte do systému typu Unix (tj. i Linux), potom soubor /etc/passwd obsahuje název příkazového interpreteru, který je uživateli implicitně přiřazen. Tento název je uložen jako poslední pole řádku uživatele v tomto souboru. Aktuální nastavení můžete zkontrolovat výpisem cat /etc/passwd a přesměrováním získaného výstupu do programu grep, který umožní vyhledat uživatelský identifikátor, tzv. userid. V následujícím příkladu je jako userid použito slovo procházka. $ cat /etc/passwd | grep -w prochazka Získáte například výstup, který je obdobou následujícího: prochazka:x:500:500:Prochazka Na Moste:/home/prochazka:/bin/ksh Vidíme, že uživateli je přiřazen příkazový interpreter Korn shell neboli ksh. Tento příkazový interpreter čte a umí inicializovat a spustit jakýkoliv soubor s názvem /etc/profile, který systémový administrátor naprogramoval pro inicializaci základních nastavovacích akcí, jež jsou potřebné v průběhu přihlašování pro každého jednotlivého uživatele. Jestliže tedy spustíte /etc/profile, spustíte vlastně $HOME/.profile, který je nastaven tak, aby obsahoval prostředí uživatele. Soubory /etc/profile i $HOME/.profile definují proměnné prostředí. Příkazový interpreter typu Bourne pracuje podobným způsobem. Příkazový interpreter C se chová analogicky, s tím rozdílem, že používá více souborů. Zpracovává /etc/csh.cshrc, potom /etc/csh.login a nakonec kolekci souborů, které jsou uloženy v domovském adresáři uživatele, ~/.cshrc, ~/.history, ~/.login a ~/.cshdirs. Bez ohledu na způsob inicializace je výsledkem definované uživatelské prostředí, tj. včetně proměnných prostředí. Stav prostředí (tzv. environment) můžete vizuálně zkontrolovat zadáním instrukce printenv nebo env. Následující zkrácený příklad je možným obrazem výstupu programu printenv: $ printenv USERNAME= HISTSIZE=1000 HOSTNAME=my.system.com LOGNAME=prochazka MAIL=/var/spool/mail/prochazka TERM=xterm PATH=.... HOME=/home/prochazka SHELL=/bin/ksh PS1=[\u@\h \W]\$ . . . LC_ALL=en_US Poznámka: Příkazový interpreter používá také proměnné, které nejsou přímou součástí prostředí. Rozdíly mezi proměnnými příkazového interpreteru a proměnnými prostředí byly uvedeny v první části článku. Proměnná PS1, která je uvedena v předcházejícím příkladu prostředí, tj. jako proměnná prostředí, je vlastně první výzva příkazového řádku (prompt). Určuje tedy, co bude zobrazováno na standardní výstupní konzole uživatele v okamžiku, kdy příkazový interpreter očekává zadání nové instrukce. Analogická proměnná příkazového interpreteru, tzv. druhá výzva PS2, obsahuje parametry, které jsou použity, když je instrukce zadávána a není dokončena, tedy ještě před konečným zadáním párového oddělovače a stiskem klávesy Enter, který předá instrukci ke zpracování. Funkci obou výzev příkazového řádku zkontrolujete pomocí návodu, který je uveden dále. První řádek zobrazuje kontrolní výstup $PS2, kdy se na monitoru po zadání instrukce echo $PS2 objeví znak ">". Zadávání nové instrukce začíná otevírací závorkou. Jestliže uživatel v tomto okamžiku stiskne klávesu Enter, příkazový interpreter očekává pokračování instrukce nebo zadání uzavírací závorky. O tomto stavu informuje uživatele znakem ">". Instrukce je zadána, je stisknuta klávesa Enter, ale protože interpreter očekává znak ")", opět zobrazí prompt ">". Konečně když uživatel zadá ")", tj. druhý párový oddělovač, a stiskne Enter, instrukce bude ukončena a předána ke zpracování. $echo $PS2 > $ ( > cat /etc/passwd | grep prochazka > ) $ Uživatel si může přizpůsobit grafickou podobu této funkce úpravou hodnoty a změnou stavu proměnné $PS2. V následujícím příkladu je změněna hodnota výzvy příkazového řádku $PS2 a zadávané instrukce stejné jako v předcházející ukázce. Nakonec je stav $PS2 vrácen na původní hodnotu definovanou prostředím. $ echo $PS2 > $ PS2="pokračujte v zadavani > " $ ( pokračujte v zadavani > cat /etc/passwd | grep prochazka pokračujte v zadavani > ) $ PS2="> " #echo $PS2 > $ Nabízí se otázka, proč výzva řádku určená PS2 obsahuje hodnotu a přitom není uvedena mezi proměnnými prostředí? Pozorně zkontrolujte obsah výstupu instrukce printenv - a skutečně, pro PS2 nespatříte žádnou definovanou proměnnou. Příkazový interpreter definuje obvykle sám o sobě několik implicitních proměnných, PS2 je jednou z nich. Ostatní užitečné proměnné interpreteru, které jsou nastaveny a používány v interpreteru typu Korn, jsou následující: _ (podtržítko) - Jestliže příkazový interpreter provádí externí instrukci, je tato proměnná nastavena v prostředí nového procesu do cesty (path) prováděné instrukce. V interaktivním režimu je tento parametr také nastaven v rodičovském příkazovém interpreteru jako poslední slovo předcházející instrukce. COLUMNS - Počet sloupců terminálu nebo okna. ENV - Jestliže je tento parametr definován, bude nastaven po zpracování libovolného souboru uživatelského profilu, expandovaná hodnota je použita jako startovací soubor interpreteru. Obvykle obsahuje funkci a alias definici. ERRNO - Celočíselná hodnota proměnné příkazového interpreteru errno, která identifikuje příčinu poslední poruchy systému. HISTFILE - Název souboru, který systém používá pro ukládání historie. Když je tento soubor definován, je historie načítána z tohoto speciálního souboru. V případě vícenásobných aktivací příkazových interpreterů, které pracují na stejném stroji, dojde ke sdílení historie, jestliže jejich parametry HISTFILE ukazují na stejný soubor. Jestliže proměnná HISTFILE není určena, je historie implicitně ukládána do souboru $HOME/.sh_history. HISTSIZE - Počet instrukcí, které jsou normálně uloženy v souboru historie. Implicitní hodnota je 128. IFS - Vnitřní pole oddělovače polí (internal field separator), které je používáno v průběhu substituce a instrukcí čtení pro oddělení hodnot do jasně formulovaných a definovaných argumentů, obvykle je tato konstanta nastavena na hodnotu "mezera", "tabulátor" a "nový řádek". LINENO - Počet řádek funkce nebo skriptu příkazového interpreteru, který byl spuštěn. Tato proměnná je užitečná pro ladění skriptů příkazového interpreteru. Jednoduše v potřebných bodech skriptu vložíte instrukci echo $LINENO a následně byste měli být schopni určit vaši aktuální pozici ve skriptu. LINES - Určuje počet řádek na terminálu nebo okně. PPID - Určuje ID procesu rodiče příkazového interpreteru. Tato hodnota je přístupná pouze pro čtení (read-only). PATH - Středníkem oddělený seznam adresářů, které jsou prohledávány při vyhledávání instrukcí. PS1 - První výzva příkazového řádku interaktivního příkazového interpreteru. PS2 - Druhá výzva příkazového řádku. Implicitní hodnotou je ">". Je používána, jestliže je pro dokončení zadávání instrukce potřeba více vstupních řádků. PWD - Aktuální pracovní adresář. Nemusí být použit nebo jeho hodnota může být null (jestliže příkazový interpreter neví, kde se právě nachází). RANDOM - Jednoduchý generátor náhodných čísel. Kdykoliv je RANDOM použit, určí další číslo z řady náhodných čísel. Bod v řadě čísel může být nastaven přiřazením čísla proměnné RANDOM. REPLAY - Implicitní parametr pro čtení instrukce, nejsou-li žádné názvy specifikovány. SECONDS - Počet sekund od okamžiku spuštění příkazového interpreteru nebo (pokud byla určena hodnota parametru v podobě celého čísla) počet sekund od okamžiku nastavení plus hodnota, která byla nastavena. TMOUT - Je-li v případě interaktivního příkazového interpreteru proměnná nastavena na hodnotu kladného celého čísla, potom definuje maximální počet sekund, po který bude příkazový interpreter čekat na vstup po vytištění prvního řetězce příkazového řádku ($PS1). Je-li tato doba překročena, potom je příkazový interpreter spuštěn. TMPDIR - Definuje adresář, v němž jsou uloženy dočasné soubory příkazového interpreteru. Není-li tento parametr nastaven nebo neobsahuje-li absolutní cestu do adresáře, jsou dočasné soubory generovány v adresáři /tmp. Příkazový interpreter typu C používá proměnné, které jsou analogické nebo jsou obdobou uvedeného seznamu, ale s tím rozdílem, že jsou definovány názvy s malými písmeny, například prompt1, prompt2, path, home apod. Další zajímavé proměnné jsou lokální proměnné. Tyto proměnné jsou LC_ALL, LC_CTYPE, LC_COLLATE a LC_MESSAGES. LC_ALL překrývá hodnoty tří ostatních proměnných. Platí, že pokud LC_ALL není definována, lze nastavení ostatních proměnných definovat nezávisle. LC_ALL - Určuje, která lokální proměnná má být použita pro překrytí jakékoliv předcházející proměnné. LC_CTYPE - Určuje lokální proměnnou pro interpretaci sekvence bajtů. LC_COLLATE - Určuje "porovnávací" sekvenci, která má být použita pro třídění. LC_MESSAGES - Určuje jazyk, který má být použit ve zprávách. Proměnná LC_ALL může být použita pro změnu úředního jazyka systému. Zkuste následující sekvence instrukcí, abyste mohli pozorovat chování těchto akcí. Jazyk je nastaven na francouzštinu (fr) a instrukce grep je inicializována s nepovoleným parametrem -x. Chybová zpráva bude vypsána ve francouzštině. Potom je LC_ALL nastavena do španělštiny (es) a chybová zpráva je generována ve španělštině. Nakonec je LC_ALL nepoužita a chybové zprávy jsou prezentovány anglicky. $ export LC_ALL=fr $ grep -x Usage: grep [OPTION] ... PATRON [FICHIER]... Pour en savoir davantage, faites: 'grep -help' $ LC_ALL=es Modo de empoleo: grep [OPTION] ... PATRON [FICHERO]... Pruebe 'grep-help' para mas informacion $unset LC_ALL $ grep -x Usage: grep [OPTION] ... PATTERN [FILE] Try 'grep -help' for more information $ To je pro tentokrát vše - v příští, závěrečné části článku se budeme zabývat jednoduchými skripty. Luděk Chmela