T: Skrypty powłoki.
Skrypt to nieskompilowany tekstowy plik wykonywalny, zawierający jakieś polecenia systemowe oraz polecenia sterujące jego wykonaniem (np. instrukcje, pętle). Wykonywany jest tylko i wyłącznie przez interpreter ( np. /bin/bash), który tłumaczy polecenia zawarte w skrypcie na język zrozumiały dla procesora.
Skrypty, czyli programy powłoki, są prostymi plikami tekstowymi zawierającymi niektóre polecenia Linuksa i powłoki bash. Po uruchomieniu programu powłoki polecenia są wykonywane jedno po drugim. Program powłoki może mieć przekazane parametry, tak jak w wypadku jakiegokolwiek normalnego polecenia. Parametry te mogą być oceniane wewnątrz programu. Ponieważ proste, sekwencyjne wykonywanie kilku poleceń nie zostawia wiele miejsca dla złożonych zadań, bash wspiera programowanie powłoki poleceniami do konstruowania pętli i rozgałęzień. Dzięki temu mamy do dyspozycji prawdziwy język programowania, do którego nie potrzebujemy wiedzy na temat kompilatora lub języka C.
Skrypty są potężnym narzędziem programistycznym (rozbudowana składania, instrukcje pętli, warunku i wyboru, zmienne, stałe i wiele wiele innych). Typowym zastosowaniem programów powłoki jest automatyzacja najczęściej wykorzystywanych sekwencji poleceń do instalacji programów, administracji systemem, tworzenia kopii zapasowych, konfiguracji i wykonywania pojedynczych programów itd.
Zadanie1:
Skrypty należy konstruować w następujący sposób:
- w pierwszej linii należy umieścić deskryptor określający rodzaj shella jaki ma być użyty do wykonania skryptu, np. o następującej treści:
- w dowolnych wierszach można tworzyć opisy w formie komentarzy dla osób analizujących skrypt, linie te należy rozpoczynać znakiem hash #, np:
- dobrym rozwiązaniem będzie umieszczenie linii z komunikatami wyświetlanymi na standardowym wyjściu (ekranie monitora) stosownych komunikatów podczas wykonywania skryptu, np.:
- każdy plik będący skryptem aby mógł być uruchamiany musi posiadać atrybuty wykonywalności, nadajemy go poleceniem chmod, np.:
Przykładowe skrypty:
- Pierwszy i najprostszy skrypt:
#!/bin/bash
echo "Jan Nowak"
- Wyświetlanie komunikatów na ekranie:
#!/bin/bash
echo "Witam. Twoj login to $USER"
echo "Lista plików w bieżącym katalogu, $PWD"
ls # wypisz listę plików
- Wykorzystanie argumentów skryptu:
#!/bin/bash
echo "Nazwa tego skryptu to: $0"
echo "Argument 1: $1"
echo "Argument 2: $2"
sleep 5
- Odczytywanie wartości podanych przez użytkownika:
#!/bin/bash
echo -n "Podaj wartość: "
read wartosc
echo "Podałeś wartość: $wartosc"
- Zastosowanie instrukcji warunkowej:
#Wyświetlenie zawartości katalogu, gdy on istnieje
if [ -x /home/soisk/skrypty ]; then
ls /home/soisk/skrypty
fi
sleep 5
- Wykorzystanie składni if-then-else w skrypcie:
#!/bin/bash
if test -f "$1" #lub zapis if [ -f "$1" ]
then
vi "$1"
else
echo "Nie ma takiego pliku."
fi
- Zastosowanie pętli i instrukcji wyboru:
#!/bin/bash
KONIEC="x";
function wybor
{
case $KONIEC in
s) echo "Jesteś w katalogu: $(pwd)" ;
p) echo "teraz wypisze wszystkie twoje procesy";
ps -e ;;
w) echo "Oto lista plików w tym katalogu";
ls ;;
esac;
}
function menu #poczatek menu
{
until [ $KONIEC = k ];do
echo "Wciśnij Enter aby kontynuować";
read;
clear; # czyść ekran
echo $KONIEC;
echo " Proste Menu ";
echo;
echo "s - wyświetl ścieżkę w której znajduje się skrypt.";
echo "p - wyświetl listę procesów użytkownika.";
echo "w - wyświetl wszystkie pliki w tym katalogu.";
echo "k - zakończ skrypt.";
read KONIEC;
wybor;
done;
}
menu;
- Przykładowa konfiguracja zapory firewall:
#!/bin/bash
INTERFACE=eth0
NETMASK=192.168.10.0/24
/sbin/iptables -F
/sbin/iptables -X
/sbin/iptables -P INPUT ACCEPT
/sbin/iptables -P FORWARD DENY
/sbin/iptables -A FORWARD -i $INTERFACE -j MASQUERADE -s $NETMASK
echo 1 > /proc/sys/net/ipv4/ip_forward
- Zamontowanie odpowiedniego systemu plików, np.:
#!/bin/bash
# zamontowanie CD-ROM
mount -t iso9660 -o ro /dev/hdc /mnt/cdrom
mount -t vfat -o rw /dev/sdb1 /mnt/flash
- Sprawdzenie parametru i wyświetlenie (imię):
#!/bin/sh
if [ $# -eq 0 ]
then
echo "Imię nie zostało podane"
else
echo "Podane imię to "$1
fi
Zadanie2:
Wykorzystując serwis internetowy Wikipedii odszukaj informacje na temat powłoki bash.
exec #słowo kluczowe wywołujące programy w skryptach (np. exec mc)
Język powłoki bash jest rozszerzeniem powłoki sh. Większość skryptów przeznaczonych dla powłoki sh działa bez zmian w powłoce bash, wyjątkami są skrypty, które odwołują się do wbudowanych zmiennych powłoki Bourne'a lub używają wbudowanych poleceń tej powłoki. Składnia poleceń powłoki bash zawiera idee pochodzące z powłoki Korna i csh takie jak edycja linii poleceń (ang. command-line editing), historia poleceń, stos katalogów, zmienne $RANDOM i $PPID oraz POSIX-owe podstawianie polecenia (składnia: $((...))). Gdy bash jest używany interaktywnie, dostępne jest dokańczanie nazw plików, poleceń wbudowanych i zewnętrznych programów, zmiennych, itd. dzieje się to po naciśnięciu klawisza TAB.
Jednym z ograniczeń powłoki sh jest to, że nie umożliwia ona operowania na liczbach całkowitych bez tworzenia nowego procesu. Bash umożliwia wykonanie obliczeń za pomocą wyrażeń w podwójnych nawiasach ((...))
oraz składni $[...]
. Przykładowo:
x1=55 #Przypisz liczbę 55 do zmiennej x1. Nie może być spacji przed i po znaku równości.
((x1 = x1 + 1)) #Dodaj jeden do x1. Nie stawia się tutaj znaku '$'.
echo $((x1 + 1)) #Wypisz wartość x1+1 na ekran.
((++x1)) #Zwiększenie o jeden w stylu języka C.
((x1++)) # Podobnie jak powyżej ale teraz post-inkrementacja.
echo $[x1=x1*20] #Pomnóż x1 przez 20, zapisz wynik do x1 i wypisz wynik na ekran.
echo $((x1 * 20)) #To samo co powyżej, ale nie zapisuj wyniku do zmiennej.
echo $((x1<1000)) #Sprawdź czy x1 jest mniejsze od 1000. Zero oznacza fałsz.
Składnia ((...))
może być także wykorzystana w wyrażeniach warunkowych, ponieważ w wyniku wykonania zwracane jest 0 lub 1 w zależności od tego czy porównanie wartości zwraca fałsz czy prawdę:
if ((x == y * 3 + z * 2))
then
echo Yes
fi
((z > 23)) && echo Yes
Składnia ((...))
umożliwia posługiwanie się operatorami: '==
', '!=
', '>
', '<
', '>=
' i '<=
'. Bash nie umożliwia wykonywania obliczeń z wykorzystaniem liczb zmiennoprzecinkowych.
Bash rozszerza składnię powłoki sh służącą do przekierowania wejścia/wyjścia. Możliwe jest skierowanie standardowego wejścia i standardowego wyjścia dla błędów do pliku w sposób krótszy niż w sh:
W powłoce Bourne'a wyglądałoby to następująco 'polecenie > plik 2>&
'. Od wersji 2.05b możliwe jest przekierowanie zmiennej na standardowe wejście polecenia:
polecenie <<< "Napis do przeczytania ze standardowego wejścia"
#można też użyć zmiennej zmienna="Ala ma"
cat <<< "${zmienna} kota."
Przykład:
Przekieruj standardowe wyjście do pliku, wypisz dane, zamknij plik, zresetuj wyjście:
exec 6>&1 #niech deskryptor pliku 6 stanie się kopią standardowego wyjścia
exec 1>test.dane #otwórz plik test.dane do zapisu, deskryptor nr 1 oznacza,
#że trafi do niego standardowe wyjście echo "dane:dane:dane"
#wypisz coś exec 1<&- #zamknij plik
exec 1>&6 #przywróć deskryptorowi 1 jego pierwotną funkcję
exec 6<&- #zamknij deskryptor 6
Otwórz i zamknij plik:
#otwórz test.dane do czytania
exec 6<test.dane
#czytaj kolejne wiersze i wypisuj je, aż do napotkania końca pliku
while read -u 6 dane
do
echo "$dane"
done
#zamknij plik
exec 6<&-
Podstaw wyjście zewnętrznego polecenia do zmiennej:
#wyszukaj pliki których nazwa kończy się na literę "h"
#i zachowaj wynik w zmiennej ZM
ZM=$(find . -name "*h")
Bash 3.0 posiada wbudowaną obsługę wyrażeń regularnych, dopasowanie odbywa się za pomocą składni przypominającej Perl:
Używa się standardowych wyrażeń regularnych opisanych na stronie regex(7) podręcznika man. Powyższe polecenie zwraca wartość 0, gdy dopasowanie udało się lub 1 w przeciwnym przypadku. Podwyrażenia otoczone nawiasami są dostępne w zmiennej powłoki BASH_REMATCH, tak jak w poniższym przykładzie:
if [[ abcfoobarbletch =~ 'foo(bar)bl(.*)' ]]
then
echo "Dopasowanie udało się\!"
echo $BASH_REMATCH #wypisuje: foobarbletch
echo ${BASH_REMATCH[1]} #wypisuje: bar
echo ${BASH_REMATCH[2]} #wypisuje: etch
fi
Używanie powyższej składni, zamiast programu grep, daje kod działający szybciej, ponieważ unika się kosztownego tworzenia nowego procesu.
Uruchamianie wcześniej utworzonego skryptu, dopisać składnię do pliku rc.local, np.:
if [ -x /bin/script ]; then
script
fi
Uruchamianie skryptu automatycznie przy starcie systemu:
gedit /etc/init.d/skrypt
chmod +x /etc/init.d/skrypt
update-rc.d skrypt defaults 90
Parametry polecenia echo:
-n brak znaku przejścia do nowej linii,
\a wywołanie alarmu dźwiękowego (brzęczek),
\n wyświetlenie pustej linii,
\r powrót do początku linii,
\t pojawienie się znaku tabulacji.
Przykład z przerwaniem działania skryptu po osiągnięciu celu:
#!/bin/bash
for imie in Adam Jarek Darek Tomek
do
echo $imie
if [ "$imie" = "Darek" ]
then
break
fi
done
Pingowanie komputerów w sieci lokalnej:
#!/bin/bash
for ((ip=21; ip<=34; ip++))
do
ping -c 2 192.168.10.$ip
done
Polecenie test służy do porównywania wartości:
#!/bin/bash
test 5 -gt 5
echo $?
Parametry polecenia test:
-d sprawdzenie, czy plik jest katalogiem (test -d plik),
-f sprawdzenie, czy plik jest wykonywalny (test -f plik),
-x sprawdzenie, czy plik istnieje i ma prawa do wykonywania,
!= sprawdzenie, czy wyrażenia są różne (test wyr1 != wyr2),
-gt sprawdzenie, czy pierwsza liczba jest większa od drugiej (test a -gt b),
-lt sprawdzenie, czy pierwsza liczba jest mniejsza od drugiej,
-eq sprawdzenie, czy liczby są równe,
-ne sprawdzenie, czy liczby są różne.
Składnia polecenia if:
if <warunek>;
then <instrukcje>;
elif <warunek>;
then <instrukcje>…;
else <instrukcje>;
fi
let i=$i+1 #zwiększenie zmiennej i o 1