| Programación en shell: Administración de linux: Una guía básica | ||
|---|---|---|
| Anterior | Ejecución y agrupación de órdenes | Siguiente |
Otra situación algo más elaborada que la anterior es ejecutar una orden condicionada a la terminación correcta o no de una orden previa.
Esta funcionalidad nos la proporcionan los operadores "&&" y "||".
El primer operador, "&& " separa dos órdenes de forma que la que tiene a la derecha sólo se ejecuta cuando la de la izquierda termina correctamente, es decir
orden1 && orden2
|
orden2 sólo se ejecutará si orden1 terminó sin ningún error.
Por ejemplo, queremos ejecutar la orden cat fichero sólo si existe fichero; entonces tendremos que buscar una orden que termine con un error si no existe fichero, por ejemplo ls fichero y condicionar la ejecución de cat fichero a esta:
$ ls fichero && cat fichero
|
Otro ejemplo, para compilar los controladores de dispositivos de linux e instalarlos, lo podemos hacer como:
make module && make modules_install
|
es decir instalará los controladores sólo si ha conseguido compilarlos correctamente.
El segundo operador, "|| " tiene un comportamiento similar al anterior, separa dos órdenes de forma que la que tiene a la derecha sólo se ejecuta cuando la de la izquierda termina incorrectamente, es decir
orden1 || orden2
|
orden2 sólo se ejecutará si orden1 terminó con algún error.
Por ejemplo si no existe fichero queremos crearlo vacía y si existe no hacemos nada. Igual que en el ejemplo anterior, buscamos una orden que termine con un error si no existe fichero y condicionamos la ejecución de la orden touch fichero al error de la orden previa:
$ ls fichero || touch fichero
|
También, al igual que en el ejempo anterior podríamos hacer que si el proceso make modules falla, se borraran todos los ficheros temporales que se crean:
make modules || rm -r *.o
|
Otra posibilidad de ejecución también posible es lanzar varios procesos simutáneamente en segundo plano; basta escribir uno a continuación de otro en la línea de órdenes separados por "&". Este es el símbolo que se utiliza para indicar que el proceso se tiene que ejecutar en segundo plano, pero también actúa como separador para la ejecución de distintas órdenes.
por ejemplo :
[pfabrega@port pfabrega]$ sleep 10 & sleep 20 & sleep 15 &
[pfabrega@port pfabrega]$ ps axu
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.2 1408 540 ? S 22:19 0:04 init [3]
...
pfabrega 1263 0.3 0.2 1624 516 pts/4 S 23:24 0:00 sleep 10
pfabrega 1264 0.0 0.2 1624 516 pts/4 S 23:24 0:00 sleep 20
pfabrega 1265 0.0 0.2 1624 516 pts/4 S 23:24 0:00 sleep 15
pfabrega 1266 0.0 0.3 2732 848 pts/4 R 23:24 0:00 ps axu
|
Podemos organizar la ejecución de varias órdenes agrupándolas convenientemente mediante paréntesis para modificar el orden predeterminado de ejecución. En primer lugar actúan los ; después los & y la ejecución es de izquierda a derecha. Para las ejecuciones condicionales se tiene en cuenta el valor de la variable $? que se fija por la última orden que se ejecuta.
Para alterar esta forma de ejecución podemos utilizar los paréntesis. En realidad los paréntesis fuerzan una nueva subshell para ejecutar las órdenes correspondientes.
Esta característica puede ser interesante en diferentes situaciones:
Quemos enviar una secuencia de órdene s a segundo pláno
(mkdir copiaseg; cp -r ./original/* ./copiaseg; rm -r ./original~; rm -r ./original.tmp) &
|
Resultado de la ejecución de una orden
Es habitual necesitar almacenar el resultado de la ejecución de una orden en una variable en lugar de que se dirija a la salida estándar o simplemente ejecutar como orden el resultado de otra orden.
Las comillas invertidas consideran una orden lo que tengan dentro y lo ejecutan devolviendo el resultado como líneas de texto a la shell. Por ejemplo:
$ A="ls /bin"
$ `echo $A`
arch consolechars ed igawk mount rpm tar
ash cp egrep ipcalc mt rvi tcsh
ash.static cpio ex kill mv rview touch
awk csh false ln netstat sed true
basename date fgrep loadkeys nice setserial umount
bash dd gawk login nisdomainname sfxload uname
bash2 df gawk-3.0.6 ls ping sh usleep
bsh dmesg grep mail ps sleep vi
cat dnsdomainname gtar mkdir pwd sort view
chgrp doexec gunzip mknod red stty ypdomainname
chmod domainname gzip mktemp rm su zcat
chown echo hostname more rmdir sync
También podríamos haber puesto:
$ A="ls /bin"
$ B=`$A`
$ echo $B
arch ash ash.static awk basename bash bash2 bsh cat chgrp chmod chown consolechars cp cpio csh date dd df dmesg dnsdomainname doexec domainname echo ed egrep ex false fgrep gawk gawk-3.0.6 grep gtar gunzip gzip hostname igawk ipcalc kill ln loadkeys login ls mail mkdir mknod mktemp more mount mt mv netstat nice nisdomainname ping ps pwd red rm rmdir rpm rvi rview sed setserial sfxload sh sleep sort stty su sync tar tcsh touch true umount uname usleep vi view ypdomainname zcat
|
La shell bash proporciona el operador $() similar a las comillas invertidas. Ejecuta como orden los que haya entre paréntesis y devuelve su resultado. El mecanismo de funcionamiento es idéntico, con la ventaja de poder anidar operadores.