Sistema Operatiu Linux
Unitat: Programació del Shell
Contingut:
1- Creació de nous comandaments
2 - Paràmetres en els comandaments
3 - Utilitzar la sortida de programes
com a paràmetres del nostre programa
4 - Variables de l'entorn
|
1- Creació
de nous comandaments
|
-
Quan tenim una sèrie de comandaments que utilitzem sovint es convenient
agrupar los sota un nom apropiat de forma que obtenim un nou comandament.
-
Per exemple, si sovint volem contar els usuaris que estan connectats escriurem:
$ who | wc -l
-
Per crear un nou comandament equivalent primer de tot crearem un fitxer
de text anomenat cu (de Contar Usuaris) que contingui l'ordre anterior:
$ echo 'who | wc -l' > cu
-
Observeu que les cometes són obligatòries. Què obtindríem
si no les posem? En el fitxer cu quedaria el nombre d'usuaris connectats
en comptes de l'ordre de comptar usuaris.
-
Recordem ara que el shell és un programa que s'està executant,
i el seu nom és bash (shell per defecte). Com és un
programa, es pot executar i redireccionar la seva entrada.
-
Per exemple, podem executar el shell redireccionant la seva entrada (que
per defecte és el teclat) per tal de que sigui el fitxer cu:
$ bash < cu
El resultat serà el mateix que si haguéssim teclejat
who
| wc -l des del terminal.
-
D'altre banda el shell admet paràmetres, igual que ho fan molts
comandaments. Si escrivim:
$ bash cu
obtindrem el mateix resultat, doncs bash pren la seva entrada
d'un fitxer si se'l passa com a paràmetre.
-
Per executar un fitxer de text que conté comandaments, com ara cu,
tenim un altre alternativa que és convertir-lo en executable:
$ chmod +x cu
-
Un fitxer executable que conté comandaments del shell s'anomena
fitxer
d'script del shell o abreviada ment script. Aleshores el podrem
executar directament:
$ cu
-
Tal com ho tenim ara cu funcionarà només si està situat
en el directori de l'usuari i si aquest directori està en la variable
d'entorn PATH. Per fer que funcioni de forma general podem moure'l al nostre
directori privat bin i després afegir el camí a la variable
PATH:
$ cd
ens situem al nostre directori personal
$ mv cu bin
movem cu al nostre directori bin
$ PATH=$PATH:/home/usuari/bin
afegim el nostre bin al camí de cerca
$ echo $PATH
comprovem que s'ha afegit correctament
-
Els usuaris d'un script l'executen de la mateixa forma que els altres comandaments
i per tant no tenen forma de saber que només conté una simple
instrucció, en comptes de ser un complicat programa escrit en 'C'.
-
La forma en que el shell executa un script és creant un nou procés
de shell (un subshell) exactament igual que si escrivim $bash
cu
-
Per tant bash cu no és el mateix que bash < cu,
malgrat el resultat sí ho sigui. En el segon cas no es crea cap
subshell.
|
2 - Paràmetres
en els comandaments
|
-
La majoria de comandaments dels shell admeten paràmetres i opcions.
Es interessant que els comandaments que nosaltres creem tinguin també
aquesta possibilitat.
-
Per exemple volem crear un comandament anomenat fx per fer que un fitxer
sigui executable, de forma que sigui equivalent escriure:
$ fx cu
a escriure:
$ chmod +x cu
-
Necessitem un fitxer de text que contingui l'ordre chmod. Ja sabem
com fer-ho això. El que no sabem és com indicar a fx
quin serà el nom del fitxer que farem executable, doncs aquest serà
diferent cada cop que executem fx.
-
Quan shell executa un fitxer de comandaments, cada ocurrència de
$1
es reemplaça per el primer paràmetre, cada ocurrència
de $2 es reemplaça per el segon paràmetre, i així
successivament fins el paràmetre $9.
-
Per tant escriurem en el fitxer fx el text chmod +x $1. Veiem
el següent exemple:
$ cd; cd bin
ens situem en el nostre directori bin personal
$ echo 'chmod +x $1' > fx
crea el comandament fx
$ bash fx fx
el fa executable
$ echo echo "Hola mon" >hola
creem el comandament de proves hola
$ hola
provem hola: no funciona encara
hola: command not found
$ fx hola
fem que hola sigui executable
$ hola
tornem a provar-lo
-
Hi tenim també casos en que el nombre de paràmetres és
variable, és a dir que de vegades no donarem cap paràmetre
en utilitzar el comandament i d'altres en donarem un o més d'un.
Per aquests casos tenim l'abreviatura $* que significa "tots els
paràmetres". Podríem definir aleshores el comandament fx
així:
chmod +x $*
-
Exemple: definim el comandament cl per comptar les lineas d'un o
més d'un fitxer:
$ echo "#cl: compta el nombre de lineas en els fitxers especificats"
> cl
$ echo 'wc -l $*' >>cl
$ fx cl
$ cl /home/usuari/bin/*
-
La primera sentencia crea una línia de comentari en el fitxer cl,
identificada per el prefix #. En la segona línia afegim (símbol
>>)
la instrucció de comptar líneas. En la tercera donem drets
d'execució al fitxer cl i en l'ùltima el provem comptant
les líneas de tots els fitxer del nostre directori
bin. També
funcionarà el següent exemple en el qual no usem cap paràmetre:
$ ls /home/usuari/bin | cl
En aquest cas comptarà quants fitxers hi han en el directori
/home/usuari/bin, doncs ls mostra els fitxers que hi han, els
quals es prenen com a entrada del programa cl, el qual compta el
nombre de lineas del fitxer d'entrada, és a dir, el nombre de fitxers
que proporciona ls.
-
El símbol $0 està reservat per el propi nom del programa
en execució. Per exemple si afegim la següent línia
al fitxer cl:
echo echo === fi execució de $0 === >>cl
i l'executem, veurem que surt al final del nombre de lineas
del fitxer la frase:
==== fi execució de cl ====
-
També podem passar paràmetres que no siguin noms de fitxers.
Per exemple considerem el fitxer agenda:
Pere Pages 977-33-44-00
Joan Pages 977-33-50-00
Marta Pages 977-58-00-00
-
Podem usar grep per buscar en ell. Creem un comandament busca
que cerca qualsevol nombre de textos en aquest fitxer i provem-lo:
$ echo 'grep $* /home/usuari/agenda' >busca
$ fx busca
$ busca Pere
Pere Pages 977-33-44-00
$ busca Pages
Pere Pages 977-33-44-00
Joan Pages 977-33-50-00
Marta Pages 977-58-00-00
$ busca 'Pere Pages'
grep: can't open Pages
-
Ens trobem un problema a l'executar $ busca 'Pere Pages' i
es que s'interpreta com si haguéssim escrit $ grep Pere Pages
/home/usuari/agenda que està malament doncs pren Pages
com un nom de fitxer. Això és així degut a l'espai
en blanc que conté la cadena que busquem. Hauríem de passar
tota la cadena 'Pere Pages' com un únic paràmetre
per a grep. La solució serà modificar el comandament busca:
$ echo 'grep "$*" /home/usuari/agenda' >busca
-
Ara el $* serà reemplaçat per els paràmetres com abans,
però aquests es passaran a grep com un únic paràmetre
malgrat tinguin espais en blanc.
PRÀCTICA: Creació de
comandaments i pas de paràmetres
|
3 - Utilitzar
la sortida de programes com a paràmetres del nostre programa
|
-
La sortida de qualsevol programa pot utilitzar-se en un comandament tancant
el programa amb cometes invertides (l'accent obert català: ` `).
-
Exemple:
$ echo Data i hora actual `date`
Data i hora actual Sun Dec 31 12:00:00 CET 2000
-
Les cometes invertides poden anar també incloses dintre de les cometes
dobles:
$ echo "Data i hora actual `date`"
-
Un altre exemple: volem enviar un mail a una llista d'usuaris els noms
dels quals estan en un fitxer de text anomenat llista. El text del
mail està en un altre fitxer anomenat carta. Podem fer-ho
de la següent forma:
$ cat llista
comprovem el contingut del fitxer llista
nom1
nom2
nom3
$ mail `cat llista` < carta
enviem la carta als usuaris de la llista
cat mostra el contingut del fitxer llista, és
a dir la llista de noms, que es converteixen en paràmetres per a
mail
gràcies a l'ús de les cometes ``. Es com si haguéssim
escrit:
$mail nom1 nom2 nom3 <carta
-
En efecte, quan el shell interpreta la sortida en cometes inverses com
a paràmetres tracta als salts de línia com a separadors de
paraules.
PRÀCTICA: La sortida de programes com a paràmetres
4 - Variables de l'entorn
|
-
El shell proporciona el manteniment del que s'anomena variables de l'entorn
-
Són cadenes de caràcters que representen valors que defineixen
l'entorn de treball
-
Hi han variables d'entorn predefinides del sistema i pròpies de
l'usuari
-
Podem modificar els valors de qualsevol d'elles (en algunes cal tenir prou
privilegis)
-
Existeixen moltes variables predefinides que depenen de cada sistema
-
Les variables s'indiquen de la següent forma (sense espais):
VARIABLE=valor
-
El nom de la variable pot ser qualsevol cadena de caràcters que
no comenci per un número ni contingui el caràcter $ ni espais
en blanc.
-
El valor pot ser qualsevol cadena, incloent espais. Si conté espais
cal tancar la cadena entre cometes dobles ("")
-
Exemples:
$MIVAR="prova variables"
-
Assigna la cadena "prova variables" a la variable MIVAR. Normalment posem
el nom de les variables d'entorn en majúscules per distinguir-les
dels noms de fitxers i comandaments.
-
Podem veure el contingut de la variable amb:
$echo $MIVAR
-
Mostrarà el contingut de la variable MIVAR. És obligatori
col·locar el signe $ davant del nom.
-
Més exemples:
$XYZ="cat fitxer"
$ $XYZ
-
Aquesta seqüència fa que assigni una ordre a una variable.
Després s'executa invocant el nom de la variable. Podem utilitzar-ho
per abreviar ordres llargues i d'ús freqüent.
export
-
Cada variable es defineix en el Shell actiu. Si canviem de Shell (per exemple
creant un subshell) la variable deixa d'existir. Podem provar-ho amb la
variable XYZ:
$sh
arranca un subshell
$echo $XYZ
no mostra res
-
En aquesta seqüència creem un subshell (sh) i cridem
a la variable XYZ que ara estarà buida. Per tornar a l'anterior
shell:
$exit
$echo $XYZ
-
Per poder disposar de la variable en tots els shells, cal exportar-la:
$export XYZ
$sh
$echo $XYZ
-
Aquest exemple d'exportació només és vàlid
si es fa des del shell principal. No podem exportar des d'un subshell al
seu superior (proveu-ho).
env
-
Mostra la llista completa de les variables d'entorn actualment definides.Algunes
variables bàsiques són: PATH, LOGNAME, etc.
set
-
Permet també veure les variables d'entorn fins i tot algunes que
no apareixen amb env perquè són utilitzades per el
propi shell. Per exemple la variable PS1 que representa el "prompt".
$PS1="Linux:"
-
Farà aparèixer el prompt Linux:
Acotació d'arguments en les variables d'entorn
-
El Shell interpreta una cadena de caràcters que contingui espais
en blanc com múltiples arguments. Per exemple:
$NOMVAR=prova variables
-
Donarà error perquè interpreta dos arguments: prova queda
assignat a la variable d'entorn i el segon l'intenta executar com si sigues
un comandament.
-
Això ho sol ventem acotant la cadena entre cometes dobles:
$NOMVAR="prova variables"
-
No obstant les variables d'entorn contingudes dintre de les cadenes acotades
també són interpretades per el shell. Per exemple:
$MEUNOM="El meu nom d'usuari es $LOGNAME"
$echo $MEUNOM
-
Resultat: El meu nom d'usuari és a0alumne
-
Si volem que el shell no interpreti la variable cal acotar la cadena amb
cometes simples:
$MEUNOM='El meu nom d'usuari és $LOGNAME'
$echo $MEUNOM
Més coses sobre variables
-
Si volem afegir més camins de cerca a la variable PATH:
$PATH=$PATH:nous camins
-
Per combinar el contingut d'una variable amb constants:
$VAR=hola
$echo ${VAR}s
-
Resultat: holas, mostra el contingut de la variable seguida de la
constant. Es diferent que fer:
$echo $VARs
que mostraria el valor de la variable VARs, si existeix.
-
Podem avaluar el valor d'una variable i prendre una decisió segons
el valor:
$echo ${BUSTIA:-valor2}
-
Si la variable BUSTIA existeix mostrarà el seu valor. En
cas contrari mostra valor2 sense assignar res a la variable.
$echo ${BUSTIA:=valor2}
-
Si la variable BUSTIA existeix mostrarà el seu valor. En
cas contrari mostra valor2 i aquest valor s'assignarà a la
variable.
unset
-
Serveix per esborrar el valor d'una variable:
$unset NOMVAR
-
Equivalentment podem fer:
$NOMVAR=
Pràctica 10: Variables del
shell
Utilitzar variables dintre de fitxers script: pas per valor i per
referència
-
Hem vist que el valor d'una variable no es passa automàticament
als subshells. Això implica que un comandament creat per nosaltres
no podrà canviar el valor d'una variable doncs els fitxers scripts
són executats per un subshell.
-
Exemple:
$ echo ´X="Adeu"
Creem un fitxer script de dues lineas per a definir i mostrar X
> echo $X´ >setx
$ cat setx
Comprovem el contingut
$ X=Hola
Definim la variable X
$ bash setx
Executem l'script
Adeu
X conté Adeu en el subshell
$ echo $X
Hola
X continua valent Hola en el shell original
-
Quan passem variables de l'entorn a un fitxer script ho podem fer de dues
formes:
-
Passar només el valor de la variable, però sense que l'script
pugui modificar la variable. Diem que el pas de la variable es fa per valor.
-
Donar a l'script l'accés complert sobre la variable. Diem que passem
la variable per referència.
-
Quan exportem (amb export variable) les variables que l'script necessita
estem fent un pas de variables per valor. Exemple:
$ export X
donem accés al valor d'X per a tots els subshells
$ bash
arranquem un subshell
$ echo $X
mostrem el valor d'X
Hola
$ X=Adeu
modifiquem en el subshell el valor d'X
$ echo $X
mostrem el nou valor en el subshell
Adeu
$ exit
tornem al shell original
$ echo $X
mostrem de nou X
Hola
el valor torna a ser l'original, no s'ha canviat
-
El shell proporciona el comandament ' . ' (un punt) que força l'execució
de l'script en el propi shell en comptes de pasar-ho a un subshell. Això
equival a donar a l'script l'accés total sobre la variable (pas
per referència). Exemple:
$ . setx
Executem l'script setx en el shell actual
Adeu
X conté Adeu durant l'execució de l'script
$ echo $X
Adeu
X ha estat modificat per l'script
-
Quan utilitzem el punt per executar un script el que realment succeeix
es que l'entrada estàndard del shell (el teclat) es redirecciona
temporalment per prendre-la del fitxer script. Realment l'script no s'està
executant, i per tant no necessita tenir permisos d'execució.
-
Hi ha un altre forma de passar només el valor d'una variable del
shell a un script (pas per valor) a banda d'usar export que es asignar-li
el valor en la mateixa línia en la que cridem a l'script. Per exemple:
$ echo 'echo $X' > veureX Creem un script
$ chmod +x veureX
Donem permís d'execució a l'script
$ X=Hola veureX
Inicialitzem X i cridem a l'script en una mateixa línia d'ordres
Hola
La variable X val Hola durant l'execució sense haber-la exportat
-
Utilitzarem l'execució amb el punt quan volem modificar permanentment
el valor d'una variable i utilitzarem les assignacions en la mateixa línia
que l'script o bé l'exportació quan les modificacions siguin
temporals (només tenen efecte dins de l'script).
PRÀCTICA: Ús de variables en fitxers script