background image

dla początkujących

BASH

64

październik 2006

dla początkujących

BASH

65

www.lpmagazine.org

   

 a

ut

or

zy

@

lpm

ag

az

ine

.o

rg

Skrypty powłoki 

w systemie Linux

Wykonywanie codziennych czynności w systemie operacyjnym jest męczące, gdy za każdym razem 
trzeba wpisywać te same zestawy komend. Znacznie wygodniej byłoby zapisać je w plikach, które 
możemy później uruchomić w dowolnej chwili. Pod Linuksem, dzięki możliwości tworzenia skryptów 
powłoki (shella) wykonamy te zadania bez problemu; co więcej, znajomość shella bywa konieczna, 
gdyż opiera się na nim duża część konfiguracji systemu....

Łukasz Sosna

S

krypty  powłoki  (shella)  to  ciągi  jego  instruk-
cji zapisane w postaci zwykłych plików teksto-
wych,  które  mogą  zostać  uruchomione  w  po-
włoce i wykonać za nas określone operacje. Taki 

skrypt może też zawierać instrukcje warunkowe, pozwa-
lające m.in. przeprowadzić wybrane działanie po wpisa-
niu odpowiedniego parametru w linii poleceń (po nazwie 
skryptu), pętle wykonujące zapisane przez nas instrukcje 
określoną ilość razy czy wspomniane już argumenty po-
dawane w linii poleceń, które przekształcimy na zmienne, 
którymi z kolei będzie można dowolnie manipulować.

Ponieważ  powłoka  traktuje  skrypty  jako  zwykłe  ko-

mendy, po każdym zapisanym w skrypcie poleceniu musi 
być znak nowej linii: w przeciwnym razie skrypt zakończy 
się  niepowodzeniem.  Ta  sama  zasada  dotyczy  instrukcji 
warunkowych, pętli, itd, które wstawiamy do pliku. Po-
między instrukcją, a otaczającymi ją znakami bądź zmien-
nymi powinien też zostać zachowany odpowiedni odstęp. 
Przykładowo, ten skrypt będzie zapisany prawidłowo:

#!/bin/bash
vdir /home

Natomiast ten jest nieprawidłowy, gdyż linia została zła-
mana w nieodpowiednim miejscu:

#!/bin/bash
vdir
/home

Pierwsza linia każdego skryptu musi zawierać wywołanie 
shella, pod którym skrypt będzie wykonywany. Najpopu-
larniejszą powłoką dla systemu Linux jest bash, znajdujący 
się  najczęściej  w  katalogu  z  plikami  binarnymi  (/bin). 
W podanych przykładach przedstawiliśmy zawartość tej 
linii dla basha (

#!/bin/bash

). Pamiętajmy, że niezależnie 

od typu shella, linia ta zaczyna się zawsze od znaku „#”.

Aby  skrypt  wykonywał  się  na  naszym  komputerze, 

trzeba  mu  nadać  odpowiednie  uprawnienia.  Ustawiamy 
je za pomocą polecenia 

chmod

 i muszą one mieć wartość 

7

 

dla osoby, która będzie wykonywała skrypt (ownergroup 
lub other). W naszych przykładach ustawimy te prawa na 
7 dla wszystkich użytkowników, więc każdy będzie mógł 
je  uruchamiać;  pamiętajmy  jednak,  że  nie  zawsze  jest  to 
zalecane; czasem ze względów bezpieczeństwa warto wy-

background image

dla początkujących

BASH

64

październik 2006

dla początkujących

BASH

65

www.lpmagazine.org

łączyć  uprawnienia  np.  dla  użytkowników 
oznaczonych  jako  other.  Oto  przykładowe 
wywołanie 

chmod

chmod 777 skrypt

.

Nasz skrypt zapiszemy w pliku o nazwie 

skrypt. Aby go wywołać, nie wystarczy wpisać 
jego nazwy nawet będąc w tym samym kata-
logu, gdyż powłoka będzie szukała polecenia 
o tej nazwie w ścieżce PATH i jeżeli go nie znaj-
dzie, zwróci błąd. Musimy podać pełną ścież-
kę  dostępu  do  skryptu,  zaczynającą  się  od  / 
– jeżeli jesteśmy w tym samym katalogu, wpi-
sujemy ./skrypt:

