Ćwiczenie 4
Temat:
Skrypty powłoki
systemowej Bash.
Tworzenie programów w języku
powłoki.
Cel ćwiczenia:
Celem ćwiczenia jest zapoznanie studenta ze składnią języka powłoki
systemowej Bash, między innymi ze zmiennymi systemowymi, zmiennymi
specjalnymi, instrukcjami warunkowymi, pętlami. Student w tym ćwiczeniu
zapozna się z metodami tworzenia własnych programów w języku powłoki oraz
pozna możliwości zastosowania własnych skryptów.
52
Tworzenie programów w języku powłoki.
Powłoka Bash – Wstęp
Powłoka Bash jest obecnie najpopularniejszym interpreterem poleceń w systemach
Linux. Powstał jako rozszerzenie powłoki „sh”, „ksh” oraz „csh”. Składnia języka pozwala na
tworzenie
własnych
programów
skryptowych,
które
znacznie
ułatwiają
pracę
administratorom systemów oraz umożliwiają zautomatyzowane zarządzanie systemem.
W wielu dystrybucjach systemu Linux podstawowa instalacja (z ang. „base”) nie zawiera
powłoki bash, a jedynie powłokę sh (w takiej sytuacji powłoka bash może zostać oczywiście
doinstalowana). Natomiast większość instalacji typu domyślnego (z ang. „default”) zawiera
powłokę bash jako domyślny interpreter komend. W celu sprawdzenia, czy w systemie
zainstalowany jest interpreter bash oraz w której wersji, wydać należy polecenie:
/bin/bash --version
Skrypty powłoki Bash
Skrypty to pliki tekstowe zawierające polecenia danego języka skryptowego interpretowane
przez zdefiniowany interpreter. Skrypty tym różnią się od innych programów
komputerowych, że nie muszą być kompilowane.
Skrypty pisane w języku powłoki bash powinny mieć rozszerzenie .sh oraz powinny
rozpoczynać się linią informującą, jaki interpreter powinien zostać użyty:
#!/bin/bash
Aby skrypt mógł zostać uruchomiony powinien mieć ustalone prawa dostępu do pliku
umożliwiające jego wykonanie:
chmod 700 moj_pierwszy_skrypt.sh
Skrypt może zawierać dowolne polecenie, które może zostać wydane w konsoli. Skrypty
umożliwiają dodatkowo stosowanie zmiennych, interakcję z użytkownikiem, stosowanie
instrukcji warunkowych, pętli, okien dialogowych itp.
53
Tworzenie programów w języku powłoki.
Zadanie 1 Pierwszy skrypt powłoki Bash
1. Stworzyć skrypt wg poniższych wytycznych:
1.1. W konsoli tty1, za pomocą edytora Vim stworzyć plik: program_01.sh
1.2. Uzupełnić plik treścią:
#!/bin/bash
echo ”Witaj !”
sleep 5
echo -e ”Minęło 5 sekund! \n Witaj \t\tponownie !!! ”
* polecenie sleep zatrzymuje wykonanie kodu na zadeklarowaną ilość sekund,
natomiast polecenie echo wywołane z flagą -e umożliwia interpretację znaków
reprezentujących (\n) nową linię czy (\t) tabulator.
1.3. Zapisać zmiany i zamknąć edytor Vim
1.4. Zmienić prawa dostępu do skryptu poleceniem:
chmod 700 program_01.sh
1.5. Wykonać skrypt, za pomocą polecenia:
./program_01.sh
Zmienne
W języku powłoki Bash zmienne można podzielić na zmienne:
• programowe
• specjalne
• tablicowe
54
Zmienne programowe
Zmienne programowe
Zmienne programowe to zmienne tworzone i widoczne w ramach jednego programu.
Zmienne w języku Bash nie mają jawnie zdefiniowanego typu. Ich deklaracja odbywa się na
zasadzie wskazania nazwy zmiennej oraz przypisaniu jej wartości np.:
x=15
y=10
tekst=”Zmienna tekstowa”
W powyższym przykładzie zmienne x,y zostały zdefiniowane jako zmienne liczbowe,
natomiast zmienna tekst jako zmienna tekstowa.
Odwołania do tak zdefiniowanych zmiennych wykonuje się stosując symbol „$” przed nazwą
zmiennej np:
echo $x
$x
$x
$x
echo $y
$y
$y
$y
lub np. poprzez bardziej złożone konstruowanie ciągów tekstowych z wykorzystaniem
polecenia echo:
echo -e "zmienna x wynosi \t$x
$x
$x
$x \nnatomiast y wynosi \t$y
$y
$y
$y"
Przypisywanie wartości do zmiennych programowych
Przypisanie wartości do zmiennej może odbywać się w najprostszym wypadku tak jak to
zostało zaprezentowane w powyższym przykładzie, poprzez bezpośrednie przypisanie :
y=10
Wartość zmiennej może także zostać pograna z konsoli, za pomocą polecenia read, którego
składnia jest następująca:
read nazwa_zmiennej
Polecenie to pozwala na pobranie z konsoli wartości i przypisanie jej do zmiennej np:
echo ”Podaj wartość zmiennej x:”
read x
read x
read x
read x
echo ”Zmienna x wynosi: $x”
55
Przypisywanie wartości do zmiennych programowych
Za pomocą polecenia read możliwe jest także pobranie wartości kilku zmiennych:
echo ”Podaj dwie liczby oddzielone spacjami:”
read x y
read x y
read x y
read x y
echo ”Zmienna x wynosi: $x \nZmienna y wynosi: $y”
Kolejną metodą przypisywania wartości do zmiennych jest zagnieżdżanie poleceń, których
wyjście zostanie przypisane jako wartość zmiennych.
A=`polecenie1`
W powyższym przykładzie wynik działania polecenia1 zostanie przypisany do zmiennej A.
Należy zwrócić uwagę, iż polecenia zagnieżdżone muszą znajdować się pomiędzy ukośnymi
symbolami apostrofu (symbol ten na klawiaturze znajduje się najczęściej razem z symbolem
„tyldy” (~) . Np:
linie=`cat /etc/group | wc -l`
echo ”Ilość linii w pliku Group wynosi: $linie”
Zadanie 2 Zmienne programowe
1. Utworzyć skrypt: program_02.sh który zapyta o nazwę użytkownika systemowego, a po
wprowadzeniu za pomocą konsoli nazwy użytkownika wyświetli jego ID, oraz ID jego
grupy na podstawie danych w pliku /etc/passwd
56
Przypisywanie wartości do zmiennych programowych
2. Rozbudować powyższy program o funkcję wyświetlania dodatkowo grupy, do której
należy wskazany użytkownik (na podstawie ID Grupy z pliku /etc/passwd, oraz
odpowiedniej nazwy grupy w pliku /etc/group):
Zmienne specjalne oraz zmienne środowiskowe
Programy pisane w języku powłoki Bash mogą odwoływać się do zmiennych specjalnych. Do
tych zmiennych należą:
• $$ - zmienna reprezentująca PID procesu skryptu
• $# - ilość parametrów przekazywanych do skryptu
• $? - kod powrotu ostatnio wykonywanego polecenia (wartość 0, jeśli polecenie
wykonało się poprawnie, inna wartość jeśli błędnie).
• $0 - nazwa i ścieżka do skryptu
• $1 - pierwszy parametr wywołania ($2 ... $9 – parametry od 2 – 9)
• $@ - wartości wszystkich parametrów
Możliwość przekazywania parametrów do skryptu jest ważnym atutem, ponieważ można
przekazywać do skryptu pewne informacje (np. ścieżkę, flagę itp.) bez wpisywania ich na
stałe do skryptu dzięki czemu skrypt staje się bardziej uniwersalny. Parametry przekazuje się
do skryptu poprzez wpisanie ich po nazwie skryptu, rozdzielonych znakiem spacji np.:
./program_03.sh name 45 2
57
Przypisywanie wartości do zmiennych programowych
W powyższym przykładzie do skryptu przekazane zostały 3 parametry, dwa liczbowe i jeden
tekstowy.
Zadanie 3 Zmienne specjalne
1. Utworzyć skrypt: program_03.sh, który może zostać wywołany z 5 parametrami.
Program powinien wyświetlić przekazane parametry wraz z innymi zmiennymi
specjalnymi , jak w przykładzie:
Zmienne tablicowe
Podobnie jak w większości języków programowania czy językach skryptowych w powłoce
Bash istnieją zmienne typu tablicowego.
Powołanie zmiennej tablicowej wraz z przypisaniem jej wartości:
tab=(e_1 e_2 e_3)
dostęp do poszczególnych elementów tablicy:
echo ${tab[0]}
echo ${tab[1]}
58
Przypisywanie wartości do zmiennych programowych
Wyświetlenie wszystkich elementów tablicy:
echo ${tablica[*]}
Ilość elementów tablicy
echo ${#tablica[@]}
Wyrażenia arytmetyczne
Wyrażenie arytmetyczne w skryptach powłoki Bash muszą znajdować się w podwójnym
nawiasie poprzedzonym symbolem $. Obliczenia w powłoce odbywają się tylko na liczbach
całkowitych. Np:
echo $(( 2 + 2 ))
lub operując na zmiennych:
a=2
b=3
wynik=$(( a + b ))
echo $wynik
Instrukcja warunkowa if
Instrukcja warunkowa if w skryptach powłoki Bash realizowana jest wg składni:
if [ warunek ]
then
echo "Warunek spełniony"
fi
lub w przypadku stosowania dodatkowego bloku (else), gdy część kodu powinna być
wykonana w przypadku gdy warunek nie jest spełniony:
59
Składnia warunku
if [ warunek ]
then
echo "Warunek spełniony"
else
echo "Warunek niespełniony"
fi
Pomiędzy symbolami nawiasów kwadratowych a warunkiem muszą być znaki spacji.
Składnia warunku
Warunki buduje się wg następującej zasady:
[ wyrażenie operator wyrażenie ]
Gdzie operatorem może być:
-lt mniejsze niż
-gt większe niż
-ge większe lub równe
-le mniejsze lub równe
= wyrażenia są równe
!= wyrażenia są różne
Możliwe też jest zastosowanie operatorów testujących cechy plików, wg składni:
[ opcja ścieżka ]
Gdzie opcją może być np:
-e plik istnieje
60
Składnia warunku
-h plik istnieje i jest linkiem symbolicznym
-d wyrażenie istnieje i jest katalogiem
-r można czytać plik
-w można zapisywać do pliku
-x można plik wykonać
plik1 -nt plik2 plik1 jest nowszy od pliku2
plik1 -ot plik2 plik1 jest starszy od pliku2
Na przykład, aby sprawdzić, czy istnieje plik: /etc/group:
if [ -e /etc/group ]
then
echo "Plik group istnieje"
else
echo " Plik group nie istnieje "
fi
Zadanie 4 Instrukcje warunkowe
1. Napisać program_04.sh który wywołuje się z jednym parametrem liczbowym. Efektem
działania programu jest wyświetlenie informacji, czy podany parametr jest większy,
mniejszy czy równy zero. Jeśli program zostanie wywołany bez parametru program
wyświetli informację „Nie podano parametru”
61
Składnia warunku
Pętla for
Pętla for nie działa jak pętle for w innych językach operując na podstawie licznika pętli, który
jest odpowiednio zwiększany lub zmniejszany, ale na podstawie listy. Składnia pętli jest
następująca:
for licznik in lista
do
echo $licznik
done
Taką listą może być np. lista plików z rozszerzeniem .sh w danym katalogu (aby listą był spis
wszystkich plików należy zastosować sam symbol *):
for licznik in *.sh
do
echo $licznik
done
Lista może być także zdefiniowana bezpośrednio w deklaracji pętli, w takim przypadku licznik
pętli przyjmuje kolejno wartości jawnie zdefiniowane np:
for licznik in 2 3 6 8
do
echo $licznik
done
Wartości listy mogą być także typu tekstowego, poniższy przykład tworzy 3 pliki: index.html,
kontakt.html oraz news.html:
for licznik in index kontakt news
do
touch $licznik”.html”
done
62
Składnia warunku
Jako listy można także użyć zagnieżdżonego polecenia seq, które wyświetla sekwencję cyfr.
Pamiętać jednak należy, iż polecenia zagnieżdżone (tak jak w przypadku przypisywaniu
wartości do zmiennych) muszą znajdować się pomiędzy symbolami cudzysłowów ukośnych
(na klawiaturze najczęściej z symbolem tyldy ~) np:
for licznik in `seq 18 -2 1`
do
touch $licznik”.html”
done
Składnia polecenia seq:
seq od_liczby krok_sekwencji do_liczby
Zadanie 5 Instrukcje warunkowe
1. Napisać program program_05.sh , który:
1.1. Sprawdzi czy istnieje katalog tmp, jeśli nie, to go utworzy, jeśli istnieje, wyświetli
informację „Katalog tmp już istniał”
1.2. Utworzy w katalogu tmp 10 plików wg wzoru indexNR.html, gdzie człon nazwy NR to
kolejny numer pliku (od 50 – 60).
Pętla while i until
Pętle while oraz until w języku powłoki Bash działają dokładnie tak samo jak w innych
językach. Pętla while jest wykonywana dopóki warunek jest spełniony, np.:
63
Składnia warunku
a=10;
while [ $a -ge 0 ];
do
touch plik_"$a".txt
x=$((x - 1))
done
w powyższym przykładzie, dopóki zmienna $a jest większa od zera, pętla tworzy nowe pliki
tekstowe (pętla jest wykonywana, dopóki warunek jest prawdą). Odwrotnie w przypadku
pętli until, gdzie pętla jest wykonywana, dopóki warunek jest fałszem.
b=1;
until [ $b -ge 10 ];
do
echo plik_"$b".txt
b=$[b + 1]
done
Zadanie 6 Pętle
1. Napisać program program_06.sh , będący grą. Według założeń:
1.1. Program wylosuję liczbę od 1 – 100
Aby przypisać zmiennej losową liczbę zastosować można zmienną systemową,
$RANDOM, która po każdym wywołaniu zwraca losową wartość. Zmienna ta
przyjmuje losowe wartości od 0 – 32767. Dlatego, aby uzyskać zmienną z zakresu od
0 do 100 należy wylosowaną wartość podzielić przez 327. Ponieważ bash operuje
tylko na liczbach całkowitych nie ma konieczności zaokrąglania wyniku:
los=`echo $((RANDOM/327))`
64
Składnia warunku
1.2. Zapyta użytkownika o podanie dowolnej liczby od 0 do 100.
1.3. Porówna liczbę wylosowaną, z podaną przez użytkownika, a następnie wyświetli
informację, czy liczba podana jest większa, czy mniejsza od wylosowanej, a
następnie ponownie poprosi o podanie liczby.
1.4. Program powinien pytać użytkownika o nowe liczby aż do momentu, gdy
wylosowana liczba zostanie odgadnięta.
1.5. Za każdym razem, gdy użytkownik zostanie poproszony o podanie nowej liczby ekran
powinien zostać wyczyszczony (polecenie clear).
Polecenie wyjścia z programu - Exit
Polecenie exit wywołane w dowolnym miejscu programu przerywa jego działanie. Polecenie
może definiować także kod błędu, czyli powód przerwania. Jest to szczególnie wygodne, gdy
jeden program jest wywoływany przez drugi program, bowiem program wywołujący może
sprawdzić, czy praca programu wywołanego zakończyła się sukcesem (zmienna $? zwróci
wartość 0) czy niepowodzeniem, a wtedy wartość zmiennej $? zwróci taką wartość, jaka
została zdefiniowana przez polecenie wyjścia programu wywołanego (np.”exit 3”) np.:
If [ -e ./tmp ]
then
echo ”katalog nie istnieje, wychodzę”
exit 1
fi
Zadanie 7 Instrukcja Exit
1. Napisać program program_07.sh obliczający potęgę liczby całkowitej przekazanej do
programu jako parametr. Program zakończy działanie jeżeli do programu przekazana
zostanie więcej niż jeden parametr, lub gdy nie zostanie przekazany żaden parametr.