You are on page 1of 43

1.

Bourne Shell

7
7.1

BOURNE SHELL

Tipuri de operatori i comenzi

Ca n toate limbajele de programare, operatorii permit programatorilor s utilizeze diverse operaii (aritmetice, logice, string etc.) asupra variabilelor. Bourne shell suport trei tipuri de operatori: aritmetici de test logici Operatorii aritmetici sunt folosii doar pentru operaiile cu numere ntregi. Operatorii de test sunt folosii pentru operaii cu fiiere, cu variabile string i cu ntregi. 7.1.1 Comanda test

Aceast comand are forma: test <conditie> sau [ <conditie> ], atunci cnd este folosit ca parte a unei comenzi if. Observaie: <conditie> are forma: [<operand1>][<operator>]<operand2> Exemple:
$ test $sir1 != $sir2

(n exemplele folosite semnul $ de la nceputul rndului reprezint prompter-ul shell-ului). Condiia va ntoarce o valoare zero (adevrat) dac variabila sir1 este diferit ca valoare de variabila sir2 i o valoare diferit de zero (fals) n caz contrar. Aceast valoare poate fi verificat prin intermediul lui exit

UNIX

status (parametrul special shell $?) care ntoarce valoarea de adevr a ultimei operaii efectuate. Fie secvena de comenzi urmtoare:
$ $ $ $ var1=15 var2=20 test $var1=$var2 echo $?

Se va afia valoarea 1, care semnific faptul c testarea s-a ncheiat cu valoarea "false" (variabila var1 are o valoare diferit de variabila var2). 7.1.2 Operatori pentru fiiere

Acetia sunt operatori unari (cu un singur argument) i de cele mai multe ori argumentul este numele unui fiier. Dintre aceti operatori amintim: -d <fiier> : este director? -f <fiier> : este fiier obinuit? -g <fiier> : are setat identificatorul GID? -r <fiier> : poate fi citit? -s <fiier> : este de lungime diferit de zero? -w <fiier> : poate fi modificat? -x <fiier> : este fiier executabil?

Exemplu. Fie comanda:


$ ls -las

cu efectul urmtor:
total 5 4 drwxrwxrwx 4 drwxrwxrwx 2 -rwxrwxrwx 1 -rwxrwxrwx 2 -rwxrwxrwx 1 1 1 1 1 root root 2048 Feb15 18:00 . root root 2048 Feb15 18:10 .. razvan cib 1022 Dec15 17:45 .profile razvan cib 102 Feb16 17:45 stud.dat razvan cib 1102 Dec10 17:45 examen.dat

Bourne shell

Fie comanda:
$ test -f stud.dat; echo $?

Se va afia 0, avnd n vedere c stud.dat este ntr-adevr fiier obinuit. Exerciiu: Ce se va afia pentru urmtoarele comenzi?
$ $ $ $ $ test test test [ -r [ -w -d examen.dat; echo $? -x examen.dat; echo $? -s examen.dat; echo $? examen.dat ] ; echo $? stud.dat ] ; echo $?

7.1.3

Operatori pentru iruri de caractere

Operatorii folosii pentru operaii cu iruri de caractere sunt: <sir1> : este sirul <sir1> nenul? -n <sir1> : are sirul <sir1> lungimea diferita de zero? -z <sir1> : are sirul <sir1> lungimea zero? <sir1>=<sir2> : este sirul <sir1> identic cu <sir2>? <sir1>!=<sir2> : este sirul <sir1> diferit de <sir2>?

Observaie: n general, este bine ca variabilele shell folosite n testare s fie ncadrate de ghilimele: "nume_variabila". Exemple. Atribuire cu valoare null:
$ var=

UNIX

Comanda:
$ test $var=hello ; echo$?

nu este corect deoarece $var trebuie s apar ntre ghilimele; n concluzie, corect este:
$ test $var=hello; echo $?

(Explicaie: comanda test ateapt 3 parametri: $var, =, hello. Conversia efectiv a lui $var la valoarea sa se face nainte de interpretarea ntregii comenzi. Deoarece valoarea lui $var este null, va rezulta interpretarea unei comenzi de genul test =hello, de unde rezult eroarea). Ghilimelele au rolul de separator pentru caracterul null. Exerciiu. Fie atribuirile:
$ $ $ $ sir1=dan sir2=maria sir3=dan sir4=

1. Care dintre comenzile urmtoare vor produce mesaje de eroare la execuie?


a. b. c. d. e. [ [ [ [ [ $sir1 ] ; echo $? -n $sir3 ] ; echo $? $sir1=$sir4 ] ; echo $? "$sir4"="$sir3" ] ; echo $? -z $sir4 ] ; echo $?

2. Care dintre comenzile urmtoare vor avea rezultat un exit status egal cu zero?

Bourne shell

a. b. c. d. e.

[ [ [ [ [

"$sir1"!="$sir2" ] ; echo $? -z "$sir3" ] ; echo $? -n "$sir4" ] ; echo $? "$sir1"="$sir3" ] ; echo $? "sir4" ] ; echo $?

7.1.4

Operatori pentru tipul integer

Sintaxa utilizrii operatorilor pentru operaii cu numere ntregi este:


[ int1 operator int2 ]

iar operatorii utilizai sunt: -eq : se testeaz egalitatea lui int1 cu int2 -ge : se testeaz dac int1 este mai mare sau egal dect int2 -gt : se testeaz dac int1 este mai mare strict dect int2 -le : se testeaz dac int1 este mai mic sau egal dect int2 -lt : se testeaz dac int1 este mai mic dect int2 -ne : se testeaz dac int1 este diferit de int2 Exerciii. 1. Fie atribuirile:
int1=5 int2=10 int3=55 int4=5

Ce vor afia comenzile:


a. b. c. d. e. [ [ [ [ [ "$int1" "$int2" "$int4" "$int3" "$int4" -gt -lt -le -eq -ne "int2" ] ; echo $? "$int3" ] ; echo $? "$int1" ] ; echo $? "$int4" ] ; echo $? "$int1" ] ; echo $?

UNIX

2. Fie atribuirile:
V1=007 v2=7

Ce vor afia fiecare dintre comenzile:


a. [ "$v1" = "$v2" ] ; echo $? b. [ "$v2" -eq "$v2" ] ; echo $?

7.1.5

Operatori pentru tipul boolean

Operatorii utilizai sunt: 1. ! <expresie> : expresie fals? 2. <expresie1> -a <expresie2> ambele adevrate? 3. <expresie1> -o <expresie2> una dintre ele adevrat? Exemplul 1. Fie atribuirile:
v1=5 v2=10

Ce va afia comanda:
[ !"$v1" -eq "$v2" ] ; echo $? (0)

Exemplul 2. Fie comanda:


[ -f fisier -a -x "fisier" ]

Bourne shell

Rezultatul va fi zero dac fiier este att fiier obinuit ct i executabil. Exemplul 3. Fie comanda:
[ "$var" -qt 1 -a "$var" -lt 90 ]

Rezultatul este zero dac variabila var are o valoare cuprins ntre 1 i 90 (strict). Observaie. Operatorul -a are o prioritate mai mic dect operatorii de comparaie pentru ntregi. Exemplul 4. Fie comanda:
[ -r "stud" -o -d "stud" ]

