[Bourne Shell]
[Pagina anterioara][Pagina continut][Pagina urmatoare]

Mediul Shell


Apelurile fork si exec


In Unix, apelul de sistem fork determina producerea unui nou proces. Apelul exec face ca un nou program sa se suprapuna peste noul proces. Dupa fiecare apel fork ce genereaza un nou proces, vechiul proces se executa in continuare avand continutul intact. Noul proces este identic cu parintele sau pana cand exec se suprapune cu imaginea noului program. Acest eveniment apare, de regula, la executia unei comenzi.
Apelul de sistem wait suspenda executia shell-ului pana cand noul proces este terminat. Atunci cand apelul de sistem exec se autoapeleaza la prompterul shell, continututl procesului vechi se pierde. Procesul original este suprapus cu imaginea noului program. Spre exemplu, puteti considera comanda:
		exec ls -l
	
In acest caz, comanda anterioara este suprapusa peste procesul shell; in momentul executiei sale, shell-ul se termina si de aceea utilizatorul este confruntat cu prompterul de login.
Un proces este un program in executie, fiecare proces avand o arie de memorie unde este stocata informatia despre acesta. Un proces aflat in executie este descris de o tabela de procese. Tabela de procese contine informatii precum:
  • identificatorul procesului (process id)
  • adrese de memorie
  • descriptori de fisiere
folosite de kernel pentru controlul executiei.
Procesul in sine contine codul ce va fi executat, avand, de asemenea, asociat o portiune de date in memorie ce contine informatii referitoare la mediul sistemului (variabilele de mediu).

Modalitati de grupare a comenzilor shell



Exista o serie de modalitati de grupare a comenzilor shell:
  • grupare secventiala: pwd;ls -l
  • grupare in paranteze: (pwd;ls -l)
  • grupare in background: sort fisier&
  • grupare in conducta(pipe): ls -l | pg
