Linux: Kniha kouzel, 2.15 (1. března 2025)
Veškerá moc příkazové řádky/příkazového řádku přehledně, pro začátečníky i pokročilé

24. Správa procesů

Vývoj vanilkové příchuti Linuxu: Knihy kouzel byl 1. března 2025 ukončen. Tento text je zachován jako historický, ale chyby již nejsou opravovány. Odnože projektu pod kompatibilní licencí jsou vítány.

1. Úvod

Tato kapitola pokrývá vyhledávání, zkoumání, sledování a ukončování procesů a omezeně také jejich spouštění. Rovněž se zabývá sledováním, jak jednotlivé procesy využívají systémové zdroje jako výkon procesoru, paměť RAM či pevný disk. Ne všechny uvedené postupy však fungují pro zacházení s démony; hodláte-li zacházet s démony, navštivte kapitolu Systém.

Když v linuxu spustíte program, vznikne tzv. proces – jakási „schránka“ pro program, která mu umožňuje běžet na procesoru a využívat systémové zdroje. Většina příkazů, které v terminálu zadáte, vytvoří nový proces. Pouze malá část spuštěných procesů si otevře také grafické uživatelské rozhraní.

Procesy jsou v linuxu identifikovány čísly PID (což neznamená „Pražská integrovaná doprava“) a jsou uspořádány do „rodinné“ struktury, kde každý proces s výjimkou dvou prvotních démonů má právě jednoho rodiče. PID rodiče je u vlastního procesu uvedeno jako vlastnost „PPID“. (Pozor – nepleťte si PID a PPID!)

2. Definice

  • Proces je instance počítačového programu v paměti, v dané chvíli jednoznačně identifikovaná kladným celým číslem PID (obvykle v rozsahu 1 až 4 194 304). PID procesu se za jeho běhu nemůže změnit; může se však změnit PPID (pokud je rodič pohřben dřív než zrozenec) nebo to, který program v rámci daného procesu ve skutečnosti běží.
  • Démon je systémový proces bez uživatelského rozhraní, konkrétně jsou to dva prvotní démoni („systemd“ – PID 1 a „kthreadd“ – PID 2) a ti jejich přímí potomci, kteří nemají textové ani grafické uživatelské rozhraní. Prvotní démoni jako procesy nemají rodiče, jsou zřízeni přímo jádrem a jejich PPID je 0.
  • Zombie je proces, který skončil, ale jeho rodič dosud nepřevzal jeho návratovou hodnotu. Převzetím návratové hodnoty rodičem je zombie pohřbena a její PID se uvolní pro přidělení dalšímu procesu.
  • Název procesu je textový identifikátor přiřazený procesu jádrem. Není jednoznačný a vzniká (asi) tak, že se z ARGV[0] vezme jen název souboru (bez cesty) a zkrátí se na prvních 15 bajtů (obsahuje-li vícebajtové znaky, může dojít ke vzniku neplatné sekvence).
  • Úloha bashe je proces spuštěný z bashe, který byl spuštěn na pozadí nebo alespoň jednou na pozadí odsunut. Takový proces dostane od dané instance bashe vedle PID ještě druhý identifikátor – „číslo úlohy“. Číslo úlohy je pak pro daný proces jedinečné, ale pouze v rámci dané instance bashe.

3. Zaklínadla

3/1 Hledání procesů (najít PID)