[lukasz@localhost ~]$ ./skrypt

Inną  możliwością  uruchomienia  skryptu  jest 
wywołanie powłoki i wpisanie pliku ze skryp-
tem jako jej argumentu:

 bash skrypt

Zamiast  wpisywać  nazwę  powłoki,  może-
my  też  użyć  znaku  kropki:  wywołana  zo-
stanie powłoka, w której aktualnie jesteśmy: 

[lukasz@ localhost ~]$ . skrypt.

My będziemy korzystali z pierwszej me-

tody,  gdyż  jest  ona  najbardziej  przystępna 
i  najczęściej  używana  przez  programistów 
w środowisku Linux.

Zmienne

Zmienne  to  oznaczone  nazwami  miejsca 
w  pamięci  przechowujące  pewne  warto-
ści, które do nich przypiszemy. W powło-
ce istnieją zmienne mogące przechowywać 
wartości  logiczne,  tekst  i  liczby.  Zmien-
ne w bashu deklarujemy na bieżąco, przy-
pisując  wartości  za  pomocą  znaku  „=”: 

zmienna="tekst"

. Jeżeli chcemy przypisać 

do zmiennej wartość zawierającą spacje, na-
leży ją umieścić w cudzysłowach (warto to 
robić niezależnie od tego, czy tekst zawie-
ra spacje, bo zapobiega to wielu potencjal-
nym błędom) – inaczej mogą wystąpić błę-
dy.  Przy  deklarowaniu  nie  poprzedzamy 
zmiennej żadnym znakiem specjalnym.

Jeżeli chcemy wyświetlić zawartość zmien-

nej, musimy poprzedzić jej nazwę znakiem do-
lara „$”:

#!/bin/bash
zmienna="tekst"
echo $zmienna

W innym wypadku nazwa zmiennej będzie po-
traktowana jako zwykły tekst i po prostu wy-
świetlona:

#!/bin/bash
zmienna="tekst"
echo zmienna

Wypisywanie tekstu na ekranie

Do wyświetlania tekstu na ekranie służy kil-
ka poleceń powłoki, z których najczęściej uży-
wamy 

echo

:

#!/bin/bash
echo To jest tekst

Po wywołaniu skryptu ujrzymy napis 

To jest

tekst

.

Wartości logiczne

Tak, jak w każdym innym języku programo-
wania,  w  bashu  występują  wartości  logiczne: 

TRUE

 (prawda) i 

FALSE

 (fałsz). Są one reprezen-

towane za pomocą cyfr (

0

 - prawda i 1 (lub ja-

kakolwiek inna niż 

0

) – fałsz). Są one zwracane 

przez różne polecenia i umieszczane  w specjal-
nej zmiennej 

$?

 :

#!/bin/bash
vdir /home/lukasz
echo $?

Skrypt  spróbuje  wylistować  katalog  (może 
się to nie powieść, jeśli nie mamy odpowied-
nich uprawnień dostępu) i pokaże informacje 
o tym, czy udało się to wykonać:

[lukasz@localhost ~]$ ./skrypt
drwx------  5 lukasz lukasz 4096 gru 
29 19:50 Desktop
drwxrwxr-x  2 lukasz lukasz 4096 lis 
24  2005 Dokumenty
0

Oto  parametry  polecenia 

echo

,  które  nale-

ży  podawać  (w  linii  poleceń  lub  skrypcie) 
przed tekstem do wypisania:

•  

-n

 na końcu linii nie będzie wypisywany 

znak przejścia do nowej linii, więc tekst 
wypisany przez kilka kolejnych 

echo

 zo-

stanie wyświetlony “ciurkiem”,

•  

-e

  pozwala  zinterpretować  wszystkie 

znaki  specjalne,  które  wpisujemy,  po-
przedzając je znakiem backslash “\”,

•  

-E

  powoduje,  że  w  wyświetlanym  tek-

ście nie będą interpretowane znaki spe-
cjalne. Zostaną one pominięte, a powło-
ka wyświetli jedynie ich symbole,

•  

\a

  spowoduje  pojawienie  się  alarmu 

dźwiękowego  na  naszym  komputerze  
(głośniczek),

•  

