Využijte prostředí Bash v Linuxu pro správu procesů běžících v popředí i na pozadí. K dispozici jsou funkce a signály pro řízení úloh, které vám umožní větší flexibilitu při spouštění příkazů. Ukážeme vám, jak na to.
Procesy v kostce
Když v operačním systému Linux nebo Unix spustíte program, zahájí se proces. Termín „proces“ označuje interní reprezentaci spuštěného programu v paměti počítače. Každý aktivní program má svůj proces. Prakticky vše, co běží ve vašem počítači, má přidělený proces. To se týká i komponent grafického desktopového prostředí, jako je GNOME nebo KDE, a systémových démonů, kteří se spouštějí při startu počítače.
Proč je proces spojen téměř se vším? Například vestavěné příkazy Bashe, jako cd, pwd a alias, nemusí vyvolávat samostatný proces, když je použijete. Bash tyto příkazy zpracovává přímo v rámci instance prostředí Bash běžící ve vašem terminálu. Tyto příkazy jsou rychlé, protože není nutné vytvářet samostatný proces. (V terminálu můžete zobrazit seznam vestavěných příkazů Bashe zadáním `help`).
Procesy mohou běžet v popředí, kde zcela ovládnou terminál až do svého dokončení, nebo na pozadí. Procesy na pozadí neblokují terminál a můžete s ním dále pracovat. Samozřejmě, neblokují terminál, pokud nevytvářejí výstup na obrazovku.
Praktický příklad
Začneme jednoduchým příkazem ping běžícím v trasování. Budeme pingat webovou stránku. To se spustí jako proces v popředí.
ping www.wdzwdz.com
Vidíme očekávané výsledky, které se posouvají v terminálovém okně. Dokud ping běží, nemůžeme v terminálu dělat nic jiného. Chcete-li příkaz ukončit, stiskněte Ctrl+C.
Ctrl+C
Efekt stisknutí Ctrl+C je zvýrazněn na obrázku. Příkaz ping krátce shrne svou činnost a skončí.
Zopakujme si to. Tentokrát ale místo Ctrl+C stiskneme Ctrl+Z. Úkol se neukončí, ale přesune se na pozadí a získáme zpět kontrolu nad terminálem.
ping www.wdzwdz.com
Ctrl+Z
Vidíme efekt stisknutí Ctrl+Z na obrázku.
Tentokrát nám systém oznámil, že proces byl zastaven. Zastavený proces neznamená ukončený. Je to jako auto na semaforu – není sešrotované, jen stojí a čeká. Proces je nyní úlohou na pozadí.
Příkaz `jobs` vypíše spuštěné úlohy v aktuální terminálové relaci. A protože úlohy jsou také procesy, můžeme je zobrazit příkazem `ps`. Použijeme oba příkazy a porovnáme jejich výstupy. S volbou `T` (terminál) vypíšeme pouze procesy běžící v tomto terminálovém okně. Všimněte si, že není nutné používat pomlčku s volbou `T`.
jobs
ps T
Příkaz `jobs` nám sděluje:
[1]: Číslo v hranatých závorkách je číslo úlohy. Můžeme na tuto úlohu odkazovat, když ji chceme ovládat příkazy pro řízení úloh.
+: Znaménko + ukazuje, že se jedná o výchozí úlohu, která se provede, pokud použijeme příkaz pro řízení úloh bez zadání konkrétního čísla úlohy. Výchozí úloha je vždy ta, která byla do seznamu přidána naposledy.
Zastaveno: Proces neběží.
ping www.wdzwdz.com: Příkazový řádek, kterým byl proces spuštěn.
Příkaz `ps` nám říká:
PID: ID procesu. Každý proces má jedinečné ID.
TTY: Terminál, ze kterého byl proces spuštěn.
STAT: Stav procesu.
ČAS: Čas strávený procesorem.
COMMAND: Příkaz, který proces spustil.
Běžné hodnoty sloupce STAT jsou:
D: Nepřerušitelný spánek. Proces čeká, obvykle na vstup nebo výstup, a nelze ho přerušit.
I: Nečinný.
R: Běží.
S: Přerušitelný spánek.
T: Zastaven signálem pro řízení úloh.
Z: Zombie proces. Proces skončil, ale nebyl „uklizen“ svým nadřazeným procesem.
Za hodnotou STAT mohou následovat další indikátory:
<: Úloha s vysokou prioritou.
Příkaz `ping` má stav `T`, což znamená, že byl zastaven signálem pro řízení úloh. V tomto případě stiskem Ctrl+Z, který ho přesunul na pozadí.
Příkaz `ps T` má stav `R`, což znamená, že běží a `+` indikuje, že je členem skupiny v popředí. Takže příkaz `ps T` běží v popředí.
Příkaz `bg`
Příkaz `bg` obnoví proces na pozadí. Může se použít s číslem úlohy nebo bez něj. Pokud jej použijeme bez čísla, obnoví se výchozí úloha. Proces běží dále na pozadí a nemůžeme do něj posílat žádný vstup.
Zadáme-li příkaz `bg`, obnovíme příkaz `ping`:
bg
Příkaz `ping` se obnoví a v okně terminálu uvidíme opět rolující výstup. Zobrazí se vám název příkazu, který byl obnoven, jak je vidět na obrázku.
Ale máme problém. Úloha běží na pozadí a nepřijímá žádný vstup. Jak ji tedy zastavíme? Ctrl+C nefunguje. Vidíme sice znaky, které píšeme, ale úloha na pozadí je nepřijímá, a tak vesele pingá dál.
Nyní jsme v podivném kombinovaném režimu. Můžeme psát v terminálovém okně, ale vše, co napíšeme, je rychle přepsáno rolujícím výstupem příkazu `ping`. Vše, co zadáme, je ale zároveň prováděno v popředí.
Abychom zastavili úlohu na pozadí, musíme ji přesunout do popředí a až pak ji můžeme ukončit.
Příkaz `fg`
Příkaz `fg` přesune úlohu z pozadí do popředí. Stejně jako příkaz `bg` ho můžeme použít s číslem úlohy nebo bez něj. Použitím s číslem úlohy bude pracovat s konkrétní úlohou. Pokud se použije bez čísla, použije se poslední příkaz, který byl odeslán na pozadí.
Napíšeme-li `fg`, dostane se náš příkaz `ping` do popředí. Znaky, které zadáváme, se smíchají s výstupem příkazu `ping`, ale shell je ovládá, jako by byly zadávány v příkazovém řádku. Z pohledu shellu Bash se přesně to stalo.
fg
A nyní, když máme příkaz `ping` opět spuštěný v popředí, můžeme ho ukončit pomocí Ctrl+C.
Ctrl+C
Důležitost správných signálů
Nebyl to zrovna elegantní postup. Je zřejmé, že proces na pozadí funguje nejlépe, když nevytváří výstup a nevyžaduje vstup.
Ale ať už byl náš příklad chaotický, docílili jsme:
- Přesunutí procesu na pozadí.
- Obnovení procesu na pozadí.
- Přesunutí procesu zpět do popředí.
- Ukončení procesu.
Při použití Ctrl+C a Ctrl+Z odesíláte do procesu signály. Jsou to zkrácené způsoby použití příkazu `kill`. Existuje 64 různých signálů, které může příkaz `kill` odeslat. Pro jejich zobrazení použijte `kill -l` v příkazovém řádku. Signály nemusí nutně pocházet jen od příkazu `kill`. Některé jsou spouštěny automaticky jinými procesy v systému.
Některé běžně používané signály:
SIGHUP: Signál 1. Automaticky se odesílá procesu, když se zavře terminál, ve kterém běží.
SIGINT: Signál 2. Odesílá se procesu po stisknutí Ctrl+C. Proces je přerušen a má se ukončit.
SIGQUIT: Signál 3. Odesílá se procesu, když uživatel pošle signál ukončení Ctrl+D.
SIGKILL: Signál 9. Proces je okamžitě ukončen bez možnosti čistého ukončení. Proces „padne“ bez elegance.
SIGTERM: Signál 15. Toto je výchozí signál vysílaný příkazem `kill`. Standardní signál pro ukončení programu.
SIGTSTP: Signál 20. Odesílá se procesu při použití Ctrl+Z. Zastaví proces a přesune ho na pozadí.
K odeslání signálů, které nemají přiřazenou klávesovou zkratku, musíme použít příkaz `kill`.
Další praktické příklady
Proces přesunutý na pozadí pomocí Ctrl+Z je zastaven. Ke spuštění znovu použijeme příkaz `bg`. Spuštění programu jako běžícího procesu na pozadí je jednoduché. Stačí připojit ampersand `&` na konec příkazového řádku.
I když je nejlepší, aby procesy na pozadí nezapisovaly do terminálu, my si pro demonstraci takový proces vyzkoušíme. Potřebujeme mít v ukázkách něco viditelného. Následující příkaz spustí nekonečnou smyčku jako proces na pozadí:
while true; do echo "How-To Geek Loop Process"; sleep 3; done &
Zobrazí se nám číslo úlohy a ID procesu. Číslo úlohy je 1 a ID procesu je 1979. Tyto identifikátory můžeme použít k řízení procesu.
Výstup naší nekonečné smyčky se začne objevovat v okně terminálu. Můžeme sice psát v příkazovém řádku, ale všechny příkazy jsou prokládány výstupem smyčky.
ls
K zastavení procesu můžeme použít příkaz `jobs`, abychom si připomněli číslo úlohy a pak použít `kill`.
Příkaz `jobs` nám hlásí, že náš proces je úloha číslo 1. Pro použití s příkazem `kill` musí předcházet znak procenta `%`.
jobs
kill %1
Příkaz `kill` odesílá procesu signál SIGTERM, signál číslo 15, a ten je ukončen. Po stisknutí klávesy Enter se zobrazí stav úlohy, který uvádí proces jako „ukončený“. Pokud proces nereaguje na příkaz `kill`, můžeme ukončení urychlit s použitím `kill` se signálem SIGKILL, což je signál číslo 9. Stačí vložit číslo 9 mezi příkaz `kill` a číslo úlohy.
kill 9 %1
Shrnutí
- Ctrl+C: Odesílá SIGINT, signál 2, do procesu – pokud přijímá vstup – a řekne mu, ať skončí.
- Ctrl+D: Odesílá SIGQUIT, signál 3, do procesu – pokud přijímá vstup – a řekne mu, ať skončí.
- Ctrl+Z: Odesílá SIGSTP, signál 20, do procesu a řekne mu, ať se zastaví (pozastaví) a stane se procesem na pozadí.
- jobs: Zobrazí seznam úloh na pozadí a ukáže jejich číslo.
- bg job_number: Restartuje proces na pozadí. Pokud nezadáte číslo úlohy, použije se poslední proces, který byl převeden na úlohu na pozadí.
- fg job_number: Přesune proces z pozadí do popředí a restartuje ho. Pokud nezadáte číslo úlohy, použije se poslední proces, který byl převeden na úlohu na pozadí.
- command &: Přidáním ampersandu `&` na konec příkazového řádku se tento příkaz spustí jako úloha na pozadí.
- kill %job_number: Vyšle SIGTERM, signál 15, do procesu, aby ho ukončil.
- kill 9 %job_number: Vyšle SIGKILL, signál 9, do procesu a náhle ho ukončí.