@procesy podle názvu procesu (obecně/příklad)#1
pgrep [-x] 'regulární výraz'
pgrep '^gimp'
@všechny procesy#2
pgrep .
@přímí/všichni potomci určitého procesu#3
pgrep -P PID
lkk procesy | sed -E 's/^([0-9]+)(:[0-9]+)*:(PID):.*/\1/;t;d'
@proces a všichni jeho předci v pořadí, až po prvotního démona#4
lkk procesy | sed -nE '/^(PID):/{s/:/\n/g;p}'
@procesy, které mají otevřený konkrétní soubor#5
sudo fuser cesta 2>/dev/null | sed -E 's/^\s+//;s/\s+|\s?$/\n/g'
@všechny procesy určitého uživatele/určité skupiny#6
pgrep -U uid-nebo-uživatel[,další]
pgrep -G gid-nebo-skupina[,další]
@sourozenci určitého procesu (včetně procesu samotného)#7
pgrep -P $(ps h -o ppid PID-procesu)
@procesy spuštěné později či společně se zadaným procesem#8
ps h -eo etimes,pid --sort -etimes | gawk '$1 <= '"$(ps h -o etimes:1 PID)"' {print $2}'
@procesy spuštěné dříve či společně se zadaným procesem#9
ps h -eo etimes,pid --sort -etimes | gawk '$1 >= '"$(ps h -o etimes:1 PID)"' {print $2}'
@procesy, které mají otevřený konkrétní adresář#10
sudo fuser cesta 2>/dev/null | sed -E 's/^\s+//;s/\s+|\s?$/\n/g'

3/2 Zjistit obecné informace o procesu

@příkazový řádek (pro člověka/txtz pro skript)#1
tr \\0 \\40 </proc/PID/cmdline | sed -E '$s/ ?$/\n/' | cat -v
cat /proc/PID/cmdline [| zpracování]
@ARGV[0]#2
head -zn1 /proc/PID/cmdline | tr \\0 \\n⊨ /bin/bash
@PPID#3 (1)
ps h -o ppid:1 -p PID⊨ 3077
@název procesu#4
ps h -o comm:1 -p PID⊨ bash
@spuštěný soubor (na disku)#5
[sudo] readlink /proc/PID/exe⊨ /bin/bash
@příslušný terminál#6 (2)
ps h -o tty:1 -p PID⊨ pts/1
@aktuální adresář (pro člověka/pro skript)#7
[sudo] pwdx PID⊨ 2343: /home/nana
[sudo] readlink /proc/PID/cwd⊨ /home/nana
@uživatel vlastnící proces (jméno/UID)#8
ps h -o ruser:1 -p PID⊨ root
ps h -o ruid:1 -p PID⊨ 0
@skupina vlastnící proces (jméno/GID)#9
ps h -o rgroup:1 -p PID⊨ root
ps h -o rgid:1 -p PID⊨ 0
@priorita procesu#10
ps h -o ni:1 -p PID⊨ 0
@označení sezení podle systemd#11
ps h -o lsession:1 -p PID⊨ c2

3/3 Zjistit okamžité využití zdrojů

@% zatížení procesoru#1
ps h -o pcpu:1 -p PID⊨ 10.1
@počet kiB RAM zabrané procesem#2
ps h -o rss:1 -p PID⊨ 6028
@% RAM zabrané procesem#3
ps h -o pmem:1 -p PID⊨ 0.1
@velikost virtuální paměti procesu v kiB#4
ps h -o vsz:1 -p PID⊨ 32024
@počet kiB virtuální paměti zabrané kódem/daty#5
ps h -o trs:1 -p PID⊨ 1037
ps h -o drs:1 -p PID⊨ 30986
@procesy, které nejvíc zatěžují procesor/RAM#6
ps h -e -o pcpu,pid,comm | sort -rn | head
ps h -e -o rss,pid,comm | sort -rn | head
@číslo přiděleného logického procesoru (od nuly)#7
ps h -o psr:1 -p PID⊨ 0
@počet vláken #8
sed -E 's/^Threads:\s+//;t;d' /proc/PID/status⊨ 1
@procesy, které nejvíc pracují s diskem#9
sudo egrep -H '^(read|write)_bytes:' /proc/[1-9]*/io >dočasný/soubor/1
sleep 1;sudo egrep -H '^(read|write)_bytes:' /proc/[1-9]*/io >dočasný/soubor/2
gawk 'BEGIN {FS="/|: ?"; OFS = "\t";} ARGIND == 1 {A[$3] += $6} ARGIND == 2 {B[$3] += $6} END {for (pid in A) {if (pid in B) {print B[pid] - A[pid], pid}}}' dočasný/soubor/1 dočasný/soubor/2 | sort -rn | head