\b

  po  wyświetleniu  tekstu  cofa  kursor 

(pozycję końca tekstu) o jeden znak w le-
wo,

•  

\n

  powoduje  pojawienie  się  nowego 

wiersza  po  zakończeniu  wypisywania 
bieżącego,

•  

\c

  wypisuje  znak  nowego  wiersza  na 

końcu linii,

•  

\r

 powoduje powrót karetki do począt-

ku  wiersza  po  wypisaniu  odpowiednie-
go fragmentu tekstu,

•  

\t

 powoduje pokazanie się znaku tabu-

lacji w poziomie,

•  

\v

 powoduje pokazanie się znaku tabu-

lacji w pionie,

•  

\

 powoduje pokazanie się znaku back-

slasha (\). Używamy dwóch backslashy 
(\),  aby  wypisać  jeden,  gdyż  normalnie 
jest on znakiem sterującym,

•  

\'

  wypisuje  znak  pojedynczego  apo-

strofu  (analogicznie  jak  w  przypadku 
backslashy:  apostrof  jest  z  kolei  ogra-
nicznikiem tekstu w zmiennych),

•  

\”

  pozwala  wypisać  podwójny  cudzy-

słów (analogicznie jak w przypadku apo-
strofów),

•  

\nnn

 pozwala na wypisanie znaku z ta-

beli  kodów ASCII  o  ósemkowej  notacji 
(gdzie 

nnn

 to kod znaku),

Parametry polecenia echo

Listing 1. 

Blok instrukcji warunkowej if 

z użyciem else

#!/bin/bash
a = 3
if [ “$a” = 3 ]
then
  echo Wartosc zmiennej a wynosi 3
else
  echo Wartosc zmiennej a jest     
       rozna od 3
fi

Listing 2. 

Blok instrukcji warunkowej if 

z użyciem elif i else

#!/bin/bash
a = 3
if [ “$a” = 3 ]
then
  echo Wartosc zmiennej a wynosi 3
elif [ “$a” = 4 ]
  echo Wartosc zmiennej a wynosi 4
else
echo Wartosc zmiennej a jest rozna 
     od 3 i od 4
fi

background image

66

październik 2006

dla początkujących

BASH

67

www.lpmagazine.org

dla początkujących

BASH

Polecenie test

Polecenie 

test

 służy do testowania wyrażeń 

logicznych,  czyli  porównywania  wartości. 
Ma  ono  wiele  możliwości,  np.  pozwala 
sprawdzić, czy 

a

 jest mniejsze od 

b

, czy wy-

brany  plik  jest  katalogiem  lub  czy  łańcuch 
tekstowy ma długość większą od 

0

. Na przy-

kład efektem działania skryptu:

#!/bin/bash
test 2 -gt 3 
echo $?

Będzie  sprawdzenie,  czy 

2

  jest  większe  (

-gt

 

od ang. greater) od 

3

 i zwrócenie wyniku, któ-

ry oczywiście jest fałszywy (

1

) i który wyświe-

tlimy używając 

echo  $?

. Większą listę para-

metrów 

test

 zamieszczamy w Ramce Parame-

try polecenia test.

Instrukcja if

If

  to  podstawowa  instrukcja  warunkowa 

bashu: testuje podane przy słowie 

if

 wy-

rażenie i jeżeli ono jest prawdziwe, wykonuje 
blok kodu zawarty pomiędzy 

then

 a 

fi

 (

fi

 jest 

zakończeniem całego bloku 

if

). Przykład:

#!/bin/bash
if [ 1 = 1 ]

then
echo Wartosci sa takie same
fi

Bardzo ważne są odstępy pomiędzy nawiasa-
mi  kwadratowymi  a  instrukcją 

if

  i  wyraże-

niem.  Pamiętajmy  też  o  konieczności  ich  za-
chowania z lewej i prawej strony znaku 

=

. Nie-

stety, bash jest pod tym względem bardzo wy-
magający  (możnaby  powiedzieć,  że  sztywny 
i nieprzyjazny) i niestosowanie się do tych za-
sad  może  zaowocować  błędami.  Pomiędzy 
blokiem  kodu  wykonywanym  przy  spełnio-
nym  wyrażeniu  a  słowem 

fi

  można  wstawić 

instrukcję 

else

