par

Transkrypt

par
Programowanie w
języku powłoki
Tomasz Borzyszkowski
Potoki, strumienie, przekierowania
Będziemy zajmować się programowaniem w powłoce sh (Bourne'a),
wspominając czasem o rozszerzeniach powłoki bash (Bourne Again
Shell).
Potoki przypominają budowanie z klocków. Możemy je składać:
ps -a | sort | uniq | grep -v sh | more
Przekierowania służą do zmiany przepływu informacji z i do
programów. Standardowe deskryptory to: 0 - wejście, 1 - wyjście,
2 - wyjście błędów. Przykłady:
ps -ax >> procesy.txt
find / -name qqq -print > findout.txt 2>finderr.txt
kill -l 1234 > killouterr.txt 2>&1
kill -l 1234 > /dev/null 2>&1
2
Wybrane komendy: grep
Służy do wyszukiwania zadanych wzorców w plikach
(szczegóły: man grep).
grep -l 'bzyk' kubus[12].*
grep -r -i 'Kubus' ..
grep -i -n -v "\-bzyk*" kubus[12].*
grep -C 2 -e '-bzyk' kubus*
grep 'dzien\>' kubus*
ps -ef | grep
'[c]ron'
grep 'tomek' /etc/passwd
cat /etc/passwd | grep 'tomek' - /etc/shadow
find ~ -name '*.c' -print | xargs grep -l 'hello'
3
Wybrane komendy: find
Służy do wyszukiwania plików o określonych własnościach
(szczegóły: man find).
Opcje
-atime n
ostatnie żądanie dostępu do pliku miało miejsce
dokładnie n dni temu
-mtime n
plik był modyfikowany dokładnie n dni temu
-newer nazwplik był modyfikowany później niż plik o nazwie nazw
-size n
rozmiar pliku wynosi dokładnie n bloków
-type c
plik jest określonego typu: f -plik zwykły, d -katalog
itp.
-fstype typ typ systemu plików: ufs, 4.2, 4.3, nfs, tmp, ...
-name wzorz nazwa pliku pasująca do wzorca wzorz
-perm p
prawa dostępu do pliku ustawione na p
-user usr
plik, którego właścicielem jest usr
-group grp plik, którego grupą jest grp
-nouser
właściciel pliku nie figuruje w pliku haseł
4
-nogroup grupa pliku nie figuruje w pliku grup
Wybrane komendy: find cd
Pow. opcje można używaæ z '+' i '-' i znaczą więcej i mniej, np.:
-mtime +7 pliki modyfikowane więcej niż 7 dni temu
-atime -2 pliki, do których ostatnie żądanie dostępu miało
miejsce mniej niż 2 dni temu
-size +100 pliki większe niż 50 Kb
-perm -002 pliki mające ustawiony najmniej drugi bit uprawnień,
czyli co najmniej prawo do pisania dla pozostałych
Koniunkcję warunków uzyskujemy wypisując je jeden za drugim.
Np.: pliki, do których nikt nie żądał dostępu od ponad dwóch
miesięcy i które od ponad czterech miesięcy nie były modyfikowane,
to:
-atime +60 -mtime +120
Alternatywę uzyskujemy tak:
\(-atime +30 -o -mtime +7\)
Negację, natomiast tak:
! -name g*.dat -name *.dat
5
Wybrane komendy: find jeszcze
Akcje
-print
-ls
-exec cmd
-ok cmd
-xdev
-prune
wyświetla nazwy znalezionych plików
wyświetla pełniejszą informację o znalezionym pliku
wykonanie na znalezionym pliku polecenia cmd
wykonanie na znalezionym pliku polecenia cmd z
żądaniem potwierdzenia
ograniczenie wyszukiwania tylko do systemu plików
zawierającego katalog początkowy
zaniechanie wyszukiwania w znajdowanych katalogach
Zastosowanie
1. Testy zużycia miejsca na dysku
find /home -size +2048 -mtime +30 -exec ls -l {} \;
pliki większe od 1MB i niemodyfikowane od ponad miesiąca;
a co to?:
find /home -size +2048 \
\( -mtime +30 -o -atime +120 \) \
6
-exec ls -l {} \;
Wybrane komendy: find i jeszcze
2. Odzyskiwanie miejsca na dysku:
find / \( -name a.out -o -name core -o -name '*~' \
-o -name '.*~' -o -name '#*#' \) \
-type f -atime +14 \
-exec rm -f {} \; -o -fstype nfs -prune
3. Wyszukiwanie plików stanowiących zagrożenie dla systemu:
find / -type f \( -perm -2000 -o -perm -4000 \) \
-print | diff - files.secure
patrz także plik find1.sh
4. Wykonywanie powtarzających się czynności:
find /home/tomek -exec chown tomek {} \; \
-exec chgrp informatyka {} \;
find . -depth -name '*.txt' ! -name 'f*' -print0 | \
tar --create --null --files-from=- -file=txty.tar
7
Wybrane komendy: awk
Nazwa AWK pochodzi od nazwisk autorów: A.V.Aho,
P.J.Weinbergera i W.Kernighana. Jest językiem interpretowanym i
nadaje się do przetwarzania logów tekstowych.
Zasada działania: wczytujemy rekord i dla niego wykonujemy
wszystkie instrukcje. Potem następny, itd.....
Programy składają się z bloków. Typowy blok wygląda nastąpująco:
<warunek> { <polecenia> }
Typowe warunki
i==5
oczywiste (składnia jak w C)
/a*bc/
akceptuje rekordy zawierające dowolną ilość liter a, a po
nich bc
warunek prawdziwy zanim zostanie wczytany jakikolwiek
rekord
warunek prawdziwy po wczytaniu ostatniego rekordu
BEGIN
END
8
Wybrane komendy: awk zmienne
Nie deklarujemy zmiennych. Inicjalizacja następuje w momencie
użycia wartością 0 lub "" (pusty ciąg znaków).
Przykład: x=5; x=2*x+y
Tablice są indeksowane napisami (tzw. tablice asocjacyjne).
Odwołanie przez liczbę powoduje zamianę liczby na odp. napis i dalej
jak z napisem.
Przykład: t["ala"]=2; t[2]=5
Prócz operatorów z C, występuje operator ~ i oznacza zawiera
wyrażenie. Np.: "aaa"~/a/ jest prawdziwe, lecz "bbb"~/a/ nie
jest.
Innym operatorem jest in i służy do sprawdzania czy dany element
jest indeksem tablicy. Np: "ala" in t. Warunki takie mogą
występować w programach (skadnia jak w C - patrz man awk):
wart="ala"
if(wart in t) print t[wart]
9
Wybrane komendy: awk zmienne cd
$0
wczytany rekord
$1,...
$x
kolejne pola we wczytanym rekordzie
pole we wczytanym rekordzie o numerze takim jak
wartość zmiennej x
liczba wczytanych pól
separator pól, wpisujemy wyrażenie regularne
opisujące separatory, domyślny: spacja
NF
FS
Itd......
Wywołania
awk -f <plik_z_programem> <plik_wej1> <plik_wej2>...
#!/bin/awk -f
awk '{print$1}' <plik1> ...
10
Wybrane komendy: awk przykłady
(date; ps -ef | grep [d]oom | \
awk '{print $1 " [" $7 "]" }' | \
sort | uniq) >> doomed.users
awk1.sh
find /home -user $1 -fstype ext3 -ls | awk \
'{sum+=$7}; END {print "Total disk use = " sum}'
awk2.sh
#!/usr/bin/awk -f
{ for (i = 1; i <= NF; i++)
freq[$i]++
}
END {
for (word in freq)
printf "%s\t%d\n", word, freq[word]
}
awk3
11
Zmienne środowiska: sh
Powłoki posiadają predefiniowane zmienne środowiskowe.
Mogą one być modyfikowane przez użytkownika. Np.:
$HOME katalog macierzysty obecnego użytkownika
$PATH podzielona znakami ":" lista katalogów przeszukiwanych
przez polecenia
$PS1
znak zgłoszenia systemu, przeważnie $
$PS2
dodatkowy znak zgłoszenia systemu, przeważnie >
$IFS
separator pól wejściowych; lista znaków używanych do
rozdzielania param. wejściowych czytanych przez powłokę
$0
nazwa wykonywanego skryptu
$1,... parametry przekazane do skryptu
$#
liczba przekazanych parametrów
$$
PID procesu wykonywanego skryptu; często używany
wewnątrz skryptu do tworzenia niepowtarzalnych nazw
$*
lista wszystkich paramertów porozdzielanych pierwszym
znakiem zmiennej $IFS
Patrz skrypt zmienne.sh 12
Deklaracja zmiennych
Składnia:
declare [-afFirx] [-p] [zmienna[=warto??]]
Polecenie to deklaruje zmienną i ewentualnie nadaje jej wartość.
Znaczenie poszczególnych opcji (patrz także man bash):
-a
definiowana zmienna jest tablicą
-f
definiowana zmienna jest funkcją
-F
jak -f z tym, że definiowana funkcja nie jest wyświetlana
-i
definiowana zmienna jest zmienna całkowitą
-r
definiowana zmienna jest przeznaczona tylko do odczytu
-x
definiowana zmienna jest przeznaczona do eksportu przez
środowisko
-p
wyświetla zmienną wraz z jej definicją
Patrz skrypt decl.sh
13
Polecenie test czyli [ ]
Polecenie to służy do testowania warunków. Np.: test -f plik
sprawdza czy istnieje plik o nazwie plik równoważne [ -f plik ]
Testy
-d
-e
-f
-g
-u
-r
-s
-w
-x
plik
plik
plik
plik
plik
plik
plik
plik
plik
czy
czy
czy
czy
czy
czy
czy
czy
czy
Porównania
plik jest katalogiem
e1 -eq
plik istnieje
e1 -ne
plik jest plikiem reg.
e1 -gt
plik posiada GUID
e1 -ge
plik posiada SUID
e1 -lt
plik daje się czytać
e1 -le
plik ma niezerowy rozm.! e1
do pliku można pisać
plik jest wykonywalny
e2
e2
e2
e2
e2
e2
czy e1 = e2
czy e1!= e2
czy e1 > e2
czy e1 >=e2
czy e1 < e2
czy e1 <=e2
negacja e1
UWAGA
1. W historii UNIXa -e bylo nieprzenośne i raczej używa się -f.
2. Własności SUID i GUID nie działają na skrypty powłoki.
14
Instrukcje sterujące
if-then-else
for-in- do-done
if warunek
then
instrukcje
else
instrukcje
fi
if1.sh i if2.sh
for zmienna in warto?ci
do
instrukcje
done
while-do-done
case-in-esac
for1.sh i for2.sh
case zmienna in
while warunek
wzorzec [| wzorzec ...]) instr;;
do
wzorzec [| wzorzec ...]) instr;;
instrukcje
...
done
case1.sh
while1.sh i while2.shesac
until1.sh i until2.sh
15
Listy AND i OR
Lista AND umożliwia wykonanie serii poleceń. Kolejne polecenie jest
wykonane, gdy poprzednie zakończy się sukcesem. Cała lista kończy
się sukcesem, gdy wszystkie polecenia zakończą się sukcesem.
instr1 && instr2 && ... && instrn
and1.sh
Lista OR umożliwia wykonanie serii poleceń, aż jedno zakończy się
sukcesem, wtedy żadne już nie będą wykonywane.
Wykonanie następuje od lewej do prawej (podobnie jak w liście AND).
instr1 || instr2 || ... || instrn
or1.sh
Pytanie
Jakie jest wiązanie operatorów list? Czyli, jak działają listy mieszane?
instr1 && instr2 || instr3
16
Funkcje
Składnia
nazwa_funkcji () {
instrukcje
}
 Funkcja może oddawać wartość