3/4 Zjistit historii využití zdrojů

@čas od spuštění procesu (v sekundách/ve formátu [[DD-]hh:]mm:ss)#1
ps h -o etimes:1 -p PID⊨ 271
ps h -o etime:1 -p PID⊨ 04:31
@čas, od kdy proces existuje#2
ps h -o lstart -p PID | date -f - "+%F %T %z"⊨ 2020-02-07 13:42:13 +0100
@spotřebovaný čas procesoru#3
ps h -o cputime:1 -p PID⊨ 00:01:13
@počet bajtů přečtených z disku/zapsaných na disk#4
[sudo] sed -E 's/^read_bytes:\s+//;t;d' /proc/PID/io⊨ 1503232
[sudo] sed -E 's/^write_bytes:\s+//;t;d' /proc/PID/io⊨ 1724416

3/5 Zjistit ostatní údaje

@seznam otevřených deskriptorů (jen čísla/s cestami k souborům)#1
[sudo] ls -U1 /proc/PID/fd
[sudo] find /proc/PID/fd -type l -printf '%f\t%l\n'
@vypsat prostředí procesu ve formátu txtz#2 (3)
[sudo] cat /proc/PID/environ [| zpracování]
@efektivní uživatel (jméno/EUID)#3
ps h -o euser:1 -p PID⊨ root
ps h -o euid:1 -p PID⊨ 0
@efektivní skupina (jméno/EGID)#4
ps h -o egroup:1 -p PID⊨ root
ps h -o egid:1 -p PID⊨ 0

4. Zaklínadla: TUI a stromové zobrazení

4/1 Stromové zobrazení

@proces a jeho potomci#1
pstree -pT[h][l] PID
@proces a jeho předkové#2
pstree -ps[h][l] PID
@všechny procesy bez parametrů/s parametry#3
pstree -pT[h][l]
pstree -paT[h][l]

4/2 TUI

@procesy nejvíc zatěžující CPU#1
top
@procesy zabírající nejvíc paměti RAM#2
top
Shift + M
@procesy nejvíc vytěžující pevný disk#3
sudo iotop
@procesy spotřebovávající nejvíc elektřiny#4 (4)
sudo powertop

5. Zaklínadla: Spouštění a ovládání procesů

5/1 Spouštění procesů

@spustit příkaz s právy superuživatele/jiného uživatele#1
sudo příkaz [parametr-příkazu]
sudo -u uživatel příkaz parametr-příkazu
@spustit příkaz s právy jiné skupiny#2
sg "příkaz [parametr-příkazu]"
@spustit příkaz a po skončení vypsat spotřebovaný čas#3 (5)
time příkaz [parametr-příkazu]
@spustit příkaz a jeho programem nahradit volající bash či sh#4
exec příkaz [parametr-příkazu]
@spustit proces s nastavenou prioritou (ne vyšší/libovolnou)#5
nice -n $((priorita - $(nice))) příkaz [parametry příkazu]
sudo nice -n $((priorita - $(nice))) sudo -u "$(id -nu)" -g "$(id -ng)" příkaz [parametry příkazu]

5/2 Ukončování procesů

@požádat o ukončení více procesů podle názvu (obecně/příklad)#1
[sudo] pkill 'regulární-výraz'
pkill '^gimp'
@požádat o ukončení/násilně ukončit#2
[sudo] kill PID
[sudo] kill -9 PID

5/3 Čekání, signály, priorita

@počkat na ukončení#1
while test -e /proc/PID; do IFS="" read -t 0.1 || :; done <> <(:)
@zaslat procesu signál#2
[sudo] kill -[signál] PID
@pozastavit proces/nechat ho pokračovat#3
[sudo] kill -SIGSTOP PID
[sudo] kill -SIGCONT PID
@změnit prioritu běžícího procesu#4 (6)
[sudo] renice priorita PID

