1
ALIASY I SKRYPTY
Skrypty są już znane z DOS-a. Były to pliki z rozszerzeniem .bat. W Linuksie (UNIXI-ie) skrypt jest plikiem tekstowym zawierającym
polecenia (programy) systemowe oraz polecenia sterujące przebiegiem wykonania samego skryptu.
Istnieją dwa rodzaje plików wykonywalnych: skrypty i pliki binarne. Skrypty przeznaczone są do wykonania przez powłokę. Pliki binarne
(przeznaczone do wykonania przez CPU) są wynikiem kompilacji tekstu źródłowego programu napisanego w wybranym języku
programowania.
Skrypty mają nie tylko zapewnić komfort automatyzacji, systematycznie powtarzanych rutynowych czynności. Ich zastosowanie jest
znacznie poważniejsze. Siła wszystkich systemów uniksowych jest w dużym stopniu oparta właśnie na elastyczności i szerokim zakresie
stosowania skryptów.
Automatyzację czynności w prostym (i ograniczonym zakresie) można uzyskać za pomocą aliasów.
Przykładowo, jeżeli często montujemy i demontujemy CD-ROM-y, możemy zdefiniować dwa aliasy jeden do montowania, a drugi do
demontowania:
# alias cdm="mount -t iso9660 -o ro /dev/hdc /mnt/cdrom"
# alias cdu="umount /mnt/cdrom"
Teraz root może zamontować CD-ROM jednym krotkim poleceniem:
# cdm
i zdemontować
# cdu
Alias może być używany tylko przez tego użytkownika, który go zdefiniował. Definicje aliasów zachowują swoją ważność tylko do
zakończenia danej sesji użytkownika. Po ponownym zalogowaniu musimy aliasy zdefiniować na nowo. Jest to kłopotliwe i nie ma nic
wspólnego z wygodą. Aby utrzymać aliasy cały czas aktualne, musimy wpisać je do odpowiedniego pliku startowego bash-a. W naszym
przypadku będzie to plik ukryty (nazwa zaczynająca się od kropki) .bashrc. Każdy użytkownik ma taki indywidualny plik w jego katalogu
domowym. Dla administratora będzie to plik /root/.bashrc. Dla użytkownika crash1 plik /home/crash1/.bashrc
Sprawdzamy dostępne aliasy
Wydanie polecenia alias bez opcji i argumentów spowoduje wyświetlenie listy zdefiniowanych aliasów.
# alias
alias cdm='mount -t iso9660 -o ro /dev/hdc /mnt/cdrom'
alias cdu='umount /mnt/cdrom'
alias cp='cd -i'
alias mv='mv -i'
alias rm='rm -i'
alias which='type -patch'
[root@linux /root]# _
Dwa pierwsze aliasy zdefiniowaliśmy sami. Pozostałe są efektem domyślnej konfiguracji systemu.
Bardziej rozbudowany alias
Za pomocą aliasu możemy zrealizować bardziej złożone zadania niż te opisane wcześniej. W definicji aliasu możemy wykorzystać istniejący
już alias (np. cdm). Ponadto powinniśmy wiedzieć, że polecenia systemowy możemy zapisać w "jednej lini", oddzielając średnikiem (;). W
takim przypadku alias jest często tasiemcowo długi, z reguły dłuższy niż jeden wiersz. W czasie wprowadzania aliasu w wierszu poleceń
systemowych bash powinien automatycznie przejść do nowej linii. Jak powinniśmy pamiętać, możemy również wymusić przejście do
nowego wiersza, bez zamykania polecenia, korzystając z maskującej klawisz [Enter] właściwości "\". To może mieć zastosowanie przy
korzystaniu z edytora do wpisania aliasu do pliku .bashrc
Na początek sprawdźmy maskujące działanie "/", wydając proste polecenie wylistowania katalogu głównego (ls /), ale zapisane w dwu
wierszach:
# ls \ [Enter]
> / [Enter]
bin etc lost+found root usr
boot home mnt sbin var
dev lib proc tmp
[root@linux /root]# _
Aby pierwsze naciśnięcie klawisza [Enter] zostało zamaskowane, nie wolno na za "\" wprowadzać żadnych znaków. Bezpośrednio po
wprowadzeniu "\" naciskamy [Enter], przechodząc w ten sposób do nowego wiersza i kontynuując wprowadzanie polecenia. Widoczny na
początku drugiego wiersza znak ">" jest generowany przez bash. Informuje on, że kontynuujemy wprowadzanie rozpoczęte w poprzednim
wierszu (wierszach).
Zdefiniujmy teraz alias kopia realizujący następującą sekwencję działań:
1. Montuje CD-ROM, korzystając z aliasu cdm
2. Zakłada na dyskietce dosowy system plików
3. Sprawdza
powierzchnię dyskietki (badblocks
4. Kopiuje na dyskietkę plik /etc/passwd
5. Wyświetla zawartość dyskietki.
2
#
> ;mbadblocks a:;mcopy /etc/passwd a:;mdir a:" [Enter]
alias kopia="cdm;mformat -t 80 -h 2 -s 18 a:\[Enter]
[root@linux /root]# _
Zapis a: oznacza napęd dyskietek. Kolejne polecenia są oddzielone od siebie średnikami. Możemy teraz wydać polecenie alias, aby
wylistować dostępne aliasy i sprawdzić, czy prawidłowo zdefiniowaliśmy alias kopia
Wkładamy do czytnika CD-ROM, a do napędu dyskietkę i wydajemy polecenie kopia:
# kopa
Volume in drive A: has no label
Volume Serial Number is 2432-5764
Directory for A:/
passwd 632 04-01-2000 19:37 passwd
1 file 632 bytes
1 456 640 bytes free
[root@linux /root]# _
Możemy sprawdzić jeszcze (df), czy CD-ROM rzeczywiście został zamontowany. W powyższym przykładzie montowanie CD-ROM-u nie
ma oczywiście żadnego logicznego związku z pozostałymi działaniami. Ma być tylko przykładem.
Wpisujemy alias do pliku .bashrc
Zalogujmy się jako crash1 i sprawdźmy, jakie (domyślne) aliasy mamy do dyspozycji:
$ alias
alias which='type -path'
[crash1@linux crash1]$ _
Zdefiniujemy trwały (przez wpisanie do pliku .bashrc) alias ll=ls -l. Zrobimy to za pomocą edytora vi. Na początek obejrzyjmy plik .bashrc
$ cat .bashrc
# .bashrc
# User specyfic aliases and functions
#Sourace global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
Definicję naszego aliasu wprowadzimy w czwartym wierszu pliku. Przed modyfikacją pliku sporządzimy kopię bezpieczeństwa
(.bashrc_old):
$ cp .bashrc .bashrc_old
[crash1@linux crash1]$ vi .bashrc
[Esc], [j], [j], [j], [a], alias ll="ls -l", [Esc], :wq , [Enter]
...
...
".bashrc" 8 lines, 140 characters written
[crash1@linux crash1]$ alias
alias which='type -path'
[crash1@linux crash1]$ logout
Red Hat Linux relase 5.2 (Apollo)
Kernel 2.0.36 on an i586
linux login: crash1
Password:
Last login: Tue Apr 1 16:43:34 on tty1
[crash1@linux crash1]$ alias
alias ll='ls -l'
alias which='type -path'
[crash1@linux crash1]$ ll .bashrc
-rw-r--r-- 1 crash1 crash1 11 Apr 1 16:50 .bashrc
[crash1@linux crash1]$ _
Zwróćmy uwagę na prawa dostępu do pliku .bashrc. Prawo pisania posiada tylko właściciel (i root) i tak powinno pozostać. Aliasy są
wygodnym narzędziem do zdefiniowania środowiska pracy. A oto kilka popularnych aliasów:
la='l -a'
rd='rmdir'
md='mkdir'
ls='ls -F'
Usuwamy aliasy
Definicje aliasów usuwamy poleceniem unalias. Oczywiście, jeżeli definicje aliasów wpisane są do pliku .bashrc, usunięcie będzie ważne
jedynie do końca bieżącej sesji użytkownika:
$ alias
alias ll='ls -l'
alias which='type -patch'
[crash1@linux crash1]$ unalias ll
[crash1@linux crash1]$ alias
3
alias which='type -patch'
[crash1@linux crash1]$ _
Ponieważ alias ll jest wpisany do pliku .bashrc, po ponownym zalogowaniu będzie dostępny.
Pierwszy skrypt
Skrypty tworzymy przez wpisanie poleceń do pliku tekstowego. Robimy to za pomocą dowolnego edytora. Możliwość tworzenia skryptów
jest silną stroną Linuksa.
Pierwszy skrypt będzie automatycznie montował CD-ROM, odczytywał liczbę 1024 kilobajtowych bloków (pojemność CD-ROM-u), podawał
tę informację na ekran, a następnie demontował CD-ROM.
Zalogujmy się jako root i za pomocą edytora vi utworzymy w katalogu bieżącym plik tekstowy o nazwie cdbl i treści:
#!/bin/bash
# zamontowanie CD-ROM
mount -t iso9660 -o ro /dev/hdc /mnt/cdrom
#wpisanie do pliku liczbabl ilosci blokow
df | grep "/mnt/cdrom" | cut -c31-36 > liczbabl
#podanie wyniku na ekran
echo "Liczba blokow na CD-ROM-ie wynosci: " 'cat liczbabl'
#zrobienie porzadkow
rm liczbapl
umount /mnt/cdrom
Większość poleceń jest tu znana, występują tylko dwa nowe cut i echo. Wiersze zaczynające się od znaku hasz "#" są liniami komentarza,
czyli w trakcie wykonywania skryptu będą pomijane przez interpreter (powłokę). W szczególności pierwsza linia skryptu jest linią
komentarza, ale ponieważ zaczyna się ciągiem dwóch znaków "#!" ma znaczenie szczególne - wskazuje na rodzaj powłoki, w jakim ma być
uruchomiony skrypt. Za znakami "#!" występuje pełna ścieżka dostępu do żądanej powłoki. Jeżeli ścieżka ta jest błędna bądź wskazana
powłoka nie występuje w naszym systemie skrypt nie będzie mógł być uruchomiony.
W pierwszym znaku akcji montujemy CD-ROM. W następnym wierszy tworzymy potok, który z rezultatu polecenia df wybiera wiersz
dotyczący CD-ROM-u a następnie z tego wiersza wycina (cut) łańcuch sześciu kolejnych znaków (-c31-36) od znaki 31 do 36 włącznie.
Ten łańcuch znaków to sześciocyfrowa liczba bloków. Łańcuch jest wpisywany do świeżo tworzonego pliku liczbabl. W trzecim wierszu
wyprowadzamy rezultat na ekran. Służy do tego celu polecenie echo.
Utworzony plik tekstowy cdbl musimy uczynić wykonywalnym, czyli nadać mu prawo wykonywania oraz skopiować go do katalogu
dostępnego w ścieżkach przeszukiwania określonych w zmiennej PATH. Będzie to podkatalog bin w katalogu domowym root-a. Jeżeli nasz
plik wykonywalny nie będzie znajdował się w którymś ze wskazanych przez PATH katalogów, to chcąc go uruchomić musimy podać pełną
ścieżkę dostępu do niego.
# ls -l cdbl
-rw-r--r-- 1 root root 307 May 26 14:23 cdbl
[root@linux /root]# chmod 755 cdbl
[root@linux /root]# ls -l cdbl
-rwxr-xr-x 1 root root 307 May 26 14:23 cdbl
[root@linux /root]# mkdir bin
[root@linux /root]# cp cdbl /root/bin
[root@linux /root]# which cdbl
/root/bin/cdbl
[root@linux /root]# _
Polecenie which wskazuje pełną ścieżkę dostępu do pliku wykonywalnego, który zostanie uruchomiony po wydaniu prostego polecenia
zawierającego tylko nazwę tego pliku.
Teraz możemy już sprawdzić działanie naszego skryptu. Włóżmy CD-ROM do czytnika i wydajmy nasze nowe polecenie:
# cdbl
Liczba blokow na CD-ROM-ie wynosi: 570782
[root@linux /root]# _
Ktoś kto napisał kilka skryptów pod DOS-a, na pewno korzystał z przekazywania parametrów do skryptu. Podobny mechanizm znajdziemy
także w Linuksie. Wykonajmy przykładowy skrypt, który będzie z niego korzystał. Zalogujmy się w tym celu jako crash1. Nasz skrypt będzie
zmieniał nazwę wskazanego pliku (pierwszy argument) na nową wskazaną przez nas ((drugi argument), ale jednocześnie utworzy kopię
zapasową tego pliku pod starą nazwą z przyrostkiem .old. Jeżeli nowa nazwa nie zostanie podana, domyślnie zostanie przyjęta nazwa
nowy. Nasz skrypt będzie się nazywał zmk i wyglądał tak:
#!/bin/bash
#czy podany jest pierwszy argument
if
[ -z "$1" ]
then
echo "zmk: uzywaj: zmk stara_nazwa [nowa_nazwa]"
exit 1
fi
#czy istnieje plik źródłowy (stara nazwa)
if
[ ! -f $1]
then
echo zmk: Plik zrodlowy nie jest dostepny
exit 1
fi
#czy mamy prawo pisania do biezacego katalogu
if
[ ! -w . ]
then
4
echo zmk: Nie mamy prawa pisania do biezacego katalogu
exit 1
fi
#czy podany jest drugi argument (nowa nazwa)
if
[ -z "#2" ]
then
cp $1 $1.old
mv $1 nowy
echo "zmk: Przyjeto domyslna nazwe 'nowy'"
exit 0
fi
#gdy drugi argument jest podany
cp $1 $1.old
mv $1 $2
exit 0
Składnia użycie tego skryptu jest następująca:
zmk stara_nazwa nowa_nazwa
Drugi argumnet (nowa_nazwa) jest opcjonalny. Jeżeli nie wystąpi, przyjmowana jest domyślna nazwa nowy.
Objaśnienie nowych konstrukcji i poleceń:
Parametry przekazywane do skryptu przypisywane są zmiennym od $0 do $9, przy czym $0 zawiera nazwę skryptu (polecenia), $1
odpowiada pierwszemu argumentowi polecenia, $2 odpowiada drugiemu polecenia, itd. Należy przy tym zaznaczyć, że zmienne $0 do $9
należą do grupy zmiennych specjalnych powłoki.
Następnie widzimy tu konstrukcję if-then kończoną przez fi (co odpowiada znanej ENDIF). Występujące tu polecenie exit, powodujące
opuszczenie skryptu z określonym kodem powrotu. W naszym skrypcie przyjeliśmy zero przy prawidłowym zakończeniu skryptu oraz jeden
przy błędzie. Jeżeli kod powrotu nie jest podany jawnie, polecenie exit przyjmuje kod domyślny (zero). Zwykle polecenia systemowe
zwracają wartość zero, kiedy ich wykonanie zakończy się powodzeniem i wartość różną od zera (z reguły 1 alvo -1), gdy wykonanie
zakończy się niepowodzeniem. Wartość ta umieszczana jest w zmiennej specjalnej $? (zawierającej kod powrotu ostatniego polecenia).
Konstrukcja w nawiasach kwadratowych to sposób zapisu polecenia test. Polecenie test jest szeroko stosowane w skryptach shellowych.
Postać polecenia test jest następująca:
test warunek
Polecenie to może być zapisane wpostaci nawiasów kwadratowych:
[warunek]
Polecenie test zwraca wartość zero (prawda), gdy warunek jest spełniony i wartość jeden (fałsz), gdy jest nie spełniony. Wartość ta
umieszczona jest w zmiennej $?.
Zapis w nawiasach kwadratowych jest najczęściej stosowany w skryptach z uwagi na większą czytelność. Wymieńmy wybrane warunki:
[ -d plik ] - plik istnieje i jest katalogiem
[ -f plik ] - plik istnieje i plikiem zwykłym
[ -r plik ] - plik istnieje i mamy do niego prawo czytania
[ -w plik ] - plik istnieje i mamy do niego prawo pisania
[ -x plik ] - plik istnieje i mamy do niego prawo wykonywania
[ -s plik ] - plik istnieje i mam rozmiar większy niż zero bajtów
[ -z s1 ] - długość łańcucha s1 jest zerowa
[ -n s1 ] - długość łańcucha s1 nie jest zerowa
[ s1 = s2 ] - łańcuchy s1 i s2 są identyczne
[ s1 != s2 ] - łańcuchy s1 i s2 nie są identyczne
[ s1 ] - łańcuch s1 nie jest pusty
Można budować bardziej złożone warunki korzystając z operatorów logicznych. Operator AND zapisywany jako -a, operator OR jako -o.
Natomiast operator negacji NOT jako wykrzykinik !.
W zapisie warunku istotne jest zachowanie spacji pomiędzy ograniczającymi nawiasami kwadratowymi a treścią warunków, tak jak
pokazano to wyżej.
A teraz warunki użyte w skrypcie:
[ -z "$1" ] - łańcuch odpowiadający pierwszemu argumentowi polecenia (stara_nazwa) ma
zerową długość
[ ! -f $1 ] - plik wskazywany przez zmienną $1 nie istnieje bądź nie jest plikiem zwykłym
[ ! -w . ] - nie mamy prawa czytania do pliku oznaczonego kropką, która jest aliasem
[ -z "$2" ] - łańcuch odpowiadający drugiemu argumentowi polecenia (nowa_nazwa) ma zerową
bieżącego katalogu, czyli nie mamy prawa czytania do bieżącego katalogu
długość (jest pusty)
Oczywiście aby nasz skrypt zadziałał, musimy mu nadać prawo wykonywania i umieścić go w odpowiednim katalogu (analogicznie jak w
przypadku poprzedniego skyrptu):
$ chmod 755 zmk
[crash@linux /crash1]$ mkdir bin
[crash@linux /crash1]$ mv zmk ./bin
[crash@linux /crash1]$ which zmk
/home/crash1/bin/zmk
[crash@linux /crash1]$ _
Teraz możemy już wypróbować skrypt zmk:
$ zmk
zmk: uzywaj: zmk stara_nazwa [nowa_nazwa]
[crash@linux /crash1]$ zmk blablabla
zmk: Plik zrodlowy nie jest dostepny
5
[crash@linux /crash1]$ ls -F
bin/ kat2/
[crash@linux /crash1]$ zmk kat2
zmk: Plik zrodlowy nie jest dostepny
[crash@linux /crash1]$ touch blablabla
[crash@linux /crash1]$ zmk blablabla
zmk: Przyjeto domyslna nazwe 'nowy'
[crash@linux /crash1]$ ls -F
bin/ kat2/ blablabla.old nowy
[crash@linux /crash1]$ zmk nowy blablabla
[crash@linux /crash1]$ ls -F
bin/ kat2/ blablabla blablabla.old nowy.old