Správa užívateľov
Existencia a potreba užívateľských účtov je jedným z fundamentálnych predpokladov systémov odvodených z UNIXu. Užívateľské účty tvoria spolu so skupinami bázu pre kontrolu riadenia prístupu k zdrojom (angl. resource access control).
Užívatelia
Užívateľom je jednoducho každý, kto s daným systémom pracuje. Okrem bežných (tzv. human) užívateľov rozlišujeme ešte užívateľov systémových a špeciálny administrátorský (angl. superuser) účet root.
S každým užívateľským účtom je asociovaný nejaký názov, napr. skoleni:
$ whoami skoleni
a jedinečný číselný identifikátor nazývaný UID. V prípade bežných užívateľov to môže byť taktiež domovský adresár (home) alebo nejaké ďalšie doplňujúce informácie o účte, ktoré súhrnne nazývame GECOS a ktoré vieme získať v zrozumiteľnej podobe programom finger
(nie je súčasťou základnej inštalácie).
Na rozdiel od názvu účtu, ktorý slúži pre jednoduchosť zapamätania si, UID nám pomáha rozlíšiť jednotlivé druhy účtov. Všeobecne platí, že UID systémových užívateľov sa pohybuje v rozmedzí 1-999 a bežných potom od 1000 vyššie.
Systémoví užívatelia
Systémoví užívatelia sú takí uživatelia, ktorí majú typicky jeden dedikovaný účel, pre ktorý existujú, napr. beh webserveru a jeho právomoci (viac o systémových právach v kapitole Práva) budú obmedzené na užívateľa apache. Ako neskôr uvidíme, nie je spravidla taktiež možné sa za nich prihlásiť.
Root (Superužívateľ)
Administrátorský účet root má vždy UID 0 a má plný prístup k celému systému. Z pohľadu bezpečnosti a ochrany systému platí zásada, že tento účet by mal byť používaný v najnižšej možnej miere, práve kvôli spomínanej skutočnosti.
Prepínanie na iných užívateľov
Hoci je možné sa prepnúť na ľubovoľného užívateľa (s patričnou dávkou
autentizácie a s výnimkou systémových užívateľov), najčastejšie to bude účet
root pre potrebu administratívnych úkonov (správa služieb, správa užívateľov,
aktualízacie, atď.). K tomu existuje príkaz su
:
$ su - Password: [root@localhost]#
prípadne za iného užívateľa:
$ su - skoleni Password: [skoleni@localhost ~]$
Zaujímavosť: Všimnime použitie voliteľného parametru -
. Jeho použitie bolo zámerné pre demonštráciu dobrých administrátorských návykov, pretože tento parameter zaručí nové čisté prostredie shell (angl. login shell), a teda eliminujeme akékoľvek potenciálne riziká v podobe vedľajších účinkov spôsobených zachovaním nastavení pôvodného prostredia. Bližšie uvidíme efekt tohto parametru pri rozširovaní skupín o nových uživateľov.
Systémová reprezentácia účtov
Každý užívateľský účet je v systéme nejakým spôsobom uložený. Filozofiou
UNIXových systémov je fakt, že „všetko je súbor“, preto aj definície účtov
nájdeme v špeciálnom súbore /etc/passwd
. Po nahliadnutí do tohto súboru
$ cat /etc/passwd | tail -n 2 skoleni:x:1000:1000:Skoleni Linuxu,Red Hat,0123456789,,:/home/skoleni:/bin/bash
uvidíme na prvý pohľad mätúci formát definujúci užívateľský účet, pozrime sa
teda bližšie na jednotlivé položky oddelených znakom :
názov účtu | heslo je uložené v /etc/shadow | | UID | | | GID | | | | |------------GECOS----------------| | | | | | domovský adresár | | | | | | login shell v v v v v v v skoleni:x:1000:1000:Skoleni Linuxu,Red Hat,0123456789,,:/home/skoleni:/bin/bash
Zaujímavou je rozhodne druhá položka x
, ktorá nám vraví, že pre heslo existuje záznam v súbore /etc/shadow
ku ktorému má prístup iba užívateľ root. Existencia x
v /etc/passwd
však neznamená, že nejaké heslo skutočne existuje. Na demonštráciu poslúži náš užívateľ skoleni a systémový užívateľ apache:
# cat /etc/shadow | egrep "apache|skoleni" apache:!!:17804:::::: skoleni:$6$cloJ.lu4v49Cz7g2$dfLjUkj7yzqQWuUuvxoXmEoMzxkf3LoctZN0EHa/tcJ3BNCY.hqM7XtucDUM.vikvQ.Pv3pDgw.ADEkbA2Xyo0::0:99999:7:::
Ako vidíme, heslo užívateľa skoleni je uložené v podobe hash, naopak u
užívateľa apache vidíme namiesto hesla !!
, to znamená, že za daného užívateľa nie je možné sa prihlásiť heslom (v našom prípade vôbec, avšak v iných prípadoch by mohlo byť možné použiť alternatívne metódy prihlásenia).
Za zmienku stojí aj posledná položka, ktorá určuje tzv. login shell, ktorý sme si už stručne popísali. Login shell je úplne prvá služba, ktorá sa spustí pri prihlásení užívateľa, vytvorí čisté prostredie a nakonfiguruje ho podľa
požiadavkov, ktoré sú nad rámec tohto kurzu. Čo je ale dôležité si pamätať, že existuje špeciálna hodnota pre položku login shell nazývaná /sbin/nologin
, ktorá zamietne akýkoľvek pokus o prihlásenie za daného užívateľa. Spravidla to nájdeme u systémových užívateľov. Na ukážku sa pozrime na záznam užívateľa apache v /etc/passwd
:
$ cat /etc/passwd | grep apache apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
Manuálové stránky
passwd
(5)pwconv
(5)shadow
(8)
Skupiny
Skupiny slúžia na združovanie užívateľských účtov podľa ich právomocí (napr.
učitelia vs študenti, učitelia môžu pridávať a modifikovať študijné materiály, študenti ich naopak môžu iba čítať). Rovnako ako v prípade užívateľov, každá skupina má svoje meno a unikátny identifikátor zvaný GID. Každý užívateľ je členom aspoň jednej skupiny (tú potom nazývame primárnou) a pokiaľ neuvedieme inak, vytvorí sa v tomto prípade automaticky nová skupina s identickým názvom. Pre súhrnné informácie o spomínaných identifikátoroch, ako aj ohľadom členstva užívateľov v skupinách použijeme príkaz id
nad aktuálnym užívateľom:
$ id uid=1000(skoleni) gid=1000(skoleni) groups=1000(skoleni)
prípadne nad iným uživateľom:
$ id root uid=0(root) gid=0(root) groups=0(root)
Ako si môžeme všimnúť, užívateľ skoleni je aktuálne členom iba jednej skupiny skoleni
, ktorá je zároveň jeho primárnou skupinou (druhý stĺpec - gid). Taktiež si všimnime, že v prípade, že ak parametre užívateľa nemodifikujeme, GID a UID bude rovnaké.
Systémová reprezentácia skupín
Podobne ako pri užívateľoch, aj skupiny sú v systéme uložené v špeciálnom
súbore /etc/group
:
$ cat /etc/group | tail -n 1 skoleni:x:1000:
Význam jednotlivých položiek je analogický k /etc/passwd
:
názov skupiny | heslo je uložené v /etc/gshadow v podobe hash | | GID | | | zoznam členov skupiny v v v v skoleni:x:1000:
Napriek tomu, že reprezentácia skupín v systéme je temer identická s užívateľmi, v praxi skupinové heslá majú použitie len v ojedinelých prípadoch, navyše značné množstvo systémových administrátorov túto funkcionalitu ani nepozná.
Manuálové stránky
group
(5)grpconv
(8)gpasswd
(8)
Spravujeme užívateľov
V predchádzajúcich sekciách sme získali základné povedomie o užívateľoch a skupinách. Nadobudnuté poznatky teraz využijeme v praktických ukážkach správy užívateľov.
Zmena hesla
Najzákladnejším úkonom správy užívateľov je zmena hesla užívateľa. Každý
užívateľ má právo zmeniť svoje vlastné heslo (na zmenu hesla iných užívateľov
je pochopiteľne potrebný root). Na zmenu použijeme príkaz passwd
:
$ passwd Changing password for user skoleni. Current password: New password: Retype new password: passwd: all authentication tokens updated successfully.
Hoci passwd
ponúka pre roota ďalšie parametre, tieto sú spoločné pre viacero nástrojov, z ktorých sa my budeme venovať tým v praxi najpoužívanejším.
Zmena login shell
Existuje mnoho nadstavieb shell prinášajúcich rôzne vychytávky a užívatelia
majú preto rôzne preferencie a preto majú možnosť si svoj login shell sami
zmeniť. Na zmenu sa používa príkaz chsh
, ktorý vie taktiež vypísať zoznam
dostupných shell-ov. Zmeňme login shell pre užívateľa skoleni na /bin/sh
$ chsh -s /bin/sh skoleni
Pridanie nového užívateľa
Je asi zrejmé, že k vytvoreniu nového užívateľa bude potrebné byť prihlásený
ako root, následne použijeme príkaz useradd
. Stručný prehľad parametrov pre
príkaz useradd použijeme parameter –help
:
# useradd --help
Ako praktickú ukážku vytvorme užívateľa ucitel s UID 5000
a primárnou skupinou skoleni
.
# useradd -u 5000 -g skoleni # id ucitel uid=5000(ucitel) gid=1000(skoleni) groups=1000(skoleni)
Všimnime si, že sme pri vytváraní účtov nešpecifikovali heslo. Ak nazrieme do
/etc/shadow
(ako root), uvidíme niečo podobné:
# cat /etc/shadow | tail -n 1 ucitel:!!:17806:0:99999:7:::
V sekcii o užívateľoch sme si povedali, že !!
namiesto hesla znamená, že
prihlasovanie heslom je pre daný účet zakázané, v našom prípade jednoducho
preto, že sme žiadne nenastavili. Nastavme teda novému užívateľovi heslo
ucitel (opäť ako root):
# passwd ucitel
Následne sa už môžeme úspešne za daného užívateľa prihlásiť do systému za použitia hesla.
Modifikácie existujúcich užívateľov
Veľmi častým úkonom je pridanie užívateľa do ďalších sekundárnych skupín,
prípadne zmenu primárnej skupiny, expirácia hesiel a expirácia celých účtov a
ich následné mazanie. Na nasledujúce úkony budeme využívať nástroje usermod
a chage
a na všetko bude potrebný root.
Skupiny
Predtým než sa pustíme do samotných nastavení, vytvorme si testovacieho
užívateľa test s heslom test
:
# useradd test # passwd test
V novej záložke terminálu (alebo v novom okne) a prihlásme sa za užívateľa test a zistime informácie o jeho identite:
$ id test uid=1001(test) gid=1001(test) groups=1001(test)
Prepneme späť na roota a pridajme užívateľa test do skupiny skoleni
za pomoci príkazu usermod
:
# usermod -a -G skoleni test
Dôležitý je parameter -a
, ktorý hovorí, že zoznam skupín daných -G
má byť pridaný do už existujúceho zoznamu skupín, ktorých je test členom.
Zaujímavosť: Ak teraz prepneme naspäť na užívateľa test a spustíme id
, tak skoleni
v zozname skupin neuvidime:
$ id test uid=1001(test) gid=1001(test) groups=1001(test)
Je tomu tak preto, že tieto zmeny vyžadujú nové prihlásenie (nový login shell). Zmenu primárnej skupiny na skoleni
vykonáme nasledovne:
# usermod -g skoleni test # id test uid=1001(test) gid=1000(skoleni) groups=1000(skoleni),1001(test)
Politika hesiel
Existujú bezpečnostné politiky, ktoré vyžadujú pravidelnú zmenu hesla inak dôjde k uzamknutiu a následnej expirácii užívateľského účtu, účet síce nezanikne, ale o jeho opätovnú aktiváciu bude užívateľ musieť požiadať administrátora. Správu hesiel a platnosť účtov riešime za pomoci príkazu chage
a taktiež z pochopiteľných dôvodov potrebujeme práva root. Pred
praktickými ukážkami sa však najprv pozrime na možnosti tohto príkazu:
# chage -h Usage: chage [options] LOGIN Options: -d, --lastday LAST_DAY set date of last password change to LAST_DAY -E, --expiredate EXPIRE_DATE set account expiration date to EXPIRE_DATE -h, --help display this help message and exit -I, --inactive INACTIVE set password inactive after expiration to INACTIVE -l, --list show account aging information -m, --mindays MIN_DAYS set minimum number of days before password change to MIN_DAYS -M, --maxdays MAX_DAYS set maximum number of days before password change to MAX_DAYS -R, --root CHROOT_DIR directory to chroot into -W, --warndays WARN_DAYS set expiration warning days to WARN_DAYS
Začnime povinnou zmenou hesla po prvom prihlásení. Použijeme k tomu užívateľa
ucitel, ktorému sme nastavili predvolené heslo ucitel
a použijeme parameter -d
# chage -d 0 ucitel
Učiteľ bude následne po prvom prihlásení vyzvaný na zmenu hesla:
$ su - ucitel Password: You are required to change your password immediately (administrator enforced) Current password: New password:
Ďalej by sme chceli, aby si ho ucitel z bezpečnostných príčin pravidelne menil, takže musíme nastaviť maximálny počet dní od poslednej zmeny hesla (v našom prípade raz za mesiac):
# chage -M 30 ucitel
Ďalším častým úkonom, ktorý si ukážeme je expirácia účtov. Pri voľbe dátumu expirácie nám systém dáva hodne veľkú flexibilitu v tom ako dátum špecifikovať, ukážeme si preto aj jednoduchší, ale aj komplexnejší prístup. Expirácia ku konkrétnemu dátumu 13.1.2019 by vyzerala nasledovne:
# chage -E 01/13/2019 ucitel
Na expiráciu napr. o 42 dní od aktuálneho dátumu by sme už museli použiť
kombináciu s príkazom date
:
# chage -E $(date +42days) ucitel
Súhrn našich dosavadných zmien si môžeme pozrieť s parametrom -l
:
# chage -l ucitel Last password change : password must be changed Password expires : password must be changed Password inactive : password must be changed Account expires : Nov 14, 2018 Minimum number of days between password change : 0 Maximum number of days between password change : 30 Number of days of warning before password expires : 7
Keďže pri expirácii môžeme špecifikovať aj počet dní (od epochy 1.1.1970),
pre okamžitú expiráciu jednoducho použijeme 0
:
# chage -E 0 ucitel
Zaujímavosť:
Hoci je možné účet uzamknúť aj za pomoci passwd -l
alebo usermod -L
, tieto metódy majú efekt IBA na autentizáciu heslom do systému, pričom dovoľujú alternatívne metódy prihlásenia, napr. použitím SSH prístupu a autentizácie verejným kľúčom. Preto sme si ukázali príkaz chage
, ktorý nám pri zaručí, že účet bude skutočne nedostupný.
Odstránenie účtu
Hoci na sa na prvý pohľad môže zdať, že zmazať účet je triviálnou operáciou,
nie je tomu celkom tak a treba k tomu pristupovať s maximálnou rozvahou, inak hrozí, že zanecháme systém v nekonzistentnom stave, napr. pokus o zmazanie účtu spolu s domovským adresárom môže ovplyvniť aj iných užívateľov, ktorí mohli domovský adresár zdieľať! Ďalším problémom mazania účtov sú súbory, ktoré po danom užívateľovi zostali a ktoré je nutné dodatočne dohľadať a zmazať, nakoľko userdel
zmaže iba domovský adresár, užívateľský mailový inbox a skupinu s rovnomenným názvom. Preto dopredu zvážme, či nie je pre nás výhodnejšie účet expirovať. Ak sme sa predsa rozhodli účet a všetko s ním súvisiace zmazať, nezabudnime najprv účet expirovať, zabezpečiť, že daný užívateľ je odhlásený a že domovský adresár, skupina a mailový inbox nie sú zdieľané s inými užívateľmi. Následne užívateľa zmažeme:
# userdel -r <uzivatel>
Manuálové stránky
useradd
(1)usermod
(1)chage
(1)chsh
(1)userdel
(1)
Spravujeme skupiny
V tejto sekcii si ukážeme ako pridať do systému novú skupinu a ako si za bežného užívateľa zmeniť primárnu skupinu. Ostatné operácie nad skupinami sú nad rámec tohto školenia, pre záujemcov sú nižšie uvedené manuálové stránky.
Vytvorenie novej skupiny v systéme
Novú skupinu vytvoríme príkazom groupadd nasledovne:
# groupadd bar
Zmena primárnej skupiny užívateľa
Zmenu skupiny sme si už ukázali v sekcii o užívateľoch. Na trvalú zmenu sme potrebovali práva administrátora. Tu si ukážeme ako si užívateľ dokáže primárnu skupinu dočasne zmeniť sám, pokiaľ už je danej skupiny členom.
Príklad:
Vytvorme užívateľa foo a pridajme mu sekundárnu skupinu bar
:
# useradd foo -u 10000 -G bar # passwd fo na zopakovanio # id foo uid=10000(foo) gid=10000(foo) groups=10000(foo),1002(bar)
Za užívateľa foo si teraz v aktuálnom prostredí zmeníme primárnu skupinu na bar
:
$ newgrp bar $ id uid=10000(foo) gid=1002(bar) groups=1002(bar),10000(foo)
Ak by foo na začiatku nebol členom skupiny bar
, operácia by vyžadovala heslo do skupiny, pokiaľ žiadne neexistuje, sú potrebné práva administrátora!
Úlohy na precvičenie
- vytvorte skupinu
ucitele
s GID5001
a pridajte do nej užívateľa ucitel - vytvorte skupiny
matematika
afyzika
- vytvorte užívateľov honza, pepa, petr a nastavte im ako primárnu skupinu
studenti
, petr patrí aj do skupinymatematika
, domovské adresáre studentov nájdeme pod/home/studenti
- každý nový študent má predvolené heslo
student
, ktoré si musí pri prvom prihlásení zmeniť - nové nariadenie školy taktiež prikazuje z bezpečnostných dôvodov meniť študentom heslo každý mesiac
- honza a pepa patria do skupiny
fyzika
- honza sa rozhodol prestúpiť z fyzikálneho do matematického krúžku, vykonajte príslušnú zmenu v skupinách
- pepa je krutoprísny a rád by si nastavil login shell na
/sbin/nologin
- petr prestúpil na inú školu, preto je treba jeho účet bezpečne invalidovať, a následne zmazať, vykonajte všetky potrebné kroky
Práva v Linuxu
Co jsou to přístupová práva?
V Linuxu má každý uživatel oprávnění (právo) provádět různé činnosti, například procházet adresáře, číst a zapisovat soubory, pracovat se zařízeními a systémovými prostředky, a podobně. V případě, že nějaký uživatel nemá k určité činnosti práva, systém mu nepovolí tuto činnost vykonat. V zásadě má však každý uživatel dostatek práv na to, aby mohl se systémem smysluplně pracovat a nebyl zbytečně omezován. Pokud náhodou by během své práce potřeboval získat dočasně práva vyšší, je to otázka několika sekund, takže není většinou nutné se přihlašovat jako jiný uživatel a střídat účty. U některých jiných operačních systémů nelze lehce získat práva k administraci systému a to nutí uživatele kvůli lenosti pracovat neustále pod plnými právy administrátora. To je však veliké bezpečnostní riziko. V Linuxu toto není nutné, protože také aplikace velmi dobře pracují v rámci omezených práv a obvykle se nestává, že by aplikace měla s omezenými právy omezenou funkcionalitu. Fakt, že uživatelé a jimi spouštěné aplikace a programy mají omezená práva, a že není potřeba tyto práva nikterak navyšovat pro běžný uživatelský provoz, je jedním z důvodů, proč je operační systém Linux robustní a bezpečný operační systém.
Základní práva v Linuxu
Všechny procesy, zařízení a data v Linuxu jsou v systému reprezentovány odkazy, které se chovají jako běžný soubor, dále tedy budeme hovořit převážně o právech, které nastavujeme uživateli vzhledem k souboru. Tyto základní práva jsou tři:
- právo číst ze souboru (read, r)
- právo zapisovat do souboru (write, w)
- právo spouštět soubor (eXecute, x)
Tato základní práva lze nastavit pro tři různé „úrovně“ přístupu pro:
- jednoho konkrétního uživatele, také nazýván vlastník souboru (zpravidla ten, kdo soubor vytvořil)
- jednu konkrétní skupinu uživatelů (např. studenti)
- všechny ostatní
Takto lze například nastavit, aby vlastník souboru (ucitel) mohl ze souboru číst a také do něj zapisovat, všichni jeho žáci ze skupiny studenti z něj mohli číst, ale nemohli do něj zapisovat, a všichni ostatní (další žáci školy) k němu neměli žádná práva. Vzápětí si vysvětlíme, jak toho dosáhnout.
Zjišťujeme, jaká práva má soubor
Jaká práva který soubor má, si můžeme lehce zobrazit pomocí příkazu ls -l
. Podívejme se na následující výstup:
-rw-rw-r--. 1 teacher students 1220 Jul 24 18:10 find.py
Seznam práv je uveden hned na začátku řádku a v tomto konkrétním případě se jedná o kombinaci -rw-rw-r–.
.
Práva jsou u každého souboru zapsána jako kombinace tří tripletů (tedy celkem devíti znaků), které jsou vypsány za sebou v pořadí uživatel
, skupina
, ostatní
. Podíváme-li se podrobněji, zjistíme, že v informačním poli se však nenachází 9 pozic, ale 11 pozic (někdy pouze 10 pozic). Úplně první pozice totiž neukazuje samotná práva, ale informaci, zda se jedná o soubor (-
) nebo adresář (d
). Poslední pozice ukazuje rozšířená práva ACL, pokud jejich použití je pro daný souborový systém zapnuto. Pokud soubor nemá rozšířená práva, zobrazuje se tam symbol tečky (.
), v opačném případě symbol +
.
Zaměříme se teda na oněch devět znaků rw-rw-r–*
. Z jednotlivých tripletů pak vyplývá, že soubor umožňuje:
- uživateli soubor číst a zapisovat (
rw-
) - skupině také číst a zapisovat (
rw-
) - všem ostatním pouze číst (
r–
)
Nastavujeme práva souboru
Představme si, že výše uvedený soubor find.py
, program v Pythonu, chceme také spouštět. Řekněme, že chceme, aby vlastník měl k souboru veškerá práva, skupina studentů mohla soubor číst a také jej spouštět, a všichni ostatní ho mohli pouze číst. Práva souboru nastavíme pomocí příkazu chmod
(change mode). Pro více informací si můžete spustit také nápovědu pro tento program pomocí příkazu man chmod
.
- Příkazem
chmod u+x find.py
přidáme právo spouštět soubor. Volbau+x
říká: Uživateli (u
) přidej (+
) právo spouštění (x
). Práva číst a zapisovat už uživatel má, tak je nemusíme přidávat. - Příkazem
chmod g+x find.py
přidáme (+
) skupině (g
) právo spouštět (x
) soubor, ale odebereme (-
) právo zapisovat (w
) příkazemchmod g-w find.py
.
Právo pro ostatní (o
) nemusíme nijak upravovat, protože ostatní mohou jenom číst a to chceme.
Když si následně zobrazíme práva pro soubor find.py
, dostaneme kombinaci rwxr-xr–
, teda všechna práva pro uživatele, práva čtení a spouštění pro skupinu a práva pro čtení pro všechny ostatní. A to je, co jsme chtěli.
Ještě jednou si rozeberme jednotlivé volby příkazu chmod
:
- písmena
u
,g
,o
zapínají práva pro uživatele, skupinu, nebo ostatní - znaky
+
nebo-
přidávají nebo odebírají příslušná práva - písmena
r
,w
,x
řídí práva pro čtení, zápis a spouštění. Lze je také kombinovat, tedy je možné napsatrw
pro čtení a zápis zároveň, neborx
pro čtení a spouštění zároveň, ale takérwx
pro přidání všech práv.
Nastavení pomocí číselného (osmičkového) módu
Někdy nechceme práva nastavovat pro každou úroveň zvlášť, ale potřebujeme rychle nastavit práva pro uživatele, skupinu a ostatní zároveň. To můžeme udělat pomocí číselné kombinace. Na první pohled nemusí být přesně jasné, jak s čísly pracovat, ale pokusme se vysvětlit to na následující ukázce:
- číslice
0
představuje žádná práva - číslice
1
představuje právo spouštění (jako x) - číslice
2
představuje právo zápisu (jako w) - číslice
4
představuje právo čtení (jako r)
Kombinace různých práv potom vypočítáme jakou součet jednotlivých hodnot, můžeme tedy získat 8 různých kombinaci práv, tedy:
- číslice
0
představuje žádná práva - číslice
1
představuje právo spouštění - číslice
2
představuje právo zápisu - číslice
3
představuje právo spouštění a zápisu (1+2) - číslice
4
představuje právo čtení - číslice
5
představuje právo spouštění a čtení (1+4) - číslice
6
představuje právo zápisu a čtení (2+4) - číslice
7
představuje právo spouštění, zápisu a čtení (1+2+4)
Předcházející úkol bychom tak jednodušše mohli vyřešit pomocí zápisu chmod 754 find.py
, kdy první číslo je pro uživatele, druhé pro skupinu, a třetí pro ostatní.
Změna vlastníka a skupiny u souboru
Ne vždycky můžeme nastavit už při vytváření souborů správně práva. Někdy je potřeba později změnit nastavení vlastníka nebo skupiny. Toho dosáhneme pomocí příkazu chown
(change owner). V zásadě můžeme tento příkaz použít třemi možnými způsoby:
chown ucitel find.py
udělá vlastníkem souborufind.py
uživatele ucitel, skupina zůstane nezměněná.chown :studenti find.py
udělá spoluvlastníkem souboru skupinu studenti, vlastník samotný zůstane nezměněn.chown ucitel:studenti find.py
udělá vlastníkem souboru uživatele ucitel a spoluvlastníkem skupinu studenti.
Další použití příkazu chown lze nastudovat z manuálových stránek příkazem man chown
.
Práva a adresáře
Práva se týkají také adresářů, ale narozdíl od souborů mají práva u adresářů trochu jiný efekt:
- právo pro čtení znamená, že dotyčný může zobrazit obsah příslušného adresáře.
- právo pro zápis znamená, že dotyčný může do adresáře ukládat soubory.
- právo pro spouštění znamená, že dotyčný může do adresáře vstoupit.
Půjčujeme práva ostatním (setuid a setgid)
Z toho, co jsme si zatím ukázali, víme, že pro každý soubor lze přístupová práva udělit vlastníkovi, skupině a ostatním. Zatímco u textových souborů skoro ani nic jiného nepotřebujeme, u spustitelných souborů, hlavně těch systémových, to ne vždy stačí. Proč?
Jestliže chci například vytvořit nový adresář, potřebuju k tomu samozřejmě program mkdir
. Tento se ve Fedoře nachází v adresáři /usr/bin
. Zobrazme si jeho práva příkazem ls -l /usr/bin/mkdir
a uvidíme, jak vypadají:
-rwxr-xr-x. 1 root root 109560 Jul 13 01:40 /usr/bin/mkdir
Vidíme, že vlastníky jsou uživatel root
a skupina root
, ale ostatní také mají povoleno program spouštět (r-x
). Co se stane, pokud program spustím jako uživatel ucitel
?
Jako ucitel
patřím z hlediska tohoto programu do skupiny ostatní. Program mohu spustit, práva mi to dovolují. Program tedy běží pod uživatelem ucitel
a tak se na jeho běh vztahují omezení, které v systému má uživatel ucitel
.
Nový adresář se mi tak povede vytvořit pouze tam, kde mám právo zápisu a nikoliv jinde. V takovém případě příkaz mkdir /home/ucitel/pisemky
bude úspěšný, protože mohu zapisovat do svého domovského adresáře, ale příkaz mkdir /pisemky
skončí s chybou, protože moje práva mi neumožňují zapisovat přímo do kořenového adresáře.
mkdir: cannot create directory ‘/pisemky’: Permission denied
Co ale dělat v případě, že například chceme, aby si každý uživatel mohl sám sobě změnit heslo, aniž by k tomu potřeboval znát heslo správce? Program passwd
, který se na takovou akci používá, musí změnit systémový soubor /etc/shadow
. Podívejme se, jaká má tento soubor práva:
----------. 1 root root 1465 Aug 20 14:07 /etc/shadow
Vidíme, že nikdo, dokonce ani vlastník, nemá právo se souborem cokoliv dělat. Pouze uživatel root
může toto přísné nastavení obejít. Kdybychom tedy spustili příkaz passwd
jako uživatel ucitel
, program by neměl oprávnění se souborem /etc/shadow
nákládat a heslo bychom si tedy změnit nemohli. Jak na to?
Řešením je nastavit tzv. uid (uživatel ) nebo gid (skupina) bit, který systému řekne, že program má běžet vždy s právy vlastníka nebo skupiny, ať ho již spouští kdokoliv. Podívejme se na práva programu passwd
pomocí ls -l /usr/bin/passwd
.
-rwsr-xr-x. 1 root root 34088 Jul 14 23:01 /usr/bin/passwd
Všimněme si, že triplet pro vlastníka je rws. Symbol s právě symbolizuje fakt, že program bude spuštěn s právy vlastníka, tedy uživatele root
a tak bude kdokoliv pomocí tohoto programu pracovat se souborem /etc/shadow
. Podmínkou je, že program má nastavená spouštěcí práva i pro ostatní, což v tomto případě splněno je.
Jak nastavit UID bit?
UID bit nastavíme pomocí příkazu chmod
stejně jako bychom nastavovali jiná práva. Můžeme jej nastavit:
- pomocí symbolů, tedy
chmod u+s find.py
- pomocí čísel, tedy
chmod 4755 find.py
, kdy tento bit je zastoupen číslem 4 před klasickou číselnou trojicí.
Jak nastavit GID bit?
V případě, že chceme nastavit práva tak, aby kdokoliv mohl spouštět program jako člen určité skupiny, pak nastavíme GID bit, stejně jako bychom nastavovali UID bit:
- pomocí symbolů, tedy
chmod g+s find.py
- pomocí čísel, tedy
chmod 2755 find.py
, kdy tento bit je zastoupen číslem 2 před klasickou číselnou trojicí.
Práva procesů
Pokud si pohráváte s myšlenkou, že každý takto bude mít právo měnit hesla uživatelům v systému, musím vás zklamat. V takovémto případě si totiž operační systém hlídá také identifikační čísla uživatelů a je si vědom toho, že uživatel ucitel
s ID 1000 se pokouší změnit heslo někomu s ID 1001 a to nepovolí. Do větší hloubky v tuto chvíli nepůjdeme.
Chráníme soubory nálepkou (sticky bit)
Sticky bit je označení ochranného štítku, který chrání soubory před smazáním v adresáři, kam má přístup více lidí. Jestliže má adresář nastavený tuto ochranu, potom soubory v něm umístěné může smazat pouze jejich vlastník, vlastník daného adresáře nebo uživatel root. Toto nastavení se často používá ve veřejně přístupných adresářích, jako třeba /tmp
.
Všimněme si, že ve výpisu práv je sticky bit zaznačený písmenem t
v tripletu pro ostatní:
drwxrwxrwt. 15 root root 320 Oct 5 14:08 tmp
Sticky bit nastavíme opět buď:
- pomocí symbolického zápisu příkazem
chmod +t adresar
, nebo - pomocí číselného zápisu
chmod 1755 adresar
, kde číslice1
reprezentuje sticky bit.
Rozšířená práva (ACL práva)
Práva ACL (access control list) jsou rozšířená linuxová práva, která umožňují jemnější nastavení přístupu jednotlivým uživatelům a skupinám. Některé souborové systémy v Linuxu nemusí tento způsob práv podporovat. Ve Fedoře je standardně použit souborový systém ext4
se zapnutou podporou ACL.
Zatímco klasická práva nám umožňují, abychom nastavili možnost přístupu vlastníkovi, skupině a ostatním, ACL práva nám dovolují daleko více. Představme si příklad, kdy měl trojici učitelů (lkratky
, zpevny
, a htrojek
), skupinu studentů navštěvujících seminář z IT (itstudenti) a mnoho dalších studentů z celé školy. Kdybychom pro adresář it_seminar
chtěli nastavit práva pro čtení, zápis a spouštění všem těmto učitelům, práva pro čtení a spouštění všem studentům semináře a zbytku školy bych jinak chtěl přístup zakázat úplně, šlo by to? Se základními právy těžko. S ACL? Lehce.
Nejprve nastavíme základní práva:
- Změníme vlastníka a skupinu tak, abychom si některé požadavky vyřešili pomocí základních práv, příkazem
chown lkratky:itstudenti it_seminar
se postaráme, že pomocí základních práv budeme schopni vyřešit jednoho učitele, skupinu studentů semináře a všechny ostatní. - Nastavíme přístupová práva,
chmod 750 it_seminar
, která se postarají o to, že skupinaitstudenti
bude mít práva ke čtení a spouštění a ostatní nebudou mít práva žádná. Taktéž jeden z učitelů již bude mít potřebná práva nastavená.
Pak pomocí ACL povolíme přístup zbývajícím učitelům. Použijeme k tomu příkazu setfacl
:
setfacl -m u:zpevny:rwx it_seminar
nastaví práva rwx pro uživatelezpevny
.- Stejně nastavíme práva i dalšímu z učitelů.
Zjišťujeme nastavení práv ACL
Potřebujeme-li zjistit, zda nějaký soubor nebo adresář používá ACL práva, podíváme se na výpis práv pomocí ls -l
. Jestliže na posledním místě ve výpisu práv vidíme +, pak soubor nebo adresář má nastavená práva ACL, například:
drw-rw-r--+ 3 lkratky itstudenti 4096 Oct 2 21:53 it_seminar
Konkrétní práva zjistíme příkazem getfacl
. Takže pro výše uvedný případ, getfacl it_seminar
by mohla situace vypadat takto:
# file: it_seminar # owner: lkratky # group: itstudenti user::rwx user:zpevny:rwx user:htrojek:rwx group::r-x mask::rwx other::---
Přidáváme ACL práva
Práva se přidávají s volbou -m
. Stejnou volbou lze také stávající práva upravit.
Přidání práv uživateli
setfacl -m u:ucitel:rw soubor.txt
Přidání práv skupině
setfacl -m g:studenti:r soubor.txt
Úprava práv pro skupinu
Pokud chceme práva upravit, spustíme příkaz pro přidání práv znovu s novými parametry:
setfacl -m g:studenti:rw soubor.txt
Práva budou přenastavena.
Mažeme ACL práva
Odebrat můžeme jenom konkrétní právo (volba -x
) nebo všechna ACL práva zaráz (volba -b
).
Smazání práv konkrétním subjektům
Práva můžu odebrat uživateli i skupině. Pro uživatel platí
setfacl -x u:zpevny it_seminar
a pro skupinu
setfacl -x g:itstudenti it_seminar
Smazání všech ACL práv
Všechna práva najednou mohu odstranit použitím volby -b
.
setfacl -b find.py
Pro veškeré další použití můžete přečíst manuálové stránky příkazu setfacl
.
Správa služeb a procesů
Procesy
Termínom proces rozumieme akýkoľvek bežiaci program (program, ktorý nebeží nie je nič iné ako súbor inštrukcií uložených na disku) v systéme. Je to teda nejaká abstrakcia, ktorá má určité charakteristiky, medzi ktoré patrí jednoznačný číselný identifikátor PID (angl. process ID), virtuálne namapovaný pamäťový priestor (angl. virtual address space), stav procesu, rôzne behaviorálne vlastnosti ako zdieľanie zdrojov, obsluha signálov, komunikácia s inými procesmi atď.
Vytvorenie procesu
Nové procesy vznikajú výlučne kopírovaním existujúceho procesu, ktorý vytvorí nový proces ako svojho potomka. Je to dôsledok toho, že procesy sú v Linuxe usporiadané do stromovej hierarchie, kde budeme v neskôr praktických ukážkach pozorovať vzťah rodič-potomok a uvidíme jeho význam. To znamená, že v systéme existuje proces, ktorý je nadradený všetkým procesom, jeho PID == 1 a historicky sa nazýval init, ktorý pri štarte systému spušťal ďalšie skripty a služby, aby systém naštartoval do stavu, v ktorom s ním môžeme pracovať. Na väčšine významných distribúcií (vrátane Fedory) dnes túto úlohu plní systemd, ktoré je v porovnaní s pôvodným init komplexný subsystém, ktorý nám okrem iného poskytuje mechanizmy na správu ďalších služieb a o ktorom si povieme viac v neskoršej kapitole.
Čo sa samotného vytvorenia procesu týka, po tom, čo nadradený proces vytvorí svoju identickú kópiu (systémové volanie fork
), tento novovytvorený proces spustí nami požadovaný program (systémové volanie execve
). Detailný popis toho, čo vytvorenie procesu obnáša na pozadí je nadrámec tohoto školenia a dá sa dohľadať v literatúre.
Vytvorme si teda nejaký proces, napr. príkazom ping
:
$ ping mojefedora.cz
Program ping vznikol vytvorením kópie shellu, v ktorom sme ho spustili. A keďže proces musí mať nejaký PID, tak to overme jednoducho príkazom pgrep
v druhom terminále:
$ pgrep ping 2633
V tejto kapitole sme spomenuli, že všetky procesy vytvárajú stromovú hierarchiu s reláciou rodič-potomok. Teraz overme, že shell, v ktorom sme ping spustili je skutočne jeho rodičom. V našom druhom terminále spustime príkaz pstree
a z celého výstupu vyselektujme iba ping za použitia '|' (pipe):
$ pstree -p | grep ping |-gnome-terminal-(2038)-+-bash(2153)---ping(2633)
Vidíme, že náš ping s PID == 2633 vznikol z nejakého shellu (PID == 2153), ktorý zase vznikol ako potomok programu gnome-terminal (PID == 2038). Príkaz pstree
zobrazí úplne všetky procesy daného užívateľa (školení) v stromčeku. Ako cvičenie si spustite pstree
samostatne bez parametrov a uvidíte, že všetky procesy majú spoločný koreň proces systemd(1).
Manuálové stránky
pgrep
(1)pstree
(1)
Komunikácia/Interakcia s procesmi
Úvod
Komunikáciu v kontexte procesov všeobecne označujeme pojmom medziprocesová komunikácia (angl. inter-process communication - IPC) a môže prebiehať na rôznych úrovniach:
- súbory
- signály
- správy (angl. message passing)
- sokety
- rúry (angl. pipe)
- zdieľaná pamäť (angl. shared memory)
- iné
Pre potreby systémovej administrácie sa obmedzíme na signály, čo je špecifický druh komunikácie systémovými správami, ktoré neslúžia na prenos dát, ale naopak slúžia na kontrolu (prípadne synchronizáciu) jednotlivých procesov.
Taká kontrola bude pravdepodobne najčastejšie spočívať v ukončení procesu, ale vo všeobecnosti plnia signály oznamovaciu funkciu pre daný proces, napr. proces sa pokúsil o neoprávnenú operáciu, nastala zmena vonkajšieho okolia (odpojenie kontrolného terminálu), vynútenie nejakej akcie alebo zmeny správania procesu. Predtým než si začneme signály skúšať je nevyhnutné o nich vedieť zopár faktov. Ku každému signálu sa viaže nejaká predvolená akcia - obsluha - ktorá sa vykoná akonáhle nejakému procesu signál pošleme. Tu nám pomôže manuálová stránka signal (7)
, kde sa dozvieme, že predvolená obsluha väčšiny signálov je ukončenie procesu. Nie vždy nám bude takáto predvolená akcia postačovať, napr. by aplikácia chcela umožniť znovunačítanie svojej konfigurácie ako akciu na signál (SIGUSR1). Interne si potom aplikácia zaregistruje obsluhu daného signálu, konkrétny signál si „odchytí“ a obslúži sama. Naopak, väčšina aplikácií nebude chcieť obsluhovať všetky signály, len preto, aby predišli tomu, že by ich takmer každý signál ukončil, a preto aplikácie môžu signály ignorovať alebo zablokovať. Ak by sme ale mohli ignorovať úplne všetky signály, stratili by sme tak možnosť nežiadúci program násilne ukončiť. Z tohto dôvodu sa signály SIGKILL a SIGSTOP nedajú odchytiť, ignorovať a ani zablokovať, a o obsluhu (ukončenie alebo zastavenie) sa postará vždy kernel.
Posielanie signálov procesom
Samotné signály potom posielame procesom pomocou príkazu kill
. Hoci názov by mohol napovedať, že pôjde iba o „vraždenie“ procesov, nie je tomu tak a my si ukážeme prácu aj s inými POSIX signálmi, konkrétne sa budeme venovať nasledovným:
- SIGTERM - nenásilné ukončenie programu
- SIGKILL - násilné ukončenie programu
- SIGINT - prerušenie z klávesnice (predvolená akcia je ukončenie)
- SIGUSR1 - užívateľský signál (angl. user-defined signal, vyvolá nejakú užívateľskú akciu)
- SIGSTOP - zastavenie procesu (proces existuje, ale nebeží)
- SIGCONT - pokračovanie procesu zastaveného SIGSTOP (!pozor, proces bude pokračovať na pozadí)
- SIGHUP - signalizácia odpojenia kontrolného terminálu
Syntax príkazu je veľmi jednoduchá:
]$ kill [-signal] <PID>
SIGTERM, SIGKILL, a SIGINT
Pokiaľ nešpecifikujeme žiaden signál, pošle sa signál SIGTERM, na ktorý proces bežne reaguje tak, že zastaví činnosť, odstráni dočasné zdroje (napr. súbory, ak nejaké vytvoril) a skončí. To, že proces na tento signál po sebe „poupratuje“ je práve tým, že SIGTERM sa dá odchytiť a obslúžiť v aplikácii a preto je dobrým zvykom túto obsluhu v aplikácii zabezpečiť, v opačnom prípade sa SIGTERM a SIGKILL budú správať rovnako.
Skúsme si teda najprv SIGTERM a SIGKILL. Spustime ping
v terminále a v druhom mu pošleme SIGTERM.
# Terminal 1 $ ping # Terminal 2 $ pkill ping
Proces ping
podľa očakávania skončí (pkill
užitočná je nadstavba kill
, ktorá nám umožňuje špecifikovať proces menom a narozdiel od PID). Už sme si povedali o vzťahu rodič-potomok, tak pošlime SIGTERM shellu, ktorý je rodičom nášho procesu ping.
# Terminal 1 $ ping # Terminal 2 $ pstree -p | grep ping |-bash(28628)---ping(29006) $ kill 28628
Očakávaný výsledok je, že sa nestalo vôbec nič, pretože shell, ktorý beží ping
na popredí zablokoval obsluhu takmer všetkých signálov, ktorých mohol. Skúsme teda tento shell odstreliť násilne
$ kill -SIGKILL 28628
Tentokrát by mal terminál a shell, v ktorom ping bežal, skončiť. Posledný z trojice je SIGINT, s ktorým sme sa už stretli v predchádzajúcej lekcii. Posielať SIGTERM alebo SIGKILL procesu na popredí z iného terminálu je trochu nemotorné, a preto máme klávesovú skratku Ctrl+C, ktorá sa v kontexte signálov preloží do SIGINT, ktorého predvolenou akciou je taktiež ukončenie.
SIGUSR<X>
SIGUSR<X> je dvojica užívateľských signálov SIGUSR1 a SIGUSR2 (najčastejšie však SIGUSR1), ktoré by mali slúžiť na to, že užívateľ nimi dokáže vynútiť určitú akciu, ktorá môže viesť aj ku zmene správania aplikácie. Typicky by nám aplikácia týmto spôsobom umožnila znovu načítať svoju konfiguráciu za behu bez potreby jej ukončenia, a tým pozmeniť svoje správanie. My si ukážeme iný zaujímavý a jednoduchší príklad efektu tohto signálu. Použijeme k tomu príkaz dd
, ktorý kopíruje data zo zdroja (parameter if=
) do cieľa (parameter of=
).
# ak nepouzijem ziadne parametre, tak prikaz bude kopirovat 0 do /dev/null (tzv.sink) donekonecna $ dd if=/dev/zero of=/dev/null
My by sme ale radi vedeli, koľko dát sme takto už nakopírovali, pretože program nám v základnej konfigurácii neposkytuje žiadne štatistiky. Program dd
však dokumentuje, že na SIGUSR1 nám štatistiku vráti.
$ dd if=/dev/zero of=/dev/null & [1] 30372 # vyziadajme si statistiku $ kill -SIGUSR1 30372 37224676+0 records in 37224675+0 records out 19059033600 bytes (19 GB, 18 GiB) copied, 32.4629 s, 587 MB/s
SIGSTOP a SIGCONT
SIGSTOP je (ako názov napovedá) veľmi jednoznačný, proces, ktorý signál dostane je pozastavený - neskončil, ale ani nebeží, systém o ňom stále vie a na signál SIGCONT bude daný proces pokračovať odtiaľ kde bol pozastavený. S týmto signálom ste sa už pravdepodobne stretli, ak ste sa pokúsili spustiť na pozadí program, ktorý očakáva nejaký vstup.
$ cat & [1] 31827 [1]+ Stopped cat
Náš príkaz cat
bol ihneď po spustení na pozadí pozastavený (Stopped). Dôvod, prečo sa tak stalo je, že proces sa pokúsil prečítať zo stdin
, ktorý však neukazuje na žiadny terminál, práve preto, že proces má bežať na pozadí. Systém to vyhodnotil tak, že proces zastavil, a učinil tak signálom SIGSTOP. Úplne ekvivalentne si môžeme cat
spustiť na popredí a zastaviť ho explicitne. Následne sa pokúsime proces znovu obnoviť signálom SIGCONT.
# Terminal 1 $ cat # Terminal 2 $ kill -SIGSTOP `pgrep cat` # Terminal 1 [1]+ Stopped cat # Terminal 2 # obnovme process cat $ kill -SIGCONT `pgrep cat` # Terminal 1 [1]+ Stopped cat
Náš proces cat
bol okamžite po obnovení znovu pozastavený, prečo je tomu tak? Signál SIGSTOP okrem iného odpojil stdin
pre daný proces a keďže cat
očakáva vstup, ktorý nemá odkiaľ čítať, tak bol automaticky pozastavený, rovnako ako keby sme ho spustili na pozadí. Ako cvičenie si SIGSTOP a SIGCONT skúste na programoch, ktoré vstup nevyžadujú.
SIGHUP
SIGHUP je signál, ktorý proces dostane v prípade, ak bol jeho kontrolný terminál alebo kontrolný proces odpojený. V praxi to znamená asi toľko, že všetky programy, ktoré z daného terminálu spustím (na popredí či na pozadí) skončia v momente keď okno terminálu zavrieme. Táto reťazová reakcia je špecifická pre UNIX shell, ktorý SIGHUP odchytí a všetkým procesom, ktorých je tento shell rodičom SIGHUP prepošle. My by sme ale radi niektoré procesy bežiace na pozadí radi pred SIGHUP zachránili, urobíme to jednoducho pomocou príkazu nohup
:
$ nohup ping mojefedora.cz & [1] 588 nohup: ignoring input and appending output to 'nohup.out'
Ak by teraz nadradený shell dostal SIGHUP (zavrieme okno terminálu), náš proces bude stále v systéme bežať, vyskúšajte!
Manuálové stránky
kill
(1)pkill
(1)signal
(7)
Monitorovanie procesov
V predchádzajúcich sekciách sme načrtli príkaz pstree
, aby sme získali usporiadanie užívateľských procesov v systéme. Predtým, než sa začneme zaoberať monitorovaním procesov, ukážeme si ako získať zoznam všetkých procesov v systéme bez nutnosti vykresľovania ich vzájomných vzťahov, ako sme to videli pri pstree
. K tomu slúži príkaz ps
.
Príkaz ps:
- Vypíše zoznam procesov a informácie o nich.
- Rôzne informácie, množiny a zobrazenia pomocou prepínačov.
Príklady:
ps
(bez parametrov)- Zobrazí procesy spustené aktuálnym užívateľom v aktuálnom termináli.
]$ ps PID TTY TIME CMD 8276 pts/1 00:00:00 ps <- tento príkaz “ps” 18653 pts/1 00:00:00 bash <- tento terminál (bash)
ps u
- Zobrazí všetky procesy vlastnené aktuálnym užívateľom.
]$ ps u -> Vyskúšajte
ps aux
- Zobrazí všetky existujúce procesy na tomto systeme.
]$ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 229808 10496 ? Ss Oct01 1:04 /usr/lib/systemd/systemd --system --deserialize 165 root 2 0.0 0.0 0 0 ? S Oct01 0:00 [kthreadd] root 3 0.0 0.0 0 0 ? I< Oct01 0:00 [rcu_gp] root 5 0.0 0.0 0 0 ? I< Oct01 0:00 [kworker/0:0H] root 7 0.0 0.0 0 0 ? I< Oct01 0:00 [mm_percpu_wq] root 8 0.0 0.0 0 0 ? S Oct01 0:10 [ksoftirqd/0] root 9 0.0 0.0 0 0 ? I Oct01 0:42 [rcu_sched] …[ a veľa ďalších ]…
Pozn.: Procesy v hranatých zátvorkách []
sú systémové procesy (tzv. kernel-threads)
Pozor: Je rozdiel medzi prepínačmi s pomlčkou -
a bez, napr. ps -aux
(UNIX syntax) a ps aux
(stará BSD syntax), preto odporúčame adoptovať novšiu UNIX syntax, napr. ekvivalent ps aux
by v UNIX syntaxi vyzeral ps -eF
(niektoré stĺpčeky sa budú mierne odlišovať).
Príkaz top:
Príkaz ps
nám poskytuje obrovské množstvo informácií o procesoch, avšak má jeden zásadný problém - ps
nevypisuje štatistiky v reálnom čase, čo nás ako administrátorov zaujíma najviac. Práve preto existuje príkaz top
, ktorý periodicky obnovuje zobrazované dáta v reálnom čase. Existuje mnoho možností, ako upraviť ktoré informácie top
zobrazuje, avšak my si ukážeme iba základné zobrazenie:
]$ top top - 17:09:51 up 6 days, 8:29, 1 user, load average: 0.95, 0.86, 0.74 Tasks: 313 total, 2 running, 246 sleeping, 0 stopped, 0 zombie %Cpu(s): 3.0 us, 1.0 sy, 0.0 ni, 95.6 id, 0.1 wa, 0.2 hi, 0.1 si, 0.0 st KiB Mem : 11857404 total, 511728 free, 7916376 used, 3429300 buff/cache KiB Swap: 6033404 total, 4828844 free, 1204560 used. 4494984 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8476 user 20 0 3167768 0.983g 85780 S 3.3 8.7 91:59.69 Web Content 23078 user 20 0 2872300 654080 160476 S 3.3 5.5 63:57.09 Web Content 17343 user 20 0 2976872 997.8m 97636 S 2.3 8.6 117:51.18 Web Content 8598 user 20 0 3423596 1.208g 112256 R 2.0 10.7 188:21.10 Web Content 8337 user 20 0 10.332g 1.188g 282536 S 1.7 10.5 160:51.69 firefox 6600 user 20 0 4329020 628316 118748 S 1.0 5.3 143:07.66 gnome-shell 8500 user 20 0 1323312 101940 45948 S 1.0 0.9 0:45.07 virt-manager 477 root -2 0 0 0 0 S 0.3 0.0 0:38.68 i915/signal:0 981 rtkit 21 1 183884 20 0 S 0.3 0.0 0:01.89 rtkit-daemon 1102 root 20 0 1737932 25908 8584 S 0.3 0.2 2:41.29 libvirtd 1538 gdm 20 0 841364 10168 5168 S 0.3 0.1 0:53.87 gsd-color 8568 qemu 20 0 6451560 1.199g 24940 S 0.3 10.6 1:14.55 qemu-system-x86 10653 user 20 0 790948 103736 31252 S 0.3 0.9 40:17.50 gnome-terminal- 12428 user 20 0 152008 3876 3092 R 0.3 0.0 0:00.10 top 1 root 20 0 229808 10484 6636 S 0.0 0.1 1:06.37 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.36 kthreadd 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp 5 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H
Okrem informácií o procesoch nám top
v „hlavičke“ zobrazuje aj ďalšie iné zaujímavé informácie:
Riadok 1 - uptime a load average
- aktuálny čas a koľko času ubehlo od posledného štartu systému (6 dní).
- počet aktívnych užívateľov v systéme - koľko sedení (angl. sessions) existuje, dá sa overiť príkazom
who
(u nás 1) - priemerná záťaž systému (angl. load average) za posledných 1 / 5 / 15 minút
- záťaž je vyjadrená vždy relatívne voči jednoprocesorovému systému, t.j. záťaž 1.0 na jednojadrovom CPU je plné vyťaženie, zatiaľ čo na 2 jadrách je to iba 50% záťaž!
Riadok 2 - informácie o procesoch (úlohách)
- celkovo 313 procesov (úloh), 2 aktuálne bežia, 246 sú v spánkovom režime, žiadne procesy nie sú pozastavené ani zombie (viď Stavy procesu nižšie)
Riadok 3 - %CPU - percentuálne vyjadrenie koľko procesorového času využívajú rôzne procesy
- us - čas strávený behom užívateľských procesov bez priority
- sy - čas strávený behom systémových procesov
- ni - čas strávený behom už. procesov s prioritou (viď Niceness)
- zvyšok je čas strávený rôznymi druhmi prerušenia, obsluhou a systémovými volaniami (viď manuálovú stránku
top
)
Záhlavie procesov:
PR
aNI
- priority, nice value- Tieto stĺpce ukazujú priority daného procesu, prípadne jeho “niceness” hodnotu
S
- State - Stav procesu- R - runnable - Pripravený / Bežiaci
- S - interruptible sleep - Spiaci
- D - uninterruptible sleep - Čakajúci (väčšinou na dokončenie I/O)
- Z - zombie - Mŕtvy / Dokončený
- T - stopped / parked - Zastavený
Pozn.: V systémoch UNIX je dobrým zvykom, aby rodičovské procesy čakali na ukončenie svojich potomkov, ak sa tak nestane, tak vznikajú tzv. zombie procesy - to sú také procesy, ktoré síce ukončili činnosť, no ich rodičovský proces nepotvrdil či neakceptoval ich ukončenie, a preto zostávajú uvedené v tabuľke procesov a zostanú v nej dovtedy, kým ich ukončenie niekto neprijme (ak by rodičovský proces skončil, prevezme ich automaticky init a ihneď prijme všetky ukončené procesy). Zombie procesy síce nespotrebovávajú výpočetné zdroje, ale blokujú dostupný PID, ak je v systéme príliš veľa zombie procesov, skonzumujú všetky možné PIDy a nebude možné vytvoriť nové procesy.
Memory
- Údaje o použití pamäte- VIRT - virtual memory space (process block)
- Všetka pamäť, ktorú má process k dispozícii (zásobník, halda, exekucný kód, atď.).
- RES/RSS - resident set size
- Časť (podmnožina) VIRT, ktorá je načítaná v RAM
- Zvyšok može byť na disku (swap) alebo SHR patriace inému procesu.
- SHR - shared memory
- Časť, ktorá patrí tomuto procesu a je zároveň zdieľaná.
- %MEM
- Koľko percent z celkovej dostupnej pamäte proces používa (RES / RAM)
Vďaka tomu, že top
je interaktívny, tak nám umožňuje priamo s procesmi interagovať, napr. im posielať signály. Skúsme nasimulovať situáciu, kedy nám systém vyťažuje nejaký nežiadúci proces a my to chceme detekovať a proces odstrániť. K tomu budeme potrebovať balíček stress, ktorý dokáže simulovať vyťaženie rôznych aspektov systému.
$ sudo dnf install -y stress $ stress --cpu 1 stress: info: [22255] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
$ top top - 22:58:25 up 12 days, 16:47, 1 user, load average: 0.94, 0.85, 0.73 ... PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 22359 skoleni+ 20 0 3880 100 0 R 99.7 0.0 0:32.49 stress ...
Vidíme, že náš nežiadúci proces konzumuje takmer 100% procesorového času, vráťme sa k interaktívnemu top
a postupujme nasledovne:
# stlacme 'k', top sa nás spýta, ktorému procesu budeme posielať signál ... MiB Swap: 0.0 total, 0.0 free, 0.0 used. 8069.7 avail Mem PID to signal/kill [default pid = 22359] ... # Enter # zvolme signal, my volime nasilnu cestu - sigkill ... Send pid 22359 signal [15/sigterm] sigkill ... # overme, ze proces 'stress' naozaj skoncil $ pgrep stress $
Manuálové stránky
ps
(1)top
(1)
Pokročilé nástroje monitorovania
Nástroj htop
Hoci je top
súčasťou základnej inštalácie, v praxi sa pravdepodobne najčastejšie stretneme s používaním nadstavby htop
, ktorý má prijateľnejšie konfigurovateľné rozhranie v ncurses, ktoré nám interakciu značne uľahčuje, napr. máme možnosť sa pohybovať šípkami a selektovať tak procesy (je potrebné doinštalovať balíček htop).
Nástroj glances
glances
je multiplatformový ultimátny nástroj pre systémových administrátorov, ktorý združuje všetky dôležité informácie o systéme (I/O, sieťový traffic, vyťaženie CPU a MEM, stav súborového systému) kombinovanom s výstupom top
v prehľadnom kompaktnom rozložení (je potrebný balíček glances).
Iné nástroje
atop
- rozšírenie
htop
, poskytuje prakticky rovnaké informácie akoglances
v tradičnej „terminálovej“ podobe
nmon
- komplexný monitoring v rozhraní ncurses, jednotlivé aspekty systému sa dajú vypínať a zapínať podľa potreby, výstup je v podobe grafov
nethogs
- v podstate
top
pre sieťovú komunikáciu, ak sa vyskytne náhly a nečakaný nárast v sieťovej komunikácii,nethogs
je ten správny program na analyzovanie, ktorý proces je za to zodpovedný
Priorita a "niceness"
V predchádzajúcich sekciách boli spomenuté termíny ako priorita a niceness. Aby sme im porozumeli je nutné si najprv povedať niečo o plánovaní procesov.
Plánovanie procesov
Plánovanie je druh aktivity, ktorá nám dovoľuje multitasking, teda konkurentné vykonávanie viaverých úloh za určité časové obdobie. Plánovač je kus kernel kódu, ktorý mapuje vykonávanie úlohy (angl.task, to môže byť proces alebo vlákno, plánovaču je to jedno, vidí iba „úlohu“) na dostupné výpočetné zdroje. To akým spôsobom sa procesy plánujú je nadrámec tohto kurzu a vyžaduje značné znalosti o konceptoch OS. Dôoležité je vedieť, že Linux nám nastaviť niekoľko typov plánovacích algoritmov (dokonca sa môžu používať rôzne algoritmy sučasne), v mnohých prípadoch budú tieto algoritmy postavené na priorite procesov.
Priority
Linux rozoznáva 140 priorít v 2 rôznych rozsahoch
- [1,99] pre real-time procesy (to sú také, ktoré uvoľnia zdroje iba ak sa nájde niekto s vyššou prioritou alebo keď skončia, taktiež majú tvrdé limity, t.j. proces musí dokončiť úlohu v stanovenom časovom okne)
- pre real-time priority platí: 1 < 99 (hodnoty sú v skutočnosti interne invertované)
- [100,139] - interval pre normálne (user-space) procesy, 100 > 139
Niceness (NI)
- hodnota v user-space, ktorá sa mapuje na skutočnú PR prioritu v kerneli, ktorá sa preloží do daného rozsahu [100,139]
- rozsah [-20,19] - čím menšie číslo, tým väčšia priorita procesu (štandardne však 0)
- NI slúži len ako váha pre plánovač, aby určil skutočnú prioritu PR
- na výpočet skutočnej priority sa používa vzťah:
PR = 20 + NI
My sa teraz zamierame na to, ako hodnoty „nice“ nastaviť. Slúži k tomu dvojica príkazov nice
a renice
, ktoré nastavujú prioritu novým, resp. menia prioritu bežiacim procesom.
Spustime opäť dd
a nastavme rovno nice na 5
$ nice -5 dd if=/dev/zero of=/dev/null & $ top 5537 skoleni 25 5 3880 892 824 R 97.3 0.0 0:04.19 dd 1437 skoleni 20 0 3453680 356776 189016 S 1.0 4.4 8:19.49 gnome-shell ...
Vidíme, že hoci sme spustili dd
s nižšou prioritou, vyťažuje náš systém najviac. V systéme jednoducho nebeží dostatok aktívnych služieb, ktoré by potrebovali konzumovať zdroje. Teraz pridajme náš program stress a pozorujme zmenu:
$ stress -c 5 -m 3 -i 2 & $ top 11361 skoleni 20 0 3880 100 0 R 42.4 0.0 0:26.08 stress 11360 skoleni 20 0 266028 73492 268 R 41.7 0.6 0:26.35 stress 11362 skoleni 20 0 266028 48940 268 R 40.7 0.4 0:27.07 stress 11356 skoleni 20 0 266028 181468 268 R 40.4 1.5 0:25.71 stress 11354 skoleni 20 0 3880 100 0 R 36.8 0.0 0:24.80 stress 11363 skoleni 20 0 3880 100 0 R 35.1 0.0 0:25.97 stress 11358 skoleni 20 0 3880 100 0 R 28.5 0.0 0:25.37 stress 5537 skoleni 25 5 215016 892 824 R 14.9 0.0 0:04.53 dd 1437 skoleni 20 0 3453680 356776 189016 D 14.6 2.9 190:30.40 gnome-shell
Stress test nám nám úspešne vyťažuje celý systém. Skúsme niektorým z procesov stress
nastaviť hodnotu nice vyššie než má dd
. Ideálne použijeme htop
, kde sa hodnota nice dá zvyšovať klávesou F8. Výsledok by mohol vyzerať nasledovne:
$ top PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 11360 skoleni 20 0 266028 64780 268 R 87.4 0.5 3:50.96 stress 11361 skoleni 20 0 3880 100 0 R 81.5 0.0 3:45.24 stress 11376 skoleni 25 5 215016 892 824 R 27.2 0.0 1:29.01 dd 11363 skoleni 27 7 3880 100 0 R 26.8 0.0 2:12.81 stress 11356 skoleni 26 6 266028 129196 268 R 25.2 1.1 2:25.45 stress
Program dd
sa teda plánuje častejšie ako niektoré procesy programu stress
. Zníženie priority môžeme vyskúšať aj manuálne príkazom renice
$ renice -n 15 11360 $ top PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 11361 skoleni 20 0 3880 100 0 R 76.8 0.0 5:43.19 stress 11376 skoleni 25 5 215016 892 824 R 56.6 0.0 2:26.26 dd 11356 skoleni 26 6 266028 163780 268 R 44.0 1.3 3:15.84 stress 11363 skoleni 27 7 3880 100 0 R 42.7 0.0 2:54.81 stress 11360 skoleni 35 15 266028 31516 268 R 19.5 0.3 5:44.80 stress
Čo ak by sme naopak chceli prioritu zvýšiť (napr. pre program dd
):
$ renice 0 11376 renice: failed to set priority for 11376: Permission denied
Vidíme, že na zvýšenie priority je potreba práva užívateľa root. Je to bezpečnostné opatrenie, aby si aplikácie samy nemohli prioritu zvyšovať a ochromiť celý systém.
Úloha: Skúste zvýšiť prioritu procesu s právami roota.
Manuálové stránky
sched
(7)nice
(1)renice
(1)
Služby
Službou v Linuxe nazývame aplikáciu (proces) alebo súbor aplikácií tvoriacich logický celok, ktoré bežia na pozadí a typicky čakajú na príchodzie požiadavky, ktoré obsluhujú (toto však nie je nutná podmienka). Existujú rôzne subsystémy (príp. softvérové kolekcie) na vytváranie a správu služieb, ale na väčšine dnešných distribúcií túto úlohu plní systemd. My sme systemd spomenuli ako predka všetkých procesov s PID == 1. Okrem kľúčovej úlohy init systému, ktorý nainicializuje celý user-space, plní systemd zároveň úlohu správcu služieb a systému ako takého.
Systemd units
Systemd nespravuje iba služby. Podobne ako plánovač v kerneli pristupuje k procesom a vláknam transparentne a jednotne ich nazýva tasks, systemd dokáže spravovať aj sokety, mount pointy, časovače (systemd.timer
ako náhrada za cron
), targets (target by sa dal v kontexte systemd preložiť ako referenčný bod - checkpoint - pre iné služby, uvidíme neskôr), a ďalšie iné entity, ktoré združene nazývame units.
Pozn.: všetky typy units rozoznáme podľa koncovky (.service, .mount, .target, .timer, atď.)
Vstupnou bránou do správy systemd je príkaz systemctl
, ktorým má obrovské množstvo zanorených príkazov, ktoré budeme v ďalších ukážkach používať.
Vypíšme si teda, aké jednotky v systéme vôbec máme.
$ systemctl list-units
Príkaz nám vrátil zoznam úplne všetkých jednotiek, o ktorých systemd vie. Keďže my sa venujeme službám, tak pridaním prepínača sa obmedzíme iba na služby
$ systemctl list-units -t service UNIT LOAD ACTIVE SUB DESCRIPTION abrt-journal-core.service loaded active running Creates ABRT problems from coredumpctl messages ... upower.service loaded active running Daemon for power management user-runtime-dir@1000.service loaded active exited /run/user/1000 mount wrapper user@1000.service loaded active running User Manager for UID 1000 wpa_supplicant.service loaded active running WPA supplicant LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 61 loaded units listed. Pass --all to see loaded but inactive units, too. To show all installed unit files use 'systemctl list-unit-files'.
Ako nám povedala nápoveda na konci, zoznam obsahuje iba aktívne služby, pre vypísanie úplne všetkých služieb by sme museli pridať parameter –all
(Vyskúšajte!). Ku každej službe prislúcha konfiguračný súbor v súborovom systéme, pre ich výpis by sme použili vnorený príkaz list-unit-files
, ktorý ponúka kompaktnejší výstup.
$ systemctl list-unit-files -t service UNIT FILE STATE abrt-ccpp.service disabled abrt-journal-core.service enabled abrt-oops.service enabled abrt-pstoreoops.service disabled abrt-vmcore.service enabled ...
Vďaka týmto 2 veľmi podobným príkazom môžeme pozorovať základné vlastnosti každej služby, ktoré nám hovoria niečo o ich stave:
- loaded - konfiguračný súbor služby bol vporiadku načítaný
- active - tzv.high-level aktivačný stav, generalizácia sub, pokiaľ služba neskončila s chybou, tak je vnímaná ako active
- sub - tzv. low-level aktivačný stav, popisuje, či aplikácia reálne beží, skončila úspešne alebo s chybou
- enabled - značí, že služba má bežať po štarte systému
- disabled - značí, že služba nemá bežať po štarte systému, beží teda na vyžiadanie
Keď už sme si povedali, v akých stavoch sa služby môžu nachádzať, zobrazme si stav a bližšie informácie o konkrétnej službe (sshd) v danom momente. K tomu slúži vnorený príkaz status
systemctl status sshd ● sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: disabled) Active: active (running) since Sun 2019-04-21 19:14:04 CEST; 44min ago Docs: man:sshd(8) man:sshd_config(5) Main PID: 819 (sshd) Tasks: 1 (limit: 4915) Memory: 2.2M CGroup: /system.slice/sshd.service └─819 /usr/sbin/sshd -D -oCiphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,... Apr 21 19:14:04 skoleni systemd[1]: Starting OpenSSH server daemon... Apr 21 19:14:04 skoleni sshd[819]: Server listening on 0.0.0.0 port 22. Apr 21 19:14:04 skoleni sshd[819]: Server listening on :: port 22. Apr 21 19:14:04 skoleni systemd[1]: Started OpenSSH server daemon.
Z výstupu okrem iného vidíme, že služba sshd
je nastavená ako enabled, a teda sa má spustiť po štarte systému. Skúsme teraz naštartovať nejakú službu explicitne. Na našich strojoch by mohla byť dobrým príkladom služba httpd (webový server), ktorý ani nebeží a ani nemá bežať po štarte systému, poďme to zmeniť. Službu štartujeme príkazom start
(root)$ systemctl start httpd $ systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled) Active: active (running) since Sun 2019-04-21 20:01:09 CEST; 3s ago
Apache server síce beží, ale po reštarte už bežať nebude, je potrebné službu povoliť (enable).
(root)$ systemctl enable httpd # overte, ze httpd bezi po restarte $ systemctl status httpd
Pozn.: My sme si ukázali, ako naštartovať a povoliť službu v 2 krokoch, v praxi sa obe operácie dajú spraviť v 1 kroku za použitia systemctl enable –now <service>
.
Analogicky by sa použili opačné operácie:
systemctl stop <service>
- zastaví bežiacu službusystemctl restart <service>
- zastaví a znovu spustí službusystemctl disable <service>
- zakáže naštartovanie služby po reštarte systému
Manuálové stránky
systemd.unit
(5)systemd.service
(5)systemctl
(1)
Konfiguračné súbory
Konfiguračné súbory služieb môžu byť v systéme uložené hneď na niekoľkých miestach:
/etc/systemd/system
- lokálna perzistentná konfigurácia, sem patria všetky užívateľské služby s efektom na celý systém/run/systemd/system
- dočasné konfigurácie pre dané systémové sedenie/usr/lib/systemd/system
a/usr/local/lib/systemd/system
- konfiguračné súbory, ktoré sa nainštalovali ako súčasť nejakého balíčku, neodporúča sa pracovať s týmito konfiguračnými súbormi priamo
Občas ale potrebujeme konfiguráciu nainštalovaných služieb pozmeniť podľa našich požiadavkov. Ak teda nemáme pracovať s konfiguráciami v /usr
priamo, mohli by sme vytvoriť našu vlastnú identickú kópiu danej služby a používať ju namiesto tej nainštalovanej, ale asi vidíme, že to nie je zrovna efektívny prístup. Systemd nám totiž poskytuje príkaz edit
, ktorý dokáže meniť exitujúce konfigurácie za pomoci špeciálneho súboru, ktorý sa vytvorí automaticky ako /etc/systemd/system/<sluzba>.d/override.conf
.
My si to ukážeme na príklade s httpd
. Ako každá iná aplikácia, aj httpd
môže skončiť abnormálne (napr. neoprávnený prístup do pamäte). V kontexte systemd by to znamenalo, že httpd
prejde do chybného stavu a služba prestane bežať, čo spôsobí výpadok služby pre klientov. Odhalenie a odstránenie príčiny je nesmierne dôležité, ale za určitých okolností chceme, aby služba bežala naďalej, než zistíme, prečo v skutočnosti spadla. V manuálovej stránke nájdeme parameter Restart=
, ktorý dovoľuje práve špecifikovať, za akých okolností sa má daná služba reštartovať.
# najprv simulujme pad httpd bez zmeny nastaveni (root)$ pkill -SIGSEGV httpd (root)$ systemctl status httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled) Drop-In: /etc/systemd/system/httpd.service.d └─override.conf Active: failed (Result: core-dump) since Mon 2019-04-22 13:29:06 CEST; 1s ago Docs: man:httpd.service(8) Process: 7177 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=dumped, signal=SEGV) Main PID: 7177 (code=dumped, signal=SEGV) Status: "Running, listening on: port 80"
Upravme teda nastavenie httpd
tak, aby sa pri chybe reštartoval
(root)$ systemctl edit httpd [Service] Restart=on-abnormal # overme, ze override.conf sa vytvoril nasou zmenou (root)$ systemctl cat httpd ... # /etc/systemd/system/httpd.service.d/override.conf [Service] Restart=on-abnormal ... # teraz nastartujme httpd znovu a vyskusajme nasimulovat pad (root)$ systemctl restart httpd (root)$ pkill -SIGSEGV httpd ● httpd.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled) Drop-In: /etc/systemd/system/httpd.service.d └─override.conf Active: active (running) since Mon 2019-04-22 13:41:56 CEST; 1s ago Docs: man:httpd.service(8) Main PID: 7846 (httpd)
Manuálové stránky
systemd.unit
(5)systemd.service
(5)systemctl
(1)
Vytvárame systémovú službu
V predchádzajúcej sekcii sme si na príklade ukázali ako zmeniť konfiguráciu existujúcej služby. V tejto sekcii si vytvoríme vlastnú službu úplne od začiatku. V našom prípade pôjde o systémovú službu a preto budú potrebné práva roota po celý čas.
Vyrobme službu, ktorá nám zaloguje aktuálny dátum a nazvime ju mydate.service a vytvoríme príslušný súbor v /etc/systemd/system
s nasledujúcim obsahom:
(root)$ cat /etc/systemd/system/mydate.service [Unit] Description=Ukazem datum [Service] Type=oneshot ExecStart=date
Parameter Type=
hovorí, o aký druh služby sa jedná, naša služba je jednorázová (angl.oneshot), teda vypíše dátum a skončí. Parameter ExecStart
zase vraví, čo sa má vykonať, ak spustíme službu, v našom prípade sa zavolá date
.
K tomu, aby systemd vedel o našej novej službe je potrebné najskôr zabezpečiť, že súbor má správne SELinux práva, aby ho systemd mohol vôbec čítať.
(root)$ ls -lZ /etc/systemd/system/mydate.service -rw-r--r--. 1 root root unconfined_u:object_r:systemd_unit_file_t:s0 0 Apr 22 13:54 /etc/systemd/system/mydate.service (root)$ restorecon -FRvv /etc/systemd Relabeled /etc/systemd/system/mydate.service from unconfined_u:object_r:systemd_unit_file_t:s0 to system_u:object_r:systemd_unit_file_t:s0
Teraz už môžeme povedať systemd o našej novej službe, to sa robí príkazom daemon-reload
.
(root)$ systemctl daemon-reload (root)$ systemctl list-unit-files -t service mydate.service UNIT FILE STATE mydate.service disabled
Po naštartovaní služby by sme mali vidieť zmenu v logu:
(root)$ systemctl start mydate (root)$ systemctl status mydate ● mydate.service - Ukazem datum Loaded: loaded (/etc/systemd/system/mydate.service; disabled; vendor preset: disabled) Drop-In: /etc/systemd/system/mydate.service.d └─override.conf Active: inactive (dead) (root)$ journalctl -e -u mydate Apr 22 14:01:27 skoleni systemd[1]: Starting Ukazem datum... Apr 22 14:01:27 skoleni date[8755]: Mon Apr 22 14:01:27 CEST 2019 Apr 22 14:01:27 skoleni systemd[1]: Started Ukazem datum.
Zároveň vidíme, že tým, že je naša služba nastavená ako oneshot, tak ihneď prejde do stavu inactive. Ak by sme chceli zachovať stav active aj keď proces už skončil, môžeme tak učiniť parametrom RemainAfterExit
.
(root)$ systemctl cat mydate.service # /etc/systemd/system/mydate.service [Unit] Description=Ukazem datum [Service] Type=oneshot ExecStart=date # /etc/systemd/system/mydate.service.d/override.conf [Service] RemainAfterExit=yes
Ďalej by sme chceli, aby sa naša služba púšťala vždy po štarte systému, tak ju skúsme povoliť, ako sme si ukazovali vyššie
(root)$ systemctl enable myservice The unit files have no installation config (WantedBy, RequiredBy, Also, Alias settings in the [Install] section, and DefaultInstance for template units). This means they are not meant to be enabled using systemctl. Possible reasons for having this kind of units are: 1) A unit may be statically enabled by being symlinked from another unit's .wants/ or .requires/ directory. 2) A unit's purpose may be to act as a helper for some other unit which has a requirement dependency on it. 3) A unit may be started when needed via activation (socket, path, timer, D-Bus, udev, scripted systemctl call, ...). 4) In case of template units, the unit is meant to be enabled with some instance name specified.
Systemd nám hneď povie, že s našou konfiguráciou nie je niečo vporiadku. Chýba nám tam totiž sekcia [Install]
, ktorá je pre systemd kľúčová, pretože mu vraví, kedy našu službu môže spustiť (služby totiž môžu mať na sebe závislosti). Tu sa dostávame k téme targets.
Systemd target
Systemd target je špeciálny druh jednotky, ktorý zoskupuje iné jednotky a vytvára tak určitý synchronizačný checkpoint pre služby, ktoré majú definované závislosti, napr. nemá význam spúšťat webserver, keď nemáme spustený NetworkManager a nemáme nakonfigurovanú sieť. Takáto závislosť sa potom prejaví v konfigurácii httpd
nasledovne
$ systemctl cat httpd [Unit] ... After=network.target remote-fs.target nss-lookup.target httpd-init.service ...
Takýchto synchronizačných bodov je v systemd niekoľko a tie úplne najzákladnejšie korešpondujú s operačnými režimami sytému SysV, známymi ako runlevels. Hoci systemd rozoznáva aj runlevels, správame sa k nim jednotne ako aj k iným targets. Mapovanie medzi starými runlevels a systemd je pekne vidno tu.
Vráťme sa teda k našej službe a nastavme ju ako službu spustiteľnú vrámci multi-user.target
a službu povoľme:
(root)$ systemctl cat mydate ... # /etc/systemd/system/mydate.service.d/override.conf [Service] RemainAfterExit=yes [Install] WantedBy=multi-user.target (root)$ systemctl enable mydate Created symlink /etc/systemd/system/multi-user.target.wants/mydate.service → /etc/systemd/system/mydate.service. (root)$ systemctl status mydate ● mydate.service - Ukazem datum Loaded: loaded (/etc/systemd/system/mydate.service; enabled; vendor preset: disabled) ...
Manuálové stránky
systemctl
(1)systemd.target
(5)