Cvičení: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.

Na tomto cvičení probereme několik témat, která nejsou příliš rozsáhlá. Navíc spolu souvisí jen částečně, takže si můžete velké části přečíst v prakticky libovolném pořadí, které vám vyhovuje.

Tohle je asi nejteoretičtější cvičení: není tu moc věcí k přímému procvičení ale zato poměrně dost informací, které snad zlepší propojení dřívějších částí.

Tohle cvičení také obsahuje malý domácí úkol za dva body.

Předstartovní kontrola

  • Pamatujete si, k čemu se používají shellové wildcardy (zástupné znaky).
  • Víte, že řetězce v C jsou zakončeny nulovým bajtem.

Unixová přístupová práva

Zatím jsme spíše ignorovali fakt, že je na každém Linuxovém systému více uživatelských účtů. A také to, že uživatelé nemůžou přistupovat ke všem souborům. V této části vysvětlíme základy Unixových přístupových práv, a jak je interpretovat.

Konec konců se můžete přihlásit ke sdílenému počítači a měli byste být schopni pochopit, k čemu máte přístup a k čemu ne.

Vzpomeňme si, co jsme říkali o /etc/passwd – obsahuje seznam uživatelských účtů na tom konkrétním stroji (technicky to není jediný možný zdroj uživatelských záznamů, ale prozatím je to dobrá aproximace).

Každá běžící aplikace, tedy process, je vlastněná jedním z uživatelů z /etc/passwd (opět to tu trochu zjednodušujeme). Také říkáme, že tento proces běží pod konkrétním uživatelem.

A každý soubor v souborovém systému (včetně jak reálných souborů jako ~/.bashrc, tak virtuálních jako /dev/sda nebo /proc/uptime) má svého vlastníka.

Když se proces pokouší číst nebo upravovat soubor, operační systém rozhodne, jestli je tato operace oprávněná. Toto rozhodnutí je založené na vlastníkovi souboru, vlastníkovi procesu a právech definovaných pro daný soubor. Je-li operace zakázána, vstupní/výstupní funkce ve vašem programu vyvolá výjimku (např. v Pythonu) nebo vrátí chybový kód (v C).

Protože model založený pouze na vlastnících by nebyl dostatečně flexibilní, máme také skupiny uživatelů (definované v /etc/group). Každý uživatel je členem jedné nebo více skupin, z nichž jedné se říká primární skupina. Tyto skupiny jsou asociované s každým procesem daného uživatele. Soubory pak mají jak vlastnícího uživatele, tak vlastnící skupinu.

Soubory mají přiřazené tři množiny oprávnění: jednu pro vlastníka souboru, druhou pro uživatele ve vlastnící skupině a třetí pro všechny ostatní uživatele. Přesný algoritmus pro určení, která množina bude použita, vypadá takto:

  1. Je-li uživatel, který proces spustil, stejný jako vlastník souboru, jsou použita přístupová práva vlastníka (někdy také označované jako uživatelská přístupová práva).
  2. Je-li uživatel běžícího procesu ve skupině, která byla nastavena u souboru, jsou použita skupinová (group) přístupová práva.
  3. Jinak systém použije ostatní přístupová práva.

Každá množina oprávnění obsahuje tři práva: čtení (r), zápis (w), spouštění (execute, x):

  • Operace čtení a zápisu souboru se chovají očekávatelně.

  • Právo na spouštění se ověřuje v případě, kdy se uživatel snaží spustit soubor jako program (připomeňme, že bez chmod +x, se v takovém případě objevovala chyba Permission denied: zde je její důvod).

    • Poznamenejme, že skript, který lze číst, ale není spustitelný, můžeme stále spustit zavoláním příslušného interpretru manuálně.
    • Po spuštění programu nový proces zdědí vlastníka a skupiny svého rodiče (např. shellu, který jej spustil). Vlastnictví samotného spustitelného souboru není směrodatné po jeho spuštění. Například /usr/bin/mc vlastní uživatel root, ale přesto může být spuštěn libovolným uživatelem a běžící proces je poté vlastněný tím, kdo jej spustil.

Stejná oprávnění se vztahují také na adresáře, ale jejich význam je trochu odlišný:

  • Právo na čtení umožňuje uživateli číst seznam souborů uvnitř (běžných, symlinků, podadresářů, atd.).
  • Právo na zápis uživateli umožňuje vytvářet, odstraňovat a přejmenovávat soubory uvnitř. Všimněte si, že odstranění práva na zápis k souboru uvnitř zapisovatelného adresáře, je bezvýznamné, protože to uživateli nezabrání v tom, aby soubor nahradil úplně novým.
  • Spustitelné (executable) právo na adresáři umožňuje uživateli otevírat položky uvnitř. (Má-li adresář x, ale ne r, můžeme používat soubory uvnitř, pokud známe jejich názvy, nemůžeme ale vypsat jejich seznam. Na druhou stranu, má-li adresář r, ale ne x, můžeme vypsat seznam souborů, ale nemůžeme je použít.)

Oprávnění souboru nebo adresáře může měnit pouze jejich vlastník a to bez ohledu na aktuální oprávnění. To znamená, že vlastník může sám sobě odepřít přístup odstraněním všech přístupových práv, ale stejně jej poté může později obnovit.

Uživatelský účet root

Vedle účtů pro normální uživatele je zde vždy i účet pro takzvaného superuživatele – obvykle nazývaného jen root – ten má administrátorská práva a je tedy oprávněn dělat cokoliv s libovolným souborem v systému. Ověřování oprávnění popsané výše jednoduše vůbec neplatí pro procesy vlastněné rootem.

Zobrazování a změna oprávnění

Podíváme-li se na zkratky rwx pro jednotlivá oprávnění, možná vám budou povědomá:

drwxr-xr-x 1 intro intro 48 Feb 23 16:00 02/
drwxr-xr-x 1 intro intro 60 Feb 23 16:00 03/
-rw-r--r-- 1 intro intro 51 Feb 23 16:00 README.md

První sloupec obsahuje typ položky (d pro adresář, - pro obyčejný soubor, atd.) a tři trojice oprávnění. První trojice se vztahuje k vlastníkovi souboru, prostřední ke skupině a poslední ke zbytku světa (k ostatním). Třetí a čtvrtý sloupec obsahují vlastníka a skupinu souboru.

Vaše osobní soubory v domovském adresáři budou typicky mít za vlastníka vás spolu se skupinou stejného jména. Jde o výchozí konfiguraci, která brání ostatním uživatelům, aby viděli vaše soubory.

Zkontrolujte, zda toto platí pro všechny adresáře pod /home na sdíleném počítači.