n acest caz, rezultatul este zero dac stud poate fi citit sau dac este director. Exemplul 5. Fie comanda:
[ "$luna" -gt 12 -o "$ziua" -gt 31]

Rezultatul este zero dac luna este mai mare dect 12 sau dac ziua are o valoare mai mare dect 31. 7.1.6 Operatori pentru tipul logic

Operatorii utilizai sunt: 1. && 2. ||

UNIX

Aceti operatori permit execuia unei comenzi n cazul n care comanda precedent se ncheie cu succes sau nu. Astfel, dac avem urmtoarea construcie: comanda1 && comanda2, atunci comanda2 este executat dac exit status-ul comenzii comanda1 este zero. n mod asemntor, pentru construcia comanda1 || comanda2, comanda2 este executat doar dac exit status-ul comenzii comanda1 este diferit de zero. Exemplul 1. Fie comanda:
[ -x fisier_prog ] && fisier_prog

Dac fiierul fsier_prog este executabil, atunci se lanseaz n execuie. Exemplul 2. Fie comanda:
[ "$luna" -le 12 -a "$ziua" -lt 32 ] || \ echo Data invalida $an $luna $ziua

Dac luna sau ziua au valori invalide, atunci se execut comanda echo. Observaii. 1. Caracterul "\" (backslash) de la sfritul liniei anuleaz semnificaia special a caracterului newline i l consider caracter whitespace. Cu alte cuvinte, comanda se continu pe linia urmtoare. 2. Parantezele rotunde (,) au semnificaie special i nu pot fi folosite n shell-script-uri n scopul gruprii diverselor comparri. Pentru a ignora semnificaia special a parantezelor ntr-o comand se folosete tot caracterul de evitare "\". Comanda anterioar poate fi rescris astfel:
[ \("$luna" -le 12 \) -a \("$ziua" -lt 32 ] \)|| \ echo Data invalida $an $luna $ziua

Bourne shell

7.1.7

Operatori aritmetici

Operatorii aritmetici sunt: +, -, *, /, % (mprire modulo). Deoarece shell-ul nu are alt concept de dat dect character string (ir de caractere), pentru a se putea face calcule aritmetice se va folosi comanda expr, care informeaz shell-ul c irul de caractere ce urmeaz dup expr trebuie evaluat ca expresie matematic. Exemplul 1. Fie atribuirile:
x=9 x=$x+6

n acest caz, comanda echo "$x" va afia 9+6 i nu rezultatul adunrii. Exemplul 2. Comanda expr are de-a face numai cu numere ntregi, astfel rezultatul expr 15 / 6 va fi 2. Observaii. 1. Operanzii i operatorii dintr-o expresie aritmetic trebuie separai de cel puin un spaiu. Astfel, dac scriem comanda de mai sus fr spaii ntre 15 i 6 : expr 15/6, rezultatul va fi 15/6. 2. Deoarece operatorul "*" are o semnificaie special pentru shell, trebuie ca atunci cnd vrem s facem o operaie de nmulire, s folosim caracterul de evitare (\). Deci, dac x=3, y=4, z=5, atunci expr $x * $y este o comand eronat, pe cnd expr $x \* $y \* $z va avea ca rezultat 60. 3. Cea mai folosit operaie este incrementarea:
var=`expr $var + 1`

UNIX

7.2 7.2.1

Gramatica Shell Comenzi simple

O comand este o secven de atribuiri (opional) urmate de cuvinte separate de spaii i redirectri, terminate cu un operator de control (||, &, &&, ; , ;; , ( , ) , | , <newline>). Primul cuvnt reprezint comanda ce va fi executat iar celelalte sunt interpretate ca argumente ale comenzii. Valoarea ntoars de o comand este exit status, sau valoarea numeric 128+n dac respectiva comand se ncheie cu semnalul n. 7.2.2 Conducte (pipelines)

O secven pipeline este aceea n care una sau mai multe comenzi sunt separate de simbolul pipe ( | ) - bar vertical. Formatul general al unei secvene pipeline este: [!] comanda1 [| comanda2 ...] Ieirea standard a comenzii 1 este conectat la intrarea standard a comenzii 2. Dac apare caracterul de negare (!), exit status-ul pipeline-ului va fi valoarea negat a exit status-ului ultimei comenzi. Shell-ul ateapt terminarea tuturor comenzilor din pipeline nainte de a ntoarce un rezultat. Fiecare comand dintr-o secven pipeline este executat ca un proces separat (ntr-un sub-shell). 7.2.3 Redirectare

Redirectarea fiierelor standard de intrare i de ieire ctre alte dispozitive periferice sau fiiere se face folosind operatorii > , >> , < , << . Operatorii > i >> se folosesc pentru redirectarea fiierului standard de ieire (output-ului). Exemple. ls -al > f1 - aceast comand redirecteaz afiarea comenzii ls n fiierul f1 n loc ca ieirea s fie afiat pe ecran. ls -al >> f1 - aceast comanda redirecteaz afiarea comenzii ls n fiierul f1 prin adugare la sfritul lui f1 (fiierul f1 nu este suprascris).

Bourne shell

Operatorul < se folosete pentru redirectarea fiierului standard de intrare (input-ului). Exemplu.
$ mail serban < mesaj

Aceast comand trimite un mesaj (preluat din fiierul mesaj) prin email utilizatorului serban. 7.2.4 Liste

O list este o secven de una sau mai multe pipelines separate de unul sau mai muli operatori ; , & , && sau || i terminat cu ; , & sau <newline>. Dac o comand se termin cu operatorul de control &, shell-ul execut comanda respectiv n background ntr-un subshell. Shell-ul nu ateapt terminarea comenzii i ntoarce valoarea zero. Comenzile separate de caracterul ; sunt executate secvenial, shell-ul ateapt terminarea fiecreia dintre comenzi, iar valoarea ntoars este exit status-ul ultimei comenzi executate. Operatorul && se folosete sub forma: comanda1 && comanda2 i n acest caz comanda2 este executat dac i numai dac comanda1 ntoarce un exit status zero. Operatorul || se folosete astfel: comanda1 || comanda2 , comanda2 executndu-se dac i numai dac comanda1 returneaz un exit status diferit de zero. Exit status-ul returnat este acela al ultimei comenzi executate. 7.2.5 Comenzi compuse

Exist dou modaliti de grupare a mai multor comenzi: prin folosirea parantezelor rotunde ( ) i prin folosirea acoladelor { }. Astfel, construcia urmtoare: (lista_de_comenzi) face ca modificrile aduse mediului de comenzile respective s nu aib efect dup terminarea comenzii (se ruleaz ntr-un subshell). Construcia {lista_de_comenzi;} face ca modificrile s aib efect asupra mediului existent deoarece lista de comenzi este executat n mediul shell existent.

UNIX

7.2.6

Caracterul escape

