Lekce 9 - Linuxový terminál (Bash) - Práce s procesy
V minulé lekci, Linuxový terminál (Bash) - Oprávnění a instalace balíčků, jsme si vysvětlili uživatelská oprávnění, naučili se vystupovat jako super uživatel a instalovat balíčky.
V dnešní lekci se seznámíme s pojmy proces, úloha či úkol. Následně se podíváme na uspořádání procesů v Linuxu a v neposlední řadě se naučíme pracovat s příkazy pro jejich obsluhu.
Procesy v Linuxu
Linux je stejně jako Windows víceúlohový operační systém. Jednotlivé aplikace běží jako procesy, o které se procesor střídá nebo které běží na různých jádrech. V procesech běží ve skutečnosti ještě vlákna, ale těmi se zabývat nebudeme. Pojďme se na úvod seznámit s pojmy úkol, úloha a proces.
Úkol
Úkol neboli task je jednotka vykonávané práce, která je podčástí úlohy. Kombinací několika úkolů poté vzniká jedna úloha.
Úloha
Úloha neboli job je kompletní jednotka práce, která se aktuálně vykonává. Úlohu tvoří vždy série jednotlivých úkolů.
Proces
Proces je synonymem pro běžící program. V Linuxu se stává procesem každý program, kterému po spuštění přidělí systém paměť a další systémové prostředky. Na jednom jádru procesoru může běžet v daný okamžik pouze jeden proces, ostatní čekají, než na ně přijde řada. O přidělení prostoru v procesoru rozhoduje jádro operačního systému. Každý proces tedy prochází následujícími stavy:
- Nový (New) - Proces je právě vytvářen. Zatím není připraven k běhu, ale již jsou připraveny některé části.
- Připravený (Ready) - Proces čeká na přidělení procesoru.
- Běžící (Running) - Instrukce procesu jsou právě vykonávány procesorem.
- Čekající (Waiting/Blocked) - Proces čeká na událost.
- Ukončený (Terminated) - Proces ukončil svoji činnost, avšak stále ještě vlastní některé systémové prostředky.
Rodičovský proces
Rodičovský proces je označení pro proces, který vytvořil jednoho nebo více potomků. Rodiče a potomci v systému vytvářejí stromovou strukturu. Potomek může od rodiče dědit například obsah paměti či zpracovávané sobory a naopak po svém ukončení předává návratový kód rodiči.
Pojďme si rodičovský proces ukázat na konkrétním příkladu. Do
terminálu napíšeme příkaz ps -l
, který nám vypíše seznam
procesů aktuálního shellu společně s doplňujícími informacemi:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 S 0 8 1 0 80 0 - 2452 - tty1 00:00:00 init 0 S 0 9 8 2 80 0 - 4531 - tty1 00:00:00 bash 0 R 0 70 9 0 80 0 - 4646 - tty1 00:00:00 ps
Ve výpisu se zaměříme zejména na sloupce PID
(Process ID) a
PPID
(Parent Process ID). Můžeme si všimnout, že program
bash
má stejné PID
jako program ps
své
PPID
. Je to z důvodu, že programem bash
jsme
spustili ps
. Proces bash
je tedy rodičovský proces
pro ps
, který je naopak potomek tohoto procesu.
Příkazem pstree
zobrazíme celou
stromovou strukturu všech procesů v operačním systému.
Systemd
Pokud je každý proces potomkem jiného procesu, pak existuje jeden, který
stojí za vznikem všech ostatních. Tímto procesem je
systemd
, ve starších verzích Linuxu označován jako
init
. Po startu vytvoří jádro systému vlákno s
PID 0
, které následně spustí proces initramfs
. Ve
starších verzích Linuxu je proces initrd
. Po jeho ukončení se
spustí systemd
s PID 1
, který následně spustí
zbylé systémové procesy.
Po zadání příkazu pstree
si můžeme všimnout,
že proces systemd
je na vrcholu celé stromové struktury.
Daemon
Daemon je proces, který běží bez
dozoru, je nezávislý na rodičovském procesu a
na pozadí se stará o chod operačního systému. Daemoni
zajišťují například síťové služby, tiskové služby a podobně.
Zpravidla je poznáme tak, že název procesu končí na d
. Mezi
nejznámější deamony patří systemd
, crond
spouštějící naplánované úlohy, sshd
zajišťující
šifrované přihlášení či ftpd
umožňující přenos
souborů.
Správa procesů v Linuxu
Nyní se naučíme používat několik základních příkazů pro správu procesů. S jejich využitím budeme schopni zobrazit seznam běžících procesů, spustit nový proces, přenést proces do popředí či daný proces ukončit.
ps
Příkaz ps
slouží k vypsání všech běžících procesů
uživatele. Vypíšou se však pouze procesy spuštěné aktuálním shellem.
Pokud k příkazu přidáme ještě atribut aux
:
ps aux
Získáme výpis všech aktuálně spuštěných procesů společně s podrobnějšími informacemi:
root 1 0.0 0.0 9788 528 ? Ssl 16:35 0:00 /init root 66 0.0 0.0 20224 908 ? Ss 16:35 0:00 sshd: /usr/sbin root 95 0.0 0.0 9808 308 tty1 Ss 20:32 0:00 /init root 96 0.0 0.0 18124 3672 tty1 S 20:32 0:00 -bash root 119 0.0 0.0 18664 1896 tty1 R 20:34 0:00 ps aux
Vidíme zde běžící terminál, v našem případě bash
, a
samotný ps
.
Všimněme si, že každý proces má své PID
,
pomocí kterého ho můžeme například ukončit. ID je nutné z důvodu, že
jedna aplikace může běžet několikrát a systém by tedy jen podle jejího
názvu nerozpoznal který proces má ukončit.
pstree
Pro přehlednější výpis použijeme pstree
, který vypíše
procesy ve stromové struktuře:
init─┬─init───bash───pstree
├─sshd
└─2*[{init}]
jobs
Kromě ps
můžeme k výpisu procesů využít i shell builtin
jobs
. Protože je součástí shellu, použijeme ho v případě,
když nás zajímají procesy, které jsme přes shell spustili:
jobs
Po spuštění nevidíme žádné procesy, jelikož nemáme žádné
spuštěné. Napravíme to a spustíme si například gedit
.
Jakmile vyskočí okno a my se vrátíme zpět do terminálu, zjistíme, že je
zaneprázdněný:
admin@itnetwork:~# gedit
█
Proces pozastavíme stisknutím klávesové zkratky CTRL + Z:
admin@itnetwork:~# gedit ^Z [1]+ Stopped gedit
bg
Pomocí příkazu bg
spustíme pozastavený proces na
pozadí:
admin@itnetwork:~# bg [1]+ gedit &
Vidíme, že nyní reaguje gedit
a zároveň je přístupný i
terminál.
Proces můžeme na pozadí spustit ihned, a to tak, že mu dáme
jako parametr ampersand (&
).
fg
Pomocí příkazu fg
přeneseme proces do popředí. Za příkaz
můžeme zadat PID
procesu po procentu nebo ho spustit bez
parametrů, kdy přenese do popředí poslední pozastavený proces nebo
poslední proces v pozadí:
admin@itnetwork:~# fg %1
gedit
█
top
Příkaz top
slouží ke sledování procesů v
reálném čase a umožňuje efektivnější řazení procesů dle
konkrétních požadavků. Například můžeme procesy seřadit podle
aktuálního využití CPU, paměti či dalších parametrů:
top - 08:37:57 up 16:02, 0 users, load average: 0.52, 0.58, 0.59 Tasks: 5 total, 1 running, 4 sleeping, 0 stopped, 0 zombie %Cpu(s): 14.9 us, 3.1 sy, 0.0 ni, 81.8 id, 0.0 wa, 0.2 hi, 0.0 si, 0.0 st MiB Mem : 16217.3 total, 6969.1 free, 9024.1 used, 224.0 buff/cache MiB Swap: 28835.8 total, 28792.3 free, 43.4 used. 7062.5 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 9788 524 476 S 0.0 0.0 0:00.07 init 66 root 20 0 20224 908 692 S 0.0 0.0 0:00.00 sshd 192 root 20 0 9808 308 260 S 0.0 0.0 0:00.01 init 193 root 20 0 18124 3672 3572 S 0.0 0.0 0:00.09 bash 214 root 20 0 18920 2160 1528 R 0.0 0.0 0:00.00 top
V hlavičce si můžeme všimnout informací o celkovém počtu spuštěných procesů, celkovém využití paměti a podobně. Pojďme se ještě podívat na význam jednotlivých sloupců ve výpisu:
PID | Identifikační číslo procesu. |
USER | Uživatel, pod kterým je proces spuštěn. |
PR | Priorita plánování úkolu. Hodnota rt znamená, že úloha
běží s prioritou plánování v reálném čase. |
NI | Priorita procesu neboli tzv. "nice value". Kladná hodnota symbolizuje nízkou prioritu, záporná hodnota pak vysokou prioritu. |
VIRT | Celkové množství virtuální paměti využité procesorem. |
RES | Celkové množství skutečné paměti využité procesorem. |
SHR | Celkové množství sdílené paměti využité procesorem. |
S | Aktuální stav procesu. |
%CPU | Procentuální využití procesoru jednotlivých procesů. |
%MEM | Procentuální využití operační paměti jednotlivých procesů. |
TIME+ | Čas v setinách sekundy, který byl jádrem procesu přidělen. |
COMMAND | Název spuštěného procesu. |
Sledování procesů ukončíme klávesou q. Pokud chceme zobrazit
pouze jeden konkrétní proces, například sshd
můžeme použít
filtr:
top | grep sshd
kill
Poslední příkaz, který si v souvislosti s procesy zmíníme, je příkaz
kill
. Jak asi tušíte, slouží k zastavení či ukončení
daného procesu. Příkazem kill
můžeme vyslat celkem 62
různých signálů. Všechny signály vypíšeme přidáním
přepínače -l
:
kill -l
Výpis příkazu vypadá následovně:
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
Signály lze v Linuxu specifikovat přidáním:
- čísla signálu (
kill -15 PID
), - názvu s předponou (
kill SIGTERM PID
), - nebo názvu bez předpony (
kill -term PID
).
Výchozí signál je SIGTERM
(signal terminate), který se
snaží proces ukončit. Pokud příkazem top
zjistíme, že
například proces s PID 200
nadměrně vytěžuje
procesor počítače nebo zamrznul, napíšeme do
terminálu:
kill 200
Pokud SIGTERM
nedokáže proces ukončit, můžeme využít
razantnější signál SIGKILL
:
kill -9 200
V případě, že tento proces měl PPID 100
, jeho
potomci automaticky změní své PPID
z 200
na
100
.
To je pro dnešní lekci vše 🙂
V příští lekci, Linuxový terminál (Bash) - Standardní vstup/výstup a expanze, přesměrujeme standardní vstup a výstup, naučíme se používat filtry a roury. Poté si ještě si vysvětlíme expanzi.