Poznamenejme, že většina souborů je ve skutečnosti přístupná ke čtení všem.

To je v pořádku, protože když se podíváte na oprávnění pro svůj ~, uvidíte, že je to typicky drwx------. Jen vlastník jej může upravovat a provést cd dovnitř. Vzhledem k tomu, že nikdo nemůže změnit svůj pracovní adresář na vaši domovskou složku, nikdo nemůže ani číst vaše soubory (technicky, čtení souboru znamená projít celou adresářovou strukturu a ověřit přístupová práva na celé této cestě).

Na změnu oprávnění můžete použít program chmod. Ten má obecně formát

chmod WHO[+=-]PERMISSION file1 file2 ...

WHO může být prázdné (pro všechny – uživatele, skupinu a ostatní) nebo určení u, g nebo o. A PERMISSION může být r, w nebo x.

Je možné je kombinovat, takže např. g-r,u=rw odstraní právo na čtení souboru pro skupinu a nastaví oprávnění čtení i zápisu pro vlastníka (čili soubor nebude spustitelný bez ohledu na předchozí stav executable bitu).

Sticky a jiné bity

Když spustíte následující příkaz, uvidíte trochu jiný výstup, než byste nejspíš očekávali.

ls -ld /usr/bin/passwd /tmp
drwxrwxrwt 23 root root   640 Mar  3 08:15 /tmp/
-rwsr-xr-x  1 root root 51464 Jan 27 14:47 /usr/bin/passwd*

Můžete si všimnout, že /tmpt na místě executable bitu a passwd tam má s.

Jde o speciální varianty executable bitu. Bit t u adresáře znamená, že uživatel může odstranit jen své vlastní soubory. Důvod je jednoduchý – neměli byste mít možnost odstraňovat cizí soubory uvnitř /tmp. S použitím jen základních oprávnění by toto nebylo možné.

Bit s (set-uid) je trochu trikovější. Ten specifikuje, že bez ohledu na to, kdo spustil shell, passwd se vždy spustí pod uživatelem vlastnícím tento soubor (což je zde root).

Přestože to může vypadat neužitečně, jde o jednoduchý způsob, jak umožnit spouštění některých programů s vyššími oprávněními. passwd je typický příklad. Tento příkaz umožňuje uživateli změnit jeho heslo. To je ale uložené v souboru, který není přístupný ani ke čtení nikomu kromě roota (z očividných důvodů). Přiřazení bitu s ke spustitelnému souboru znamená, že proces poběží pod rootem a bude tak moci upravovat databázi s uživateli (tedy /etc/passwd a /etc/shadow, který obsahuje vlastní hesla).

Vzhledem k tomu, že změnu oprávnění může provést pouze vlastník souboru, není zde nebezpečí, že by podlý uživatel přidal bit s k jiným spustitelným souborů.

Jsou zde ještě drobné odlišnosti vztahující se k Unixovým oprávněním a jejich nastavování, viz chmod(1) pro podrobnosti.

Nád rámcem tradičních Unixových oprávnění: POSIX ACL

Model oprávnění popsaný výše je vzácným příkladem konceptu pocházejícího z Unixu, který je považovaný za málo flexibilní pro dnešní použití. Přesto je také považován za typický příklad jednoduchého ale dobře použitelného bezpečnostního modelu.

Mnoho programů tento model okopírovalo a můžeme si jej tak všímat i na jiných místech. Jde tak určitě o něco, co je dobré si zapamatovat a pochopit.

Malá flexibilita systému spočívá v tom, že povolení přístupu k souboru konkrétní skupině lidí vyžaduje vytvoření speciální skupiny pro tyto uživatele. Skupiny jsou přitom definovány v /etc/group, jehož změna ale vyžaduje administrátorská práva.

S rostoucím počtem uživatelů nám také může exponenciálně růst potřebný počet skupin. Na druhou stranu pro většinu situací stačí základní Unixová oprávnění.

Abychom se vypořádali s tímto problémem, Linux poskytuje také tzv. POSIX access control lists, díky čemuž lze přiřadit libovolný seznam uživatelů k libovolnému souboru pro specifikování jejich oprávnění.

getfacl a setfacl jsou nástroje pro řízení těchto práv, ale protože jsou prakticky potřeba jen zřídka, ponecháme jejich znalost na úrovni čtení příslušných manuálových stránek a acl(5).

Kontrola přístupových práv

Vraťme se ještě na chvíli k přístupovým právům.

Změňte oprávnění některých skriptů na --x. Zkuste je spustit. Co se stane?Odpověď.

Odstraňte zapisovatelný bit pro soubor a zapište do něj pomocí přesměrování standardního výstup. Co se stane?

Kvíz o přístupových právech

Za předpokladu následujícího výstupu ls -l (script.sh je skutečně skript shellu) a za předpokladu, že uživatel bob je ve skupině wonderland, zatímco uživatel lewis nikoli.

-rwxr-xr-- 1 alice wonderland 1234 Feb 20 11:11 script.sh

Vyberte všechna pravdivá tvrzení.

You need to have enabled JavaScript for the quiz to work.

Procesy (a signály)

Soubory v systému jsou jeho pasivními prvky. Aktivními částmi jsou spuštěné programy, které data skutečně mění. Podívejme se, co vlastně běží na našem počítači.

Když spustíte program (tj. spustitelný soubor), stane se procesem. Spustitelný soubor a běžící proces sdílí kód – ten je stejný v obou. Ale proces také obsahuje zásobník (stack) (např. pro lokální proměnné), haldu (heap), seznam otevřených souborů apod. – tomu všemu se obvykle říká kontext procesu. Obvykle jsou slovní spojení běžící program a proces zaměňována.

Pro zobrazení seznamu běžících procesů na našem počítači můžeme použít htop, který zobrazí informace o procesech. Podobně jako v MidnightCommanderu provádějí nejdůležitější akce funkční klávesy a nápověda je viditelná v dolní liště. Můžete také nakonfigurovat htop tak, aby zobrazoval informace o systému, jako je množství volné paměti nebo využití procesoru.

Pro neinteraktivní použití můžeme spustit ps -e (nebo ps -axufw pro podrobnější seznam).

Pro ilustraci uvádíme příklad výstupu ps (s volbou --forest pro zobrazení vztahu rodič/dítě).

Chcete-li však zobrazit i běžící procesy svých kolegů, spusťte na sdíleném počítači příkaz ps -ef --forest.

Výpis procesů není nijak chráněn před ostatními uživateli. Každý uživatel na daném počítači může vidět, co ostatní uživatelé spouštějí (včetně argumentů příkazového řádku).

Mějte tedy na paměti, že hesla se nemají nikdy předávat jako argumenty příkazového řádku a vždy je předávejte prostřednictvím souborů (s příslušnými právy) nebo interaktivně na stdin.