Caracterul escape (\) are o semnificaie special n shell, fiind folosit, de regul, pentru a se ignora semnificaia special a unor caractere. Spre exemplu, folosit la sfritul unui rnd i urmat de caracterul <newline>, \ este considerat ca i continuator de linie, astfel nct comanda se poate continua pe linia urmtoare. Se poate folosi aceast facilitate atunci cnd avem de-a face cu comenzi foarte lungi pe care le putem scrie mai convenabil pe dou sau chiar mai multe linii. Caracterul backslash i pstreaz semnificaia special dac este urmat de $ , ` , " , \ sau <newline>. 7.2.7 Comentarii ntr-un shell-script

Comentariile ntr-un shell-script se introduc folosindu-se caracterul #, care face s se ignore caracterele existente dup semnul # i pn la sfritul liniei respective (excepie face construcia #!nume_shell care apare pe prima linie a shell-script-ului i specific tipul de shell utilizat). 7.2.8 Variabile

O variabil este o entitate ce memoreaz valori ntr-un mod asemntor unei variabile ntr-un limbaj de programare convenional. O variabil este setat atunci cnd i se atribuie o valoare (variabila=valoare), putnd fi dezactivat folosind comanda unset. Variabilele shell pot fi modificate n mod dinamic de ctre interpretor sau atribuite la intrarea n sesiune. Dintre variabilele modificate dinamic enumerm: $# - reprezint numrul parametrilor poziionali ai unui program shell; $? - reprezint exit status-ul (codul de revenire) celei mai recente comenzi executate; $- - reprezint opiunea curent cu care a fost lansat shell-ul; $$ - reprezint identificatorul de proces al shell-ului; $! - reprezint identificatorul de proces al celei mai recente comenzi lansate n background; $0 - reprezint numele shell-ului sau al shell-script-ului; $1..$9 - reprezint argumentele (parametrii) ultimei comenzi lansate n execuie la linia de comand; $_ - reprezint ultimul argument al comenzii anterioare.

Bourne shell

Dintre variabilele atribuite la intrarea n sesiune enumerm: $HOME - reprezint directorul atribuit utilizatorului (directorul implicit) la intrarea n sesiune; $PATH - reprezint lista directorilor ce sunt parcuri de shell la cutarea unui fiier executabil corespunztor comenzii introduse; $PS1 - reprezint prompter-ul asociat interpretorului; $PS2 - reprezint al doilea prompter (pentru continuarea liniei de comand, cel implicit este >); $MAIL - reprezint numele directorului implicit pentru pota electronic; $LOGNAME - reprezint numele de login al utilizatorului; $SHELL - reprezint numele interpretorului de comenzi implicit atribuit la intrarea n sesiune (acesta se poate schimba folosind comanda chsh); $TERM - reprezint tipul de terminal folosit de editorul vi i de alte editoare orientate pe ecran. 7.3 7.3.1 Instruciuni de selecie Instruciunea if

Sintaxa acestei instruciuni este:


if <com_test1> then <secventa_comenzi1> else <secventa_comenzi2> fi

unde else este opional. n astfel de situaii este folosit scrierea testrilor folosind notaia cu paranteze drepte n loc de comanda test.

UNIX

Exemplul 1.
unitati=0 if [ $contor -lt 10] then unitati=`expr $unitati + 1` else unitati=0 zeci=1 fi

Instruciunile if pot fi ncuibate, dup modelul:


if <com_test1> then if <com_test2> then <secventa_comenzi1> fi else if <com_test3> then <secventa_comenzi2> fi fi

O alternativ a construciei else...if este dat de elif:


if <com_test1> then <secventa_comenzi1> elif <com_test2> then <secventa_comenzi2> else <secventa_comenzi3> fi

Bourne shell

Exemplul 2. Fie un shell-script denumit verif_fisier care ia drept argument un nume de fiier i verific dac este director sau fiier obinuit:
if [ -f "$1" ] then echo "$1 este fiier obisnuit!" elif [ -d $1 ] then echo "$1 este director!" fi

7.3.2

Comanda null

Comanda null este reprezentat de caracterul special : (n englez colon) i este o comand care nu face nimic i returneaz un exit-status egal cu zero. Aceast comand se poate utiliza n cadrul unei comenzi if cnd nu avem nici un mesaj de afiat sau alt comand de efectuat (conform sintaxei comenzii if trebuie ns introdus o comand dup cuvntul cheie then pentru a nu produce o eroare). Fie exemplul urmtor:
#!/bin/sh nume=george if grep $nume database > /dev/null 2>&1 then : else echo $nume nu a fost gasit in baza de date! exit 1 fi

Conform acestui shell-script se caut n fiierul database irul de caractere george folosind comanda grep. Dac acest ir de caractere este gsit, se execut comanda null care va returna un exit-status de valoare zero (programul se termin cu succes); dac nu, se va afia mesajul corespunztor faptului c george nu a fost gsit n baza de date i programul se va ncheia cu un exit-status egal cu 1.

UNIX

7.3.3

Instruciunea case

Sintaxa instruciunii case este:


case <valoare> in sablon_1) <comanda11> <comanda12> ... <comanda1n>;; sablon_2) <comanda21> <comanda22> ... <comanda2n>;; ... sablon_m) <comandam1> <comandam2> ... <comandamn>;; esac

Observaie. Putem utiliza metacaracterul * pentru a specifica orice ablon, dac nici unul nu a fost adevrat. Exemplul 1. Presupunem c avem un program care cere o opiune pentru urmtorul meniu:
Alegeti opiunea dintre variantele: 1...Afisarea unui fisier 2...Stergerea unui fisier 3...Iesire din program

Codul de program pentru citirea opiunii i verificarea acesteia este: Observaie:

Bourne shell

Dac utilizatorul trebuie s introduc o liter n locul unei cifre i dorim s nu conteze dac litera introdus este majuscul sau nu, putem s nlocuim 1) cu a|A) n cazul n care "A" este opiunea pentru afiarea unui fiier, 2) cu s|S) n cazul n care "S" este opiunea pentru tergerea unui fiier i 3) cu i|I) n cazul n care "I" este opiunea pentru ieirea din program. Exemplul 2. Considerm programul urmtor:
#!/bin/sh # Nume shell-script: culori echo "Ce culoare va place? " read culoare case "$culoare" in [Aa]l??????) echo $culoare este culoarea cerului! ;; [Vv]erde) echo Padurea este $culoare ! ;; galben | portocaliu) # Bara verticala semnifica "sau" echo $culoare este o culoare calda!;; *) echo Nu stiu nimic despre culoarea $culoare;; esac echo "Sfarsit case"

Explicaii: Se citete la nceput un ir de caractere care este atribuit variabilei culoare. Comanda case evalueaz expresia $culoare. n cazul n care culoarea introdus ncepe cu A sau a, continu cu litera l i urmeaz alte 6 caractere (pentru a se forma Albastru sau albastru), se afieaz mesajul corespunztor i instruciunea case se ncheie. Dac nu este ndeplinit prima condiie, se continu cu verificarea celorlalte dou condiii (pentru culorile verde, apoi pentru galben i portocaliu) i dac nici acestea nu sunt ndeplinite se va afia mesajul care corespunde opiunii *, ce reprezint toate celelalte cazuri (un fel de else n cazul instruciunii case, atunci cnd toate celelalte condiii anterioare nu au fost ndeplinite). n final, instruciunea case se termin cu cuvntul cheie esac i este afiat mesajul de ieire din instruciunea case.

UNIX

7.4 7.4.1

Instruciuni iterative Instruciunea for

Sintaxa instruciunii for este:


for <variabila> in <valoare_1> <valoare_2> <valoare_n> do <comenzi> done

Exemplul 1. Secvena urmtoare de program copiaz fiierele cu numele fis1, fis2 i fis3 n directorul copie din directorul curent:
for f in fis1 fis2 fis3 do cp $f copie done

Comanda for poate fi folosit pentru ciclarea printre elementele coninute de variabila special $*. Secvena urmtoare afieaz argumentele cu care este apelat shell-script-ul (presupunem c l denumim afisare_arg).
for argum in $* do echo "$argum" done

Exemplul 2. n acest exemplu presupunem c avem de trimis acelai mesaj prin e-mail mai multor persoane. Adresele de e-mail ale persoanelor vor fi introduse anterior ntr-un fiier text simplu, fiecare adres de email pe cte o linie. Dac denumim fiierul cu adresele de e-mail adrese, acesta va arta astfel:

Bourne shell

stud anca@yahoo.com cristi@hotmail.com george paul serban@k.ro

Observaie. Avem de-a face n exemplul de mai sus cu trei adrese complete de email i cu trei adrese locale corespunztoare utilizatorilor locali stud, george i paul. Mesajul pe care l trimitem se afl n fiierul mesaj. Cu aceste explicaii, shell-script-ul este:
# Numele script-ului: trimite_mesaj for persoana in `cat adrese` do mail $persoana < mesaj echo A fost trimis mesajul lui $persoana. done echo "Mesajul a fost transmis."

7.4.2

Instruciunea while

Sintaxa instruciunii while este:


while <comanda_adev> do <comenzi> done

Exemplul 1. Secvena urmtoare de program citete o opiune i execut comenzile specificate att timp ct variabila final are valoarea "n".

UNIX

final=n while [ "$final" = n ] do read opiune case "$opiune" in 1) echo "Introduceti numele fiierului afisat:" read nf cat "$nf";; 2) echo "Introduceti numele fiierului sters:" read nf rm "$nf";; 3) fin=y echo "Iesire din program..." sleep 5;; *) echo "Opiune invalida!";; esac done

ce

va

fi\

ce

va

fi\

Exemplul 2. Programul urmtor afieaz pe rnd argumentele cu care a fost apelat. Folosind comanda shift putem face s afim nti toate argumentele apelului, apoi mai puin cu unul, .a.m.d., pn la ultimul argument.
while [ $# -gt 0 ] do echo $* shift done

Presupunnd c programul se numete afisarg, apelul: $ afisarg 1 2 3 4 5 va afia: 12345 2345 345 45 5

Bourne shell

7.4.3

Instruciunea until

Sintaxa instruciunii until este:


until <comanda_adev> do <comenzi> done

De regul, instruciunea until se folosete atunci cnd trebuie executat o secven de instruciuni pn n momentul n care o comand se termin cu valoarea de adevr zero (true). Exemplul 1. Fie secvena urmtoare de program care verific dac un utilizator al crui nume este specificat drept argument n momentul apelului shell-script-ului s-a conectat la sistem. n acest moment se afieaz mesajul: "Utilizatorul <nume_utilizator> s-a conectat!".
nume=$1 until who | grep ^$nume > /dev/null do sleep 30 done echo Utilizatorul $1 s-a conectat!

Comanda grep caut un ablon specificat (n cazul nostru numele utilizatorului) ntr-un fiier. Metacaracterul "^" specific faptul c ablonul se potrivete cu ieirea comenzii who doar dac este gsit la nceputul liniei (tiind faptul c who afieaz la nceputul fiecrei linii numele utilizatorilor conectai la sistem n momentul respectiv). Deoarece ieirea comenzii grep nu este folosit n nici un fel, ea este redirectat spre /dev/null. Instruciunea sleep determin oprirea temporar a execuiei programului pentru un interval de 30 de secunde; cu alte cuvinte, verificarea conectrii utilizatorului se face la intervale de 30 de secunde. Dac shell-script-ul este denumit lookout, atunci el poate fi apelat n background folosindu-se sintaxa:
$ lookout <nume_utilizator>&

iar mesajul de conectare va aprea n momentul n care utilizatorul se conecteaz la sistem i este "descoperit" de comanda lookout.

UNIX

Exemplul 2. Urmtorul program va afia cte un mesaj pentru toate orele zilei ntre 8 i 24:
ora=8 until [ $ora gt 24 ] do case "$ora" in [8-9] |1[0-1]) echo "Buna dimineata!" ;; 1[2-3]) echo "Ora pranzului!" ;; 1[4-6]) echo "Siesta!" ;; *) echo "Buna seara!" ;; esac ora=`expr $ora + 1` done

Execuia programului va afia pe ecran:


Buna dimineata! Buna dimineata! Buna dimineata! Buna dimineata! Ora pranzului! Ora pranzului! Siesta! Siesta! Siesta! Buna seara! Buna seara! Buna seara! Buna seara! Buna seara! Buna seara! Buna seara! Buna seara!

Bourne shell

7.4.4

Instruciunile break i continue

Instruciunile break i continue sunt instruciuni de salt, fiind folosite n mod asemntor cu instruciunile omonime din limbajul C. Astfel, instruciunea break determin ieirea din cel mai interior ciclu ce o conine i continund cu execuia primei comenzi dup ciclul respectiv, iar instruciunea continue determin saltul la nceputul ciclului ce o conine. Exemplu Secvena urmtoare de program citete valoarea unui an care trebuie s fie cuprins ntre 1900 i 2000 iar dac nu se introduce nici o valoare se reia introducerea anului.
valid=n until [ "$valid" = y ] do echo "Introduceti anul (n intervalul 1900-2000) i\ tastati <ENTER>" read an if [ "$an" = "" ] then continue fi if [ "$an" -lt 1900 -o "$an" -gt 2000 ] then echo "\n Anul trebuie sa fie n intervalul 1900-\ 2000" else valid=y fi done

Ce se va ntmpla n cazul n care n exemplul anterior continue este nlocuit de break? 7.5 Funcii n Shell

Ca i n limbajul C, avem posibilitatea i n Bourne Shell s folosim funcii definite de utilizator pentru a conferi modularitate programelor. De asemenea, funciile se apeleaz mai rapid dect ar fi apelate alte shell-script-uri. La apelul unui alt shell-script, shell-ul trebuie s caute pe hard disc programul i s-l deschid nainte de a fi citit, situaie n care se creeaz un nou proces; acest lucru nu se ntmpl n cazul apelului unei funcii.

UNIX

O funcie definit ntr-un shell-script exist doar n cadrul procesului respectiv i nu poate fi exportat. Formatul general al declarrii unei funcii este:
nume() { <secventa_de_comenzi> }

Parantezele rotunde ce urmeaz dup numele funciei specific interpretorului de comenzi c este vorba despre o funcie. Observaie: Spre deosebire de limbajul C, parantezele ce urmeaz dup numele funciei nu au niciodat coninut. Apelul funciei se face prin numele ei, ca o comand obinuit; de aceea, numele funciilor nu trebuie s coincid cu numele comenzilor UNIX sau ale comenzilor Shell. O funcie poate accesa variabilele setate pentru shell-ul curent (att cele stabilite la nceputul procesului de login ct i cele ce se modific pe parcurs). De regul, funciile se scriu la nceputul shell-script-ului; n caz contrar, codul funciei trebuie s precead apelul su. Exemplu. Fie funcia:
go() {

} go $1

cd $1 PS1="`pwd`>"

Dac numele shell-script-ului este gofunc, atunci el poate fi apelat n modul urmtor:
$ gofunc /home/serban

iar rezultatul apelului va fi schimbarea directorului curent n /home/serban i schimbarea primului prompter n "/home/serban>".

Bourne shell

7.6 7.6.1

Mediul Shell Apelurile fork i exec

n UNIX, apelul de sistem fork determin producerea unui nou proces. Apelul exec face ca un nou program s se suprapun peste noul proces. Dup fiecare apel fork ce genereaz un nou proces, vechiul proces se execut n continuare avnd coninutul intact. Noul proces este identic cu printele sau pn cnd exec se suprapune cu imaginea noului program. Acest eveniment apare, de regul, la execuia unei comenzi. Apelul de sistem wait suspend execuia shell-ului pn cnd noul proces este terminat. Atunci cnd apelul de sistem exec se autoapeleaz la prompter-ul shell, coninutul procesului vechi se pierde. Procesul original este suprapus cu imaginea noului program. Spre exemplu, se poate considera comanda:
$ exec ls -l

n acest caz, comanda anterioar este suprapus peste procesul shell; n momentul execuiei sale, shell-ul se termin i de aceea utilizatorul este confruntat cu prompter-ul de login. Un proces este un program n execuie, fiecare proces avnd o arie de memorie unde este stocat informaia despre acesta. Un proces aflat n execuie este descris de o tabel de procese. Tabela de procese conine informaii precum: identificatorul procesului (process id) adrese de memorie descriptori de fiiere. Aceste informaii sunt folosite de ctre kernel pentru controlul execuiei. Procesul n sine conine codul ce va fi executat, avnd, de asemenea, asociat o poriune de date n memorie ce conine informaii referitoare la mediul sistemului (variabilele de mediu). 7.6.2 Modaliti de grupare a comenzilor shell

Exist o serie de modaliti de grupare a comenzilor shell: grupare secvenial: pwd;ls -l grupare n paranteze: (pwd;ls -l) grupare n background: sort fiier& grupare n conduct (pipe): ls -l | pg

UNIX

n timp ce gruparea n paranteze i execuia n background produc un singur proces copil, gruparea secvenial i cea de tip pipe produc procese copil multiple. Datorit vitezei operaiunilor, utilizatorul nu realizeaz cte procese sunt generate de fiecare dat. n cazul gruprii secveniale, shell-ul genereaz un proces de execuie a primei comenzi. Cnd comanda este ncheiat, shell-ul genereaz alt proces pentru execuia celei de-a doua comenzi, deci procesele sunt generate secvenial. Gruparea n paranteze se folosete atunci cnd ieirile comenzilor sunt trimise ctre o singur destinaie. Este generat n acest caz un singur proces ce este suprapus de fiecare dat cnd trebuie executat alt comand. Gruparea n conduct se folosete atunci cnd ieirea primei comenzi trebuie preluat de a doua comand ca intrare. Comanda pipe determin generarea attor procese cte comenzi exist pe linia de comand. Comenzile sunt suprapuse peste aceste procese i sunt executate. Comunicarea dintre procesele n execuie este stabilit de un fiier special de tip pipe. Comenzile rulate n background sunt executate n mod normal, adic procesul este generat de fork i comanda este executat de exec. Totui, apelul de sistem wait este omis. Aceast lucru permite shell-ului s continue de ndat ce comanda din background a nceput. Uneori este necesar ca o comand n background s atepte pna la terminarea unei alte comenzi din background nainte ca s fie executat codul. n acest caz este folosit o combinaie de wait i $! ($! conine identificatorul procesului ultimei comenzi lansate n background). Secvena urmtoare justific aceasta:
sort sort ... wait wait hugefile > outfile1& pid1=$! hugefile > outfile2& pid2=$! $pid1 $pid2

diff outfile1 outfile2 >&1

7.6.3

Modaliti de apel al shell-ului

Exist dou modaliti de apel al shell-ului: apelul standard i apelul la linia de comand. Apelul standard se face prin intermediul procedurii de login, procedur n care se folosesc anumite fiiere i programe pentru a face iniializrile configuraiei utilizatorilor. Spre exemplu, n UNIX System V se folosesc fiierele /etc/inittab, /etc/profile, /etc/passwd i .profile.

Bourne shell

Dup ce numele i parola utilizatorului (preluat din /etc/passwd, unde este memorat criptat) sunt verificate, programul login folosete informaia coninut n /etc/passwd pentru urmtorul pas din procedur. Fiecrui utilizator i este asociat o linie n acest fiier ce conine numele, parola, directorul home i shell-ul implicit ce este apelat la intrarea n sistem. Dup ce au fost executate fiierele /etc/profile i .profile programul login se suprapune peste sh folosind apelul de sistem exec. O alt modalitate de apel al shell-ului este de a introduce numele la linia de comand. Comanda exec poate fi folosit la linia de comand, urmat de numele programului shell ca opiune:
$ exec -sh

Aceast comand asigur faptul c fiierele /etc/profile i .profile sunt executate. Comanda nu creaz un nou proces ci suprapune programul sh peste un proces n execuie. Deoarece const din execuia att a unui fork ct i a unui exec, comanda sh creeaz un nou proces. 7.6.4 Comanda sh

O posibilitate de folosire a acestei comenzi este aceea de a folosi opiunea -r prin intermediul creia se pornete un shell restricionat (rsh - restricted shell). Acest shell reduce posibilitile de aciune ale utilizatorului fa de aciunile permise n cadrul shell-ului obinuit (de regul comanda este folosit pentru utilizatorii noi din sistem). Aceste restricii sunt: Variabilele PATH i SHELL nu pot fi modificate; Comenzile nu pot fi specificate folosindu-se ntreaga cale; Redirectarea operatorilor este dezactivat (pentru <, >, >>); Programele nu pot fi pornite cu exec; Comanda cd este dezactivat; Cu alte cuvinte, rsh dezactiveaz toate comenzile ce nu sunt n directorul curent sau n calea standard de cutare, protejeaz fiierele de creare sau modificare prin redirectare, asigur protecia suprancrcrii shell-ului de ctre utilizator i foreaz utilizatorul s rmn n directorul home. Alte opiuni ale comenzii: Opiunea -c <sir_caractere> face s se execute comanda identificat de irul de caractere;

UNIX

Opiunea -i face shell-ul interactiv; Opiunea -s permite posibilitatea citirii de comenzi de la intrarea standard. 7.6.5 Subshell-uri

Este important n UNIX s cunoatem modul de execuie a comenzilor i shell-script-urilor din punct de vedere al "locului" de rulare a acestora. Astfel, atunci cnd o comand este oferit spre execuie shell-ului este creat un subshell, care este un proces copil. Cea mai uzual metod de a rula o comand este aceea de a introduce comanda la prompter-ul UNIX. Totui, comanda poate fi executat i astfel:
$ sh nume_comanda

Fiecare metod creeaz de fapt cte un subshell. Ce este important de tiut este faptul c modificrile aduse mediului de ctre subshell nu sunt valabile i n shell-ul printe. 7.6.6 Comenzile env i set

Shell-ul ofer posibilitatea modificrii mediului de execuie prin: env set Atunci cnd folosim env fr argumente, se vor lista doar variabilele ce au fost motenite (exportate) de la procesul printe. Exemplu:
$ env VAR=1 EXPORTED=vt100

Atunci cnd folosim set fr argumente, se ateapt o list a tuturor variabilelor din mediul shell al utilizatorului (variabile locale sau exportate).

Bourne shell

Exemplu:
$set PATH=/home/razvan:/bin:/usr/bin TERM=vt220 VAR1=1 EXPORTED=vt100 $

Formatul general al comenzii env este:


$ env [-] [<nume=valoare ...>][<comanda>

Exemplu:
$ env TERM=tvi050 vi myfile

Scopul lui env este modificarea temporar a mediului shell. Atunci cnd comanda env este folosit fr semnul minus (-), preia mediul curent i l modific n concordan cu atribuirile specificate, executnd apoi comanda ce apare n mediul temporar. Dac apare semnul minus (-), mediul motenit este ignorat i se execut comanda respectiv folosind mediul specificat. Formatul general al lui set este:
$ set [optiuni] [argumente]

Atunci cnd sunt specificate valori drept argumente, sunt setate valorile parametrilor poziionali corespunztori. Atunci cnd set este folosit cu opiuni, ea modific execuia shell-ului curent. Opiunile sunt activate dac sunt precedate de semnul minus (-) i dezactivate cnd sunt precedate de semnul plus (+). Una dintre utilizrile de baz ale comenzii set este aceea de depanare a shell-script-urilor folosind opiunea -v care urmrete execuia shell-script-ului. Opiunile existente pentru comanda set sunt: -a export n mod automat toate variabilele ce sunt definite sau modificate; -e iese dac o comand returneaz un exit-status false; -f dezactiveaz generarea numelui de fiier; -n citete comenzile fr s le execute;

UNIX

-u genereaz o eroare dac o variabil este referit nainte de a fi definit; -v tiprete fiecare linie de comand shell nainte de a fi folosit; -x tiprete comenzile i argumentele lor atunci cnd sunt folosite; - dezactiveaz opiunile x i v. Fie shell-script-ul denumit test:
set -x cmd=wc cat fisier | $cmd -l

Execuia shell-script-ului este:


$ + cat fiier + wc -l 33 $

Un shell-script poate stabili care dintre opiunile set sunt activate folosind variabila special $-. Semnificaia semnalelor recunoscute n UNIX
Tabelul 7.1
Numrul semnalului 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Semnal Semnificaie semnal special shell ce determin execuia unei comenzi la ieirea din shell terminal hangup ntrerupere (DEL - tast apsat) quit (s-a apsat CTRL+\) instruciune ilegal trace/breakpoint trap abort emulation trap excepie aritmetic semnal kill eroare bus segmentation fault bad system call broken pipe alarm clock terminated

SIGHUP SIGINT SIGQUIT SIGILL SIGTRAP SIGABORT SIGEMT SIGFPE SIGKILL SIGBUS SIGSEGV SIGSYS SIGPIPE SIGALARM SIGTERM

Bourne shell

7.6.7

Semnale

Este necesar uneori ca shell-script-ul s poat fi ntrerupt pentru a ne ntoarce la prompter. Putem apsa DELETE, BREAK sau CTRL+C. n funcie de necesiti, uneori este necesar s executm o operaie de ntreinere atunci cnd un shell-script este ntrerupt (trebuie s nchidem sau s tergem fiierele temporare). n alte circumstane, se poate dori ndeplinirea unei anumite sarcini fr ntrerupere. UNIX ofer posibilitatea manevrrii exprese a evenimentelor iniiate de lumea din afar prin folosirea semnalelor. n funcie de versiunea de UNIX utilizat, numrul de semnale recunoscute variaz ntre 15 i 30. Lista acestora este prezentat n tabelul 7.1. Semnalele 1..9 i 15 sunt relevante pentru programatorul Shell. Celelalte apar pentru completitudine i pentru a arta ce fel de semnale pot fi manipulate de UNIX. Observaie. De regul, semnalele sunt interceptate de apelul de sistem signal ce poate fi folosit n programe C. Exemplu: Fie o instruciune dintr-un program C ce face o mprire la zero: printf("Impartire la zero:%d",6/0); n acest caz este semnalat un SIGFPE, iar programul trebuie s includ cod care s recepioneze acest semnal: signal(SIGFPE,f_cleanup), unde f_cleanup este funcia ce rezolv problema i afieaz un mesaj corespunztor. Comanda trap O alt modalitate de interceptare a mesajelor este aceea realizat prin intermediul comenzii interne trap. Aceast comand permite interceptarea i prelucrarea semnalelor ce ar afecta shell-script-ul ntr-o manier imprevizibil. Formatul general al comenzii este:
$ trap comenzi semnale

unde comenzi reprezint comenzi ce se execut la apariia unuia dintre semnale. Fie comanda:
$ trap "rm tmp*;echo interrupt!;exit 3" 1 2

UNIX

Aceast comand poate inhiba ntreruperile n cazul proiectrii unor interfee prietenoase cu utilizatorii. De exemplu, o interfa utilizator poate s ignore apsarea tastelor DEL, BREAK sau CTRL+C. Urmtoarea comand face ca semnalele respective s fie ignorate:
$ trap "" 1 2 3 15

Atunci cnd trap este folosit pentru a ignora semnale, afecteaz toate subshell-urile. Cnd trap este folosit s ia aciune, nu le afecteaz. Dac se dorete ca aciunea lui trap s aib efect n subshell-uri, trebuie specificat n mod explicit acest lucru n fiecare subshell. Totui, nu orice semnale pot fi ignorate; n caz contrar nu ar mai putea fi intrerupte anumite programe sub nici o form! Exist SIGKILL care nu poate fi ignorat! Acest semnal este generat de comanda intern kill. Exemplu:
$ kill -9 12345

unde 12345 este identificatorul procesului ce trebuie terminat. 7.7 7.7.1 Comenzi interne Introducere

Comenzile nglobate sau interne (built-in commands) sunt comenzi ce pot fi apelate din interiorul unui shell-script sau de la linia de comand. Shell-ul are 32 de comenzi nglobate. Fiecare comand ce este executat returneaz un cod de ieire denumit exit-code sau exit-status. Atunci cnd comanda nu se termin pe o singur linie, shell-ul prezint cel de-al doilea prompter (al doilea prompter este implicit semnul mai mare (>)) utilizatorului pentru introducerea caracterelor de continuare pn cnd se ncheie comanda.

Bourne shell

Exemplu:
$ for i in f1 f2 >do >file $i >done $

7.7.2

getopts

Exist posibilitatea ca un shell-script s fie apelat cu opiuni. Dac un shell-script denumit test.cmd are urmtoarea sintax:
$ test.cmd [-a] [-b] [-c]

atunci el poate fi apelat n oricare dintre modalitile urmtoare:


$ $ $ $ $ test.cmd test.cmd test.cmd test.cmd test.cmd -a -abc -a -b -a -b -c

.a.m.d n acest caz vom folosi getopts n interiorul uneia dintre instruciunile for, while sau until. Comanda getopts returneaz valoarea logic "true" att timp ct exist opiuni ce trebuie luate n considerare. Formatul general al comenzii este:
$ getopts optiuni nume_variabila

UNIX

Exemplu. Fie shell-script-ul test.cmd:


# test.cmd ... while getopts abc optiune do ... done

Care este modalitatea de lucru a lui getopts? Spre exemplu, dac apelul s-a fcut test.cmd -abc, comanda getopts verific prima dat dac exist simbolul minus (-) n linia de comand. Verific apoi dac litera ce urmeaz este una dintre opiunile valide. Dac opiunea este valid, atunci ea este memorat n variabila optiune. n acest moment este returnat un exit status cu valoarea zero, deci corpul ciclului while este executat. Opiunile urmtoare sunt tratate n mod asemntor. Atunci cnd se epuizeaz toate opiunile, getopts returneaz o valoare diferit de zero i astfel ciclul while se ncheie. n cazul apariiei unei opiuni invalide, spre exemplu se face apelul test.cmd -abcd, opiunile corecte sunt tratate ca mai sus, iar opiunea invalid d este considerat i ea de getopts deoarece face parte din grupul precedat de semnul minus (-). n acest caz, getopts ia valoarea special ?, apoi returneaz un exit status de valoare zero i corpul ciclului while este executat. Shell-script-ul va conine cod corespunztor pentru fiecare opiune valid. Un exemplu ar putea fi acela construit cu un case:
while getopts abc optiune do case $optiune in a) ...;; b) ...;; c) ...;; \?) echo "Optiune invalida..." esac done

Bourne shell

Fie un nou shell-script, cu urmtorul format:


$ test2.cmd [-a] [-b] [-c] infocib

Opiunile a,b i c sunt tratate ca mai nainte iar getopts ntoarce o valoare diferit de zero deoarece argumentul infocib nu este o opiune. Ciclul se termin drept rezultat al apariiei unei valori false (diferit de zero) iar argumentul infocib este luat n considerare n continuare, dup ciclul getopts. Fie acum cazul n care o opiune necesit i un argument ce trebuie specificat. Fie shell-script-ul:
$ test3.cmd [-a] [-b argument] nume_fisier

Comanda getopts devine: getopts ab: opiune, unde apariia semnului dou puncte (:) nseamn c aceast opiune trebuie urmat de cel puin un caracter whitespace i de un argument. Argumentul va fi memorat ntr-o variabil special numit OPTARG. Dac linia de comand conine -b fr nici un argument n continuare, n variabila opiune este memorat un semn de ntrebare (?). O alt variabil special, numit OPTIND este incrementat de fiecare dat cnd getopts returneaz o valoare. Ea are iniial valoarea 1. Se poate verifica n acest mod dac a fost introdus argumentul specificat pentru execuia corect a comenzii. Astfel, n apelul test3.cmd -a -b nume infocib, dac valoarea lui OPTIND este mai mare dect valoarea lui $#, atunci numele fiierului nume_fisier pentru execuia corect a scriptului nu a fost introdus. 7.7.3 Comanda hash

Comanda hash este folosit pentru mrirea vitezei primirii comenzilor. Sintaxa general a acestei comenzi este:
$ hash [-r] comenzi

UNIX

Acest apel al comenzii "spune" shell-ului s caute comanda sau comenzile specificate i s adauge directorul n care sunt localizate acestea la "lista hash". Spre exemplu, odat executat comanda:
$ hash inter

urmtoarele apeluri ctre shell-script-ul inter se vor executa cu vitez mai mare. Dac folosim comanda hash fr nici un argument, se va afia o list cu comenzi ce sunt deja n lista hash. Opiunea -r se folosete atunci cnd dorim tergerea din list a unei comenzi. Comanda hash -r terge toate componentele listei. Comanda hash fr nici un argument afieaz toate componentele listei. 7.7.4 Comanda type

Comanda type afieaz informaii despre comanda sau comenzile specificate, avnd sintaxa:
$ type comenzi

Comanda type poate fi folosit mpreun cu: comenzi interne comenzi UNIX shell-script-uri funcii 7.7.5 Comanda newgrp

Comanda newgrp modific pentru un utilizator UNIX identificatorul de grup (group_id). Sintaxa general este:
$ newgrp [nume_grup]

Presupunnd c grupul utilizatorului se intituleaz cibernetica i trebuie schimbat n comert, comanda este: newgrp comert. Pentru motive legate de securitatea sistemului, modificarea este permis doar dac utilizatorul apare n lista membrilor grupului comert din

Bourne shell

fiierul /etc/group. Cu ajutorul acestei modificri, utilizatorul poate accesa programe disponibile grupului comert. 7.7.6 ulimit

Dimensiunea fiierului pe care un proces copil l poate scrie este limitat de un anumit numr de blocuri folosind comanda ulimit. Sintaxa general a acestei comenzi este:
$ ulimit dimensiune_fisier

Pentru a afla setarea curent, introducem pur i simplu comanda fr nici un argument. Utilizatorul obinuit poate micora dimensiunea; doar root poate crete aceast dimensiune. 7.7.7 umask

Comanda umask determin drepturile de acces implicite la fiiere (default mask). Acestea sunt create folosind valori octale. Pentru un fiier obinuit, drepturile de acces deplin sunt de forma: -rw-rw-rw-, iar valoarea octal a reprezentrii este 666. Dreptul de acces pentru un anumit fiier se obine scznd din 666 valoarea lui umask. n general, valoarea lui umask este setat de root la valoarea octal 022. Se obine astfel valoarea 666-022=644, care reprezint drepturile implicite pentru fiierele nou create: -rw-r--r--. Dac dorim drepturi depline de acces, vom seta umask la valoarea 0, prin comanda umask 0. Pentru un director, drepturile depline de acces sunt: -rwxrwxrwx (777 n octal). Dreptul x (de execuie) pentru un director ofer utilizatorului dreptul de citire a coninutului directorului. Astfel, dreptul de acces la director se obine scznd din 777 valoarea lui umask: 777-022=755, care reprezint drepturile: -rw-r-xr-x. 7.7.8 Comanda times

Comanda times se folosete pentru afiarea de ctre shell a timpului necesitat de toate procesele rulate de ctre acesta. Sunt listate att timpul utilizator ct i cel sistem. Fie exemplul:
$ times
0m30s 3m30s

UNIX

Primul timp reprezint 30 de secunde petrecute n mod utilizator iar cel de-al doilea timp este timpul ce a fost alocat proceselor sistem. 7.7.9 Comanda eval

Comanda eval asigur evaluarea complet a unei variabile. Exemplu:


$ dir_curent=$pwd $ echo $dir_curent $ pwd

n cazul utilizrii comenzii eval vom obine urmtorul rezultat:


$ eval $dir_curent /home/stud/an3/i97aaa

7.8

Crearea unui shell-script

Pentru a crea un shell-script avem nevoie de un editor de text cu care putem insera comenzi shell ntr-un fiier. Este bine s introducem n cadrul script-ului pe lng comenzile folosite i comentarii, pentru a face neles rolul comenzilor i scopul shell-script-ului. Comentariile se introduc folosindu-se simbolul special diez (#). Tot ce urmeaz dup simbolul # pn la captul rndului pe care se gsete acesta este considerat comentariu. Excepie face prima linie din program, care indic tipul programului shell ce va executa liniile din script (sh, csh, bash etc.). Astfel, n cazul utilizrii shell-ului Bourne, prima linie din script va fi:
#!/bin/sh

Aici semnul special # nu mai are rolul de nceput de comentariu, ci mpreun cu semnul exclamrii (!) formeaz un numr magic - #! - ce specific kernel-ului s identifice programul ce va interpreta shell-script-ul respectiv. Aceast linie trebuie neaprat s se afle la nceputul programului

Bourne shell

(pe prima linie din script). n cazul folosirii shell-ului Bash din Linux, prima linie dintr-un shell-script va arta astfel:
#!/bin/bash

Dup ce am creat fiierul shell-script ce poate conine comenzi shell, comenzi UNIX sau comentarii, trebuie s facem acest fiier executabil. Acest lucru se realizeaz folosind comanda UNIX chmod. Spre exemplu, dac shell-script-ul nostru se intituleaz program_shell, atunci comanda prin care acest fiier devine executabil este:
$ chmod +x program_shell

7.9

Depanarea programelor shell

Utilizarea opiunii n la apelul comenzii sh ne ofer posibilitatea verificrii sintaxei unui shell-script fr a executa vreuna din comenzile acestuia. Dac exist vreo eroare de sintax n cadrul script-ului, shell-ul va semnaliza acea eroare. n caz contrar, nseamn c programul este corect din punct de vedere sintactic i nu se va afia nimic. Opiuni de depanare pentru Bourne Shell
Tabelul 7.2
Denumirea opiunii Opiunea echo Comanda sh x nume_script Explicaii Afieaz fiecare linie a script-ului dup substituirea variabilelor, naintea execuiei Afieaz fiecare linie a script-ului naintea execuiei, exact aa cum a fost scris Interpreteaz dar nu execut comenzile Urmrete execuia unui script Oprete urmrirea execuiei unui script

Opiunea verbose Opiunea noexec Seteaz echo-ul Reseteaz echo-ul

sh v nume_script sh n nume_script set x set +x

Cel mai des se folosete opiunea x a comenzii set pentru depanarea script-urilor, sau se poate apela direct comanda sh cu opiunea x. Utiliznd aceast opiune, se va afia fiecare comand din shell-script (dup ce s-a

UNIX

fcut n prealabil substituirea valorilor variabilelor) i apoi este executat. Atunci cnd se afieaz o linie din shell-script, este precedat de semnul plus (+). O alt opiune folosit este opiunea v (verbose) vorbrea (sh v nume_script) cnd se afieaz fiecare linie din shell-script ca i cum ar fi fost scris la linia de comand iar dup aceea este executat. n tabelul 7.2 sunt prezentate opiunile folosite pentru depanare n cazul shell-ului Bourne. 7.10 Exemple de programe Bourne shell Exemplul 1.
iesire=F while [ $iesire = "F" -o $iesire = "f" ] do clear echo "Alegeti o opiune:" echo echo "1. Lansare Midnight Commander" echo "2. Editare cu Nice Editor" echo "3. Afisare cale curenta" echo "4. E-mail" echo "5. Afisarea numarului de utilizatori conectati la\ sistem" echo "0. Iesire" echo read optiune case $optiune in 1) mc ;; 2) echo "Nume fiier de editat: " read fis if [ -f $fis ] then ne $fis else echo "Fiier inexistent. Il\ creati?(d/n)" read rasp if [ $rasp = "d" ] then ne $fis fi fi ;; 3) pwd echo "Apasati o tasta pentru continuare..." read y ;;

Bourne shell 4) echo "Introduceti adresa destinatarului:" read adresa mail $adresa echo "Apasati o tasta pentru continuare..." read y ;; 5) echo "Sunt conectati `who | wc -l`\ utilizatori in acest moment!" echo "Apasati o tasta pentru continuare..." read y ;; 0) iesire=D ;; esac done

Explicaii. Programul afieaz un meniu cu 6 opiuni. Opiunea este citit n variabila optiune i n funcie de valoarea acesteia se execut comenzile specificate folosindu-se o instruciune case. Totul este inclus ntr-un ciclu while, care se va repeta pn n momentul selectrii opiunii 0, cnd variabila iesire ia valoarea D i se iese astfel din ciclul while. Exemplul 2. n acest exemplu vom lucra cu o baz de date simpl vom crea funcii pentru adugare, tergere, actualizare i un program principal ce apeleaz aceste funcii. Baza noastr de date va conine informaii despre studenii unei faculti: nume i prenume, grupa, adresa, i data naterii. Fiierul ce va conine aceste informaii se va numi studenti. S presupunem c vom defini funciile n fiierul functii. Fie funcia de adugare:
adaug () { # Functia este definita in fisierul functii while true do echo "Adaugare de informatii " echo "Introduceti numele si prenumele studentului " read nume echo "Introduceti grupa " read grupa echo "Introduceti adresa " read adresa echo "Introduceti data nasterii (zz/ll/aaaa) " read datan echo $nume:$grupa:$adresa: $datan

UNIX echo "Datele sunt corecte? " read ans case "$ans" in [Dd]*) echo "Adaugarea informatiilor..." echo $nume:$grupa:$adresa: $datan >> studenti sort -u studenti -o studenti echo "Vreti sa continuati introducerea? " read ans if [ $ans = D -o $ans = d ] then return # revenire in programul apelant else continue # salt la inceputul ciclului fi ;; *) echo "Incercati din nou?(D/N) " read answer case "$answer" in [Dd]*) continue;; *) exit;; esac ;; esac done # Sfarsitul definitiei functiei

Programul principal ce va apela funciile de adugare, tergere, actualizare va arta astfel:


#!/bin/sh # Numele script-ului: program # Acest shell-script va apela functiile #fisier=$HOME/studenti fisier=./studenti .functii # Comanda punct citete fis functii n memorie if [ ! -f $fisier ] then echo "`basename $fisier` nu exista" 1>&2 exit 1 fi echo "Selectati optiunea: "

Bourne shell cat <<EOF [1] Adaugare de informatii [2] Stergere de informatii [3] Actualizarea informatiilor [4] Iesire din program EOF read optiune case $optiune in 1) adaug # Apelul functiei adaug ;; 2) sterg # Apelul functiei sterg ;; 3) actualizare # Apelul functiei actualizare ;; 4) echo La revedere! exit 0 ;; *) echo Optiune gresita! exit 2 ;; esac echo Intoarcere din apelul functiei

Funciile de tergere i de actualizare se las ca tem.

You might also like