Procesy v Linuxu aneb jeden admin vládne všem

11. 1. 2011
Doba čtení: 7 minut

Sdílet

V dnešním článku se společně podíváme na práci s procesy – jejich sledování, řízení a ukončování. Znalost práce s procesy je pro uživatele unixového systému velmi důležitá. Bez takových činností bychom degradovali práci v shellu jen kousek výš než je příkazová řádka v MS-DOS. Ovládněte své procesy.

Co to takový proces vlastně je? Jedná se o každý spuštěný program v Linuxu, kterému systém po spuštění přidělí paměť a další systémové prostředky. Systémy Linux/Unix jsou víceúlohové a víceuživatelské, což znamená více procesů, z hlediska uživatele, běžících najednou. Není to tak úplně pravda, v jednoprocesorovém jednojádrovém procesoru běží v jeden okamžik pouze jeden proces. V systému je samozřejmě více procesů, které čekají na přidělení procesorového času. Toto přidělování řídí náš operační systém a není to jednoduchá věc, protože procesy mohou mít různé priority nebo být v různých stavech.

Výpis spuštěných procesů

My se podíváme, co vše můžeme s procesy dělat. Začneme jednoduchým výpisem procesů, k tomu slouží program ps. Bez parametrů vypíše námi spuštěné procesy v právě používaném terminálu:

pm@pm-laptop:~/Documents$ ps
  PID TTY          TIME CMD
 2049 pts/1    00:00:00 bash
 2105 pts/1    00:00:00 ps

Pomocí ps můžeme získat mnohem více informací, proto použijeme další parametry, pro výpis všech procesů:

pm@pm-laptop:~/Documents$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1   2624  1532 ?        Ss   21:45   0:01 /sbin/init
root         2  0.0  0.0      0     0 ?        S<   21:45   0:00 [kthreadd]
...
...
pm        1963  0.0  1.2  93968 12352 ?        S    21:46   0:00 gnome-volume-control-applet
ntp       1965  0.0  0.1   4228  1264 ?        Ss   21:46   0:00 /usr/sbin/ntpd -p /var/run/ntpd.pid -u 114:123 -g
pm        1972  0.0  0.3  18208  3072 ?        Ss   21:46   0:00 gnome-screensaver
root      1974  0.0  0.3   5844  3512 ?        S    21:46   0:00 /usr/lib/policykit-1/polkitd
pm        3605  0.0  0.1   5396  1784 pts/0    Ss   21:02   0:00 bash

Zobrazí se více sloupečků, v prvním je uživatel, který proces spustil. Pro nás bude důležitý druhý sloupec PID. To je identifikátor procesu, pro každý proces to znamená jedinečné číslo. Později s ním budeme pracovat. Pak jsou tu údaje udávající zatížení CPU a paměti. Zajímavý může být třeba sloupec TTY, který udává terminál, v kterém je proces spuštěn. Proces nemusí být ale spuštěn vždy z nějakého terminálu (třeba při startu systému), pak zde bude znak ?. Další sloupec je stav procesu, např. R je právě běžící, T zastavený, … Zajímavý je proces označený písmenem Z (zombie). Pokud takové procesy vidíte, něco není dobře. Jedná se o proces, který je ukončený, ale jeho rodič se o něj nepostaral a neuklidil po něm. Kompletní seznam stavů se dočtete v man ps.

Je možné si vypsat třeba procesy konkrétního uživatele nebo jakýsi strom procesů pomocí  ps axjf:

    1  8340  1688  1688 ?           -1 Rl    1000   0:22 gnome-terminal
 8340  8341  1688  1688 ?           -1 S     1000   0:00  \_ gnome-pty-helper
 8340  8342  8342  8342 pts/0     8342 Ss+   1000   0:00  \_ bash
 8340  8442  8442  8442 pts/1     8465 Ss    1000   0:00  \_ bash
 8442  8465  8465  8442 pts/1     8465 R+    1000   0:00      \_ ps axjf

Lepší pohled na strom procesů nabídne program pstree, jeho výpis se dá opět ovlivnit několika parametry, třeba:

$ pstree -pu

        ├─gnome-terminal(8340,pm)─┬─bash(8342)───pstree(8583)
        │                         ├─bash(8442)───mc(8545)───bash(8547)
        │                         ├─gnome-pty-helpe(8341)
        │                         └─{gnome-terminal}(8343)
        ├─go-home-applet(1860,pm)
        ├─gvfs-fuse-daemo(1768,pm)─┬─{gvfs-fuse-daemo}(1769)
        │                          ├─{gvfs-fuse-daemo}(1770)
        │                          └─{gvfs-fuse-daemo}(1771)
        ├─gvfs-gdu-volume(1881,pm)
        ├─gvfs-gphoto2-vo(1922,pm)
        ├─gvfsd(1761,pm)
        ├─gvfsd-burn(1930,pm)
        ├─hald(487,haldaemon)───hald-runner(571,root)─┬─hald-addon-acpi(967,haldaemon)
        │                                             ├─hald-addon-cpuf(963)
        │                                             ├─hald-addon-gene(930)
        │                                             └─hald-addon-inpu(971)