5/4 Úlohy bashe (ve skriptu)

Poznámka: každý interpret má svoji tabulku úloh, takže není možné v jednom interpretu čekat na úlohu spuštěnou jiným interpretem.

@spustit příkaz na pozadí (jako „úlohu“)(volitelně: do proměnné uložit jeho PID)#1
příkaz [parametr-příkazu] &
[proměnná=$!]
@počkat na dokončení úlohy#2 (7)
wait PID
@počet úloh#3
jobs -pr | wc -w
@počkat, dokud nebude počet úloh ≤ N#4
lkk_limit_jobs N
@poslat úloze signál#5
kill [parametry] PID
@vyřadit úlohu ze seznamu (ale nechat běžet jako obyčejný proces)#6
disown PID

5/5 Úlohy bashe (interaktivní režim)

@spustit příkaz na pozadí#1
příkaz [parametr-příkazu] &
@požádat proces v popředí o ukončení#2
Ctrl + C
@pozastavit proces v popředí a odsunout ho jako úlohu bashe#3
Ctrl + Z
@přenést úlohu na popředí#4 (8)
fg [%číslo-úlohy]
@vypsat seznam úloh#5
jobs
@nechat pozastavenou úlohu pokračovat v pozadí#6
bg [%číslo-úlohy]
@požádat úlohu o ukončení/násilně ji ukončit#7
kill %číslo-úlohy
kill -9 %číslo-úlohy
@počkat na dokončení úlohy běžící v pozadí#8
wait %číslo-úlohy [%číslo-další-úlohy]

6. Parametry příkazů

6/1 ps

ps parametry [-e]
ps parametry PID
☐ --no-headersPotlačí zobrazení hlavičky na začátku výpisu.
☐ -o sloupceUrčí, které sloupce se vypíšou. Seznam platných hodnot najdete v manuálové stránce příkazu ps.
○ -eZobrazit všechny procesy v systému. (Výchozí chování: zobrazí jen procesy příslušné témuž terminálu.)
☐ -HOdsadí názvy příkazů pro zdůraznění struktury stromu procesů.
☐ --sort klíčeNastaví řazení výpisu.

6/2 pgrep

pgrep [volby] 'regulární výraz'
pgrep [volby a kritéria] ['regulární výraz']

Volby:

☐ -xU regulárního výrazu požadovat přesnou shodu.
○ -o ○ -n ○ -vZ nalezených procesů vybrat: jen nejstarší proces/jen nejnovější proces/všechny procesy, které nevyhovují kritériím. (Výchozí: všechny procesy vyhovující kritériím.) Poznámka: staří procesu se zde posuzuje podle času spuštění.
☐ -fRegulární výraz testovat proti celé příkazové řádce procesu. (Normálně jen proti názvu procesu.)
☐ -d řetězecNastavit oddělovač výpisu nalezených PID.
○ -c ○ -l ○ -aVypsat: jen počet nalezených PID; PID a název procesu; PID a příkazový řádek procesu.
☐ -iPři testu regulárního výrazu nerozlišovat velká a malá písmena.

Kritéria:

☐ -G gid-nebo-skupina...Vybrat podle skupiny (RGID).
☐ -P PPID...Vybrat podle PPID.
☐ -t terminál...Vybrat podle příslušného terminálu (např. „pts/1“).
☐ -u uid-nebo-uživatel...Vybrat podle EUID.
☐ -U uid-nebo-uživatel...Vybrat podle RUID.

7. Instalace na Ubuntu

Většina uvedených příkazů je základními součástmi Ubuntu. Pouze některé konkrétní příkazy ve stejnojmenných balíčcích je potřeba doinstalovat, pokud je chcete použít:

sudo apt-get install iotop powertop

V kapitole je použit také příkaz gawk:

sudo apt-get install gawk