:  zamieszczony  w  jej  ramach 

blok  kodu  zostanie  wykonany  przy  niespeł-
nieniu wyrażenia podanego przy 

if

. Oczywi-

ście, sprawdzanie wyrażeń typu 

1 = 1

 nie ma 

żadnego sensu – lepiej jest użyć zmiennych czy 
nazw  plików,  stosując  te  same  operatory,  co 
w poleceniu 

test

. Spójrzmy na Listing 1: spraw-

dzamy, czy zmienna a jest równa 

3

. W wyraże-

niu  używamy  nazwy  zmiennej  poprzedzo-
nej znakiem 

$

. Co więcej, otaczamy ją cudzy-

słowem, co zapobiega wielu przykrym niespo-
dziankom związanym ze specyficznym trakto-
waniem zmiennych przez basha

Nic nie stoi na przeszkodzie, aby w jednym 

bloku 

if

 zawrzeć więcej warunków: służy do 

tego słowo 

elif

 (Listing 2), które pozwala do-

dawać kolejne wyrażenia (u nas: czy a jest równe 
4?
). Blok zapisany pod else zostanie wykonany 
jedynie  wtedy,  gdy  żadne  z  wymienionych 
wyrażeń nie będzie spełnione (u nas: gdy 

a

 jest 

różne zarówno od 

3

, jak i od 

4

).

Instrukcja case

Instrukcja 

case

  jest  podobna  do  instrukcji 

if

, ale różni się od niej składnią. Nic nie stoi 

na przeszkodzie, aby używać obu instrukcji 
zamiennie (

if

 zamiast case i vice versa). Oto 

składnia 

case

:

case warunek in
odpoweidz1)
pierwszy blok kodu
;;
Esac

Spójrzmy na Listing 3, na którym zamieściliś-
my  przykład  użycia 

case

.  Jak  widzimy, blok

case

  zaczyna  się  od  słowa 

case

,  a  kończy  na 

esac

.  Poszczególne  warunki  są  oznaczone 

prawymi  nawiasami  okrągłymi  (np. 

1)

2)

i  oddzielone  od  siebie  podwójnymi  znakami 
średnika (

;;

). Przy słowie 

case

 wymieniamy 

zmienną (ponownie ze znakiem 

$

 na początku 

i otoczoną cudzysłowami), której wartość bę-
dziemy  sprawdzali  oraz  słowo  kluczowe 

in

Użycie  gwiazdki  (

*

)  pozwala  nam  uwzględ-

nić wartości niewymienione w kolejnych wa-
runkach (u nas np. 

67

).

Pętla while

Pętla 

while

  służy  do  powtarzania  czynno-

ści w niej zawartych, a jej struktura jest na-
stępująca:

While polecenie
do
  blok czynności do wykonania
done

Czynności zapisane w bloku kodu pomiędzy 
słowami 

do

 i 

done

 będą powtarzane (iterowa-

ne) tak długo, aż warunek postawiony pętli nie 
zostanie spełniony. Spójrzmy na Listing 4: zde-
finiowana na nim zmienna 

i

 ma początkową 

wartość 

0

. Następnie wartość ta jest wyświetla-

na w pętli 

while

 instrukcją 

echo

 i zwiększana 

(inkrementowana) o 1 z każdym przebiegiem 
pętli.  Zawarte  w  nagłówku  while  wyrażenie 

[ $i -lt 5 ]

 powoduje, że instrukcje w pętli 

będą  wykonywane,  aż  zmienna 

i

  osiągnie 

wartość 

5

.

Pętla for

Pętla 

for

, której konstrukcja jest inna niż 

whi-

le

, powtórzy czynności zapisane w bloku po-

między 

do

 a 

done

 wobec każdego elementu li-

sty, którą jej podstawimy (może być nią też np. 
tablica albo katalog na dysku). Jej konstrukcja 
jest następująca:

Listing 3. 

Przykład skryptu sprawdzającego jaką 

wartość ma zmienna

#!/bin/bash
wartosc=1
case "$wartosc" in
1)
  echo Liczba ma wartosc 1
  ;;
2)
  echo Liczba ma wartosc 2
  ;;
*)
  echo Liczba ma inna wartosc
  ;;
Esac

Listing 4. 