Posledním programem, který si pro zobrazení procesů ukážeme, je program top:

top - 12:54:21 up  2:11,  3 users,  load average: 0.05, 0.08, 0.07
Tasks: 168 total,   2 running, 166 sleeping,   0 stopped,   0 zombie
Cpu(s): 11.1%us,  4.8%sy,  0.0%ni, 80.8%id,  1.5%wa,  0.7%hi,  1.1%si,  0.0%st
Mem:   1016796k total,   994564k used,    22232k free,     8408k buffers
Swap:  1855468k total,     4352k used,  1851116k free,   664312k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 2129 pm        20   0  114m  26m  11m S   11  2.7  16:31.78 transmission
  897 root      20   0 60156  18m 8996 S    9  1.8  11:46.27 Xorg
 8340 pm        20   0 38864  15m  10m S    3  1.6   0:37.70 gnome-terminal
 1850 pm        20   0 84124  25m  15m S    3  2.6   1:41.56 gnome-panel
 8237 pm        20   0  199m  70m  21m S    2  7.1   2:10.27 firefox
 1855 pm        20   0 21136  10m 8544 S    1  1.1   0:14.10 gtk-window-deco
 1849 pm        20   0 80700  26m 7740 S    1  2.6   1:56.40 compiz.real
 1750 pm        20   0 15652 5108 4012 S    1  0.5   2:16.38 at-spi-registry
 8623 pm        20   0  2472 1192  884 R    1  0.1   0:00.28 top
 1872 pm        20   0 33120  13m  10m S    1  1.4   0:20.61 window-picker-a
   50 root      15  -5     0    0    0 S    0  0.0   0:01.89 kondemand/0
 1656 ntp       20   0  4228 1188  864 S    0  0.1   0:03.50 ntpd
 1751 pm        20   0 98252  10m 7920 S    0  1.0   0:07.24 gnome-settings-
 1787 pm        20   0 27224  12m 8668 S    0  1.2   0:13.61 notify-osd
 1852 pm        20   0 74292  23m  14m S    0  2.4   0:14.36 netbook-launche
 1882 pm        20   0 32044  12m 9388 S    0  1.3   0:07.29 update-notifier
    1 root      20   0  2616 1444 1064 S    0  0.1   0:01.42 init
    2 root      15  -5     0    0    0 S    0  0.0   0:00.00 kthreadd

Všimněte si procesu s PID 1. Je to první proces, který je spuštěn při startu systému. Sám dál řídí spouštění dalších. Tvrdí se, že má vždy PID 1, ale není to zcela pravda. Třeba terminálový klient thinstation se chová jinak.

Práce s procesy

Občas se každému stane, že je připojen na konzoli a pustí příkaz, který běží dlouho a konzoli nám tím blokuje. Pokud proces nic nevypisuje (nebo nás výpis nezajímá) můžeme proces pustit na pozadí. Typicky se jedná třeba o mazání nebo kopírování. Pokud rovnou vím, že proces poběží dlouho, stačí na konec příkazu zadat znak &: $ rm -rf /usr/ports & a dále můžeme v konzoli pracovat. Po dokončení úlohy jsme systémem informováni, jak činnost dopadla:

[1]+  Dokončena        rm -rf /usr/ports

Číslo na začátku je identifikátor úlohy (jobu). Úloh na pozadí může být samozřejmě více. Vraťme se ale k našemu problému – spustili jsme mazání a nedali jsme za konec &, takže se proces spustil na popředí. Nevadí, pomocí ctrl + z úlohu pozastavíme.

[1]+  Pozastavena   rm -rf /usr/ports

Kolik úloh a v jakém stavu máme, zjistíme příkazem jobs.

[root@localhost pm]# jobs
[2]+  Pozastavena             ftp ftp.xxx.cz
[3]-  Pozastavena                 ping 188.120.193.2 > vystup &

A zbývají příkazy fg (foreground) a bg (background). Pomocí nich můžeme určit, jak budou procesy dále spuštěny. Zadáme třeba bg 3. Proces pingu se dále rozběhne na pozadí a jobs ukáže:

[root@localhost pm]# jobs
[2]+  Pozastavena             ftp ftp.xxx.cz
[3]-  Běží                 ping 188.120.193.2 > vystup &

Pomocí fg 2 se můžeme vrátit do procesu s ftp klientem. Ale není problém jej znovu odložit.

Ještě malé zjednodušení – pokud si odložíme jen jeden proces (takže jobs ukazuje pouze jeden, může být zastavený nebo běžící), nemusíme už zadávat číslo jobu, ale stačí jen bg nebo fg.

Pokud máme na pozadí odložené úlohy a zkusíme se odhlásit, systém nás varuje a můžeme procesy korektně ukončit.

