Spouštění úloh na pozadí

Úlohy v shellu

Nejjednodušším způsobem, jak spustit z povelové řádky úlohu na pozadí, je využítí úloh (jobs) v shellu. I když úlohy na pozadí podporují i jiné shelly, zde si popíšeme pouze nejpoužívanější linuxový shell - bash.

Úlohu odešleme na pozadí kombinací kláves CTRL-Z. Úloha odeslaná na pozadí tímto způsobem je pozastavená, takže chceme-li ji pustit, musíme použít příkaz bg.

$ sleep 100
^Z
[1]+  Pozastaven              sleep 100
$ bg
[1]+ sleep 100 &
$ 
[1]+  Dokonán                sleep 100

Mimo příkaz bg, kterým spustíme úlohu pozastavenou na pozadí, můžeme svůj spuštěný program příkazem fg z pozadí vylovit a poslat opět na povelovou řádku, do popředí:

$ sleep 100
^Z
$ fg
sleep 100
$

Úlohu lze odeslat na pozadí i přímo, bez nutnosti mačkat kombinaci CTRL-Z, uvedením znaku & (ampersand) na konci řádku s příkazem. S takto spuštěnou úlohou lze pracovat pomocí příkazů fg, bg a CTRL-Z, jak jsme si popsali v odstavcích výše:

$ sleep 100
[1] 26579
$ fg
sleep 100
^Z
[1]+  Pozastaven              sleep 100
$ bg
[1]+ sleep 100 &
$ 
[1]+  Dokonán                sleep 100

Úloh lze na pozadí spustit libovolné množství. Protože už dvě úlohy jsou dost na to, aby uživatel ztratil o úlohách na pozadí přehled, nabízí shell příkaz jobs. Tímto příkazem vypíšete všechny úlohy na pozadí:

$ sleep 100 &
[1] 26804
$ sleep 200 &
[2] 26806
$ jobs
[1]-  Běží                 sleep 100 &
[2]+  Běží                 sleep 200 &

Povšimněte si čísla v hranaté závorce na začátku řádku - jde o číslo úlohy v shellu (liší se od PID, čísla procesu v systému, zde 26804 a 26806). Číslo úlohy v shellu usnadňuje práci s úlohami na pozadí pomocí příkazů fg, bg a kill. U těchto tří příkazů lze uvést jako parametr číslo úlohy uvezené znakem % (procento):

$ sleep 100 &
[1] 26924
$ sleep 200 &
[2] 26926
$ fg %1
sleep 100
^Z
[1]+  Pozastaven              sleep 100
$ kill %1
[1]-  Ukončen (SIGTERM)      sleep 100

U výpisu spuštěných úloh si můžete povšimnout znaků + (plus) a - (minus):

[2]   Běží                 sleep 100 &
[3]-  Běží                 sleep 200 &
[4]+  Běží                 sleep 300 &

Aktuální úloha je označená znakem + (plus). Příkazy fg a bg použité bez parametrů budou pracovat právě s touto úlohou. Pro úlohy lze použít i identifikátory %% (aktuální úloha) %+ (aktuální úloha) a %- (předchozí úloha):

kill %%
[4]+  Ukončen (SIGTERM)      sleep 300

nohup

Spustíte-li na pozadí podle předchozí části článku například překlad rozsáhlého projektu a odhlásíte se, po návratu k počítači budete nepříjemně překvapení - vaše úlohy na pozadí byly ukončené signálem SIGHUP zároveň s odhlášením (ukončením shellu). Abyste se této situaci vyhnuli, můžete použít příkaz nohup. Sám od sebe tento příkaz nespouští úlohy na pozadí, musíte uvést znak & za příkazem nebo použít kombinaci CTRL-Z a úlohu na pozadí rozběhnout příkazem bg:

