Tento seriál se snaží seznámit především začínající uživatele s textovým prostředím operačního systému GNU (Linux), jehož předním představitelem je příkazový interpretr Bash. Dnešní díl se věnuje problematice řízení procesů, což znamená spouštění, přerušování a ukončování programů (textových i grafických) v prostředí Bash. Mezi jinými bude řeč i o populárním programu kill.
Našemu seriálu o práci s textovým interpretrem Bash se dostává prostoru ke třetímu pokračování. Minule jsme se seznámili s řízením procesů a úloh. Jen připomínám, že proces je jakákoli aplikace běžící právě v systému, kdežto úloha je proces spuštěný v konkrétním interpretru Bash.
V tomto dílu si předvedeme některé způsoby spouštění programů v Bashi. Je jich totiž více, než jen napsat jméno spustitelného souboru do příkazové řádky. Ukážeme si ale též možnosti, jak běžící procesy sledovat.
Jméno aplikace a cesta
Nejjednodušší způsob spouštění aplikací v Bashi již znáte. Je to prosté zapsání jména spouštěného programu a jeho odentrování. Pokud máme program schován v nějakém nesystémovém adresáři (co to znamená nesystémový, si popíšeme později), musíme zadat celou cestu. Celá cesta se skládá ze jmen všech adresářů od začátku adresářového stromu, tj. od adresáře /. Např. program mojehra uložený v adresáři hry, který je podadresářem adresáře /opt, bychom spustili zadáním příkazu /opt/hry/mojehra.
Tomuto zápisu se říká absolutní cesta. My však můžeme využít i cesty relativní, tj. popsat cestu k souboru nikoli od kořenového adresáře /, ale od místa, kde se právě nacházíme. Naše momentální umístění v adresářovém stromu můžeme tušit ze samotného promptu, ale nejspolehlivěji je zjistíme příkazem pwd. Dejme tomu, že stojíme v adresáři /opt a chceme spustit stejný program jako v předchozím odstavci. Potom nejkratší cestou je hry/mojehra.
Pro relativní cesty můžeme využívat také speciální názvy adresářů. Jedním z nich jsou dvě tečky (..), které značí nadřazený adresář. Dejme tomu, že stojíme právě v adresáři /home/kuba, ale chceme spustit soubor /home/public/editor. Potom stačí zadat ../public/editor. Všimněte si, že při zadávání relativní cesty nezadáváme na začátku znak /.
Druhým pseudoadresářem pro zadávání relativní cesty je tečka (.), která označuje aktuální adresář. Ptáte se, proč pojmenovávat aktuální adresář? Je to proto, že GNU (a Unix) pracuje trochu jinak než DOS. Když zadáme jméno spustitelného souboru v DOSu, ten se dívá, zda toto jméno existuje v aktuálním adresáři, a pokud ano, tak jej spustí.
Bash prohledává systémové adresáře, protože jsou to většinou ty, kam může instalovat programy jen správce a sníží se tak nebezpečí různých podvržených aplikací, trojských koní a podobných věcí.
Popišme si takové ohrožení bezpečnosti na jednoduchém příkladu. Pokud třeba v domovském adresáři nějakého uživatele napíšeme ls, spustí se ls nainstalovaný v systémovém adresáři /bin, a nikoli skript ls, který si do svého adresáře umístil škodolibý uživatel, aby pomocí něj mazal soubory jiných uživatelů, kteří jeho adresář navštívili a chtěli se v něm porozhlédnout.
Pokud ale přece jen z nějakého důvodu chceme úmyslně spustit program nebo skript ležící v aktuálním adresáři (např. když jsme před tím do příslušného adresáře přešli kupř. pomocí příkazu cd /opt/hry), stačí zadat ./mojehra a zmáčknout [Enter] nebo [Return].
Složené závorky
V praxi někdy nastávají situace, kdy potřebujeme, aby bylo více příkazů provedeno pospolu. Ukážeme si tedy, jak se v Bashi provádějí groupové orgie a že jejich výsledkem jsou děti. Další zářný příklad toho, že Bash a GNU jsou zcela v souladu s přírodou.
Když jsme chtěli na chvíli uspat shell, použili jsme k tomu v prvním díle příkaz sleep. Pokud bychom chtěli, aby se po skončení mikrospánku něco přihodilo, můžeme postavit na jeden řádek dva či více příkazů vedle sebe a oddělit je středníkem. Takže zadáním sleep 10; echo Budíček! získáme "Budíček", ale až po deseti sekundách.
A nyní si představte, že chceme tuto konstrukci spustit na pozadí. Řeknete si fajn, to je úkol pro ampersand. Správně, ale kam ho dát? Žeby sleep 10; echo Budíček! &? Chyba - tím pošleme na pozadí pouze echo, ale celý spánek (sleep) bude probíhat na popředí, tedy bránit nám využívat shell.
Pak tedy zůstává jen možnost sleep 10 & ; echo Budíček!. A zase chyba - ampersand může stát jen na konci příkazového řádku. Co teď? Je to jednoduché. Skupinu příkazů, které potřebujeme provést současně, uzavřeme do složených závorek. Ty pak můžeme klidně poslat na pozadí. Takže vítězem soutěže je { sleep 10; echo Budíček! ; } &
Provede přesně to, co jsme chtěli. Bude spát na pozadí a po probuzení vypíše text Budíček! Během spánku na pozadí můžeme s Bashem normálně pracovat. Důležitý v této syntaxi je středník před uzavírací závorkou. Doporučuji také kolem obou závorek nechávat mezery.
Ještě jsem dlužen vysvětlit to, jak se sdružováním příkazů souvisejí děti. Nechám si to ale na kapitolu Sledování procesů. Zatím se spokojme s tím, že příkazy uvedené ve složených závorkách se spouštějí v aktuálním shellu.
Exec
Příkaz exec (zkratka z anglického execute - provést, vykonat) prostě provede za ním následující příkaz. Říkáte si, že je to zbytečnost? Byla by - nebýt toho, že se takto spuštěný příkaz chová trochu jinak, než příkaz zadaný bez exec.
Exec je zřejmě nástroj z dob nedostatku operační paměti. Příkaz jím spuštěný totiž v paměti nahradí rodičovský shell. A už tu máme rodinnou ságu. Skutečně - v GNU se vztahy mezi procesy přiměřují ke vztahům rodovým. Setkáváme se tak s rodiči. Jimi spuštěné procesy jsou děti. Ty mohou mít další potomky, atd.
Proces spuštěný pomocí exec bychom ve světle zmíněného mohli označit za pohrobka. Rodič totiž během porodu (resp. těsně před ním) umírá - obětuje své místo v paměti pro své dítě. Tato situace může budit dojem dobrého skutku, ale má i svá úskalí.
Unixové procesy udržují rodinné vztahy. Někdo se narodí, někdo umře.
Pokud shell ukončí před spuštěním procesu svou činnost, nemá se systém kam vrátit, až nový proces dokončí svůj úkol. Ve virtuální konzoli to vede k odhlášení, v emulátoru terminálu k zavření okna nebo záložky. Na to je třeba pamatovat.
Sledování procesů
Už minule jsme se dívali pod pokličku našeho systému, když jsme si vypisovali různé seznamy běžících procesů. Používali jsme k tomu ovšem jen jednoduché nástroje ps a jobs. Dnes si v této oblasti ukážeme sofistikovanější programy, které dovedou např. řadit procesy dle různých veličin nebo zobrazit příbuzenské vazby mezi procesy.
Pokud v systému nastanou problémy, je nutné najít viníka - většinou nějakou spuštěnou aplikaci. K tomu nám dopomůže nástroj top. Je to interaktivní textový program, tzn. že po spuštění reaguje na určité klávesy. Jeho úlohou je zobrazovat seznam běžících procesů seřazených dle určité charakteristiky.
Zkusme si prostě spustit top. Uvidíme záhlaví s aktuálním časem a údaji o systému. Pod ním je tabulka procesů uvozená inverzním záhlavím. Tabulka se každých pět sekund aktualizuje. Chod programu můžeme ovlivnit mj. těmito klávesami:
[Shift+n] - třídění procesů podle PID;
[Shift+a] - třídění procesů podle PID od konce;
[Shift+p] - třídění procesů podle zatížení CPU (odhalení zaseknutých procesů);
[Shift+m] - třídění procesů podle objemu zabrané paměti (odhalení viníků swapování);
[Shift+t] - třídění procesů podle spotřebovaného strojového času (odhalení procesů nejvíce zatěžujících systém);
[Shift+a] - třídění procesů podle PID od konce;
[m] - zapnutí nebo vypnutí informací o paměti;
[t] - zapnutí nebo vypnutí souhrnných informací o systému;
[h] - nápověda;
[q] - ukončení programu.
Po zjištění viníka svých problémů nemusíme top opouštět. Po stisknutí [k] budeme vyzváni k zadání PID, kterému chceme poslat signál (v rétorice minulého dílu by to byl onen pověstný balíček). Po odentrování správného PID nám bude nabídnuto zadání signálu. Nezadáme-li žádný, bude odeslán SIGTERM (15).
Kernel - jádro systému Linux, které je po startu počítače aktivováno. Je nastaveno tak, aby jako první spustilo proces init. Mnoho obslužných programů (včetně programu init, který napsal Miquel van Smoorenburg) je z projektu GNU, proto Linux jako takový se někdy označuje jako GNU/Linux - jádro a sada programů. V LinuxEXPRESu však z praktických důvodů užíváme kratší variantu.
pstree
Minule jsme si předvedli prográmek ps, který vypisuje seznam běžících procesů. Umí to na mnoho různých způsobů. Nás dnes bude zajímat ten, kde se vyskytuje sloupeček PPID, tedy např. ps ajx.
Takto získaná tabulka nám ve druhém sloupci ukazuje PID - identifikační číslo procesu. První sloupeček představuje PPID - PID rodičovského procesu. Kupř. na posledním řádku bychom měli vidět námi spuštěný ps ajx. Má své PID a podle PPID najdeme proces, kterým jsme jej spustili, tedy aktuální shell.
Podle PID a PPID můžeme sestavovat celé rodokmeny, jež by nás zavedly až k jednomu jedinému místu - číslu 1 (kdyby to byla nula, nabízelo by se "One ring to rule them all"). Tento praotec proces je init - první program spouštěný kernelem, který má na starosti spuštění systému. Automaticky také adoptuje sirotky - procesy, jejichž rodiče "zemřeli".
Láká vás představa znázornit si tuto strukturu graficky? Pokud se spokojíte s pseudografikou terminálu, je tu pro vás pstree, tedy něco jako stromečkový ps. Lze jej spustit bez parametrů, aby vykreslil standardní podobu stromu. Pomocí přepínačů můžeme tuto podobu změnit. Výběr některých zajímavých je k dispozici v následujícím seznamu:
pstree -a - zobrazení argumentů, s nimiž byly procesy spuštěny;
pstree -c - zabrání shlukování stejných procesů, tj. vypíšou se i ty, které se několikrát za sebou opakují;
pstree -G - na terminálech VT100 bude pro vykreslování čar používat hezčí znaky;
pstree -n - seřadí procesy podle PID (číselně), a ne podle jména;
pstree -p - za každým procesem zobrazí v závorce jeho PID.
kpm
Pokud vám seskupení znaků v textovém terminálu pro znázornění procesového stromečku nestačí, můžete v prostředí X Window využít služeb programu kpm. Spustit jej lze např. z emulátoru terminálu nebo pomocí funkce Spustit příkaz (tu vyvoláme též klávesovou zkratkou [Alt+F2]) prostým zadáním kpm a odentrováním.
Objeví se typické KDE okno nahoře s nabídkou. Největší část okna zabírá oblast se seznamem procesů. Dole pak najdeme stavovou lištu a několik ovládacích prvků. V seznamu vidíme mj. název procesu, jeho PID, kolik procent času uživatele a systému spotřebovává, kdo jej spustil a celou syntaxi spuštění.
Podle kteréhokoli pole můžeme seznam třídit tak, že na jeho název v záhlaví klikneme. Druhým kliknutím na nadpis provedeme seřazení v obráceném pořadí. Ptáte se, kde je slibovaný stromeček? Odkáži vás na zaškrtávací políčko vlevo dole s příznačným názvem Strom. Pokud jej zaškrtneme, seznam se přeskupí dle rodičovských vazeb procesů.
Dále mezi ovládacími prvky v dolní části okna najdeme roletku s filtrem pro vymezení skupiny zobrazených procesů. Tlačítko Obnovit, jak název napovídá, aktualizuje údaje v seznamu. Další tlačítko (Zabít) slouží k ukončování vybraných procesů. Jednotlivé položky seznamu totiž můžeme označovat levým tlačítkem myši. Ve stavové liště vidíme počet spuštěným procesů, volnou paměť a zaplněnost swapu (odkládacího oddílu).
Z dalších klávesových zkratek KDE bychom upozornili na [Alt+Ctrl+D], jež zobrazí plochu, [Alt+Ctrl+L] uzamkne stanici nebo [Alt+Ctrl+K] přepínající rozložení klávesnice.
Za povšimnutí stojí také magické čtyřkombinace pro rychlé odhlašování, restartování a vypínání počítače nebo pouhý stisk klávesy Print Screen (snímek obrazovky).
Závěr
Tak jsme zvládli probrat spouštění procesů a dokončit výklad o jejich kontrole a řízení. Problematice proměnných jsem se tentokrát úspěšně vyhnul, ale nebojte. Příště si to bohatě vynahradíme. Dozvíte se nejen, co to je, a jak se to používá. Ukážeme si i některé z nich, např. tu se jménem PATH (cesta).