UID          PID    PPID  C STIME TTY          TIME CMD
root           2       0  0 Feb22 ?        00:00:00 [kthreadd]
root           3       2  0 Feb22 ?        00:00:00  \_ [rcu_gp]
root           4       2  0 Feb22 ?        00:00:00  \_ [rcu_par_gp]
root           6       2  0 Feb22 ?        00:00:00  \_ [kworker/0:0H-events_highpri]
root           8       2  0 Feb22 ?        00:00:00  \_ [mm_percpu_wq]
root          10       2  0 Feb22 ?        00:00:00  \_ [rcu_tasks_kthre]
root          11       2  0 Feb22 ?        00:00:00  \_ [rcu_tasks_rude_]
root           1       0  0 Feb22 ?        00:00:09 /sbin/init
root         275       1  0 Feb22 ?        00:00:16 /usr/lib/systemd/systemd-journald
root         289       1  0 Feb22 ?        00:00:02 /usr/lib/systemd/systemd-udevd
root         558       1  0 Feb22 ?        00:00:00 /usr/bin/xdm -nodaemon -config /etc/X11/...
root         561     558 10 Feb22 tty2     22:42:35  \_ /usr/lib/Xorg :0 -nolisten tcp -auth /var/lib/xdm/...
root         597     558  0 Feb22 ?        00:00:00  \_ -:0
intro        621     597  0 Feb22 ?        00:00:40      \_ xfce4-session
intro        830     621  0 Feb22 ?        00:05:54          \_ xfce4-panel --display :0.0 --sm-client-id ...
intro       1870     830  4 Feb22 ?        09:32:37              \_ /usr/lib/firefox/firefox
intro       1966    1870  0 Feb22 ?        00:00:01              |   \_ /usr/lib/firefox/firefox -contentproc ...
intro       4432     830  0 Feb22 ?        01:14:50              \_ xfce4-terminal
intro       4458    4432  0 Feb22 pts/0    00:00:11                  \_ bash
intro     648552    4458  0 09:54 pts/0    00:00:00                  |   \_ ps -ef --forest
intro      15655    4432  0 Feb22 pts/4    00:00:00                  \_ bash
intro     639421  549293  0 Mar02 pts/8    00:02:00                      \_ man ps
...

Především má každý proces svoje ID, často označované jen PID (neplést s tímto). PID je číslo přiřazené jádrem operačního systému a je používáno nástroji pro správu procesů. PID 1 je určeno pro první proces spuštěný v systému (0 je vyhrazená pro speciální účely – mrkněte na fork(2) pokud vás zajímají detaily). Když tento proces skončí, systém se vypne. Ostatní procesy dostávají (v jednoduchosti) postupně se zvyšující PIDy, časem jsou PIDy recyklovány.

Jako důležitý technický detail: proces s PID 1 je první proces a tudíž řídí zbytek systému (protože (nepřímo) spouští libovolný další program).

Pokud spustíte /bin/sh pod PIDem 1, spustí se vám na počítači jen shell a nic dalšího. To může být velmi užitečné pro nějakou speciální údržbu (podívejte se po init= v kernelové dokumentaci parametrů jádra).

Typicky, PID 1 bude něco jako /lib/systemd/systemd, který kontroluje další služby (vizte cvičení 08).

Vzpomeňte si, že tyto informace jsou obsažené též v adresáři /proc/PID a odtamtud je také ps čte.

Pro zobrazení všech procesů v počítači znovu spusťte ps -ef --forest. Vzhledem ke grafickému rozhraní bude seznam pravděpodobně poměrně dlouhý.

Prakticky může mít malý server nabízející webové stránky, kalendář a přístup přes SSH asi 80 procesů, u desktopu s prohlížečem běžícím v Xfce a několika dalšími aplikacemi se počet zvýší na téměř 300 (tohle opravdu hodně závisí na konfiguraci, ale je to rozumný přibližný odhad). Asi 50-60 z nich jsou ve skutečnosti vnitřní vlákna jádra. Jinými slovy, webový/kalendářový server potřebuje asi 20 “skutečných” procesů, desktop jich potřebuje asi 200 :-).

Rychlá kontrola znalostí procesů

Vyberte všechna pravdivá tvrzení. You need to have enabled JavaScript for the quiz to work.

Signály

Linuxové systémy používají signály pro asynchronní komunikaci mezi běžícími programy (procesy). Slovo asynchronní znamená, že signál může být odeslán (a doručen) bez ohledu na stav procesu. Toto je v kontrastu s komunikací prostřednictvím (například) standardního vstupu, kde program řídí, kdy bude ze standardního vstupu číst (tím, že zavolá odpovídající IO funkce pro čtení).

Signály nicméně nenabízejí příliš bohatou možnost komunikace: jediná informace (kromě toho, že byl vůbec poslán) je jejich číslo. Čísla signálů jsou definována v kernelu, který také některé signály sám zpracovává. V ostatních případech jsou signály doručené aplikaci, která na ně může reagovat. Pokud aplikace na signál nereaguje, je signál zpracován výchozím způsobem. V některých případech se jedná o ukončení aplikace (což je nejčastější). V ostatních případech jsou signály ignorovány.

Tohle je také vyjádřeno tím, že prográmek, kterým se signály posílají se jmenuje kill (protože obvykle proces zabije – ukončí), detaily níže.

Bez dalších parametrů kill posílá signál 15 (nazvaný též TERM nebo SIGTERM), který aplikaci říká, že má být ukončena. Aplikace se může rozhodnout, že signál tzv. odchytí, např. zavře otevřené soubory a teprve pak skončí. Aplikace ale může udělat v podstatě cokoliv a dokonce i signál ignorovat. Kromě TERM můžeme též pomocí kill poslat signál KILL (číslo 9), který je vždy odchycen kernelem a okamžitě (a násilně) program ukončí. Aplikace se může pokusit zaregistrovat si zachycení signálu KILL, ale jádro operačního systému ho stejně nedoručí.

Většina signálů je poslána procesu v reakci na specifickou událost. Například signál PIPE je poslán, pokud proces zkouší zapsat do roury, jejíž čtecí konec byl uzavřen. (Vzpomeňte si na problém z labu 04.) Ukončení programu pomocí Ctrl-C v terminálu ve skutečnosti pošle signál INT (interrupt, číslo 2). Pokud vás zajímají i ostatní signály, mrkněte na signal(7).

Na příklad pokud se systém vypíná, pošle TERM všem procesům. To jim dá možnost rozumně skončit. Procesy, které po nějaké době stále běží, jsou násilně ukončeny signálem KILL.

