Linux: Kniha kouzel, vanilková příchuť 2.14 (15. července 2022)
Veškerá moc příkazové řádky/příkazového řádku přehledně, pro začátečníky i pokročilé
7. Metapříkazy
Řada 2.x vanilkové příchuti Linuxu: Knihy kouzel je od 15. července 2022
do 1. března 2025 ve stavu dlouhodobé pasivní údržby;
nahlášené chyby budou opravovány, ale aktivní vývoj se již věnuje jiným
projektům. Máte-li zájem pokračovat v tvorbě Linuxu: Knihy kouzel
pro novější verze linuxových operačních systémů,
kontaktujte autora nebo rovnou vytvořte odnož.
Předmětem této kapitoly jsou příkazy jako „sudo“ či „exec“,
které přijímají další příkaz i s jeho argumenty. Většina těchto příkazů
najde externí program toho názvu a spustí ho v nějakým způsobem pozměněném
prostředí, např. s právy superuživatele, s nižší prioritou nebo v jiném
adresáři. Některé metapříkazy je možno použít i s vestavěnými příkazy
Bashe.
Metapříkaz je příkaz, kterému lze smysluplně zadat jiný příkaz k vykonání.
Pseudometapříkaz je syntaktická konstrukce bashe podobná formou i účelem metapříkazům.
Kde je v zaklínadlech uvedeno příkaz a parametry, zadává se metapříkazu název vnořeného příkazu a každý jeho argument samostatně, např.:
sudo příkaz a parametry
sudo printf TEST\\n
Naopak kde je uvedeno "příkaz s parametry", zadává se celý příkazový řádek jako jeden argument (tento argument pak zpravidla bude interpretován interpretem „sh“):
Pozor na pořadí: Jsou-li pseudometapříkazy použity spolu s dalšími
metapříkazy, musejí být jako první! Navíc je u nich nutno dodržet
toto pořadí: „“, „time“, „!“ (může být i víckrát), „=“ (proměnné prostředí, může být i víckrát).
Zvláštnosti: Příkaz „“ (mezera) účinkuje na celý příkazový řádek,
i když obsahuje více příkazů. Příkazy „time“ a „!“ účinkují na celou
posloupnost příkazů spojených rourami.
Příkaz watch: d — zvýrazňovat změny oproti předchozímu běhu
(užitečný parametr); t - nepřidávat záhlaví.
Neuvedete-li parametr -n, výchozí interval jsou 2 sekundy.
Parametr -n přijímá i desetinná čísla (minimální dovolená hodnota je „0.1“).
Všechny použité příkazy jsou základními součástmi Ubuntu přítomnými i v minimální
instalaci; výjimkou jsou příkazy eatmydata, fakeroot a nocache, které je nutno doinstalovat:
Typickou začátečnickou chybou je očekávání, že „sudo“ bude účinkovat na přesměrování nebo substituované příkazy, např. „sudo echo "$(whoami)" >/root/test.txt“. V uvedeném příkazu proběhne jak příkaz „whoami“, tak přesměrování do souboru s právy aktuálního uživatele; práva superuživatele v tomto příkladu získá teprve až příkaz „echo“ (který je zrovna moc nepotřebuje).
Metapříkazy je možno řetězit, ale ne libovolně — záleží na tom, který příkaz je vestavěný a který externí. Třeba „sudo exec“ nefunguje vůbec a „exec sudo“ zase nezachová PID (protože původní PID obsadí proces „sudo“). Doporučuji s takovými možnostmi počítat a trochu experimentovat, než získáte dostatek znalostí a zkušeností, abyste dokázal/a posoudit, který příkaz se kterým a v jakém pořadí lze skombinovat a co to udělá.
Příkaz „xargs“ s parametrem „-n“ lze použít k rozdělení vstupu na n-tice a volání příkazu pro každou z nich. (Nebude-li počet vstupních záznamů beze zbytku dělitelný n, xargs sestaví poslední n-tici kratší.)
Příkaz „chroot“ pro nově spouštěný příkaz (a všechny jeho potomky) nastaví určitý adresář VFS jako kořenový. Příkaz se pak vyhledá v tomto podstromu a nebude z něj mít přímý přístup ven (dokonce i symbolické odkazy se mu budou vyhodnocovat podle nového kořenového adresáře). Aby to fungovalo, daný adresář musí obsahovat části systému, které program potřebuje ke svému spuštění a běhu. Správné použití příkazu „chroot“ je náročné na znalosti systému, proto doporučuji ho používat opatrně a raději si nejprve přečíst příslušný článek na ArchWiki.
V podstromu nového kořenového adresáře musí být nainstalovaná nějaká instalace linuxu (do které se chystáte vstoupit).
Spouštěný příkaz se musí v této instalaci nacházet a mít tam i knihovny, které ke svému běhu potřebuje, a všechno nastavení.
Spouštěný příkaz se spustí jako root, přepnutý do nového kořenového adresáře.
Instalace, do které vstupujete, nemusí být stejná distribuce a nemusí obsahovat funkční jádro, musí však být stejné architektury (z 64bitového systému prý nelze vstoupit do 32bitové instalace a naopak).
Příkaz tedy z instalace, do které vstupujete, používá:
Programy, které spouští.
Knihovny.
Systémová a uživatelská nastavení (/etc).
Naopak z hostujícího operačního systému používá vše ostatní, zejména:
Hlavním účelem prostředí „fakeroot“ je zdánlivě nastavit vlastnictví,
skupinu a mód souborů při jejich ukládání do archivu, a to i v případech,
kdy k jejich nastavení nemáte právo (popř. jsou na souborovém systému
jen pro čtení, např. na DVD). Příkaz „fakeroot“ vytvoří v paměti tabulku,
která k adresářovým položkám mapuje vlastnictví, skupinu a mód
(ACL není v tomto prostředí dostupné, uživatelské datové položky jsem
nezkoušel/a).
Následně „fakeroot“ pro spouštěný příkaz (a jeho potomky) přesměruje
účinky operací „chmod“, „chgrp“ a „chown“; každá operace je nejprve
provedena nad tabulkou v paměti a následně se ji program pokusí vykonat
i ve skutečnosti (přičemž nevadí, když selže). Odpovídající operace čtení
(např. příkazem „ls“, „stat“ či „getfacl“) budou uvnitř prostředí fakeroot
vidět údaje z virtualizované tabulky namísto skutečných.
Nepoužijete-li parametr „-u“, vlastnictví a skupina se v tabulce inicializují
u všech položek na „root“:„root“; mód se vždy inicializuje
na jeho skutečnou hodnotu.
Spuštěnému příkazu se jeví, jako by měl práva superuživatele
(např. „whoami“ vypíše „root“), ale ve skutečnosti je nemá (proto když
např. vytvoří nový soubor, jeho vlastníkem bude přihlášený uživatel,
nikoliv root), a namísto skutečného vlastnictví a módu vidí
údaje z virtualizované tabulky.
Uvnitř prostředí „fakeroot“ nelze použít příkazy „setfacl“
a „fakeroot“; příkaz „getfacl“ zde nedokáže přečíst rozšířená přístupová práva
(ale pravděpodobně to není záměr, takže se to v budoucích verzích může změnit).
Příkazy, u kterých spouštění (resp. podmíněné spouštění či nespouštění) programu není jejich hlavní činností (např. „find“ s parametrem „-exec“).
Příkazové interprety, interprety programovacích jazyků a emulátory terminálu; výjimkou jsou „sh“ a „bash“.
Příkazy úzce svázané s konkrétním programem, který není široce používaný (např. „docker exec“).
Syntaktické konstrukce bashe (jako např. „&“) s výjimkou několika málo tzv. pseudometapříkazů.
1 Poznámka: „sudo“ u příkazu „runuser“ je pouze symbolické; ve skutečnosti se nezadává, protože příkaz „runuser“ spouští pouze root (resp. skripty běžící pod účtem root) a sudo by zde bylo zbytečné.
2 Nový proces získá PID aktuálního interpretu a většinu jeho kontextu. Parametr „-c“ před vykonáním náhrady smaže všechny proměnné prostředí (dokonce i HOME, PATH apod., takže to možná není moc dobrý nápad).
3 Hlavní smysl tohoto metapříkazu spočívá v situacích, kdy má interpretace příkazu očekávané vedlejší účinky (např. nastavení zvláštní proměnné $_ nebo uložení do historie příkazů v interaktivním režimu interpretu).
4 Neuvedete-li parametr „-n“, použije „xargs“ v každé dávce co nejvíc parametrů, kolik mu umožní systémové limity. Neuvedete-li parametr „-P“, výchozí hodnota je 1, což znamená, že další dávka se spustí, teprve až ta předchozí doběhne. Parametr „-a“ použijte v případě, že vykonávaný příkaz potřebuje přístup ke standardnímu výstupu.
5 Obsah vstupního záznamu bude dosazen do parametrů vnořeného příkazu za všechny výskyty podřetězce nastaveného parametrem „-I“ (obvykle „{}“).
6 Výchozí signál je SIGTERM (tedy požadavek na ukončení). Zadáte-li parametr „-k“, pak se po zaslání signálu odpočítá ještě „trvání2“ a příkaz se ukončí signálem SIGKILL. Obě trvání jsou v sekundách. Signály se zašlou i potomkům, které příkaz mezitím spustí.
7 Potlačení účinku operace „sync“ tímto příkazem závisí na určitých proměnných prostředí, proto se rozšíří do všech procesů, které tyto proměnné zdědí.
8 Zvýšení/snížení se počítá relativně vůči prioritě interpretu, ve kterém je příkaz použit, a výsledek se omezí do intervalu 19 (nejnižší možná priorita) až -20 (nejvyšší možná priorita). Takže když zadáte „nice -n 10 bash“, dostanete interpret s prioritou „10“, a když v něm zadáte „nice -n 6 bash“, nový interpret bude mít prioritu 16. Když pak v něm zadáte ještě „nice -n 9 bash“, třetí interpret bude mít prioritu 19.
9 Primárním účelem je bránit čtením z souborů na disku, aby se ukládala do keše; nevím jistě, nakolik se lze spolehnout, že toto čtení nebude přistupovat k datům již v keši uloženým.
10 Při použití příkazu „nohup“ důrazně doporučuji ručně přesměrovat standardní vstup a oba standardní výstupy mimo terminál; pokud to neuděláte, příkaz „nohup“ to udělá za vás, ale vypíše přitom rušivou zprávu „nohup: vstup ignoruji a výstup připojuji k 'nohup.out'“. Ostatní deskriptory přesměrovávat nemusíte, ale pokud některý z nich povede na terminál, který mezitím zavřete, program pravděpodobně skončí s chybou, jakmile se z něj pokusí číst či do něj zapisovat.
11 Užitečnost tohoto příkazu je velmi nízká, protože bude účinkovat jen na programy, které si nastavení bufferování svých vstupů nemění samy, a ani u nich nemusí výsledky odpovídat očekávání. Raději se podívejte do dokumentace příslušného programu, zda nepodporuje nějaký způsob zapnutí „nebufferovaného režimu“.
12 Pozor! Příkaz musí být spuštěn na popředí; pokud jeho běh přerušíte zkratkou Ctrl+Z, příkaz „time“ vypíše naměřený údaj a dál už měřit nebude.
13 Mezera musí prvním znakem příkazové řádky vůbec (tzn. před ní nesmí být žádný další příkaz ani jiný znak), a aby tento způsob potlačení ukládání do historie fungoval, musí být proměnná HISTCONTROL nastavena na hodnotu „ignorespace“ nebo „ignoreboth“ (což je ve výchozím nastavení v Ubuntu v interaktivním režimu bashe splněno).
14 Do $? se uloží 1 pro nulový návratový kód a 0 pro nenulový. Tento příkaz nemá žádný vliv na pole PIPE_STATUS (tam zůstanou původní hodnoty). Tento příkaz ovlivní zřetězení operátory „&&“ a „||“, protože tyto operátory čtou proměnnou $?
Líbí se vám tento projekt a chcete, aby byl ještě lepší? Můžete mi s tím pomoci. Zmiňte se o něm technicky zdatným přátelům, opravte překlepy a nahlašte nefunkční zaklínadla, aby mohla být opravena; poskytněte mi zpětnou vazbu nebo se zapojte do vývoje nových kapitol. Další informace na GitHubu v dokumentu Jak se zapojit.