In timp ce gruparea in paranteze si executia in background produc un singur proces copil, gruparea secventiala si pipe produc procese copil multiple. Datorita vitezei operatiunilor, utilizatorul nu realizeaza cate procese sunt generate de fiecare data.
  • In cazul gruparii secventiale, shell-ul genereaza un proces de executie a primei comenzi. Cand comanda este incheiata, shell-ul genereaza alt proces pentru executia celei de-a doua comenzi, deci procesele sunt generate secvential.
  • Gruparea in paranteze se foloseste atunci cand iesirile comenzilor sunt trimise catre o singura destinatie. Este generat in acets caz un singur proces ce este suprapus de fiecare data cand trebuie executata alta comanda.
  • Gruparea in conducta se foloseste atunci cand iesirea primei comenzi trebuie preluata de a doua comanda ca intrare. Comanda pipe determina generarea a atator procese cate comenzi exista pe linia de comanda. Comenzile sunt suprapuse peste aceste procese si sunt executate.
    Comunicarea dintre procesele in executie este stabilita de un fisier special pipe.
  • Comenzile rulate in background sunt executate in mod normal, adica procesul este generat de fork si comanda este executata de exec. Totusi, apelul de sistem wait este omis. Aceasta permite shell-ului sa continue de indata ce comanda din background a inceput. Uneori este necesar ca o comanda in background sa astepte pana la terminarea unei alte comenzi din background inainte ca sa fie executat codul. In acest caz este folosita o combinatie de wait si $! ($! contine identificatorul procesului ultimei comenzi lansate in background). Secventa urmatoare justifica aceasta:
    		sort bigfile > outfile1& pid1=$!
    		sort bigfile > outfile2& pid2=$!
    		...
    		wait $pid1
    		wait $pid2
    		diff outfile1 outfile2 >&1
    	

    Modalitati de apel al shell-ului


    Exista doua modalitati de apel al shell-ului:
    • Apelul standard este prin procedura de login, procedura in care se folosesc anumite fisiere si programe pentru a face initializarile configuratiei utilizatorilor. Spre exemplu, in UNIX System V se folosesc fisierele /etc/inittab, /etc/profile, /etc/passwd si .profile. Dupa ce numele si parola utilizatorului (preluata din /etc/passwd, unde este memorata criptat) sunt verificate, programul login foloseste informatia continuta in /etc/passwd pentru urmatorul pas din procedura. Fiecarui utilizator ii este asociata o linie in acest fisier ce contine numele, parola, directoul home si shell-ul implicit ce este apelat la intrarea in sistem.
      Dupa ce au fost executate fisierele /etc/profile si .profile programul login se suprapune peste sh folosind apelul de sistem exec.
    • O alta modalitate de apel al shell-ului este de a introduce numele la linia de comanda. Comanda exec poate fi folosita la linia de comanda, urmata de numele programului shell ca optiune:
       $ exec -sh 
      Aceasta comanda asigura faptul ca fisierele /etc/profile si .profile sunt executate. Comanda nu creeaza un nou proces ci suprapune programul sh peste un proces in executie. Deoarece consta din executia atat a unui fork cat si a unui exec, comanda sh creeaza un nou proces.

    Comanda sh


    O posibilitate de folosire a acestei comenzi este aceea de a folosi optiunea -r prin intermediul careia se porneste un shell restrictionat (rsh - restricted shell). Acest shell reduce posibilitatile de actiune ale utilizatorului fata de actiunile permise in cadrul shell-ului obisnuit (de regula comanda este folosita pentru utilizatorii noi din sistem). Restrictiile sunt:
    • Variabilele PATH si SHELL nu pot fi modificate
    • Comenzile nu pot fi specificate folosindu-se intreaga cale
    • Redirectarea operatorilor este dezactivata (pentru <, >, >>)
    • Programele nu pot fi pornite cu exec
    • Comanda cd este dezactivata
    Cu alte cuvinte, rsh dezactiveaza toate comenzile ce nu sunt in directorul curent sau in calea standard de cautare, protejeaza fisierele de creare sau modificare prin redirectare, asigura protectia supraincarcarii shell-ului de catre utilizator si forteaza utilizatorul sa ramana in directorul home.
    Alte optiuni ale comenzii:
  • Optiunea -c <sir_caractere> face sa se execute comanda identificata de sirul de caractere.
  • Optiunea -i face shell-ul interactiv.
  • Optiunea -s permite posibilitatea citirii de comenzi de la intrarea standard.

    Subshell-uri


    Este important in Unix sa cunoastem modul de executie a comenzilor si shellscript-urilor din punct de vedere al "locului" de rulare a acestora. Astfel, atunci cand o comanda este oferita spre executie shell-ului este creat un subshell, care este un proces copil. Cea mai uzuala metoda de a rula o comanda este aceea de a introduce comanda la prompter-ul Unix. Totusi, comanda poate fi executata si:
    		$sh <comanda>
    	
    Fiecare metoda creeaza de fapt cate un subshell. Ce este important de stiut este faptul ca modificarile aduse mediului de catre subshell nu sunt valabile si in shell-ul parinte. Fie programul cdtest:
    	
    	

    Comenzile env si set


    Shell-ul ofera posibilitatea modificarii mediului de executie prin:
    • env
    • set
    Atunci cand folosim env fara argumente, se vor lista doar variabilele ce au fost mostenite (exportate) de la procesul parinte. Exemplu:
    		$env
    		VAR=1
    		EXPORTED=vt100
    	
    Atunci cand folosim set fara argumente, se asteapta o lista a tuturor variabilelor din mediul shell-ului utilizatorului (variabile locale sau exportate). 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 temporara a mediului shell. Atunci cand env este folosita fara -, preia mediul curent si il modifica in concordanta cu atribuirile specificate, executind apoi comanda ce apare in mediul temporar. Daca apare -, mediul mostenit este ignorat si se executa comanda respectiva folosind mediul specificat.
    Formatul general al lui set este:
    	set [<optiuni>] [<argumente>]
    	
    Atunci cand sunt specificate valori drept argumente, sunt setate valorile parametrilor pozitionali corespunzatori. Atunci cand set este folosita cu optiuni, ea modifica executia shell-ului curent. Optiunile sunt activate daca sunt precedate de - si dezactivate cand sunt precedate de +. Una dintre utilizarile majore ale lui set este aceea de depanare a shellscript-urilor folosind optiunea -v care urmareste executia shellscript-ului. Optiunile pentru set sunt:
    • -a exporta in mod automat toate variabilele ce sunt definite sau modificate
    • -e iese daca o comanda returneaza un exit-status false
    • -f dezactiveaza generarea numelui de fisier
    • -n citeste comenzile fara sa le execute
    • -u genereaza o eroare daca o variabila este referita inante de a fi definita
    • -v tipareste fiecare linie de comanda shell inainte de a fi folosita
    • -x tipareste comenzile si argumentele lor atunci cand sunt folosite
    • - dezactiveaza optiunile x si v.
    	Fie shellscript-ul test:
    	set -x
    	cmd=wc
    	cat fisier | $cmd -l
    	
    Executia shellscript-ului este:
    $
    + cat fisier
    + wc -l 33
    $
    Un shellscript poate stabili care dintre optiunile set sunt activate folosind variabila speciala $-.

    Semnale


    Este necesar uneori ca shellscript-ul sa poata fi intrerupt pentru a ne intoarce la prompter. Putem apasa DELETE, BREAK sau CTRL+C. In functie de necesitati, uneori este necesar sa executam o operatie de intretinere atunci cand un shellscript este intrerupt (trebuie sa inchidem sau sa stergem fisierele temporare). In alte circumstante, se poate dori indeplinirea unei anumite sarcini fara intrerupere. Unix ofera posibilitatea manevrarii exprese a evenimentelor initiate de lumea din afara prin folosirea semnalelor. In functie de versiunea de Unix folosita, numarul de semnale recunoscute variaza intre 15 si 30. Lista acestora este:
    • Nr: 0
      Semnal:
      Specificare: semnal special shell ce determina executia unei comenzi la iesirea din shell
    • Nr: 1
      Semnal: SIGHUP
      Specificare: terminal hangup
    • Nr: 2
      Semnal: SIGINT
      Specificare: intrerupere (DEL - tasta apasata)
    • Nr: 3
      Semnal: SIGQUIT
      Specificare: quit (s-a apasat CTRL+\)
    • Nr: 4
      Semnal: SIGILL
      Specificare: instructiune ilegala
    • Nr: 5
      Semnal: SIGTRAP
      Specificare: Trace/breakpoint trap
    • Nr: 6
      Semnal: SIGABORT
      Specificare: abort
    • Nr: 7
      Semnal: SIGEMT
      Specificare: emulation trap
    • Nr: 8
      Semnal: SIGFPE
      Specificare: exceptie aritmetica
    • Nr: 9
      Semnal: SIGKILL
      Specificare: semnal kill
    • Nr: 10
      Semnal: SIGBUS
      Specificare: eroare bus
    • Nr: 11
      Semnal: SIGSEGV
      Specificare: segmentation fault
    • Nr: 12
      Semnal: SIGSYS
      Specificare: bad system call
    • Nr: 13
      Semnal: SIGPIPE
      Specificare: broken pipe
    • Nr: 14
      Semnal: SIGALARM
      Specificare: alarm clock
    • Nr: 15
      Semnal: SIGTERM
      Specificare: terminated
    Semnalele 1..9 si 15 sunt relevante pentru programatorul Shell. Celelalte apar pentru completitudine si pentru a arata ce fel de semnale pot fi manipulate de Unix.
    Observatie: de regula, semnalele sunt interceptate de apelul de sistem signal ce poate fi folosit in programe C.
    	Exemplu: fie o instructiune dintr-un program C ce face o impartire la zero:
    	printf("Impartire la zero:%d",6/0);
    	in acest caz este semnalat un SIGFPE, iar programul trebuie sa includa cod care sa receptioneze acest
    	semnal:
    	signal(SIGFPE,f_cleanup), unde f_cleanup este functia ce rezolva problema si afiseaza un mesaj corespunzator. 
    	
    O alta modalitate de interceptare a mesajelor este prin intermediul comenzii interne trap. Aceasta permite interceptarea si prelucrarea semnalelor ce ar afecta shellscript-ul intr-o maniera imprevizibila. Formatul general al comenzii este:
    		trap <comenzi> <semnale>
    	
    <comenzi> reprezinta comenzi ce se executa la aparitia unuia dintre semnale. Fie:
    $trap "rm tmp*;echo interrupt!;exit 3" 1 2
    Aceasta comanda poate inhiba intreruperile in cazul proiectarii unor interfete prietenoase cu utilizatorii. De exemplui, o interfata utilizator poate sa ignore apasarea tastelor DEL, BREAK sau CTRL+C. Urmatoarea comanda face ca semnalele respective sa fie ignorate:
    $trap "" 1 2 3 15
    Atunci cand trap este folosita pentru a ignora semnale, afecteaza toate subshell-urile. Cand trap este folosita sa ia actiune, nu le afecteaza. daca se doreste ca actiunea lui trap sa aiba efect in subshell-uri, trebuie specificat in mod explicit in fiecare subshell. Totusi, nu orice semnale pot fi ignorate; in caz contrar nu ar mai putea fi intrerupte anumite programe sub nici o forma! Exista SIGKILL care nu poate fi ignorat! Acest semnal este generat de comanda interna kill.
    	Exemplu: $kill -9 12345
    	unde 12345 este identificatorul procesului ce trebuie terminat
    	
  • [Pagina anterioara][Pagina continut][Pagina urmatoare]