Použití kill, pkill a pgrep

Příkaz `pgrep lze použít k vyhledání procesů odpovídajících zadanému názvu.

Otevřete dva další terminály a v jednom spusťte sleep 600 a ve druhém sleep 800. Program sleep jednoduše počká daný počet sekund, než se ukončí.

Ve třetím terminálu spusťte následující příkazy, abyste pochopili, jak probíhá vyhledávání procesů.

pgrep sleep
pgrep 600
pgrep -f 600

Co jste se dozvěděli? Odpověď.

Když známe PID, můžeme použít nástroj kill a program skutečně ukončit. Zkuste spustit kill PID s PID jednoho ze sleepů a podívejte se, co se stalo v terminálu, kde sleep běžel.

Měli byste vidět něco takového:

Terminated (SIGTERM).

Tato zpráva nás informuje, že příkaz byl násilně ukončen.

Podobně můžete použít pkill k zabíjení procesů podle jména (ale buďte opatrní, protože s velkou mocí přichází i velká zodpovědnost). Další podrobnosti naleznete na stránkách manuálu.

Dále také existuje příkaz killall, který se chová podobně. V některých Unixových systémech (např. Solaris) má tento příkaz zcela jinou sémantiku a používá se k vypnutí celého počítače.

Reakce na signály v shellu

Reakce na signály v shellu se provádí pomocí příkazu trap.

Všimněte si, že typickou akcí pro obsluhu signálů v shellovém skriptu je úklid dočasných souborů.

#!/bin/sh

set -ueo pipefail

on_interrupt() {
    echo "Interrupted, terminating ..." >&2
    exit 17
}

on_exit() {
    echo "Cleaning up..." >&2
    rm -f "$my_temp"
}

my_temp="$( mktemp )"

trap on_interrupt INT TERM
trap on_exit EXIT

echo "Running with PID $$"

counter=1
while [ "$counter" -lt 10 ]; do
    date "+%Y-%m-%d %H:%M:%S | Waiting for Ctrl-C (loop $counter) ..."
    echo "$counter" >"$MY_TEMP"
    sleep 1
    counter=$(( counter + 1 ))
done

Příkaz trap obdrží jako první argument příkaz, který se má v reakci na signál vykonat. Další argumenty obsahují seznam signálů, na které se má reagovat. Všimněte si, že speciální signál EXIT znamená normální ukončení skriptu. Proto nemusíme po ukončení smyčky volat on_exit.

Pro označení ukončení pomocí obsluhy Ctrl-C použijeme exit 17 (hodnota je sama o sobě libovolná).

Návratovou hodnotu můžete zkontrolovat pomocí echo $? po ukončení příkazu. Speciální proměnná $? obsahuje výstupní kód posledního příkazu.

Pokud váš shellový skript začíná příkazem set -e, budete $? potřebovat jen zřídka, protože jakákoli nenulová hodnota způsobí ukončení skriptu.

Následující konstrukce však zabrání ukončení a umožní vám v případě potřeby větvit kód na základě výstupní hodnoty.

set -e

...
# Prevent termination through set -e
rc=0
some_command_with_interesting_exit_code || rc=$?
if [ $rc -eq 0 ]; then
    ...
elif [ $rc -eq 1 ]; then
    ...
else
    ...
fi

Použití - (pomlčky) místo handleru způsobí, že příslušný handler bude nastaven jako výchozí.

Vaše shellové skripty musí vždy obsahovat obsluhu signálu pro úklid dočasných souborů.

Všimněte si použití $$, které vypíše aktuální PID.

Spusťte výše uvedený skript, poznamenejte si jeho PID a v novém terminálu spusťte následující příkaz.

kill THE_PID_PRINTED_BY_THE_ABOVE_SCRIPT

Skript byl ukončen a byla zavolána rutina pro úklid. Srovnejte se situací, kdy jste příkaz trap odkomentovali.

Spusťte skript znovu, ale předejte -9 do kill, abyste určili, že chcete poslat signál devět (tj. KILL).

Co se stalo? Odpověď.

Signály jsou sice primitivním mechanismem, který předává binární události bez dalších dat, ale jsou hlavním způsobem řízení procesů v systému Linux.

Pokud potřebujete bohatší komunikační kanál, můžete místo něj použít D-Bus.

Rozumná reakce na základní signály je pro serverové aplikace nutností (např. webový server by měl reagovat na TERM dokončením nevyřízených požadavků bez přijímání nových spojení a následným ukončením). V shellových skriptech se považuje za vhodné vždy zajistit úklid dočasných souborů.
Podívejte se do knihovny signal pro práci se signály v Pythonu.

Nedostatky v návrhu a realizaci signálu

Signály jsou základním mechanismem pro komunikaci mezi procesy v systémech Unix. Bohužel jejich návrh má několik chyb, které komplikují jejich bezpečné použití.

Nebudeme zabíhat do podrobností, ale měli byste mít na paměti, že manipulace se signály může být složitá v situacích, kdy si nemůžete dovolit ztratit žádný signál nebo kdy signály mohou přicházet rychle jeden za druhým. A při používání signálů ve vícevláknových programech se otevírá celá Pandořina skříňka problémů.

Na druhou stranu pro jednoduché shellové skripty, ve kterých chceme při násilném ukončení provést úklid, postačí přístup, který jsme si ukázali výše. Ve skriptu tím ohlídáme situaci, kdy uživatelé stiskli Ctrl-C, protože zjistili, že pracují se špatnými daty, nebo něco podobného.

Všimněte si však, že takový skript obsahuje chybu pro případ, kdy uživatelé stisknou Ctrl-C velmi brzy během provádění skriptu.

my_temp="$( mktemp )"
# User hits Ctrl-C here
trap on_interrupt INT TERM
trap on_exit EXIT

Dočasný soubor byl již vytvořen, ale obslužná rutina ještě nebyla zaregistrována, a proto nebude soubor odstraněn. Změna pořadí však komplikuje obsluhu signálu, protože musíme otestovat, že $MY_TEMP byl již inicializován.

Skutečnost, že signály mohou být záludné, však neznamená, že bychom měli opustit základní prostředky, které zajistí, že naše skripty po sobě uklidí i v případě, že jsou násilně ukončeny.

V jiných programovacích jazycích je úklid poněkud jednodušší, protože je možné vytvořit dočasný soubor, který se vždy automaticky odstraní, jakmile se proces ukončí.

Spoléhá na šikovný trik, kdy můžeme soubor otevřít (vytvořit) a ihned jej odstranit. Dokud však uchováváme deskriptor souboru (tj. výsledek Pythonovského open), systém zachovává obsah souboru nedotčený. Soubor je však již pryč (ve smyslu označení obsahu) a zavření souboru jej zcela odstraní.

Protože shell je založen na spouštění více procesů, výše uvedený trik pro shellové skripty nefunguje.

Rychlá kontrola znalosti signálů

Vyberte všechna pravdivá tvrzení o signálech a procesech. You need to have enabled JavaScript for the quiz to work.

Soubory a správa uložišť

Než budete pokračovat, připomeňte si, že soubory se nacházejí v souborových systémech, což jsou struktury na skutečných blokových zařízeních (typicky discích).

Práce se souborovými systémy a blokovými zařízeními je nutná při instalaci nového systému, při záchraně dat z poškozeného zařízení nebo při prosté kontrole volného místa.

Běžné soubory a adresáře již znáte. V systému Linux však můžete najít i jiné typy souborů.

Symbolické odkazy

Linux umožní vytvořit symbolický odkaz na jiný soubor. Tento speciální druh souboru nemá žádný obsah a jen odkazuje na další soubor.

Zajímavou vlastností symbolických odkazů je, že jsou transparentní pro standardní souborové I/O API. Pokud zavoláte Pythoní open na symbolickém odkazu, otevřete tím (transparentně) soubor, na který odkazuje. To je zamýšlené chování.

Účelem symbolických odkazů je umožnit jiný pohled na stejné soubory bez nutnosti cokoliv kopírovat a synchronizovat.

Například uvažujme, že přehrávač videí umí přehrávat jen soubory v adresáři Videos. Ve skutečnosti ale máme soubory jinde, protože jsou na sdíleném disku. S pomocí symbolického odkazu můžete složku Videos nasměřovat na skutečné úložiště a přehrávač nic nepozná. (Pro pořádek, neznáme žádný přehrávač s podobných chováním, ale existuje spousta jiných programů, kde podobná magie umožní jejich funkci i v prostředí, pro které nebyly navrženy.)

Symbolický odkaz je něco jiného než zástupce na ploše apod. Tito zástupci jsou ve skutečnosti normální soubory, kde kromě cílového souboru určíte třeba i ikonu apod. Symbolické odkazy fungují o úroveň níže.

Abyste vytvořili symbolický odkaz stačí spustit ln -s. Například, spuštění tohoto příkazu vytvoří symbolický odkaz na /etc/passwd pojmenovaný users.txt. Spuštění cat users.txt pak otevře users.txt ačkoliv kernel jeho obsah přečte z /etc/passwd.

ln -s /etc/passwd users.txt

Program strace tiskne informace o provedených systémových voláních – tj. když aplikace potřebovala nějakou službu od operačního systému.

Následující spustí cat users.txt, ale vytiskne systémová volání na stderr. Zachycení těch souvisejících s open ukáže, že aplikace neví, jestli otvírá normální soubor nebo symbolický odkaz (všimněte si poslední řádky výstupu).

strace cat users.txt 2>&1 | grep 'open.*"'
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "users.txt", O_RDONLY) = 3

Kromě symbolických odkazů existují ještě tzv. pevné (občas též nazývané tvrd) odkazy (hard-links). Zatímco symbolické odkazy jsou speciální druh souborů, pevné odkazy jsou ještě o úroveň níže. Pevný odkaz znamená, že určitý název souboru míří na stejnou oblast dat (strukturu) na disku, na kterou už mířil jiný název (na rozdíl od symbolického odkazu, které interně obsahuje jeden nepřímý odkaz navíc).

Pevné odkazy jsou součástí předmětu Administrace Linuxu.

Speciální soubory

Kromě toho také existují speciální soubory, které reprezentují fyzická zařízení, nebo soubory, které fungují jako kukátka do stavu systému.

Hlavním důvodem je, že je to tak mnohem jednodušší pro vývojáře. Nepotřebujete speciální programy na práci s diskem, nepotřebujete zvláštní program na zjištění stavu paměti. Prostě jen přečtete obsah dobře známého souboru a máte potřebná data.

Je také mnohem jednodušší takové programy testovat – můžete jim předhodit jiný soubor jen změnou cesty. Což je změna, která by neměla rozbít zbytek programu.

Soubory, které reprezentují stav systému, jsou typicky textové. Například soubor /proc/meminfo může vypadat takto:

MemTotal:        7899128 kB
MemFree:          643052 kB
MemAvailable:    1441284 kB
Buffers:          140256 kB
Cached:          1868300 kB
SwapCached:            0 kB
Active:           509472 kB
Inactive:        5342572 kB
Active(anon):       5136 kB
Inactive(anon):  5015996 kB
Active(file):     504336 kB
Inactive(file):   326576 kB
...

Tento soubor není nikde na disku, ale když soubor otevřete, Linux vytvoří jeho obsah za běhu.

Všimněte si, jak je informace strukturována: jde o textový soubor, takže nepotřebujete žádné speciální nástroje na přečtení. Navíc je obsah snadno čitelný pro člověka. Na druhou stranu, struktura souboru je pevně daná: co řádek, to záznam; klíč a hodnota jsou odděleny dvojtečkou. Snadné i pro zpracování programem.

Hierarchie souborových systémů

Nyní si stručně uvedeme některé důležité soubory, které najdete prakticky na každém počítači s Linuxem.

Nebojte se skutečně zobrazit obsah souborů, které zde uvádíme. hexdump -C je opravdu skvělý nástroj.

/boot obsahuje zavaděč pro načtení operačního systému. Po instalaci systému se tímto adresářem budete zabývat jen zřídka.

/dev je speciální adresář, ve kterém jsou umístěny soubory reprezentující hardwarová zařízení Pravděpodobně tam uvidíte soubor sda nebo nvme0, který reprezentuje váš pevný (nebo SSD) disk. Pokud tedy nepracujete pod superuživatelem, nebudete mít k těmto souborům přístup ale kdybyste je hexdumpovali, viděli byste bajty tak, jak jsou na skutečném pevném disku.

A zápis do takových souborů by přepsal data na disku!
Diskové nástroje v Linuxu totiž přijímají cesty k diskovým jednotkám, na kterých budou pracovat. Je tedy velmi snadné zadat jim soubor a předstírat, že se jedná o disk, který je třeba naformátovat. Toho lze využít k vytváření obrazů disků nebo k obnově souborů. A značně to zjednodušuje testování takových nástrojů, protože k testování není třeba mít skutečný disk.

Je důležité si uvědomit, že tyto soubory nejsou fyzickými soubory na disku (to by přece znamenalo mít disk uvnitř disku). Při čtení z nich to jádro rozpozná a vrátí správná data.

Tento adresář obsahuje také několik speciálních, ale velmi užitečných souborů pro vývoj softwaru.

/dev/urandom vrací náhodné bajty po neomezenou dobu. Pravděpodobně se interně používá uvnitř vašeho oblíbeného programovacího jazyka k implementaci jeho funkce random(). Zkuste na tomto souboru spustit hexdump (a připomeňte si, že <Ctrl>-C program ukončíte, až vás už náhodnost přestane bavit).

/dev/null je taková soukromá černá díra: zahazuje všechno, co se do ní zapíše.

K dispozici je také /dev/full, který emuluje plný disk nebo /dev/zero, který poskytuje nekonečný proud nulových bajtů.

/etc/ obsahuje konfiguraci systému. Většina programů v systémech UNIX se obvykle konfiguruje prostřednictvím textových souborů. Důvodem je to, že správce se musí naučit pouze jeden nástroj – dobrý textový editor – pro správu systému. Výhodou je, že většina konfiguračních souborů má podporu pro komentáře a je možné komentovat i konfiguraci. Pro představu, příklad takového konfiguračního souboru si můžete prohlédnout v /etc/systemd/system.conf.

Asi nejdůležitějším souborem je /etc/passwd, který obsahuje seznam uživatelských účtů. Všimněte si, že se jedná o textový soubor, kde každý řádek představuje jeden záznam a jednotlivé atributy jsou jednoduše odděleny dvojtečkou :. To je velmi jednoduché na čtení, velmi jednoduché na úpravu a velmi jednoduché na pochopení. Jinými slovy, princip KISS v praxi.

/home obsahuje domovské adresáře pro běžné uživatelské účty (tj. účty pro skutečné – lidské – uživatele).

/lib a /usr obsahují dynamické knihovny, aplikace a celosystémové datové soubory.

/var je určen pro volatilní data. Pokud byste chtěli na svůj počítač nainstalovat databázi nebo webový server, byly by jeho soubory uloženy zde.

/tmp je obecné umístění pro dočasné soubory. Tento adresář je automaticky vyčištěn při každém restartu, proto jej nepoužívejte pro trvalé uložení souborů. Mnoho systémů také automaticky odstraňuje soubory, které nebyly změněny v v posledních několika dnech.

/proc je virtuální souborový systém, který umožňuje ovládání a čtení nastavení jádra (operačního systému). Například soubor /proc/meminfo obsahuje poměrně podrobné informace o využití paměti RAM.

Opět platí, že /proc/* nejsou normální soubory, ale virtuální. Dokud je nepřečtete, jejich obsah nikde fyzicky neexistuje.

Když otevřete /proc/meminfo, jádro přečte své vnitřní datové struktury, připraví jeho obsah (pouze v paměti) a předá vám ho. Není to tak, že by se tento soubor fyzicky zapisoval každých 5 sekund nebo tak nějak, aby obsahoval nejaktuálnější informace.

Připojování a přípojné body (mounts, mount-points)

Každý souborový systém (ke kterému chceme přistupovat) je někde přístupný jako adresář (v porovnání například s písmenem jednotky v jiných systémech).

Pokud chceme přistoupit k zařízení /dev/sda3 pod /home, říkáme, že /dev/sda3 je připojené do /home, /home je potom přípojný bod a /dev/sda3 se často také nazývá svazek (volume).

Většina zařízení je připojena automaticky při startu. To zahrnuje / (kořen, root) kde je systém, ale také /home, kde jsou data uživatelů. Všimněte si, že /dev a /proc (kromě jiných) jsou speciální souborové systémy připojené do těchto míst. Takže, soubor /proc/uptime fyzicky vůbec neexistuje (tj. nenajdete žádný sektor na disku, který by obsahoval jeho data).

Souborové systémy připojené při startu jsou vyjmenovány v /etc/fstab. Málokdy jej budete muset měnit (obzvláště na notebooku) a tento – instalátorem vytvořený – soubor zůstane často beze změn. Všimněte si, že obsahuje identifikaci svazku (čili cestu k oddílu – partition), přípojný bod a další možnosti.

Když připojíte vyjímatelný USB disk, vaše desktopové prostředí ho obvykle připojí automaticky. Je možné ho připojit i ručně pomocí programu mount. Nicméně, program mount musí běžet pod uživatelem root (tohle vlákno vysvětluje, proč může připojení disku být bráno jako nebezpečná operace). Takže si s mountem můžete hrát jen na svých instalacích, kde máte oprávnění superuživatele. Na sdílených strojích to fungovat nebude.

Technická poznámka: výše uvedený text se může zdát jako protimluv, protože když mount vyžaduje rootovské heslo, jak může vaše desktopové prostředí (DE) připojit disk bez ptaní se na administrátorské heslo. Vaše DE totiž uvnitř nezavolá mount, ale použije jiný program (obvykle postavený nad Udisks nebo Polkitem) které dohromady ověří, že připojované zařízení je skutečně flash disk (nebo něco podobného) a uživatel je tzv. lokální (tj. aby to nefungovalo přes SSH). Pokud jsou tyto podmínky splněny, může disk pro uživatele připojit. Mimochodem, s UDisks můžete mluvit z shellu pomocí udiskctl.

Pokud chcete otestovat připojování ručně, připojte USB disk a odpojte ho v GUI (pokud byl připojen automaticky). Obvykle je zařízení připojeno někam do podadresáře v /media.

Vaše USB bude pravděpodobně dostupné jako /dev/sdb1 nebo /dev/sda1 podle toho, jaký disk v počítači máte (mrkněte do další části o lsblk, pokud chcete vidět seznam zařízení).

Připojování disků ručně

sudo mkdir /mnt/flash
sudo mount /dev/sdb1 /mnt/flash

Vaše data budou viditelná v adresáři /mnt/flash.

Chcete-li disk odpojit, spusťte následující příkaz:

sudo umount /mnt/flash

Všimněte si, že spuštění příkazu mount bez argumentů vypíše seznam aktuálně připojených disků. K tomu nejsou vyžadována práva roota.

Prográmky pro zjištění zaplněnosti disku

Základním nástrojem pro kontrolu volného místa na disku je df (disk free).

Filesystem     1K-blocks    Used Available Use% Mounted on
devtmpfs         8174828       0   8174828   0% /dev
tmpfs            8193016       0   8193016   0% /dev/shm
tmpfs            3277208    1060   3276148   1% /run
/dev/sda3      494006272 7202800 484986880   2% /
tmpfs            8193020       4   8193016   1% /tmp
/dev/sda1        1038336  243188    795148  24% /boot

Ve výchozím provedení (výše) se používají kilobajtové bloky. Pro čitelnější výstup jej spusťte s -BM nebo -BG (megabajty a gigabajty) nebo s -h, abyste jej nechali vybrat nejvhodnější jednotku.

Vrátíme se k tématu úložišť ještě v posledním cvičení.

Zkontrolujte si zda všemu rozumíte

Vyberte všechna pravdivá tvrzení. You need to have enabled JavaScript for the quiz to work.

Archivace a komprese souborů

S výše uvedeným tématem do jisté míry souvisí i způsob, jakým Linux řeší archivaci a kompresi souborů.

Archivace v systému Linux obvykle znamená sloučení více souborů do jednoho (pro snadnější přenos) a kompresi tohoto souboru (pro úsporu místa). Někdy se za archivaci považuje pouze první krok (tj. sloučení).

Ačkoli se tyto dvě činnosti obvykle provádějí společně, Linux je od sebe odděluje, protože to umožňuje kombinovat vhodné nástroje a formáty pro každou část práce. Všimněte si, že v jiných systémech, kde je preferovaným formátem soubor ZIP, jsou tyto činnosti sloučeny do jedné.

Nejpoužívanějším programem pro archivaci je tar. Původně byl primárně určen k archivaci na pásky, odtud jeho název: tape archiver. Spouští se vždy s volbou určující režim práce:

  • -c pro vytvoření nového archivu z existujících souborů,
  • -x pro extrakci souborů z archivu,
  • -t pro vypsání tabulky souborů uvnitř archivu.

Jméno archivu se zadává pomocí volby -f; pokud není jméno zadáno, archiv se čte ze standardního vstupu nebo zapisuje na standardní výstup.

Volba -v jako obvykle zvyšuje upovídanost programu. Například tar -cv vypíše jména souborů přidávaných do archivu, tar -cvv vypíše také atributy souborů (podobně jako ls -l). (Vše se vypíše na stderr, takže stdout lze stále používat pro archiv) Obyčejný tar -t vypíše pouze názvy souborů, tar -tv vypíše i atributy souborů.

Tímto způsobem lze vytvořit nekomprimovaný archiv:

tar -cf archiv.tar adresar_k_archivaci/

Komprimovaný archiv vytvoříte tak, že výstup příkazu tar předáte příkazu gzip:

tar -c adresar_k_archivaci/ | gzip >archiv.tar.gz

Protože je to však velmi časté, tar podporuje přepínač -z, který automaticky volá gzip, takže můžete psát:

tar -czf archiv.tar.gz adresar_k_archivaci/

tar má další přepínače pro další (de)kompresní programy: bzip2, xz atd.. Nejdůležitější je přepínač -a, který vybírá (de)kompresní program podle názvu archivního souboru.

Pokud chcete komprimovat jen jeden soubor, často se používá prostý gzip bez tar. Některé nástroje nebo rozhraní API mohou dokonce zpracovávat soubory komprimované pomocí gzip transparentně.

Chcete-li archiv rozbalit, můžete do tar rourou poslat gzip -d (dekomprimovat) nebo použít -z následujícím způsobem:

tar -xzf archive.tar.gz
Stejně jako mnoho jiných programů souvisejících se souborovým systémem přepíše tar existující soubory bez jakéhokoli varování.

Pro usnadnění práce s archivy vám doporučujeme nainstalovat si atool jako obecný obal kolem tar, gzip, unzip a mnoha dalších nástrojů. Například:

apack archive.tar.gz dir_to_archive/
aunpack archive.tar.gz

Všimněte si, že atool ve výchozím nastavení nepřepisuje existující soubory (což je další velmi dobrý důvod pro jeho použití).

Je dobré vždy archivovat jeden adresář. Uživatel, který váš archiv rozbalí, tak nebude mít vaše soubory roztroušené v aktuálním adresáři, ale přehledně připravené v jediném novém adresáři.

Pro vypsání souborů v archívu můžete spustit příkaz als.

find

I když jsou ls(1) a wildcardy dosti mocné, někdy potřebujeme vybrat soubory pomocí složitějších kritérií. Zde je užitečný program find(1).

Bez argumentů vypíše všechny soubory v aktuálním adresáři, včetně souborů ve vnořených adresářích.

Nespouštějte jej v kořenovém adresáři (/), pokud nevíte, co děláte (a rozhodně ne na sdíleném počítači linux.ms.mff.cuni.cz).

Pomocí parametru -name můžete omezit vyhledávání na soubory odpovídající zadanému wildcardu.

Následující příkaz vyhledá všechny soubory alpha.txt v aktuálním adresáři a v libovolném podadresáři (bez ohledu na hloubku).

find -name alpha.txt

Proč následující příkaz pro vyhledání všech souborů *.txt nebude fungovat?

find -name *.txt

Nápověda. Odpověď.

find má mnoho voleb – nebudeme zde opakovat jeho manuálovou stránku, ale zmíníme se o těch, které stojí za zapamatování.

-delete okamžitě odstraní nalezené soubory. Velmi užitečné a velmi nebezpečné.

-exec spustí daný program pro každý nalezený soubor. Musíte použít {} pro zadání názvu nalezeného souboru a příkaz musíte ukončit pomocí ; (protože ; ukončuje příkazy i v shellu, budete ho muset escapovat).

find -name '*.md' -exec wc -l {} \;

Všimněte si, že pro každý nalezený soubor dojde k novému vyvolání příkazu wc. To lze změnit změnou terminátoru příkazu (\;) na +. Podívejte se na rozdíl mezi voláním následujících dvou příkazů:

find -name '*.md' -exec echo {} \;
find -name '*.md' -exec echo {} +

Upozornění

Ve výchozím nastavení vypíše find jeden název souboru na řádek. Jméno souboru však může obsahovat i znak nového řádku (!), a proto následující idiom není 100% bezpečný.

find -options-for-find | while read filename; do
    do_some_complicated_things_with "$filename"
done

Pokud chcete být opravdu bezpeční, použijte -print0 a IFS= read -r -d $'\0' filename, neboť tak se použije jediný bezpečný oddělovač – \0. Alternativně můžete výstup find -print0 přesměrovat do xargs --null.

Pokud však pracujete s vlastními soubory nebo je vzor bezpečný, výše uvedená smyčka je v pořádku (jen nezapomeňte, že adresáře jsou také soubory a mohou ve svém názvu obsahovat \n).

Shell také umožňuje exportovat funkci a volat ji zevnitř xargs. Vypadá to ošklivě, ale je to bezpečný přístup, pokud chcete provádět složité operace nad nalezenými soubory.

my_callback_function() {
    echo ""
    echo "\$0 = $0"
    echo "\$@ =" "$@"
}
export -f my_callback_function

find . -print0 | xargs -0 -n 1 bash -c 'my_callback_function "$@"' arg_zero arg_one
Pochopitelně, vy si funkci pojmenujte podle toho, co dělá. Námi zvolené jméno má jedinou výhodu – je dobře vidět na všech třech místech, kde je použité.

Připomeňme, že funkce lze definovat přímo v shellu a výše uvedené lze skutečně vytvořit interaktivně, aniž by se cokoliv muselo ukládat jako skript.

Úlohy k ověření vašich znalostí

Očekáváme, že následující úlohy vyřešíte ještě před příchodem na cvičení, takže se budeme moci o vašich řešeních na cvičení pobavit.

Hodnocený malý domácí úkol

Spusťte příkaz nswi177-signals na linux.ms.mff.cuni.cz.

Abyste splnili tuto úlohu, budete mu muset ve správném pořadí poslat různé signály.

Program vás úlohou sám provede: vždy vytiskne, jaký signál máte poslat.

Termín dokončení tohoto úkolu je 11. května.

Zkopírujte poslední řádek výstupu (budou to dvě čísla) z tohoto programu do 13/signal.txt ve vašem GitLabovém repozitáři student-LOGIN.

Tato úloha je pouze částečně testována automatickými testy.

K dispozici je více možností, odpovědi oddělujte mezerami nebo čárkami, např. **[A1]** 1,2 **[/A1]**.

Předpokládejme, že máme soubor `test.txt`, pro který `ls -l` vypíše následující:

    -rw-r----- 1 bjorn ursidae 13 Mar 21 14:54 test.txt

Který z následujících uživatelů bude moci číst obsah souboru?

 1. `bjorn` ve skupině `ursidae`
 2. `bjorn` ve skupinách `carnivora` a `mammalia`
 3. `iorek` ve skupině `ursidae`
 4. `iorek` ve skupinách `carnivora` a `mammalia`
 5. `root` (superuživatel)
 6. všichni

**[A1]** ... **[/A1]**

Uvažujte, že soubor z předchozího příkladu je uložen v rámci
v adresáři `/data` s následujícími právy, jak je vypsal příkaz `ls -l`:


    drwxrwx-wx 3 bjorn ursidae 4096 21.3.14:53 data


Který z následujících uživatelů bude moci tento soubor smazat?

 1. `bjorn` ve skupině `ursidae`
 2. `bjorn` ve skupinách `carnivora` a `mammalia`
 3. `iorek` ve skupině `ursidae`
 4. `iorek` ve skupinách `carnivora` a `mammalia`
 5. `root` (superuživatel)
 6. všichni

Lze předpokládat, že kořenový adresář `/` je čitelný a spustitelný
pro každého.

**[A2]** ... **[/A2]**

V návaznosti na předchozí otázky uveďte, které příkazy lze použít k tomu, abyste
soubor `test.txt` učinili čitelným a zapisovatelný pouze pro vlastníka a nikoho jiného?

 1. `chmod u=rw test.txt`
 2. `chmod =rw test.txt`
 3. `chmod g= test.txt`
 4. `chmod o= test.txt`
 5. `chmod g=,o= test.txt`
 6. `chmod g-r test.txt`
 7. `chmod g-rwx test.txt`

**[A3]** ... **[/A3]**

Tento příklad vám může zkontrolovat GitLab skrz automatizované testy. Uložte vaše řešení jako 11/rights.md a commitněte ho (pushněte) do GitLabu.

Přesuňte se do vašeho repozitáře s úkoly (student-LOGIN).

Zkontrolujte všechny vaše shellové skripty pomocí Shellchecku a Pythonové pomocí Pylintu.

Řešení.

Zkomprimujte pomocí GZ (gzip) všechny soubory .csv, které jsou větší než 1M.

Nepřepisujte existující soubory bez vyzvání.

Nápověda.

Řešení.

Vzpomeňte si na generátor statických stránek ze Cvičení 09. V něm jsme měli následující smyčku pro generování HTML souborů ze zdrojů v Markdownu.

generate_web() {
    local page
    for page in src/*.md; do
        if ! [ -f "$page" ]; then
            continue
        fi
        build_markdown_page "$page"
    done
}

Aktualizujte implementaci tak, aby podporovala i vnořené podadresáře.

Řešení.

Učební výstupy a kontrola po cvičení

Tato část podává zhuštěný souhrn základních konceptů a dovedností, které byste měli umět vysvětlit a/nebo použít po každém cvičení. Také obsahují absolutní minimum, které je potřebné pro pochopení navazujících cvičení (a dalších předmětů).

Znalosti konceptů

Znalost konceptů znamená, že rozumíte významu a kontextu daného tématu a jste schopni témata zasadit do většího rámce. Takže, jste schopni …

  • vysvětlit, jaká jsou základní přístupová práva na unixových operačních systémech soubory a pro adresáře

  • vysvětlit co znamenají jednotlivá oprávnění r, w a x pro běžné soubory a pro adresáře

  • vysvětlit, co je to signál v kontextu Linux procesů

  • vysvětlit rozdíl mezi normálním (obyčejným) souborem, adresářem, symbolickým odkazem, souborem zařízení a souborem reprezentujícím stav systému (např. ze souborového systému /proc)

  • vyjmenovat základní adresáře nejvyšší úrovně v typické instalaci Linuxu a popsat jejich funkci

  • vysvětlit v obecné rovině, jak je strom adresářů vytvořen připojením jednotlivých (souborových) podsystémů

  • vysvětlit, proč Linux zachovává oddělení archivace a komprese (např. tar a gzip)

  • vysvětlit co je to set-uid bit

  • vysvětlit, co je proces a jak se liší od spustitelného souboru

  • vysvětlit rozdíl mezi vlastnictvím souboru a běžícího programu

  • volitelné: vysvětlit, co je POSIX ACL, jen základní přehled

Praktické dovednosti

Praktické dovednosti se obvykle týkají použití daných programů pro vyřešení různých úloh. Takže, dokážete …

  • zobrazovat a měnit základní přístupová oprávnění souborů

  • pomocí ps zobrazit seznam existujících procesů (včetně přepínačů -e, -f a --forest)

  • použít pgrep pro vyhledání konkrétních procesů

  • poslat signál běžícímu procesu

  • použít htop k interaktivnímu sledování existujících procesů

  • připojit a pracovat s disky pomocí příkazu mount (jak s fyzickými tak s obrazy disků)

  • získat souhrnné informací o využití disku pomocí příkazu df

  • použít pro práci se standardními linuxovými archivy tar nebo atool

  • použít find se základními predikáty (-name, -type) a akcemi (-exec, -delete)

Seznam změn na této stránce

  • 2025-04-09: Další příklad na find.

  • 2025-04-09: Oprava učebních výstupů.