liczbową, używając polecenia:
return warto??
 Ciągi znaków mogą być przekazywane
jedynie przez zmienne globalne
 W funkcjach można używać
zmiennych lokalnych
Przykłady
1. Prosta funkcja
2. Zmienne lokalne funkcji
fun1.sh
fun2.sh
3. Funkcja zwracająca wartość
fun3.sh
4. Przekazywanie wartości do funkcji fun4.sh
5. Funkcje robiące coś
fun5.sh
6. Funkcja rekursywna
hanoi.bash
17
Tablice
W bashu dostępne są jednowymiarowe tablice. Deklaruje się je za
pomocą plecenia declare -a lub niejawnie przez wystąpienie wyr.
nazwa[indeks]=warto??, gdzie indeks jest wyr. arytm. > 0.
Tablice są indeksowane od 0. Można im nadawać wartości w sposób
tradycyjny:
nazwa[indeks]=warto??
lub w bardziej złożony:
nazwa=(wart_1, ..., wart_n)
gdzie wart_i jest postaci [indeks_i]=string_i
Dowolny element tablicy może być odczytany za pomocą wyrażenia:
${nazwa[indeks]}
${nazwa[@]} rozwinie się do listy elementów tablicy
rozdzielonych pierwszym elementem zmiennej IFS
${nazwa[*]} jw. lecz wynik jest jednym ciągiem znaków
${#nazwa[idx]} długość ${nazwa[idx]}
Patrz array-stuff i array-to-string
18
Rozwijanie parametrów
Język powłoki udostępnia również mechamizmy: rozwijania
parametrów, dopasowywania wzorca, itp. (patrz man bash).
${par:-wyr} jeżeli par jest pusty, to wynikiem jest wyr, w
przeciwnym przypadku par
${par:=wyr} jeżeli par jest pusty, to jego wartością staje się
wyr, następnie wynikiem jest par
${par:+wyr} jeżeli par jest pusty, to brak wyniku, w przeciwnym
przypadku wynikiem jest wyr
${par:off:len} wynikiem jest len znaków ciągu par zaczynając
od znaku off, jeżeli brak parametru len, wynikiem jest ciąg
znaków od off do końca par
${!prefix*} wynikiem jest lista nazw zmiennych zaczynających
się od prefix
${#par} wynikiem jest liczba znaków par, jeżeli par jest * lub @,
wynik to liczba przekazanych parametrów lub jeżeli par jest
tablicą z indeksem * lub @, wynikiem jest jej długość
19
Rozwijanie parametrów cd
${par#wyr} wyr opisuje wzorzec, wynikiem jest reszta pozostała
po najmniejszym dopasowaniu wzorca do par zaczynając od
początku par
${par##wyr} jw. z tym, że następuje największe dopasowanie
wzorca; patrz parametry1.sh
${par%wyr} i ${par%%wyr} jak ${par#wyr} i ${par##wyr} z
tym, że następuje dopasowanie wzorca do końca par;
patrz parametry2.sh
${par/wyr/str} i ${par//wyr/str} wynikiem jest par, w
którym pierwsze największe dopasowanie wzorca wyr
zamieniono na str; w drugim przypadku zamienione zostaną
wszystkie dopasowania wzorca; wyr rozpoczynające się od #
oznacza dopasowanie do początku par; natomiast %, do
końca par
patrz parametry3.sh
20
Polecenia source i exit
source skrypt
Zwykle skrypt wykonuje się w podpowłoce powłoki wywołującej, tj.
w jej nowym środowisku. Po zakończeniu skryptu, środowisko to jest
usuwane i do środowiska macierzystego przekazywany jest tylko kod
wyjścia skryptu. Zastosowanie polecenia source skrypt lub
. skrypt, spowoduje wykonanie skryptu w powłoce wywołującej.
sou1.sh i sou2.sh
exit n
Polecenie to powoduje zakończenie skryptu z kodem wyjścia n.
Jeżeli nie użyjesz exit do zakończenia skryptu, to kod wyjścia
skryptu będzie kodem wyjścia ostatnio wykonywanego polecenia.
0
sukces
1-125
kody zdefiniowane przez użytkownika
126
plik nie był wykonywany
127
polecenie nie zostało znalezione
>127
pojawił się sygnał nr, gdzie nr+127 = kod wyjścia
21
Polecenie trap
trap [-l] polecenie sygna?
Jest stosowane do określania działań podejmowanych po otrzymaniu
sygnału. trap -l wypisuje nazwy dostępnych sygnałów wraz z ich
wartościami liczbowymi. Polecenie trap powinno być wykonane
przed częścią kodu, którą chcemy chronić.
Sygnały
HUP (1) zawieszenie; wysyłany, gdy terminal zostaje wyłączony
lub użytkownik się wyloguje
INT (2) przerwanie; np. naciśnięcie Ctrl-C
QUIT(3) wyjście; np. naciśnięcie Ctrl-\
ABRT(6) przerwanie; wysyłany po poważnym błędzie w trakcie
wykonywania
ALRM(14)alarm; obsługa przekroczenia dopuszczalnego czasu
TERM(15)zakończenie; wysyłany np. podczas zamykania systemu
trp1.sh
22
Przykłady skryptów
Do jednych z ważniejszych zadań administratora systemu należy
zabezpieczenie systemu przed niepowołanym dostępem oraz dbanie
o zasoby systemowe (np. zasoby dyskowe). Poniższe przykłady
pokazują w jaki sposób możemy zautomatyzować oba te zadania,
używając skryptów powłoki.
Przykład 1 - skrypt ckpwd.sh
Skrypt ten sprawdza poprawność wpisów w pliku /etc/passwd,
oraz: czy istnieją konta bez haseł, czy istnieją inni użytkownicy niż
root, którzy mają UID=GID=0, jakie konta zostały ostatnio dodane /
usunięte i czy plik haseł posiada odpowiednie prawa dostępu.
Przykład 2 - skrypty ckdsk.sh i cmp_size.sh
Skrypty te pozwalają śledzić zmiany w wykorzystaniu przestrzeni
dyskowej przez użytkowników.
Oba przykłady prezentują skrypty, które administrator powinien
wykonywać często, przez cały czas życia systemu, to też można
zautomatyzować...
23

Podobne dokumenty