Někdy se může stát, že jste u počítače na chvilku a potřebujete spustit nějaký proces na pozadí, který ale poběží dlouho. Buď můžete spustit například program screen, v něm danou úlohu a pak se od screenu odpojit (tím se zabývá samostatný článek) nebo použít program nohup. Ten způsobí ignorování signálu SIGHUP, takže se proces neukončí při ukončení shellu.

$ nohup rm -rf /usr/ports &

Mazání rovnou odsuneme na pozadí a můžeme se odhlásit. Nohup nám výstup programu uloží do souboru nohup.out v aktuálním adresáři. Pokud takový výstupní soubor není možné použít, zkusí ~/nohup.out.

Změna priority procesu – nice a renice

Další dva programy, které si ukážeme slouží ke změně priority procesu. Když se podíváte na výpis programu top, pátý sloupeček je nice. To je číslo, které určuje prioritu procesu. Může dosahovat hodnot –20 až 20 (v některých systémech 19). Výchozí hodnotou spuštěných procesů je 0. Např. hodnota +20 ve FreeBSD způsobí, že se daný proces bude vykonávat pouze pokud žádný jiný proces po systému nic nepožaduje. Běžný uživatel může spustit příkaz pomocí nice a nastavit mu jinou prioritu, ale pozor – běžný uživatel může zadávat jen vyšší hodnotu nice a tím nižší prioritu procesu. Pouze uživatel root může zadat i zápornou hodnotu a tím prioritu zvýšit.

nice -n 15 prikaz -parametr

To je sice pěkné, ale co když už program běží s prioritou, která nám nevyhovuje? Pak je tu druhý program – renice. Zadá se mu nová priorita a PID procesu:

pm@gate ~ $ renice +5 21283
21283: old priority 0, new priority 5

Opět platí, že root může nastavit zápornou hodnotu a tím prioritu zvýšit. Je možné ale zvedat prioritu ne jednomu procesu, ale např. všem procesům jednoho uživatele:

pm@gate ~ $ renice +6 -u pm

Ukončování procesů

Jako někdy zlobí děti své rodiče, i leckterý potomek procesu nebo sám proces zazlobí. V reálném životě ho za to asi nezabijete, ale tady můžete. V textovém režimu se používají nejčastěji příkazy kill a killall.

pm@gate ~ $ kill PID

Takto zadaný příkaz pošle procesu signál pro ukončení (TERM). Někdy ani to nestačí a je nutné říct, který signál použít, nejčastěji to bude patrně signál KILL. Lze spustit:

pm@gate ~ $ kill -s KILL PID
nebo
pm@gate ~ $ kill -9 PID
nebo
pm@gate ~ $ kill -HUP PID

Některé používané signály

1 HUP (hang up)
2 INT (interrupt)
3 QUIT (quit)
6 ABRT (abort)
9 KILL (non-catchable, non-ignorable kill)
14 ALRM (alarm clock)
15 TERM (software termination signal)

Programu kill předáváme PID procesu, pokud ale chceme zabít více procesů (třeba kousnutý prohlížeč firefox) použijeme killall, stačí zadat:

pm@gate ~ $ killall firefox

Případně můžeme opět doplnit typem signálu. Stejně jako u kill můžete použít název signálu (bez úvodního SIG, takže třeba HUP) nebo číslo signálu.

Ještě pro doplnění uvedu programy pgrep a pkill. Dovolují nám o trochu více než killall, mají více parametrů pro výběr procesu (dle uživatele, skupiny, pouze potomky nějakého procesu nebo třeba nejstarší/nejmladší ze skupiny stejných procesů). Rozhodně si pgrep prozkoumejte. Většinou si pomocí pgrep najdete vhodné procesy a pak jen s těmito parametry spustíte pkill.

pm@gate ~ $ pgrep openvpn
89653
12281
4964
77940
56163
41886

Velice pěkné a účinné může být takovéto spojení nice +19 `pgrep bash -u jiny_uzivatel`.

bitcoin školení listopad 24

Ještě zmíním program xkill. Po spuštění v okenním manažeru se nám změní kurzor a po kliknutí na zlobivé okno bude tento problematický „objekt“ ukončen. Pozor, nezabijte si něco, co nechcete. Já si jednou uklepnutím zabil panel v Gnome a nemohl jej dostat zpět (nepomohl ani restart).

Jistě jsem nezmínil všechny možnosti. Pokud vám nebude souhlasit nějaký parametr, podívejte se do manuálové stránky. Čerpal jsem z FreeBSD a Ubuntu a vše není úplně stejné. Ale většina uváděných příkladů bude fungovat na Linuxu i ostatních unixech, některé uváděné programy nemusí být v systému a bude nutné je doinstalovat, například pstree na FreeBSD:

$ cd /usr/ports/sysutils/pstree
$ make install clean

Autor článku

Petr Macek studoval aplikovanou informatiku na Jihočeské univerzitě, pracuje jako síťový specialista ve firmě Kostax, s. r. o. Baví ho především FreeBSD, sítě a monitoring Cacti.