$ nohup sleep 200 &
[1] 27701
nohup: vstup ignoruji a výstup připojuji k „nohup.out“
$
# po odhlášení a přihlášení:
$ ps xa | grep sleep
28045 ?        S      0:00 sleep 100

Příkaz nohup přesměruje standardní výstup a standardní chybový výstup programu do souboru nohup.out v aktuálním adresáři. Nelze-li do aktuálního adresáře zapisovat, pokusí se nohup vytvořit soubor nohup.out v domácím adresáři uživatele. Nepodaří-li se vytvořit ani zde, nebude příkaz proveden.

disown

Spuštění úlohy na pozadí tak, aby přežila i odhlášení, lze dosáhnout i příkazem disown. Chování tohoto příkazu se však od příkazu nohup liší. Příkaz nohup odchytí signál SIGHUP odesílaný shellem a přesměruje výstup programu. Příkazem disown naproti tomu informujete shell, že uvedenemu programu se nemá při ukončení shellu signál SIGHUP posílat. O výstupy programu při odhlášení příjdete. Na druhou stranu lze příkazem disown odeslat na pozadí i program, u kterého jsme to předem neplánovali. Jako parametr lze příkazu disown poslat UID procesu, případně číslo úlohy v shellu (uvozené procentem):

$ sleep 100 &
[1] 28150
$ disown %1
# po odhlášení a přihlášení:
$ ps xa | grep sleep
28150 ?        S      0:00 sleep 100

screen

Všechny výše uvedené způsoby spouštění úloh na pozadí mají několik nevýhod. Zásadní nevýhodou je, že výstup z programu je neustále přesměrovaný na výstup. Pustíte-li si na pozadí překlad většího projektu, je použitá povelová řádka pro další interaktivní práci prakticky nepoužitelná, protože se vám na ni bude vypisovat průběh překladu. Můžete sice použít příkaz nohup a výstup přesměrovat do souboru, ale takto zase přijdete o možnost překlad dále jakkoliv ovlivnit (vstup se ignoruje). Pro úlohy, které jsou alespoń částečně interaktivní, postrádá výše popsaný způsob spouštění na pozadí přijatelný komfort.

Omezení a nevýhody uvedených postupů odstraňuje příkaz screen. Správa úloh v programu screen je zcela odlišná od úloh v shellu. Program screen vytváří několik instancí shellu (a obrazovek), mezi kterými lze libovolně přepínat. V každém shellu lze samozřejmě spouštět další úlohy na pozadí s použitím shellu. Nastartoval lze i další screen, ale vhodnější je vytvoření další obrazovky.

$ screen
$ sleep 100
^AD
[detached]
$ screen -r
$ sleep 100

Příkaz screen se ovládá pomocí přepínačů a zkratek. Pro nejjednodušší použítí stačí znát jen několik základních postupů:

screen Vytvoření nové nezávislé obrazovky.
CTRL-A D Odpojení od obrazovky
CTRL-A C Vytvoření nové obrazovky v nastartovaném programu screen (musíte být připojení)
CTRL-A N Přepnutí na další obrazovku v pořadí
CTRL-A P Přepnutí na předchozí obrazovku v pořadí
CTRL-D Ukončení aktuální obrazovky. Ve skutečnosti jde o příkaz shellu, obrazovka se ukončí, jakmile je ukončen program v ní spuštěný (obvykle právě shell).
screen -r Připojení ke screenu. Zde může běžet libovolný počet obrazovek.
screen -r 12345 Připojení ke screenu s uvedeným PID. Screenů můžete mít nastartovaných více.
screen -D -R Připojení ke screenu a to i v případě, že je screen připojený už někam jinam (druhá obrazovka se odpojí). Užitečné, pokud v práci spustíte překlad, zapomenete se odpojit, a doma se chcete podívat na průběh překladu.
screen -wipe Vyčištění seznam screenů od nefunkčních instancí.

Možnosti programu screen jsou mnohem širší. Podrobnosti najdete v manuálové stránce.