Pętla while, która wyświetla liczbę

i zwiększa jej wartość o 1, aż do osiągnięcia 5

#!/bin/bash
i=0
while [ $i -lt 5 ]
do
  echo $i
  i=`expr $i + 1` 
done

Listing 5. 

Pętla for wyświetlająca w kolejnych 

liniach nazwy systemów operacyjnych

#!/bin/bash
for system in Linux Windows MacOS
do
  echo $system
done

Listing 6. 

Polecenie continue nie pokazuje napi-

su „kolejny system” po systemie Linux

#!/bin/bash
for system in Windows Linux MacOS
do
  echo $system
  if [ "$system" = "Linux" ]
  then
    continue
  fi
  echo kolejny system
done

background image

68

październik 2006

dla początkujących

BASH

For zmienna in lista
do
  blok_kodu_do_wykonania
done

Spójrzmy na Listing 5. Przedstawiona tam pę-
tla 

for

 przypisze zmiennej 

system

 kolejne war-

tości. Każdą z nich wypiszemy używając 

echo

uzyskując tym samym listę popularnych syste-
mów operacyjnych (każda nazwa w osobnej li-
nijce). Możemy też używać innej składni pętli 

for

, przypominającej tę z języka C/C++:

for ((wyrażenie1; wyrażenie2; 
wyrażenie3))

Przykładowo:

for ((licznik=5; licznik <= 23; 
licznik++))
do
  echo wartosc zmiennej licznik: 
$licznik
done

W tym przypadku, w pierwszym przebiegu 
pętli 

for

  zmiennej 

licznik

  zostanie  przy-

pisana  wartość 

5

,  która  będzie  wzrastać 

z  każdym  kolejnym  przebiegiem  (decyduje 
o  tym 

wyrażenie3

,  w  naszym  przypadku 

licznik++

), aż osiągnie wartość 

23

.

Instrukcje continue i break

Polecenie 

continue

 wymusza przejście do na-

stępnego kroku w pętli (iteracji). Polecenia te-
go używamy z warunkiem, po którym ma się 
ono wykonać, gdyż inaczej pętla się w ogóle 
nie wykona. Spójrzmy na Listing 6. Po natra-
fieniu na nazwę 

Linux

, pętla 

for

 przeskoczy 

do następnego elementu, więc nie ujrzymy na-
pisu kolejny system. Polecenie 

break

 może za-

kończyć działanie dowolnej pętli, jeżeli poda-
my  warunek  jej  zakończenia,  np.  liczbę  po-
wtórzeń  dla  pętli.  Przykład  użycia 

break

  za-

mieściliśmy na Listingu 7: tym razem, po na-

Polecenie 

test

  wykorzystuje  parametry 

i  operatory  pozwalające  wykonywać  za-
awansowane porównania, np.:

•  

-d

  sprawdza,  czy  plik  jest  katalogiem 

(

test -d nazwa_pliku

)

•  

-f

 sprawdza, czy plik ma prawa do wy-

konywania (

test -f nazwa_pliku

)

•  

-L

 informuje, czy plik jest dowiązaniem 

symbolicznym do innego miejsca (

test 

-L nazwa_pliku

)

•  

-r

  sprawdza,  czy  plik  istnieje  i  czy  są 

mu nadane prawa do odczytu (

test -r 

nazwa_pliku

)

•  

-w

  sprawdza,  czy  plik  istnieje  i  są  mu 

nadane  prawa  zapisu  (

test  -w  na-

zwa_pliku

)

•  

-x

  sprawdza,  czy  plik  istnieje  i  czy  są 

mu  nadane  prawa  do  jego  uruchomie-
nia (

test -x nazwa_pliku

)

•  

-s

 sprawdza, czy plik istnieje i czy jego 

wartość nie jest zerowa (

test  -s  na-

zwa_pliku

)

•  

-nt

 porównuje daty zapisu i sprawdza, 

czy czy 

plik1

 jest nowszy (ang. newer

than) od 

plik2

 (

test plik1 -nt plik2

)

•  

-ot

  sprawdza,  czy  plik1  jest  starszy 

(ang. older than) od plik2 (

test  plik1 

-ot plik2

)

•  

=

  sprawdza,  czy  ciągi  znaków,  zmien-