8. Tipy a zkušenosti

  • Existuje také příkaz „pkill“, který kombinuje většinu schopností příkazu „pgrep“ s příkazem „kill“ – tzn. vyhledaným procesům rovnou zašle signál.
  • Pokud rodič zanikne dřív než samotný proces, „adoptuje“ proces systemd.

9. Další zdroje informací

10. Pomocné funkce a skripty

@lkk_limit_jobs() – počká, než počet úloh běžících na pozadí klesne na požadovanou úroveň nebo pod ni#1
function lkk_limit_jobs() {
local j r=0
while j=($(jobs -pr)); ((${#j[@]} > ${1:-0}))
do wait -n; r=$?
done
return $r
}
@lkk procesy – vypíše přehled procesů ve snadno zpracovatelném tvaru#2 (9)
#!/bin/bash
x=$(ps h -e -o pid,ppid)
x=$(perl -MEnglish -e '
my $stdin = \*STDIN; my $s; my %p;
while (defined($s = scalar(readline($stdin)))) {
my ($ppid, $pid) = split("\x{0}", $s =~ s/^\s*(\S+)\s+(\S+)\s*$/$2\x{0}$1/r);
$p{$pid + 0} = $ppid + 0 if ($pid != $PID);
}
c: foreach my $k (keys(%p)) {
$s = $k;
while ($k > 2) {
next c if ($k == '$$');
$s = $s . ":" . ($k = $p{$k});
}
print $s, "\n";
}' <<< "$x")
sort -n <<< "$x"

11. Zákulisí kapitoly

V této verzi kapitoly chybí:

  • sledování systémových volání procesů (ptrace, strace)
  • sledování systémových knihoven

Tato kapitola záměrně nepokrývá:

  • správu systémových zdrojů
  • kvóty, kontejnery, izolační a virtualizační techniky jako chroot, lxc či cgroups
1 Pro procesy zřízené jádrem (systemd a kthreadd) vrací „0“.
2 Nepříluší-li proces žádnému terminálu ani konzoli, vypíše „?“.
3 Každý záznam začíná názvem proměnné prostředí a znakem „=“, za ním následuje obsah proměnné.
4 Funguje především na notebooku, nemám příliš vyzkoušené.
5 Jde o vestavěnou konstrukci bashe, která dovoluje na místo jednoduchého příkazu zadat také více příkazů spojených rourou, např. „time seq 10000 | wc -l“. Účinek příkazu „time“ se pak vztahuje na všechny procesy spojené rourou.
6 Priorita je číslo v rozsahu -20 (nejvyšší) až 19 (nejnižší); normální priorita je 0. Obyčejný uživatel (tzn. bez sudo) může pouze snižovat prioritu vlastních procesů.
7 Návratovým kódem příkazu „wait“ bude návratový kód úlohy odpovídající poslednímu uvedenému PID. Tento příkaz bude fungovat i v případě, že dané úlohy již skončily, ale pouze jednou — nelze ho volat vícekrát pro tutéž úlohu.
8 Byla-li úloha pozastavená, tento příkaz ji nechá pokračovat.
9 Procesy realizující samotný skript se nevypíšou, proto můžete při opakovaném volání dostat stejný výsledek.
[BY-SA]

Veškerý obsah této stránky (text, obrázky, zdrojový kód) je možno upravovat a šířit pod podmínkami licence Creative Commons Attribution-ShareAlike 4.0 International. Upozorňuji, že uvedená licence vyžaduje uvedení seznamu autorů, licence a zdroje a poskytnutí stejné či kompatibilní licence k provedeným změnám, jsou-li nějaké. Příslušné údaje jsou dostupné na stránce „Přehled autorů“. Šíření obsahu bez těchto údajů nebo šíření upravené verze bez poskytnutí adekvátní licence k provedeným úpravám je pravděpodobně porušení licenčních podmínek a může být postihováno. Poskytování zdrojového kódu při šíření není touto licencí vyžadováno.

Pro nové verze, další informace, aktuální zdrojový kód a možnost se zapojit do projektu „Linux: Kniha kouzel“ navštivte jeho repozitář na GitHubu.