Přesunutí aktivní úlohy v GNU/Linux pod jiný terminál

Linux - terminalDnes 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ě pskill) 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čí.

Leave a Reply