Dnes se mi stala zlá, nepěkný věc. V linuxovém terminálu (bash shell), připojeném k serveru přes SSH, běžela úloha, která měla být zpočátku rychle dokončena. Jak tomu ale nezřídka bývá, z původně plánovaných pěti minut se rázem stala hodina, dvě, … Ať už z důvodu možného přerušení spojení či potřeby odpojení a odnesení terminálu je v takovém případě potřeba zajistit úspěšné proběhnutí všech procedur. Pokud s takovým scénářem počítám, používám léty ověřený manažer
screen
, po jehož ne/násilném odpojení zůstanou zjednodušeně aktivní úlohy spuštěny na pozadí. Co ale v případě, že takový program není k dispozici nebo jej nespustíme?
Lidé pohybující se v příkazovém řádku operačních systémů unixového typu pravděpodobně dobře znají základní skupinu příkazů umožňující práci s aktivními úlohami běžícími v aktuální relaci.
Základní příkazy pro práci s úlohami/procesy
jobs
– zobrazení seznamu aktivních úloh
ps
– zobrazení seznamu aktivních procesů
bg
– spuštění úlohy na pozadí
fg
– spuštění úlohy v popředí
kill
– ukončení běžící úlohy
Tyto příkazy (kromě ps
a kill
) lze ale použít pouze pro práci s úlohami v rámci relace, ve které se nacházíme. Při jejím ukončení dojde k ukončení i všech aktivních úloh, které běží jak na pozadí, tak v popředí.
Jak ale zabezpečit, aby byly aktivní úlohy spuštění i po ukončení relace?
V takovém případě můžeme využít právě manažer screen
, jemu podobné, nebo odpojit úlohu od aktuální relace (terminálu).
Odpojení úlohy od aktuální relace
Pokud chceme pouze odpojit příslušný proces od procesu aktivního terminálu, můžeme ve shellu bash
použít příkaz disown
. Ten slouží k odstranění úlohy ze seznamu úloh aktuální relace. Tzn., při jejím ukončení zůstane tato úloha dále aktivní a nebude ukončena.
Jak je možné vidět na příkladu, úloha (proces 1220) je ze seznamu úloh aktuální relace opravdu odstraněna, zůstává ale připojena pod rodičovským procesem (proces 1043). Pravděpodobně se však nepovede tímto způsobem odpojit úlohu programu typu Midnight Commander (mc).
Po ukončení aktuální relace je tento proces odpojen a zůstává v systému samostatný, bez rodičovského procesu a připojené terminálové relace (místo „pts/5“ je ve výpisu „?“).
Nevýhodou je, že tento proces nelze jednoduše opětovně připojit do jiné relace. Pokud je například průběžně vypisován stav na standardní nebo chybový výstup, zůstane nám skryt.
Pokud trváme na nutnosti zachovat tyto výstupy, můžeme použít např. GDB a procesu vnutit jejich přesměrování:
Připojení úlohy do jiné relace
Pokud, jak bylo v úvodu popsáno, potřebujeme běžící úlohu „přemístit“ pod screen
, můžeme použít program reptyr
. Pokud jej spustíme v jiné relaci, než ve které běží úloha našeho zájmu, provede odpojení této úlohy od rodičovského procesu a pomocí systémového volání ptrace
se na tuto úlohu napojí. Je nutné brát v úvahu, že toto systémové volání má určitou režii a operační systém zatěžuje.
Zdrojová relace:
Cílová relace, jako argument slouží číslo procesu úlohy PID (viz předchozí výpis „ps“):
Použití systémového volání ptrace
může být na některých systémech GNU/Linux, např. Ubuntu, z bezpečnostních důvodů zakázáno. Pokud jej tedy chceme využít, musíme jej povolit. (pomůže Google + „/proc/sys/kernel/yama/ptrace_scope“).
Reptyr není samozřejmě jediným svého druhu, ale rozhodně dokáže pomoci v neočekávaných situacích. Jen je potřeba brát v úvahu vlastníky jednotlivých procesů. Nelze tedy přebírat úlohy jiného uživatele.
Další
Před spuštěním dlouhotrvajícího programu můžeme použít kupříkladu známý příkaz nohup
:
Zde je vidět přesměrování výstupů do souborů. Příklad s dd
není příliš vhodným, ale pro názornost stačí.