ne bądź liczby są identyczne, czyli rów-
ne sobie (

test  liczba1  =  liczba2

). 

UWAGA:  pomiędzy  porównywanymi 
wartościami  a  znakiem  “=”  muszą  być 

odstępy o długości jednej spacji z każ-
dej strony,

•  

!=

 sprawdza, czy ciągi znaków lub licz-

by  po  jego  końcach  nie  są  identyczne 
(analogicznie jak 

=

)

•  

-z

 sprawdza, czy ciąg znaków podany 

po  nim  ma  zerową  długość  (

test  -z 

ciąg_znaków

)

•  

-n

 sprawdza, czy ciąg podany za nim 

ma  niezerową  długość  (analogicznie 
jak 

-n

)

•  

-eq

  sprawdza,  czy  wartości  liczbowe 

(wyłącznie  one)  podane  po  jego  obu 
stronach  są  sobie  równe  (

test  war-

tość1 -eq wartość2

)

•  

-ne

 sprawdza, czy wartości liczbowe po-

dane po jego obu stronach nie są iden-
tyczne (analogicznie jak 

-eq

)

•  

-gt

  sprawdza,  czy  pierwsza  wartość 

liczbowa  jest  większa  od  drugiej  (

test 

liczba1 -gt liczba2

)

•  

-ge

  sprawdza,  czy  pierwsza  wartość 

liczbowa jest większa lub równa drugiej 
(

test liczba1 -ge liczba2

)

•  

-lt

  sprawdza,  czy  pierwsza  wartość 

liczbowa jest mniejsza od drugiej (

test 

liczba1 -lt liczba2

)

•  

-le

  sprawdza,  czy  pierwsza  wartość 

liczbowa jest mniejsza lub równa drugiej 
(

test liczba1 -le liczba2

)

•   Wykrzyknik  (

!

)  to  znak  przecze-

nia:  stosujemy  go,  gdy  chcemy  uzy-
skać  wynik  odwrotny  do  wyniku  tekstu 
(TRUE  zamiast  FALSE  lub  vice  versa)

Parametry polecenia test

Listing 7. 

W tym skrypcie polecenie break koń-

czy działanie pętli po natrafieniu na słowo Linux

#!/bin/bash
for system in FreeBSD Linux Windows
do
  echo $system
  if [ "$system" = "Linux" ]
  then
    break
  fi
done

trafieniu na nazwę 

Linux

, pętla 

for

 zakończy 

swoje działanie.

Argumenty z linii poleceń

Jak już wiemy, do skryptu bashowego może-
my  przekazać  argumenty,  które  umieszcza-
my za nazwą pliku ze skryptem (w linii po-
leceń albo innym skrypcie, gdyż możliwe jest 
wywoływanie jednych skryptów z drugich). 
Przykład: 

./ulubiony_system super.

Do  przekazanych  wartości  odwołujemy 

się za pomocą specjalnych zmiennych numer-
cznych oznaczanych jako 

$1

$2

$3,

 itd. W na-

szym przykładzie, wartością 

$1

 będzie 

super

Oto skrypt ulubiony_system:

#!/bin/bash
echo "System Linux jest $1”

W efekcie działania skryptu uzyskamy napis: 

System Linux jest super

.

Podsumowanie

W  tym  artykule  przedstawiliśmy  podsta-
we możliwości tworzenia skryptów powło-
ki, które pomogą Ci zacząć przygodę z ba-
shem. Na omówienie wszystkich aspektów
tego shella nie wystarczyłoby miejsca nawet, 
gdyby zajmował on cały magazyn Linux+. 
Dodajmy, że skrypty bashowe są nie tylko 
przydatne w automatyzowaniu powtarzal-
nych czynności (np. montowania i odmon-
towywania dysków, kasowania pamięci ca-
che  przeglądarek  internetowych  czy  porząd-
kowania  plików  tymczasowych),  ale  rów-
nież są wykorzystywane w instalacji i kon-
figuracji  systemu  Linux  i  jego  elementów 
(np. sieci). Warto się więc ich nauczyć, do 
czego  potrzebna  jest  długotrwała  prakty-
ka: znając basha wykonasz każdą czynność 
w Linuksie i cały system będzie pod Two-
ją komendą.