Oprávnění jste probrali na přednášce. Pro připomenutí se můžete podívat na jejich přehled.
Ve chvíli, kdy by náš příkaz byl příliš komplikovaný či příliš rozsáhlý na to, abychom jej psali na příkazovou řádku, můžeme místo toho vytvořit shellový skript. V něm jsou zapsány jednotlivé příkazy, tak jako bychom je psali jeden po druhém do příkazové řádky. Pokud je každý příkaz na novém řádku, nemusíme je oddělovat středníky. První řádek skriptu je speciální. Jmenuje se shabang (též she-bang či sh-bang) a vypadá takto: #!/bin/sh. Tento řádek zodpovídá za to, že se soubor v případě spuštění bude interpretovat jako shellovský skript.
Komentáře můžeme zapisovat pomocí # – cokoliv za tímto znakem až do konce řádku je považováno za komentář. Skript můžeme spustit pomocí sh skript.sh, případně, pokud je spustitelný, pomocí ./skript.sh.
V příkazové řádce i v shellových skriptech můžete používat proměnné, podobně jako v jiných programovacích jazycích. Nutno podotknout, že pouze skalární proměnné, tedy žádné pole, objekty apod. Obsahem proměnné v shellu je vždy řetězec. Shell nahradí každý výskyt $xyz v příkazové řádce nebo v shellovém skriptu obsahem proměnné xyz. Pozor! Jedná se opravdu o jednoduché nahrazení. Pokud se v proměnné nachází mezera a my ji předáme příkazu, ten si ji vyloží jako dva různé parametry. Pokud tomu chceme zabránit, můžeme uzavřít proměnnou do uvozovek "$xyz", které potlačí speciální význam metaznaků jako je mezera.
Naopak, pokud chceme napsat znak $, musíme před něj napsat \ nebo jej uzavřít do apostrofů. Pokud potřebujeme zapsat proměnnou doprostřed řetězce, můžeme použít syntaxi ${xyz}. Pokud zapíšeme proměnnou, která ještě nebyla definována, shell nevyhodí chybu, ale nahradí ji prázdným řetězcem!
Do proměnné přiřadíme pomocí znaku =. Mezery před ani za = nejsou přípustné, přiřazovanou hodnotu ale můžeme uzavřít do uvozovek či apostrofů.
xyz="ahoj světe"
echo $xyz
Existuje velká hromada předdefinovaných globálních proměnných. Postupně budeme jejich seznam rozšiřovat, zatím si vystačíme s těmito:
$0 ... jméno běžícího shellového skriptu
$n ... n-tý parametr předaný na příkazové řádce;
n>9 je třeba uzavřít do {}
$@ ... všechny parametry předané na příkazové řádce
$$ ... číslo běžícího procesu (shellu, nebo shellového skriptu) – PID
$USER ... přihlášený uživatel
$HOME ... domovský adresář
$PWD ... aktuální adresář
$PATH ... cesta, ve které se vyhledávají spustitelné soubory
$RANDOM ... náhodné číslo od 0 do 32767
POSIX specifikuje pouze jednočíslicové parametry $n. Podpora pro vyšší čísla je však široce implementována. Později se dozvíme, jak snadno pracovat s libovolným počtem parametrů, aniž bychom museli přistupovat ke každému zvlášť.
Někdy by se nám hodilo uložit do proměnné výstup nějakého příkazu. K tomu nám pomůže substituce příkazů. Kdykoliv uvidí shell ve skriptu $(příkaz), příkaz provede a jeho výstup dosadí na místo uvedeného výrazu. Stejného výsledku jde docílit uzavřením příkazu do zpětných apostrofů: `příkaz`. Substituce se provede i pokud je výraz uzavřen v uvozovkách, ne však v apostrofech.
pwd=$(pwd)
... uloží aktuální adresář do proměnné $pwd
echo "Ahoj, $(whoami | cut -c1 | tr 'a-z' 'A-Z')."
... pozdraví uživatele iniciálou jeho loginu
Pozor! Veškeré příklady týkající se oprávnění provádějte v adresáři /tmp nebo v jeho podadresářích. Ve vašem domovském adresáři nebudou kvůli afs oprávnění fungovat tak, jak očekáváte. Spustitelné skripty ale můžete vytvářet i ve svém domovském adresáři.
fhdn;Frank Herbert;Duna
grrm;George R. R. Martin;Hra o trůny
tpbk;Terry Pratchett;Barva kouzel
tplf;Terry Pratchett;Lehké fantastično
A soubor vypujcky:
fhdn;pk;12.12.2014
grrm;mb;3.1.2015
tpbk;jm;24.9.2014
A soubor ctenari:
jm;Jan Musílek
mb;Martin Babka
mh;Martin Hykl
pk;Petr Kučera
join -t\; knihy vypujcky | cut -d\; -f 2,3,5
join -t\; knihy vypujcky | sort -t\; -k 4 |
join -t\; -1 4 -2 1 - ctenari | cut -d\; -f 4,6
mkdir adresar
touch adresar/soubor
chmod 311 adresar
chmod a+r adresar/soubor
#!/bin/sh
echo Hello, world!
chmod a+x helloworld.sh
curl "http://kam.mff.cuni.cz/~stinovlas/unix/materialy/ctecka.c"
> ctecka.c
gcc ctecka.c -o ctecka
Nastavte binárce ctecka stejná práva jako skriptu ctecka.sh.
touch databaze
chmod 600 databaze
cat > ctecka.sh
#!/bin/sh
head -n3 databaze
Ctrl-D
chmod 4755 ctecka.sh
Klíčem je tedy nastavení setuid bitu. Postup výše by měl fungovat, ale nefunguje. Je tomu tak proto, že na Linuxových systémech je nastavení setuid bitu na shellovém skriptu považováno za bezpečnostní riziko a proto je ignorováno. Kdybyste místo toho vytvořili zdrojový kód v jazyce C, který by také vypisoval první tři řádky databaze, ten přeložili a nastavili mu setuid bit, vše by fungovalo jak má (vyzkoušeli jsme si na cvičení).
#!/bin/sh
echo "Ahoj $USER, dáš si $1?"
Nebo s použitím printf
:
#!/bin/sh
printf "Ahoj %s, dáš si %s?\n" "$USER" "$1"