Piatok 10:00 · 15 otázok · 30 minút · každá možnosť P/N, bod iba za celú správnu otázku · minimum 5 bodov.
Pri každej možnosti klikni P (pravda) alebo N (nepravda). Ak možnosť nechceš označiť, počíta sa ako chyba, rovnako ako na teste. Po vyhodnotení uvidíš pri každej otázke vysvetlenie. Otázky so značkou „starý test“ sú zo zápočtov z minulých rokov a pravdepodobne sa zopakujú.
Z prednášok som vybral iba to, čo sa dá pýtať ako P/N. Žltými rámčekmi sú označené formulácie, na ktorých stavajú chytáky.
| Monolitické jadro | Microkernel | |
|---|---|---|
| Čo beží v privilegovanom režime | celé jadro (jeden veľký blok) | iba minimum: pamäť, I/O, prerušenia |
| Ostatné časti OS | funkcie sa volajú bez reštrikcií | služby a procesy v user režime, komunikujú cez IPC |
| Latencia | nízka | vyššia (kontextové prepnutia, kopírovanie správ) |
| Stabilita | chyba často zrúti celý systém | pád jednej služby nezrúti OS |
| Úroveň | Prístup | Veľkosť | Poznámka |
|---|---|---|---|
| Registre | ~1 ns | kB | časť jadra CPU, obsadenie registrov riadi kompilátor |
| Cache L1, L2, L3 | ~10 ns | MB | väčšinou riadená výlučne HW, delí sa na cache lines. Hit = dáta sú v cache, miss = treba ísť do RAM |
| RAM | ~100 ns | GB | po odpojení napájania stratí dáta |
| Disk | ~10 ms | TB | dáta v blokoch |
U = 1 − pⁿ, kde p je pravdepodobnosť čakania na I/O a n je počet procesov. S rastúcim n utilizácia rastie. (3) naplánovaný
READY ─────────────────► RUNNING
▲ ◄───────────────── │
│ (2) preplánovaný │ (1) čaká na udalosť
│ (4) udalosť prišla ▼
└──────────────────── BLOCKED
pthread_create() vytvorí vlákno, pthread_join() čaká na ukončenie iného vlákna. POSIX definuje vyše 60 volaní pre vlákna.| User space threads | Kernel threads | |
|---|---|---|
| Kto ich spravuje | knižnica, bez systémových volaní | kernel, cez systémové volania |
| Podpora v OS | nie je potrebná | potrebná |
| Rýchlosť vytvorenia | rýchle | rádovo pomalšie |
| Blokujúci syscall | zablokuje celý proces | zablokuje iba vlákno |
| Prepínanie | vlákno musí samo zavolať yield() | kernel prepína sám a plánuje ich |
| Systém | Kritériá plánovania |
|---|---|
| Spoločné (všetky) | férovosť, vynucovanie politiky, vyváženosť |
| Batch | throughput (priepustnosť), turnaround (doba obratu), utilizácia CPU. Preempcia nie je potrebná. |
| Interaktívne | doba odozvy, proporčnosť. Preempcia je nutná. |
| Real-time | dodržanie doby odozvy, predvídateľnosť |
| Algoritmus | Typ | Podstata |
|---|---|---|
| FCFS / FIFO | nepreemptívny | kto skôr príde, ten beží. Zvýhodňuje CPU-bound úlohy. |
| SJF (Shortest Job First) | nepreemptívny | najkratšia úloha ide prvá, skracuje turnaround. Dlhé úlohy môžu hladovať. |
| Shortest Remaining Time | preemptívny | preemptívna obdoba SJF |
| Round-robin | preemptívny | preemptívna obdoba FCFS s časovým quantom. Malé quantum = lepšia odozva, ale vyššia réžia. |
| Prioritné | preemptívny | hrozí vyhladovanie, preto sa priorita časom znižuje. Pri rovnakej priorite sa používa RR. |
| Lotériové | preemptívny | procesy dostanú lístky a plánovač náhodne losuje |
| Garantované | preemptívny | každý proces dostane 1/n CPU |
| Primeraný podiel (fair-share) | preemptívny | CPU sa delí rovnomerne medzi používateľov alebo skupiny |
| Riešenie | Porušuje | Poznámka |
|---|---|---|
| Zakázanie prerušení | 2. | funguje iba na 1 CPU a má globálny vplyv. Používa sa vo vnorených systémoch a v jadre na veľmi krátko. |
| Lock variable | 1. | vôbec nefunguje |
| Strict alternation | 3. | procesy sa musia striedať |
| Manifest interest | 4. | hrozí nekonečné čakanie |
| Peterson | nič | funguje, ale iba pre 2 procesy |
| TSL, XCHG (špeciálne inštrukcie) | nič | sú atomické, ale nie každý CPU ich má |
init(), up() a down().down(): ak s = 0, proces sa zablokuje a ide do radu (nečaká v cykle!). Inak s−−.up(): ak je rad neprázdny, zobudí jeden proces. Inak s++.pthread_mutex_lock / unlock / trylock.synchronized.pthread_cond_wait(cond, mutex), pthread_cond_signal zobudí jedno vlákno, pthread_cond_broadcast zobudí všetky.send(dest, msg) a receive(src, msg). Problémy a riešenia: strata správy → ACK, opakované prijatie a zmena poradia → identifikátor správ, autentickosť → autentifikácia a šifrovanie.| Problém | Podstata |
|---|---|
| Producent–konzument | rad veľkosti N. Pri plnom rade čaká producent, pri prázdnom konzument. Riešenie: semafory mutex, plné a voľné miesta; mutex a cond. variables; monitor; message passing. |
| Večerajúci filozofi | 5 filozofov a 5 vidličiek, na jedenie treba 2. Ak každý vezme ľavú vidličku, nastane uviaznutie (deadlock). Riešenie: stavy THINKING, HUNGRY, EATING a funkcia test(). |
| Čitatelia–zapisovatelia | zapisovať môže naraz iba jeden, čítať môže naraz viac čitateľov, ak nikto nezapisuje. Semaforové riešenie z prednášky uprednostňuje čitateľov, takže zapisovatelia môžu hladovať. |
Každá časť má najprv poznámky (čo príkaz a jeho prepínače znamenajú) a pod nimi krátke príklady. Za $ je to, čo píšeš, riadky bez $ vypíše bash a za ← je vysvetlenie. Všetky príklady sa odohrávajú v tomto priečinku:
/home/jano/skola/
├── ovocie.txt jablko / hruska / slivka (3 riadky)
├── zvierata.txt na grep (obsah v časti 8)
├── cisla.txt na sort a uniq (obsah v časti 10)
├── skript.sh
├── .skryty skrytý súbor (meno začína bodkou)
└── data/
├── udaje.txt
└── zaloha/
└── stare.txt
pwd = print working directory, vypíše, kde práve stojíšls = vypíše obsah aktuálneho priečinka (alebo zadaného: ls data)ls -a = aj skryté súbory, vrátane . (tento priečinok) a .. (rodič)ls -A = skryté súbory bez . a ..ls -l = dlhý výpis (práva, vlastník, veľkosť, dátum)ls -h = veľkosti čitateľne (K, M, G), -r = opačné poradie, -1 = jeden súbor na riadokls -R = rekurzívne (aj podpriečinky). Bez -R ls do podpriečinkov nejde.ls -d priecinok = vypíše samotný priečinok ako jeden záznam, NIE jeho obsah. ls -ld data = práva a vlastník priečinka data.ls -i = pridá číslo inode (identifikátor dát súboru). Hard linky majú rovnaké číslo.ls -l je číslo hneď za právami počet hard linkovcd priecinok = vojdi do priečinka, cd .. = o úroveň vyššiecd, cd ~ alebo cd $HOME = domov (/home/jano)cd - = späť do predošlého priečinka/home = priečinok všetkých používateľov, nie tvoj domov/ je absolútna, ostatné sú relatívne (od miesta, kde stojíš)$ ls
cisla.txt data ovocie.txt skript.sh zvierata.txt ← .skryty tu nie je
$ ls -A
.skryty cisla.txt data ovocie.txt skript.sh zvierata.txt
$ ls data
udaje.txt zaloha ← obsah priečinka
$ ls -ld data
drwxr-xr-x 3 jano jano 4096 Oct 22 14:00 data ← -d: iba záznam o priečinku samotnom
$ cd data
$ pwd
/home/jano/skola/data
$ cd /etc
$ cd - ← späť tam, kde som bol
/home/jano/skola
$ cd ← domov
$ pwd
/home/jano
ls a ls $PWD. ls ~ a ls $HOME vypíšu domov, ls / koreň disku a echo .* iba skryté súbory.cat subor = vypíše celý súbor. Viac súborov spojí za sebou (concatenate). Bez súboru číta z klávesnice.tac subor = vypíše súbor odzadu (posledný riadok prvý)less subor = listovanie: medzera ďalej, b späť, /slovo hľadaj, n ďalší výskyt, g začiatok, G koniec, q koniechead subor = prvých 10 riadkov, head -3 alebo head -n 3 = prvé 3tail subor = posledných 10 riadkov, tail -1 = posledný riadoktail -n +2 = od 2. riadku do konca (nie posledné 2!)wc = počíta: -l riadky (presnejšie znaky nového riadku), -w slová, -c bajty, -m znakywc s viacerými súbormi pridá na koniec riadok total. Pri čítaní zo stdin (wc -l < f alebo cez pipe) nevypíše meno súboru.tail -f log = sleduje súbor, do ktorého niečo pribúda (logy), a vypisuje nové riadky$ tac ovocie.txt
slivka
hruska
jablko
$ head -2 ovocie.txt
jablko
hruska
$ tail -n +2 ovocie.txt ← od 2. riadku
hruska
slivka
$ wc -l ovocie.txt
3 ovocie.txt
$ wc -l < ovocie.txt ← zo stdin: meno súboru sa nevypíše
3
touch f = vytvorí prázdny súbor (0 bajtov, 0 riadkov). Ak súbor existuje, iba mu zmení čas.cp a b = kópia (nezávislá, nový inode). cp -r = kopíruje priečinok aj s obsahom.mv a b = presun alebo premenovanierm f = zmaže meno súboru. rm -r priečinok s obsahom, rm -f bez pýtania, rm -i pýta sa. rmdir zmaže iba prázdny priečinok.cat neexistuje súbor nevytvorí. Súbory vytvára touch alebo > subor.ln original hard = druhé meno tých istých dát. Má rovnaký inode a zmena cez jedno meno je vidno aj cez druhé. Po rm original dáta ostávajú, zmiznú až s posledným hard linkom. Nie je to kópia ani záloha. Nedá sa urobiť na priečinok ani na iný disk.ln -s original soft = malý samostatný súbor, v ktorom je uložená cesta k cieľu, čiže „skratka“. Má vlastný inode a v ls -l vyzerá ako soft -> original. Po zmazaní cieľa ostane nefunkčný (dangling). Môže ukazovať aj na priečinok a na iný disk.find -type l nájde symlinky$ echo first > original
$ ln original hard ← hard link
$ ln -s original soft ← symbolický link
$ ls -li
1234 -rw-r--r-- 2 jano jano 6 ... hard ← rovnaký inode 1234, počet linkov 2
1234 -rw-r--r-- 2 jano jano 6 ... original
5678 lrwxrwxrwx 1 jano jano 8 ... soft -> original ← vlastný inode, obsahuje cestu
$ echo extra >> hard
$ cat original
first
extra ← zápis cez hard je vidno aj cez original (tie isté dáta)
$ rm original
$ cat hard
first ← dáta žijú ďalej, lebo hard je stále ich meno
extra
$ cat soft
cat: soft: No such file or directory ← symlink ukazuje na cestu, ktorá už neexistuje
$ echo second > original ← vznikne ÚPLNE NOVÝ súbor (nový inode)
$ cat hard
first ← hard o novom súbore nevie
extra
$ cat soft
second ← symlink ide podľa mena, takže ukazuje na nový súbor
alias ll='ls -lah' = vytvorí skratku ll, platí iba v aktuálnom shellialias ll = vypíše definíciu aliasu, samotné alias vypíše všetkyunalias ll = alias zruší. Potom alias ll vypíše chybu (alias neexistuje).~/.bashrc a načítať cez source ~/.bashrc (alebo otvoriť nový terminál).$ alias ll='ls -lah'
$ ll ← spustí ls -lah
$ alias ll
alias ll='ls -lah'
$ unalias ll
$ alias ll
bash: alias: ll: not found
echo text = vypíše text a nový riadokecho -n = bez nového riadku na konciecho -e = interpretuje \n (nový riadok), \t (tabulátor), \\. Bez -e sa vypíšu doslova.x=hodnota bez medzier okolo =. Čítanie: $x alebo ${x}."..." (dvojité úvodzovky) = rozvinie $premenna aj $(prikaz), zachová medzery'...' (jednoduché) = nerozvinie nič, všetko je doslova\" = escapnutá úvodzovka (vypíše sa)$(prikaz) alebo prikaz = nahradí sa výstupom príkazucat <<< text = reťazec ide na stdin príkazu$HOME domov, $USER meno, $PWD aktuálny priečinok, $SHELL cesta k shellu$$ = PID aktuálneho shellu$? = návratový kód posledného príkazu (0 = OK, iné = chyba)$_ = posledný argument predošlého príkazu!! = zopakuj posledný príkaz, !ec = posledný príkaz začínajúci na „ec“history = história príkazov (~/.bash_history), Ctrl+R = hľadanie v nejman prikaz, help cd (vstavané príkazy), prikaz --help$ meno=Jano
$ meno = Jano
meno: command not found ← s medzerami bash hľadá príkaz „meno“
$ echo "Ahoj $meno"
Ahoj Jano
$ echo 'Ahoj $meno'
Ahoj $meno
$ echo "${meno}ko"
Janoko
$ echo "$menoko"
← premenná „menoko“ neexistuje, takže prázdny riadok
$ echo \"Ahoj svet\"
"Ahoj svet"
$ echo '"Ahoj svet"'
"Ahoj svet"
$ echo ""Ahoj svet"" ← "" je prázdny reťazec, takže úvodzovky zmiznú
Ahoj svet
$ echo "ah""oj" ← reťazce vedľa seba sa spoja
ahoj
$ echo $(echo ahoj)
ahoj
$ $(echo ls -la) ← výsledok „ls -la“ sa SPUSTÍ ako príkaz
$ ls neexistuje
ls: cannot access 'neexistuje': No such file or directory
$ echo $?
2 ← chyba
$ echo $?
0 ← teraz 0, lebo posledný príkaz bol úspešný echo
ls -l ukáže napríklad -rwxr-x---. Prvý znak je typ (- súbor, d adresár, l link), potom 3 trojice: user, group, others.r čítať, w zapisovať, x spustiťr vypísať obsah (ls), w vytvárať a mazať v ňom, x vojsť doň (cd)r = 4, w = 2, x = 1, sčítajú sa: 7 = rwx, 6 = rw-, 5 = r-x, 4 = r--, 0 = ---chmod 644 f = nastaví presne rw-r--r--, nezávisle od pôvodných právchmod u+w pridá, g-w uberie, o=r nastaví presne. Kto: u user, g group, o others, a všetci.chmod +x f = bez u, g alebo o: všetkým+ a - menia práva relatívne k pôvodným, takže výsledok závisí od toho, čo súbor malchown jano:skupina f = zmeň vlastníka a skupinu (treba sudo), -R = rekurzívnemkdir -p a/b/c = vytvorí aj chýbajúce priečinky po ceste, mkdir -m 700 d = rovno s právamiw a x. Práva samotného súboru na to nemajú vplyv.chmod -R = rekurzívne, a+rw = všetkým čítanie aj zápis$ ls -l f
-r--r--r-- f
$ chmod u+w f
-rw-r--r-- f
$ chmod g+wx f
-rw-rwxr-- f
$ chmod u=rwx,g=rx,o= f ← o= znamená, že ostatní nemajú nič
-rwxr-x--- f
$ chmod 644 f
-rw-r--r-- f
$ chmod 640 file ← rw-r-----
$ chmod u+x file ← rwxr----- (740): skupina má stále iba r, ostatní nič
$ chmod g-r file ← z 640 by vzniklo 600 = rw-------
$ ls -ld d d/item
dr-------- d ← priečinok d má 400: vlastník iba r
-rwxrwxrwx d/item ← súbor má 777
$ rm d/item
rm: cannot remove 'd/item': Permission denied ← na d chýba w+x a 777 na súbore nepomôže
chmod 444 f; chmod u+w f dá vždy rw-r--r--. chmod 222 f; chmod u+w f dá -w--w--w-, čo je zle. Samotné chmod u+w f výsledok nezaručí, lebo nevieš, aké práva mal súbor predtým.ps = procesy v tomto termináli, ps x = všetky moje, ps ax = všetkých používateľovps aux = všetky procesy (nie iba joby na pozadí). Stĺpce: USER, PID, %CPU, %MEM, VSZ, RSS (pamäť), TTY, STAT (stav), START, TIME, COMMAND.ps -elf = tiež všetky procesy, iný formát. Stĺpce: F, S (stav), UID, PID, PPID (PID rodiča), C, PRI, NI, ADDR, SZ, WCHAN, STIME, TTY, TIME, CMD.prikaz & = spusti na pozadíjobs = zoznam jobov aktuálneho shellu (nie všetkých procesov). Číslo jobu [1] je lokálne číslo v shelli, nie PID.fg %1 = job 1 do popredia, bg %1 = zastavený job 1 nech beží na pozadí, kill %1 = signál jobu 1kill PID = pošle signál, predvolene SIGTERM (15), ktorý sa dá zachytiť aj ignorovaťkill -9 PID = SIGKILL, nedá sa zachytiť ani ignorovaťkill -CONT PID = spustí zastavený procesCtrl+Z = proces zastaví (neukončí). Ctrl+C = preruší, čiže ukončí (SIGINT).w a who = kto je prihlásený, last = posledné prihlásenia$ sleep 100 &
[1] 4242 ← PID
$ kill 4242
[1]+ Terminated sleep 100
$ sleep 100
^Z
[1]+ Stopped sleep 100 ← iba zastavený, proces STÁLE EXISTUJE
$ jobs
[1]+ Stopped sleep 100 ← [1] je číslo jobu, PID je napríklad 4300
$ bg %1 ← beží ďalej na pozadí (alebo kill -CONT %1)
$ fg %1 ← späť do popredia
* = hocijaké znaky (aj žiadne)? = presne jeden znak[ab] = jeden znak, a alebo b. [0-9] = jedna číslica.* nezahŕňa$ echo *.txt
cisla.txt ovocie.txt zvierata.txt
$ echo ?????.txt ← 5 znakov + .txt
cisla.txt
$ echo [cz]*
cisla.txt zvierata.txt
$ echo .*
. .. .skryty
$ echo *.pdf
*.pdf ← nič nesedí
find [kde] [podmienky] [akcia]. Bez cesty hľadá v . a bez akcie výsledky vypíše (-print).-name "vzor" = meno súboru (iba posledná časť cesty), rozlišuje veľké a malé písmená, glob vzor-iname = meno, nerozlišuje veľké a malé písmená (insensitive)-path / -ipath = porovnáva celú cestu-type f súbor, -type d adresár, -type l link-type d) a nájde aj skryté súbory-maxdepth 1 = štart + priamy obsah, bez podpriečinkov-maxdepth 0 = iba samotný štartovací bod. find . -maxdepth 0 -type f nenájde nič, lebo . je priečinok.-mindepth 1 = vynechá štartovací priečinok-noleaf = vypne optimalizáciu prehľadávania (pre zvláštne súborové systémy ako CD-ROM alebo MS-DOS). Výsledok nemení a find je stále rekurzívny.-mtime = zmena obsahu (dni), -ctime = zmena statusu (práva, vlastník, nie creation!), -atime = prístup (čítanie)-mmin, -cmin, -amin = to isté v minútach-3 = menej ako, +3 = viac ako, 3 = presne-size: c = bajty, k = KiB, M = MiB, G = GiB. Bez jednotky (alebo b) = 512-bajtové bloky.-size 0c = presne 0 bajtov (prázdny súbor, napríklad po touch)-or alebo -o = alebo, ! alebo -not = negácia. AND má prednosť pred OR.-name 'a.txt' -name 'c.txt' = AND, takže súbor by sa musel volať oboma menami naraz a nenájde sa nič\( ... \)-delete = zmaže nájdené-exec prikaz {} \; = spustí príkaz pre každý súbor zvlášť ({} = súbor)-exec prikaz {} \+ = spustí príkaz raz so všetkými súbormi$ find . -name "*.txt"
./ovocie.txt
./zvierata.txt
./cisla.txt
./data/udaje.txt
./data/zaloha/stare.txt ← aj hlboko v podpriečinkoch
$ find . -name "ovocie" ← presné meno, takže nič
$ find . -name "*ovocie*"
./ovocie.txt
$ find . -maxdepth 1 -type d
.
./data
$ find . -path "*zaloha*"
./data/zaloha
./data/zaloha/stare.txt
$ mkdir -p outer/inner; touch outer/file
$ find outer -type d
outer ← štartovací priečinok sa počíta!
outer/inner
$ find outer -type d | wc -l
2
$ mkdir sub; touch top.txt sub/deep.txt
$ find . -maxdepth 1 -type f
./top.txt
$ find . -mindepth 1 -maxdepth 1 -type f
./top.txt
$ find . -maxdepth 0 -type f
← nič: hĺbka 0 je iba „.“, a to je priečinok
$ touch a.txt b.log c.txt
$ find . -type f \( -name 'a.txt' -o -name 'c.txt' \)
./a.txt
./c.txt
$ find . -type f -name 'a.txt' -name 'c.txt'
← nič (AND)
$ touch empty; find empty -size 0c
empty
$ find . -name "*.txt" -exec wc -l {} \; ← wc 5-krát
3 ./ovocie.txt
7 ./zvierata.txt
...
$ find . -name "*.txt" -exec wc -l {} \+ ← wc 1-krát
...
22 total
$ find . -name "*.txt" | wc -l
5 ← toto je POČET SÚBOROV, nie ich riadkov!
find . -name *.txt bez úvodzoviek: bash rozvinie *.txt v aktuálnom priečinku, takže find dostane -name cisla.txt ovocie.txt zvierata.txt a skončí chybou.find . -name "*.c" -or -name "*.h" -delete zmaže iba .h súbory, lebo -delete sa naviaže iba na poslednú časť. Správne je \( ... -or ... \) -delete.grep [prepínače] 'vzor' [súbory]. Bez súboru číta zo stdin (z pipe).-i = nerozlišuje veľké a malé písmená-v = invertuje: riadky, ktoré vzor NEobsahujú-w = iba celé slová-c = počet riadkov so zhodou (nie počet výskytov)-o = vypíše iba zhodnú časť, každú zhodu na nový riadok-n = pridá čísla riadkov-l = iba mená súborov so zhodou-r = rekurzívne v priečinku, -R = aj cez symlinky-q = nič nevypíše, výsledok je iba v $? (0 = našiel, 1 = nenašiel)-A 2 = aj 2 riadky za zhodou (After), -B 2 = pred zhodou (Before)-E = rozšírený regex (sprístupní + ? | { } ( ))subor:riadok-vc, -in…. = ľubovoľný jeden znak* = predchádzajúci znak 0 a viackrát (nie „hocičo“!).* = hocičo^ = začiatok riadku, $ = koniec riadku, ^$ = prázdny riadok[abc] = jeden z týchto znakov, [^abc] = jeden znak, ktorý NIE JE a, b ani c[0-9], [a-z], [[:alpha:]] (písmeno), [[:digit:]] (číslica)\< a \> = začiatok a koniec slova-E: + = 1 a viac, ? = 0 alebo 1, {3} = presne 3-krát, {3,5} = 3 až 5-krát, {3,} = aspoň 3-krát, a|b = a alebo b, ( ) = skupina-E treba tieto znaky escapnúť: \{3\}, \+\. = obyčajná bodkaObsah zvierata.txt: pes, macka, Pes je dobry, # komentar, kocur a pes, pesnicka a prázdny riadok (7 riadkov).
$ grep pes zvierata.txt
pes
kocur a pes
pesnicka ← „pes“ je aj vnútri slova
$ grep -i pes zvierata.txt
pes
Pes je dobry
kocur a pes
pesnicka
$ grep -w pes zvierata.txt
pes
kocur a pes
$ grep -c pes zvierata.txt
3
$ grep -vc pes zvierata.txt ← riadky BEZ „pes“: macka, Pes je dobry, # komentar, prázdny
4
$ grep '^pes' zvierata.txt
pes
pesnicka
$ grep 'pes$' zvierata.txt
pes
kocur a pes
$ grep -c '^$' zvierata.txt
1
$ grep -E 'macka|kocur' zvierata.txt
macka
kocur a pes
$ grep 'macka|kocur' zvierata.txt ← bez -E hľadá doslova „macka|kocur“, takže nič
$ grep 'ab*c' ← sedí na ac, abc, abbbc (b je 0+ krát)
grep "A*" /public nenájde súbory začínajúce na A.> f = stdout do súboru. Súbor sa vytvorí alebo vymaže ešte pred spustením príkazu.>> f = stdout sa pripíše na koniec súboru (vytvorí ho, ak neexistuje)2> f = iba chyby do súboru2> /dev/null = zahoď chyby (/dev/null je čierna diera)> f 2>&1 = stdout aj stderr do f (skratka &> f)2>&1 = stderr pošli tam, kam práve teraz ide stdout. Bash číta presmerovania zľava doprava, takže poradie je dôležité.1>&2 = stdout na stderr. Bez & (1>2) vznikne súbor s menom „2“.< f = obsah súboru ide na vstup príkazucat chyba 2> err stále zlyhá ($? ≠ 0), iba chyba ide do súboruecho hello > wc nespustí program wc, ale vytvorí súbor s menom wc$ echo ahoj > pozdrav.txt
$ cat pozdrav.txt
ahoj
$ echo cau > pozdrav.txt ← > prepíše
$ echo svet >> pozdrav.txt ← >> pripíše
$ cat pozdrav.txt
cau
svet
$ ls neexistuje > vypis.txt
ls: cannot access 'neexistuje': No such file or directory ← chyba ide stále na obrazovku
$ cat vypis.txt
← PRÁZDNY: > ho vymazal a ls doň nič nezapísal
$ ls neexistuje 2> chyby.txt
← na obrazovke nič, chyba je v chyby.txt
$ ls ovocie.txt neexistuje > vsetko.txt 2>&1
$ ← oboje je v súbore
$ ls ovocie.txt neexistuje 2>&1 > vsetko.txt
ls: cannot access 'neexistuje': ... ← chyba je na OBRAZOVKE
← 2>&1 sa vykonalo prvé, keď stdout ešte šiel na obrazovku
subor1 a spustíš ls subor2 > vypis.txt; ls >> vypis.txt. Chyba ide na obrazovku. vypis.txt sa vytvorí alebo premaže a bude obsahovať dva riadky, subor1 a vypis.txt, lebo druhé ls už súbor vidí.a | b = stdout príkazu a ide na vstup príkazu b. Oba bežia súčasne ako samostatné procesy.2>&1 | alebo skratka |&.> vedie do súboru, | vedie do príkazu$? po pipe = návratový kód posledného príkazu v pipe. cat missing.txt | wc -l vypíše 0 a $? je 0, hoci cat zlyhal. Zmení to iba set -o pipefail, ktorý vráti chybu, ak zlyhal hocijaký príkaz v pipe.sort = triedi ako text (preto je „10“ pred „9“)sort -n číselne, -r zostupne, -u bez duplicít, -t, -k2 podľa 2. stĺpca oddeleného čiarkouuniq = odstráni iba susedné duplicity, preto pred ním takmer vždy ide sortuniq -c = pred každý riadok pridá počet výskytov, uniq -d = iba duplicitné riadkycut -d: -f1 = 1. stĺpec (field), oddeľovač :. -f1,7 = 1. a 7. stĺpec.tr a-z A-Z = nahrádza znaky, tr -d ' ' = zmaže znakytee f = pošle výstup na obrazovku aj do súboruxargs prikaz = zo vstupu spraví argumenty príkazu$ ls ovocie.txt neexistuje | wc -l
ls: cannot access 'neexistuje': ... ← chyba obišla pipe
1
$ ls ovocie.txt neexistuje 2>&1 | wc -l
2
$ ls ovocie.txt neexistuje |& wc -l
2
$ ls neexistuje 2>&1 >/dev/null | wc -l
1 ← do pipe ide iba chyba
Obsah cisla.txt, každé číslo na samostatnom riadku: 3, 10, 3, 7, 10, 3.
$ sort cisla.txt ← bez -n triedi ako TEXT, znak po znaku ako v slovníku
10 ← „1“ je menší znak ako „3“, preto je 10 pred 3
10
3
3
3
7
$ sort -n cisla.txt ← -n = ako ČÍSLA
3
3
3
7
10
10
$ uniq cisla.txt ← NIČ sa nezmení: uniq porovnáva iba s riadkom tesne nad sebou
3 a v súbore nie sú dve rovnaké čísla pod sebou
10
3
7
10
3
Top najčastejšie: sort | uniq -c | sort -nr po krokoch
$ sort cisla.txt ← KROK 1: rovnaké čísla budú pod sebou
10
10
3
3
3
7
$ sort cisla.txt | uniq -c ← KROK 2: zlúči ich a pred každé napíše POČET
2 10 ← vľavo počet, vpravo číslo: 10 bolo 2-krát
3 3 ← 3 bolo 3-krát
1 7
$ sort cisla.txt | uniq -c | sort -nr ← KROK 3: zoradí podľa počtu, zostupne
3 3 ← najčastejšie navrchu
2 10
1 7
$ ... | head ← KROK 4: vezme prvých 10 = 10 najčastejších
$ cut -d: -f1,7 /etc/passwd
root:/bin/bash
jano:/bin/bash
$ echo ahoj | tr a-z A-Z
AHOJ
$ head -5 subor | tail -1 ← 5. riadok
$ head -1 subor | tail -1 subor ← tail má vlastný súbor, takže vypíše POSLEDNÝ riadok
sort | uniq -c | sort -nr | head je správne a sort | uniq -c | sort -n | tail tiež. uniq -c bez predošlého sort je zle.#!/bin/bash (shebang) = prvý riadok, za ním cesta k interpretu. Nie je povinný, súbor ním nebude spustiteľný a nie je to meno autora../skript.sh potrebuje chmod +xbash skript.sh funguje aj bez +xskript.sh bez cesty funguje, iba ak je jeho priečinok v $PATH. Aktuálny priečinok . v PATH nie je.$PATH = priečinky so spustiteľnými programami oddelené :. Dá sa meniť a každý používateľ ho môže mať iný.$0 = meno skriptu (shift ho nemení)$1, $2… = argumenty$# = počet argumentov$@ = všetky argumenty. "$@" = každý zvlášť (správny spôsob).$* = všetky argumenty. "$*" = jeden reťazec.shift = zahodí $1 a posunie ostatné, shift 2 = o dvaexit 1 = ukončí skript s návratovým kódom 1export X=1 = premenná bude viditeľná aj v spustených skriptoch (detských procesoch)source s.sh alebo . s.sh = vykoná skript v aktuálnom shellibasename /a/b/c.txt = c.txt (posledná časť), dirname /a/b/c.txt = /a/b (všetko okrem nej)$ cat skript.sh
#!/bin/bash
echo "$0 | $1 | $2 | $#"
shift
echo "$1 | $#"
$ ./skript.sh jablko "zelena hruska" slivka
./skript.sh | jablko | zelena hruska | 3 ← úvodzovky držia „zelena hruska“ pokope
zelena hruska | 2
$ ./skript.sh
bash: ./skript.sh: Permission denied ← chýba +x
$ bash skript.sh ← funguje
$ skript.sh
skript.sh: command not found ← „.“ nie je v PATH
$ echo '$PATH'
$PATH ← v jednoduchých úvodzovkách sa nerozvinie
pri spustení ./s.sh a "b c":
for x in "$@" → [a] [b c] (2-krát, správne)
for x in "$*" → [a b c] (1-krát)
for x in $@ → [a] [b] [c] (3-krát)
while (( "$#" )); do echo "$1"; shift; done funguje. while [ "$#" ]; ... je nekonečný, lebo „0“ je neprázdny reťazec, takže podmienka je stále pravdivá.$((a + b)) = aritmetika, iba celé čísla (7 / 2 = 3, % = zvyšok)[ $a -eq $b ] čísla: -eq =, -ne ≠, -lt <, -le ≤, -gt >, -ge ≥(( a > b )) = číselné porovnanie, kde sa smie písať >[ "$a" = "$b" ], != = porovnanie reťazcov (medzery okolo sú povinné)-f existuje a je súbor, -d adresár, -e existuje, -r/-w/-x práva, -z prázdny reťazec, -n neprázdny reťazec[ ] znamená > presmerovanie: [ 5 > 3 ] vytvorí súbor „3“a && b = b sa vykoná, iba ak a uspela || b = b sa vykoná, iba ak a zlyhala ; b = b sa vykoná vždyfor i in 1 2 3, for i in $(seq 10 20), for ((i=0; i<5; i++)), while read r; do ...; done < subor$ a=5; b=3
$ echo $a+$b
5+3
$ echo $((a + b))
8
$ [ $a -gt $b ] && echo vacsie
vacsie
$ [ -d data ] && echo adresar
adresar
$ ls xyz || echo zlyhalo
ls: cannot access 'xyz': ...
zlyhalo
$ for i in $(seq 1 3); do echo "cislo $i"; done
cislo 1
cislo 2
cislo 3
$ while read r; do echo "-> $r"; done < ovocie.txt
-> jablko
-> hruska
-> slivka
for i in $(seq 10 20); do echo "cislo $i" > subor; echo $i; done sa na obrazovku vypíšu čísla 10 až 20. Súbor sa však v každom kole prepíše (>), takže v ňom ostane iba cislo 20.z=(a b "c d") = pole s 3 prvkami (úvodzovky držia „c d“ pokope)${z[0]} = prvý prvok (indexy sú od 0)$z bez indexu = iba prvý prvok${z[@]} = všetky prvky${#z[@]} = počet prvkov${#z[0]} = dĺžka reťazca v prvku 0${!z[@]} = indexy, ${z[-1]} = posledný prvok${z[@]:1:2} = od indexu 1 dva prvkyz+=(x) = pridá prvok, z[1]=X = zmení prvok"${z[@]}" s úvodzovkami = prvky ostanú celé. Bez úvodzoviek sa prvky s medzerou rozdelia.$ z=(jeden dva "tri styri")
$ echo ${z[0]}
jeden
$ echo $z
jeden ← iba prvý prvok!
$ echo ${#z[@]}
3
$ echo ${#z[0]}
5 ← dĺžka slova „jeden“
$ z+=(pat)
$ echo ${z[@]}
jeden dva tri styri pat
$ k=(${z[@]}) ← bez úvodzoviek
$ echo ${#k[@]}
5 ← „tri styri“ sa rozdelilo
zoznam=(jeden dva tri štyri päť "šesť sedem") má 6 prvkov. zoznam2=(${zoznam[@]} osem) má 8 (6 + 1 za rozdelenie + osem).set -x = zapne debug (pred každý vykonávaný príkaz vypíše +)set +x = vypne debug (mínus zapína a plus vypína, opačne, ako by si čakal)bash -x skript.sh = spustí celý skript v debug móde#!/bin/bash -x = debug pre celý skript priamo zo shebanguset -v = vypisuje riadky skriptu tak, ako ich bash čítaset -e nie je debug, ale ukončenie skriptu pri prvej chybe$ cat pokus.sh
#!/bin/bash
a=5
echo "a je $a"
$ bash -x pokus.sh
+ a=5
+ echo 'a je 5'
a je 5
whoami = moje meno, id = UID, GID a všetky skupiny, groups = skupiny/etc/passwd = čitateľný pre všetkých. Obsahuje meno, UID, GID primárnej skupiny, GECOS (celé meno, telefón…), domov a shell. Heslo je nahradené znakom x./etc/shadow = hashe hesiel, číta ho iba root/etc/group = skupiny a ich členovia/etc = konfiguračné súbory. Bežný používateľ by ich nemal meniť a reštart po zmene väčšinou netreba.scp jano@server:/cesta/subor . = skopíruje súbor zo servera (secure copy)$ id
uid=1000(jano) gid=1000(jano) groups=1000(jano),27(sudo)
$ grep jano /etc/passwd
jano:x:1000:1000:Jano,izba 12,0900123456:/home/jano:/bin/bash
$ cat /etc/shadow
cat: /etc/shadow: Permission denied