Cvičení z Úvodu do UNIXu – záskok na úterní paralelce od 10.40


https://kam.mff.cuni.cz/~had/ --> Záskok na UNIXu

Funkce

Abychom se vyhli opakování stejného kusu kódu, můžeme si nějaké funkční celky uzavřít do funkcí, které následně budeme volat. Funkce se také občas hodí k tomu, abychom neměli zbytečně dlouhý kus kódu. V neposlední řadě se hodi ke zkoušce, protože na papíře se špatně vkládá několik řádků.

#!/bin/sh
funkce() {
	echo ahoj!
	echo já jsem funkce "$0" a byla jsem zavolána s "$#" parametry.
	echo Například druhý parametr má hodnotu: "$2".
	echo také vím, že mám dostat parametr v proměnné vstup. Jeho hodnota je následující: "$vstup"
	echo Protože jsem hodná, tak na výstup uložím o jedna vyšší číslo:
	vystup="$(( vstup + 1 ))"
	echo
}


funkce 1 2 3

echo $vystup

vstup=6

funkce 1 2 3

echo $vystup

Co se traduje: Za šipky na papíře údajně Forst vyhazuje od zkoušky. Pokud použijete funkci, je to ok.

Příklady:
  1. Vyzkoušejte si, jaký je rozdíl mezi proměnnou "$*" a "$@"? Vysvětlete...

    Mějme skript:

    #!/bin/sh
    
    funkce() {
    	echo prvni parametr je: "$1"
    	echo druhy parametr je: "$2"
    	echo treti parametr je: "$3"
    	echo ctvrty parametr je: "$4"
    }
    
    funkce "$@"
    echo 
    funkce "$*"
    echo
    funkce $@
    echo 
    funkce $*
    

    A zkusme si jej spustit:

    ./skript.sh "1. argument" "2. argument" "3. argument" "4. argument"
    
  2. Vypište rekurzivně všechny adresáře a podaresáře. nesmíte ale použít příkaz, který to rovnou udělá sám (např. find, ls -R). Zkuste to udělat tak, že jako jeden z argumentů dostanete maximáľní povolenou hloubku zanoření.
    # Příklad testovacích dat:
    mkdir -p test/prvni/druha/treti/ctvrta/pata/sesta
    mkdir -p test/prvni/druha/treti/ctvrta/pata/sesta2
    mkdir -p test/prvni/druha/treti2/ctvrta/pata/sesta
    mkdir -p test/prvni/druha/treti2/ctvrta/pata2/sesta
    mkdir -p test/prvni2/druha
    mkdir -p test/prvni2/druha2
    mkdir -p test/prvni2/druha3/treti
    mkdir -p test/prvni2/druha3/treti2
    mkdir -p test/prvni2/druha4
    

Procesy a vlákna

Aspoň na Linuxu je rozdíl mlhavý -- jednotlivá vlákna od sebe mohou být různě izolovaná a od určité míry izolace to už nazveme jako separátní proces.

Interaktivní příkazy: top, htop.

Důležité: PID, PPID, init proces (PID 1)

Pouštění příkazu na pozadí pomocí &

Příkazy fg, bg, jobs, pozastavení pomocí Ctrl+Z

Ukázali jsme si exec (Ale příliš jsme si nevysvětlili podobu s vytvořením nového procesu (fork & exec).

Ukázali jsme si wait a $!

Příklady:
  1. Napište sleep sort. Tip: na konec se hodí dopsat wait
  2. Zkuste si napsat funkci, max, která najde maximum ze svých argumentů. Tou se pak dá sleep sort rozšířit: wait na konci bude čekat jen na ten proces, který byl volaný s maximálním argumentem. Využití: takto přímo asi nulové, ale aspoň je to dobře definovaná úloha, kterou si člověk může vyzkoušet

Exitcode

Jen řešeno ve spěchu, neukázali jsme si příklady v terminálu. Ale občas někdo exit použil...

Napište si vlastní funkci, která bude fungovat jako taková podmínka. Dostane jako argument soubor a uspěje, pokud se v daném souboru nevyskytuje slovo bagr. (Pokud soubor neexistuje, nebo je to adresář, podmínka neuspěje.)

$?

Jestli zbyde čas, tak zkrácené vyhodnocování && || (nezbyl)

Signály

Procesy si navzájem mohou posílat signály (obdoba Interruptů – přeušení, viz principy počítačů).

# Údajně POSIX definuje následující (neověřoval jsem si):
1  SIGHUP    (hang up)
2  SIGINT    (interrupt)
3  SIGQUIT   (quit)
6  SIGABRT   (abort)
9  SIGKILL   (kill)
14 SIGALRM   (alarm)
15 SIGTERM   (terminate)

# Důležité podle mě:
jméno    číslo   popis
--------------------------------------------------------
SIGINT           To co pošle Ctrl+C
SIGKILL  (9)     Nelze se mu bránit, zabije proces
SIGHUP           Zavření terminálu (pro daemony načtení konfigurace)
SIGTERM          Měkké ukončení -- posílá se automaticky pří vypínání systému všem procesům, po nějakéĺ timeoutu se pošle SIGKILL
SIGTSTP          To, co posílá Ctrl+Z, zastavení procesu
SIGCONT          Rozběhnutí procesu
SIGCHLD          Tento signál obdrží proces, když doběhne nějaký jeho potomek
wait
$PID
$!

Tipické využití: kopíruji si disk pomocí dd, chci znát průběh, pošlu mu signál SIGUSR1

Chci ukončit nějaký konkrétní proces, zavolám kill "$pid". Pokud vzdoruje, pošľu mu SIGKILL: kill -9 "$pid".

Pro pokročilé: příkaz pkill

Chci-li signál odchytit v shellu, použiji trap příkaz signál

Příklady:
  1. Napište program, který vypíše jméno signálu, který mu byl zaslán (kromě SIGKILL) a běží dál bez ukončení. Stačí umět zpracovat standardní POSIXové signály. Posílejte tomuto programu různé signály pomocí kill, abyste vyzkoušeli jeho chování.
  2. Vyzkoušejte si uklízení dočasných souborů. Máme následující skript:
    #!/bin/sh
    
    zpracovavej_data () {
    	echo "Vypisuji cislo $1 do souboru $docasny_adresar/$1.temp"
    	echo "$1" > "$docasny_adresar/$1.temp"
    	sleep 1
    }
    
    docasny_adresar="`mktemp -d`"  # mktemp není v POSIXu, na zkoušce si jej možná budete muset naprkogramovat sami, ale pro reálný život je moc užitečný
    
    echo "Ahoj! Jsem skript, který si právě založil dočasný adresář $docasny_adresar"
    echo "Teď do něj jdu ukládat svá data..."
    
    seq 40 | while read number; do
    	zpracovavej_data "$number"
    done
    
    rm -rf "$docasny_adresar"
    
    Doplňte do něj pomocí trap takovou funkcionalitu, aby při předčasném zabití skriptu pomocí Ctrl+C došlo k pročištění dočasných souborů.

Awk

Zde se budou průběžně objevovat případné skripty či vstupy a výstupu, které napíšeme na projektoru.