Tegyük fel, hogy felhasználók vagyunk egy rendszeren, ahol nincs screen utasítás, nincs a telepítésére jogosultságunk. Hosszan tartó dolgokat akarunk futtatni, amit nincs időnk kivárni és nem hagyhatjuk ott a gépet bejelentkezve egy másik rendszerbe, esetleg félünk hogy meg szakad a távoli kapcsolat és kezdhetjük a munkát előröl.

Utólag a háttérben (fg, bg, jobs)

Ebben az esetben a processz indítása után jövünk rá, hogy ezt inkább háttérben szeretnénk futtatni. Próba képpen indítsunk egy dd-t ami random adatokkal tölt fel egy 1GB-os image.img fájlt.

# dd if=/dev/urandom of=image.img bs=1k count=1000000

Láthatjuk, hogy ameddig a processz nem végez, addig nem kapjuk vissza a vezérlést. De ne várjuk ki a végét, hanem nyomjuk le a CTRL+Z billentyűt. Ez ideiglenesen megállítja a processzt. Ezek után a bg utasítással a háttérbe küldve folytatódik a processz futása.

# dd if=/dev/urandom of=image.img bs=1k count=1000000
^Z
[1]+  Megállítva            dd if=/dev/urandom of=image.img bs=1k count=1000000
# bg
[1]+ dd if=/dev/urandom of=image.img bs=1k count=1000000 &

Hogy megnézhessük a háttérben futó processzeinket, adjuk ki a jobs utasítást.

# jobs
[1]+  Fut                     dd if=/dev/urandom of=image.img bs=1k count=1000000 &

Ha előtérbe akarjuk hozni a háttérbe tett processzünket, akkor erre a fg parancsot használhatjuk.

# fg
dd if=/dev/urandom of=image.img bs=1k count=1000000

Az fg parancs, mindig az utoljára háttérbe tett processzt hozza előtérbe. Ha több is fut háttérben és nem az utolsót akarjuk előtérbe hozni, akkor a jobs sorszámával kiválaszthatjuk a megfelelőt.

# jobs
[1]-  Fut                     ping google.com > /dev/null &
[2]+  Fut                     dd if=/dev/urandom of=image.img bs=1k count=1000000 &
# fg %1
ping google.com > /dev/null

Ugyan ez érvényes a CTRL+Z-vel megállított processzek háttérbe tételére is.

# jobs
[1]-  Megállítva            ping google.com > /dev/null
[2]+  Megállítva            dd if=/dev/urandom of=image.img bs=1k count=1000000
# bg %1
[1]- ping google.com > /dev/null &
# jobs
[1]-  Fut                     ping google.com > /dev/null &
[2]+  Megállítva            dd if=/dev/urandom of=image.img bs=1k count=1000000

Háttérben indítás (&, nohup)

A másik lehetőség, hogy a processzt indításakor tesszük háttérbe. Erre a sorvégi & jelet használhatjuk.

# dd if=/dev/urandom of=image.img bs=1k count=1000000 &
[1] 13078
# jobs
[1]+  Fut                     dd if=/dev/urandom of=image.img bs=1k count=1000000 &

A háttérbe tett processz kezelése ugyanaz (fg, bg, jobs) mint az előzőekben. Ha a háttérbe tett processznek van stdout kimenete, akkor az bizony a terminálba fog ömleni, ha csak nem irányítjuk egy fájlba vagy a /dev/null-ba ha nincs rá szükség. Ha nohup utasítással indítunk egy processzt, akkor annak a kimenete - ha van - a nohup.out fájlba tárolódik, de ha az indítás helyére nincs írás jogunk, akkor a $HOME/nohup.out fájlba. Persze itt is a sor végét az & karakterrel zárjuk.

# pwd
/usr/bin
# nohup ping -c100 google.com &
[1] 13146
# nohup: bemenet figyelmen kívül hagyása és kimenet hozzáfűzése a következőhöz: ”/home/peter/nohup.out”
# jobs
[1]+  Fut                     nohup ping -c100 google.com &
# tail ~/nohup.out 
...
64 bytes from muc03s07-in-f4.1e100.net (173.194.44.4): icmp_seq=99 ttl=55 time=32.7 ms
64 bytes from muc03s07-in-f4.1e100.net (173.194.44.4): icmp_seq=100 ttl=55 time=32.6 ms

--- google.com ping statistics ---
100 packets transmitted, 100 received, 0% packet loss, time 99068ms
rtt min/avg/max/mdev = 32.212/33.133/37.348/0.960 ms

Láthatjuk, hogy a nohup.out fájl tartalmazza a ping parancs kimenetét. Ha le akarunk állítani egy háttérben futó processzt, akkor a kill parancsal könnyedén megtehetjük. Elég csak paraméterként megadni a jobs ID-t % után.

# jobs
[1]-  Fut                     dd if=/dev/urandom of=image.img bs=1k count=1000000 &
[2]+  Fut                     ping google.com > /dev/null &
# kill %1
# jobs
[1]-  Befejeződött          dd if=/dev/urandom of=image.img bs=1k count=1000000
[2]+  Fut                     ping google.com > /dev/null &
# jobs
[2]+  Fut                     ping google.com > /dev/null &
# kill %2
# jobs
[2]+  Befejeződött          ping google.com > /dev/null

Amikor indítunk egy processzt, akkor a szülő processze általában a shell lesz, amiben indítottuk.

# pstree
...
/usr/bin/terminator
  `-bash
      `-dd if=/dev/urandom of=image.img bs=1k count=1000000
..

Látszik, hogy a terminator nyitott egy shell-t és abban indult a dd. Háttérben futtatás nélkül a terminator vagy a shell bezárásával a dd processz megszakad. Ha viszont háttérben futtatjuk és úgy zárjuk be a shell-t, akkor a futása nem szakad meg, hanem a szűlője a legelső processz vagyis az init vagy systemd lesz. Az alábbi példán látszik, hogy a dd szülője a 17069-es processz.

# ps -ef
...
peter    17079 17069 88 20:58 pts/7    00:00:16 dd if=/dev/urandom of=image.img bs=1k count=1000000
...

Mivel háttérben futott, így a shell megszíktása után a szülő processz az 1-es lesz.

# ps -ef
...
peter    17079     1 89 20:58 ?        00:00:32 dd if=/dev/urandom of=image.img bs=1k count=1000000
...

Lám ez is milyen egyszerű :)