Jak spouštět a ovládat procesy na pozadí v Linuxu

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čí.