LinuxParty

Inicio desactivadoInicio desactivadoInicio desactivadoInicio desactivadoInicio desactivado
 

EN ESTE CAPÍTULO SE ABARCAN LOS SIGUIENTES OBJETIVOS DEL EXAMEN:

  • 105.1: Personalizar y utilizar el entorno de la consola (4)
  • 105.2: Programar shell scripts (4)
  • 108.3: Funcionamiento y configuración del correo electrónico (3)
  • 105.3: Administración básica de datos SQL (2)

 

El entorno de Consola, Shell Scripts, el Correo Electrónico y uso básico de SQL

Administrar el entorno de la consola

En el Capítulo 1 “Herramientas básicas para la línea de comandos Linux” vimos las consolas mas comunes para entornos Linux, como se exportaba una variable, diferencia entre comandos internos y externos a la shell, y alguna que otra característica del empleo del modo comando. Durante el Capítulo 7 “Administrar el sistema” aprendimos como crear un entorno para un usuario y que archivos eran los que definirían sus características, archivos que dependían en gran medida del directorio /etc/skel (comúnmente llamado directorio esqueleto). Vimos que este directorio contenía aquellos archivos con los que de algún modo queríamos preconfigurar o proporcionar una configuración local base para un entorno de usuario. Vamos a repasar brevemente estos archivos puesto que a continuación veremos en cual de ellos deberemos de modificar datos dependiendo de donde queremos que tomen efectos, bien de forma local y aislada para un usuario, o de forma global, lo que afectará a todos los usuarios del sistema.

Nota: Un usuario individual puede invalidar aquello que se configure de modo global, mediante la edición de los archivos que configuran su entorno, por lo que no es recomendable usar los archivos de configuración global para determinar aspectos sobre la seguridad del sistema.

Los archivos de configuración del entorno pueden clasificarse de la siguiente manera:

conf_entor

 Entonces, explicando brevemente la tabla anterior, diríamos que si queremos configurar el diseño de un prompt que afecte a todos los usuarios del sistema, deberíamos de definir la variable PS1 en el archivo /etc/bashrc (o /etc/bash.bashrc, dependiendo de la distribución) que es el archivo que contiene el valor para PS1. De este modo el prompt cambiará tanto si accedemos en un modo de ejecución de consola como si accedemos en un runlevel gráfico y posteriormente abrimos una terminal, pero… ¿Por qué también si accedemos directamente en un modo de solo consola si es /etc/profile el que se ejecuta y no /etc/bashrc? – Porque si nos fijamos en el contenido de /etc/profile veremos que llama a /etc/bashrc y entonces este setea el prompt para el usuario.De este modo a menos que comentemos las líneas de /etc/profile en las que se llama a /etc/bashrc en ambos casos el prompt cambiará y además de forma global.

 Si lo que queremos es que el nuevo valor de la variable PS1 solo afecte a un determinado usuario y además únicamente cuando abre una terminal desde el entorno de escritorio, es decir el prompt no cambiaría si accedemos en un modo de ejecución de modo consola, tendremos que definir la variable PS1 en el archivo ~/.bashrc del usuario en cuestión y además tendremos que comentar las líneas de ~/.bash_profile (o ~/.profile dependiendo de la distribución) en las que se llama a ~/.bashrc. De lo contrario el prompt cambiará esta vez solo para ese usuario, pero en ambos casos, es decir, tanto si el usuario accede directamente desde el modo consola como si lo hace desde el entorno gráfico a través de una terminal virtual.

 Nota: Dependiendo de la distribución podremos o no encontrarnos con el archivo ~/.bashrc. De todos modos podremos crearlo nosotros en /etc/skel de manera que cuando creemos un nuevo usuario, este ya cuente con el archivo.

Al igual que las consolas poseen scripts de inicio, puede que también cuenten con scripts de desconexión o logout. Estos scripts como suponemos, se ejecutan cuando el usuario se desconecta. El script ejecutado normalmente es ~/.bash_logout el cual puede ejecutar programas para limpiar los directorios temporales, eliminar claves de seguridad de la memoria o realizar otras tareas que incluso nosotros mismos hayamos programado para que sean ejecutadas.

Advertencia: Debemos de comprobar que es lo que realiza este script o si hemos programado algunos comandos para que sean ejecutados al desconectar, deberemos de tener en cuenta, que cabe la posibilidad (muy frecuentemente) que tengamos mas terminales del mismo usuario abiertas, por lo que si cerramos una y se ejecuta el script puede que eliminemos archivos que estamos usando en otras terminales, o simplemente no queremos que sean eliminados hasta que la última sesión sea cerrada.

Otro archivo de configuración de bash es ~/.inputrc. Este archivo sirve para personalizar la configuración del teclado. La sintaxis básica de las líneas del archivo es:

combinación_de_teclas: acción_a_realizar

Si tenemos la sensación de que determinadas combinaciones de teclas no funcionan como deberían funcionar en modo texto, es aconsejable investigar la configuración de este archivo.

Nota: La configuración de archivo ~/.inputrc no afectará a los programas que se ejecuten en X, aunque sean programas en modo texto que se ejecuten dentro de ventanas Xterm.

Sobre la variable PS1

 Hacer un pequeño inciso para comentar el valor de la variable PS1. La variable PS1 como hemos mencionado, define el aspecto del prompt por ejemplo, para un prompt estándar el aspecto sería el siguiente:

nebul4ck@LiMinCinn ~ $

Lo que indica que el usuario es nebul4ck, el equipo se llama LinMinCinn, nuestro directorio de trabajo actual es nuestro home (~) y el caracter $ nos identifica como usuario estándar (# para root). En este caso la variable PS1 tendría el siguiente valor:

PS1='\u@\h \W \$ '

Disponemos de las siguientes variables del sistema para modificar esto:

  • Indicar la fecha del sistema: \d
  • El nombre del la máquina: \h
  • El shell que utilizamos: \s
  • El nombre del usuario activo: \u
  • La versión del bash: \v
  • El directorio de trabajo: \w
  • El número de histórico del comando ejecutado: \!
  • Indicar $ para usuario estándar y # para root: \$

Definir variables y alias de comandos

Los scripts de bash que acabamos de recordar y otros nuevos que hemos mencionados sirven como hemos visto para configurar un entorno, pero para ello se necesitarán comandos que ejecutar y construir una cierta lógica que permita al archivo realizar determinadas acciones. A continuación vamos a ver como declarar una variable de entorno y un alias de comando en un shell script y dejaremos para la próxima sección el estudio de funciones y estructuras de las que nos serviremos para programar un script en bash.

Recordemos también que las variables de entorno proporcionan los medios para pasar datos mediante nombres a programas iniciados desde una consola. Quizás un programa necesite conocer el nombre del ordenador, es por ello que existe una variable (y si no existe podremos crearla y exportarla para nuestro entorno en los archivos de inicio de consola anteriormente estudiados) llamada $HOSTNAME. Vamos a imaginar que esta variable no existiese en nuestro entorno y un programa de terceros señala en su documentación que el programa necesitará del valor de la variable $HOSTNAME, el cual debe de ser el nombre del equipo que ejecuta el comando. Pues bien para definir esta variable de entorno, editaríamos el archivo ~/.bash_profile (o ~/.profile) declarando la variable de la siguiente manera:

HOSTNAME=freeser
export HOSTNAME

Nota: Si el valor de la variable contiene espacios es obligatorio encerrarlo entre dobles comillas.

En la primera línea declaramos la variable $HOSTNAME y en la segunda convertimos a la variable local en variable de entorno de manera que en cuanto el script de inicio sea ejecutado, esa variable estará disponible para cualquier programa.

Cuando exportamos una variable directamente desde la línea de comandos, el valor de esta solo estará disponible para la terminal desde la que ha sido exportada, anulándose su valor en cuanto cerremos la sesión o en cualquier otra terminal virtual.

Podemos hacer que una variable sea de solo lectura anteponiendo la palabra ‘readonly‘ al nombre de la variable, de manera que su valor no pueda ser modificado pero si visualizado hasta que el proceso que hace uso de ella (un script, un determinado shell o sesión…) haya finalizado, es decir, en teoría una variable que se ha modificado para solo lectura no puede ser modificada ni eliminada hasta que el proceso que la utiliza finalice.

Cuando definamos una variable en un shell script, no será necesario exportarla, si no que la definiremos y posteriormente el programa irá haciendo uso de ella conforme se vaya necesitando. Una variable debe de empezar por una letra o un guión bajo ‘_‘ pero no por un número. A este tipo de variables simples se les conoce como escalares (scalar)

Podemos ver el valor de una variable concreta desde la línea de comandos así:

$ echo "$HOSTNAME"

Nota: Fijémonos en la importancia de preceder el nombre de la variable con el signo ‘$‘, algo que no se debe de hacer cuando se declara o define.

Si lo que queremos es ver todas las variables definidas para un entorno utilizaremos el comando env. Este comando dispone de un par de opciones útiles pero para listar todas las variables bastará con invocarlo sin parámetro alguno:

nebul4ck@LiMinCinn ~ $ env
SSH_AGENT_PID=1872
TERM=xterm
SHELL=/bin/bash
USER=nebul4ck
USERNAME=n0name
LOGNAME=nebul4ck
PWD=/home/nebul4ck
HOME=/home/alberto
LANG=es_ES.UTF-8
...

Nota: La salida del comando env ha sido cortada ya que suele ser bastante extensa.

Podemos definir una variable para un único programa con env de la siguiente manera:

$ env DISPLAY=freeser.4sysadmins.es:0.0 nedit

Nota: En la mayoría de los casos podremos omitir el comando env

Esto provocará que el programa nedit intente iniciar usando la pantalla :0.0 en freeser.4sysadmins.es en lugar de la pantalla local predeterminada o definida en la variable $DISPLAY

Si queremos comenzar con un entorno vacío es decir, ignorando el entorno heredado, acompañaremos a env del parámetro -i (–ignore-environment) y para anular el valor de una variable específica usamos -u <nombre_variable> o –unset=nombre_variable.

Antes vimos como mostrar el valor de una variable mediante el comando echo. Otra forma de hacerlo con env sería así:

$ env | grep NOMBRE_VARIABLE

Para terminar con las variables de entorno vamos a presentar una lista de las que quizás sean las más conocidas o nos vayan a ser mas útiles:

  • USER o USERNAME: Nombre de usuario actual
  • SHELL: Contiene la ruta a la consola de comandos en uso
  • PWD: Esta variable la mantiene el sistema y su valor es el directorio de trabajo actual. Por ello puede ser utilizada por programas para buscar archivos cuando no se proporciona la ruta completa.
  • HOSTNAME: Como ya vimos anteriormente, esta variable contiene el nombre del equipo de trabajo
  • PATH: Es una variable cuyo valor es lo suficientemente importante como para abrir una brecha de seguridad. Su cometido es contener rutas de directorios separados por el caracter ‘:‘, por ejemplo PATH=/bin:/sbin:/usr/bin:/usr/sbin:/home/nebul4ck/bin, este valor indicaría donde buscar archivos ejecutables, de manera que el usuario pueda ejecutar aquellos programas que se encuentran bajo estas rutas (sea cual sea su directorio de trabajo), ahorrando la necesidad de escribir ./archivo_ejecutable. Se recomienda no añadir la ruta ‘.‘ (directorio actual) al valor de esta variable, especialmente para el usuario root ¿Porqué? – Un usuario malintencionado podría crear en un directorio que solemos frecuentar un programa llamado por ejemplo ‘ls‘ de manera que cuando root invoque a ls en el directorio donde se encuentra el programa malicioso, este sea ejecutado en vez de el comando ls del sistema. En el caso de que sea necesario para un usuario normal, deberemos de colocar esta ruta al final del valor de la variable PATH
  • HOME: El valor de esta variable es la ruta de nuestro directorio principal, y al igual que la variable PWD, puede ser utilizada por programas
  • MAIL: Su valor es la ruta del buzón de correo del usuario en cuestión, que suele ser /var/spool/mail/nombreusuario
  • LANG: Utilizada para guardar el idioma actual
  • TZ: Indica la zona horaria que tenemos configurada o podemos emplearla precisamente para eso, para configurar nuestra zona horaria en caso de que estemos usando un ordenador remoto
  • LD_LIBRARY_PATH: Indica los directorios en los que los programas pueden encontrar archivos de bibliotecas. Es similar a PATH pero en vez de ejecutables son librerías
  • PS1: También hemos visto ya la función de esta variable, la cual define el prompt del sistema
  • TERM: Indica la terminal en uso.
  • DISPLAY: Otra variable ya vista, identifica la pantalla utilizada por X que suele ser :0.0. Este valor puede ir precedido del nombre de un host remoto o cambiar a :1.0 por ejemplo si tenemos dos sesiones de X abiertas (:0.0 para la primera sesión y :1.0 para la segunda).
  • EDITOR: El editor de texto iniciado por defecto será aquel que conste en el valor de esta variable.

Igual que definimos las variables podemos definir los alias de comandos, pero… ¿Que son o para que sirve? – La principal ventaja de utilizar alias de comandos es la de crear una versión acortada de un comando,  para que cada vez que queramos que un comando actúe de determinada manera no tengamos que escribirlo de forma completa. Vamos a ver esto con un ejemplo sencillo:

Supongamos que cuando ejecutamos ls -l, el listado que nos devuelve el comando es un listado de directorios y archivos sin color, es decir el mismo color utilizado para las letras de la consola. Cabe la posibilidad de listar el contenido de un directorio de forma que los archivos sean mostrado en diferentes colores, para que a simple vista reconozcamos de que tipo de archivo se trata, por ejemplo verde para ejecutables, azul para directorios, celeste para enlaces simbólicos, rojo con fondo negro para enlaces rotos, amarillo con fondo negro para archivos de caracter, etc… ¿y como conseguimos esto? – Para hacer que cada vez que ejecutemos el comando ‘ls’ a secas despleguemos un listado en formato de una sola columna (con los permisos, propietario, fecha, etc..) en color y ordenado por fecha descendente, haremos lo siguiente:

$ alias ls='ls -lt --color'

Así de sencillo es crear un alias.

Nota: Para utilizar este alias de forma persistente podremos definirlo en alguno de los archivos de inicio de consola. Dependiendo si queremos que sea aplicado de forma global o local elegiremos uno u otros archivos.

Los Arrays

Un array o vector es una variable que tiene asignado un conjunto de valores a los cuales podemos acceder mediante su número de posición, el cual nos sirve como índice de valores. Podemos definir un array de la siguientes maneras:

  • Múltiples valores de forma simultánea:
$ array=(ford renault "mercedes benz" dacia vw bmw)
  • De uno en uno:
$ array[0]=ford
$ array[1]=renault
$ array[2]="mercedes benz"
...

Nota: Los indices no necesariamente tienen que ser numéricos, por ejemplo sería válido también definir los valores del array tal que así: $ array[primero]=ford, $ array[segundo]=renault, etc…

  • Igualmente podemos añadir un nuevo valor al array:
$ array[6]=chevrolet

Para consultar todos o un valor específico del array:

  • Consultar un valor concreto:
$ echo ${array[1]}
renault
  • Mostrar todos los valores:
$ echo ${array[*]}
ford renault mercedes benz dacia vw bmw chevrolet
$ echo ${array[@]}
ford renault mercedes benz dacia vw bmw chevrolet

Programación de shell scripts

Ahora que ya sabemos ejecutar comandos desde la terminal o desde un script de inicio (la forma de hacerlo es la misma), sabemos declarar variables y crear alias, vamos a estudiar la forma de crear un script ejecutable que sea reconocido por el shell y realice una serie de tareas en base a estructuras lógicas (expresiones condicionales), bucles y funciones.

Antes de comenzar ha crear un script, los cuales son archivos de texto plano, por lo que podremos hacerlo mediante un editor de texto corriente, debemos de saber algunas características básicas. A estas alturas no es una sorpresa saber que la consola bash es la mas utilizada en entornos Linux, al menos es la que viene por defecto en la gran mayoría de distribuciones, por lo que algo normal puede ser programar un script de consola para bash. No obstante un script de consola bash puede ser ejecutado en tcsh y otros lenguajes de programación de consola, a menos que el script utilice funciones muy específicas de una consola concreta (en este caso bash).

La línea shebang o hashbang

Shebang o hashbang es el nombre con el que se conoce a la primera línea por la que está formado un script de consola (shell script de ahora en adelante), aunque también recibe otros nombres como hashpling o poundbang. Antes de mostrar el formato de esta línea es interesante saber que a través del caracter ‘#‘ podremos escribir líneas dentro de un shell script las cuales no serán ejecutadas aunque si interpretadas por el kernel. Dicho esto pasamos a mostrar el contenido de esta primera línea del shell script:

#!/bin/bash

Está línea esta formada por el caracter de comentario, por el signo de exclamación ‘!‘ y por una ruta. Los dos primeros caracteres forman un código que le indica al kernel de Linux que se trata de un script y que utilice el resto de la línea como ruta al programa que va a interpretar el script, bash en nuestro ejemplo.

Nota: Es posible encontrar la ruta a otro interprete o incluso a /bin/sh que en la mayoría de las veces no es mas que un enlace simbólico a la consola de la distribución, por lo que de esta manera nos aseguramos de que el shell script va a ser interpretado. No obstante como comentamos antes, si tiene funciones muy específicas de una consola concreta, mejor indicar a esta.

Ejecutando un shell script

Cuando finalizamos la programación de un shell script, llega el momento de ejecutarlo para ver sus resultados. Existen diferentes formas de ejecutar un script cada cual con su debida implicación:

  • Establecer con chmod los permisos de ejecución. Usaremos u para el usuario, g para el grupo o a para todos:
$ chmod a+x myshell.sh

Nota: Las extensiones como ya sabemos no son necesarias en Linux pero si identificativas.

  • Utilizando el programa de la consola seguido del nombre del script. Se recomienda utilizar la forma del ejemplo anterior, aunque esto puede ser útil si no hemos conseguido modificar los permisos con chmod:
$ bash myshell.sh
  • Ejecutar el shell script con el comando exec. Si ejecutamos un programa a través de exec este tomará el control del proceso de la terminal desde el que ha sido invocado y una vez finalice el script o programa ejecutado la terminal se cerrará. Esto puede ser útil en determinadas ocasiones aunque no es muy utilizado, por ejemplo cuando un script llama a otro y este a su vez a otro y así… De esta manera el nuevo toma el control del proceso del anterior. Puede ser un método útil para controlar los recursos dedicados a la ejecución de una seríe de script.
$ exec /opt/myshell.sh

Podemos hacer la prueba ejecutando por ejemplo nuestro editor de texto desde la consola. Veremos que cuando cerremos el editor la terminal virtual será igualmente cerrada:

$ exec nedit

El comando exec lo estudiamos en el Capítulo 1 concretamente entre los comandos “Redirecciones y Canalizadores

  • Otra forma de ejecutar un script es aplicarle source. Para ello se utiliza el propio comando source o el caracter ‘.‘ tal que así:
$ source myshell.sh
$ . myshell.sh

De este modo el script se ejecuta en la consola actual y no se inicia una instancia nueva de la consola, como sucede cuando se ejecuta un shell script introduciendo su nombre o utilizando el comando exec (que si que inicia una instancia nueva aunque esta controle a la terminal desde la que se ha ejecutado). Existen ciertas ventajas a la hora de ejecutar un script con source, por ejemplo, si queremos que el script haga uso de las variables de entornos definidas en la consola (aunque no se hayan exportado) desde la que se ha ejecutado, este deberá de ser llamado con source.

Nota: Por lo general, sólo las variables de entorno que se hayan exportado de forma explícita, estarán disponibles para los script que se ejecuten.

Esto pasa igualmente si un script que ha sido ejecutado de forma digamos ‘convencional‘ y en el se definen ciertas variables que se usarán a lo largo del programa. Si en un punto de este programa llamamos a otro script y queremos que este haga uso de esas variables, este nuevo script deberá de ser llamado con source.

Otra ventaja de ejecutar con source un script es que si este establece variables de entornos, estás estarán disponibles para la consola desde la que se ha invocado al script. Esto es lo que ocurre cuando se inicia una terminal y /etc/profile o ~/.bash_profile llaman a /etc/bashrc o ~/.bashrc respectivamente. Si nos fijamos en estos script de inicio de consola veremos que se ejecutan así:

 if [ -f /etc/bash.bashrc ]; then
 . /etc/bash.bashrc
 fi

Esto produce que el entorno creado por profile pueda ser utilizado e incluso modificado por bashrc

También, ejecutar un script de esta manera evita la sobrecarga asociada a iniciar nuevas consolas, que aunque suele ser imperceptible, podría requerir de recursos si este script llamara de forma normal a múltiples scripts secundarios generando cada uno una nueva instancia de consola.

Otro dato y como último apunte, es interesante saber que al ejecutar un script con source se ejecuta en el idioma de la consola que realiza la invocación, mientras que al ejecutar un script de la forma normal, se usa el lenguaje de consola especificado en la línea hashbang.

Uso de variables en los shell scripts

Ya hemos estudiado como definir una variable de entorno y exportarla para que esté disponible en el entorno local o global de los usuarios. Las variables de los shell scripts suelen utilizarse para facilitar la modificación de estos en un futuro. Los shell script pueden usar variables que hayan sido pasadas como parámetros, definidas internamente, extraídas del propio entorno del script o pasándoselas a petición del propio script

Cuando llamamos a un shell script bastará normalmente con escribir su nombre (si se encuentre dentro de alguno de las rutas que contiene el path), ejecutarlo con ./nombre_script.sh, con el programa de consola (bash nombre-script.sh) o pasándoselo a source (source nombre-script.sh ó . nombre-script.sh). Sea cual sea la forma de ejecutarlo podremos escribir tras el nombre una serie de palabras a las que se le denominan argumentos de programa y de las que este hará uso durante su ejecución. Para el siguiente ejemplo el valor de la primera palabra podremos recuperarla desde dentro del script con $1, el valor de la segunda palabra con $2 y así sucesivamente hasta $9. La variable $0 indica el nombre del propio script:

$ ./myscript.sh Juán 24 Madrid

Hola me llamo Juán, tengo 24 años y vivo en Madrid.

Para recibir este mensaje tras la ejecución del script bastaría con que myscript tuviese el siguiente contenido:

#!/bin/bash
echo "Hola me llamo $1, tengo $2 años y vivo en $3"

Importante: Podemos recuperar el número de parámetros pasados al comando mediante la variable $#, con $* recuperamos todos los parámetros sin incluir a $0 (muestra su valor, no el número), con $$ podemos conocer el PID que ha creado nuestro script y con $? recuperamos el código de retorno del último comando ejecutado.

El comando shift desplaza los parámetros, de modo que lo que es $2 se convierte en $1, $3 pasaría a ser $2 y así sucesivamente, menos $0 que no es alterado. Podríamos usar shift junto con un bucle para examinar los parámetros que son pasados a un script.

Como siempre mediante un ejemplo lo veremos mas fácil. Supongamos que hemos ejecutado la siguiente línea:

$ ./miscript.sh uno dos tres cuatro y cinco

Y que el contenido de myscript.sh es:

#!/bin/bash
echo "El número de parámetros es: $#" \\ Esta línea desplegará un 5
echo "Los valores de los parámetros son: $*" \\ El valor que despliega esta línea es uno dos tres cuatro cinco
shift 3  \\ Con el comando shift indicamos que ahora el parámetro primero sea $4, pues hemos hecho que empiece inmediatamente después de la tercera posición
echo -e "Ahora que hemos usado shitf 3 el parámetro 1 es: $1 y el parámetro 2 es: $2 \\ Esto devuelve: cuatro cinco
echo "Ahora el número de parámetros es: $#" \\ Pues el número de parámetros ahora es: dos (cuatro cinco)

 Para definir una variable dentro del script basta con escribir nombre=valor:

MYVAR="Este es mi valor"
$ echo "$MYVAR"
Este es mi valor

Podemos concatenar variables así:

YO="Soy Juán"
años=" y tengo 24 años"
Todo="$YO$años"
echo "$Todo"
Soy Juán y tengo 24 años

También podemos hacer que valga la salida de un comando. Para esto deberemos de rodear el comando con acentos graves tal que así:

COMANDO=`ls -l | cut -d" " -f1`
echo -e "$COMANDO\n"
total 
lrwxrwxrwx 
drwxr-xr-x 
lrwxrwxrwx 
...

Nota: El parámetro -e de echo como ya sabemos por el Capítulo 1, hace que se interpreten los caracteres especiales en este caso \n inserta un salto de línea.

Otras formas de utilizar variables es a través del entorno donde se está ejecutando el script o que sea este quien nos pida que la introduzcamos.

  • Usando variables del propio entorno: Si sabemos que nuestro entorno (y si no lo sabemos lo comprobamos con echo “$VARIABLE”) está utilizando una variable (por ejemplo $HOSTNAME) podremos hacer uso de ella dentro del script y será reconocida, o bien si definimos como hemos hecho en el método anterior ciertas variables y luego llamamos con source a otro script dentro de este script que contiene a las variables, el segundo script (el que es llamado) podrá hacer uso de estas variables igualmente.
  • El script nos pide que introduzcamos un valor: Podemos hacer que el propio script sea quien nos pregunte por algún valor que almacenará para utilizarlo como variable dentro de su contenido. Podríamos conseguir esto con el comando read de la siguiente manera:
#!/bin/bash
echo "Introduzca un nombre sin apellidos: "
read nombre
echo "Introduzca una edad: "
read edad
echo "Introduzca su ciudad de nacimiento: "
read ciudad
echo -e "\nHola me llamo $nombre, tengo $edad años y nací en $ciudad \n"

Aritmética con variables

Si queremos realizar operaciones aritméticas en el shell (algunos shell antiguos cono sh no soportan esto) podemos utilizar el siguiente formato:

$((expresión))

Expresión estará formado por cualquier valor numérico específico, variables que contengan valores numéricos y operadores.

$ echo $((b=a*2))
$ b=$((a*2))

Esto desplegará el resultado de ‘b‘ que será el valor que contenga la variable ‘a‘ multiplicado por dos. Tenemos que prestar atención a como declaramos la variable dentro de la expresión, que como vemos no se antepone el signo ‘$‘, esto es porque el shell reconoce que al no ser un operador o valor numérico se trata de una variable. Si la variable no está previamente definida o su valor no contiene un valor numérico se le autoasigna el valor 0.

Algunos operadores aritméticos:

+    suma
*    mutiplicación
–    resta
/    división entera
%    resto de la división entera
( )  agrupar operaciones. Al igual que en matemáticas esto fuerza a que el grupo sea resuelto en primera instancia

Uso de expresiones condicionales

La expresión condicional literal:

Si el valor de X es menor que el valor de Y, haz esto

Si el valor de X es igual a Y, entonces haz esto, o si no haz esto otro

Si esto es verdadero y esto otro no lo es, haz esto, si esto no es verdadero o esto si lo es, haz esto, y si no es ninguno haz esto otro

podríamos representarlo de la siguiente manera:

Si hablamos de dígitos:

if [ "$X" -lt "$Y" ]
then
         echo "El valor de X es $X y es menor que el valor de Y que es $Y"
fi

Si lo que se comparan son cadena de caracteres:

if [ "$COCHE1" == "$COCHE2" ]
then
          echo "El coche1 es de la misma fábrica que coche2. La fabrica es Ford"
else
          echo "La marca de los coches no coinciden"
          exit 0
fi

Podemos alargar la estructura así:

if [ "$a" -eq "$b" ] && [ "$COCHE1" != "$COCHE2" ]
then
          echo "A y B son iguales, y además coche1 y coche2 son distintos"
elif [ ! -f "$archivo" ] || [ $(($1*$2)) -eq "$c" ]
then
          echo "No existe el archivo $archivo ó A es igual a B
else
          echo "Ninguna de las condiciones anteriores se cumplen"
          exit 0
fi

Nota: Podemos crear una estructura if a partir del comando test o incluso usarlo únicamente para recuperar el valor de retorno de un comando y utilizarlo luego:

if test $n -le $N
then
          echo "El número $n es menor o igual que $N"
fi
test -d /home/nebul4ck
if [ "$?" -eq "0" ]
then
          echo "El directorio principal existe"
fi

Para terminar con if debemos de saber que podemos anidar diferentes if siempre y cuando los cerremos todos debidamente, por ejemplo:

if [....]
then
      if [....]
      then
            .......
      else
            if [....]
            then
                  .......
            fi
      fi
else
      .........
fi

Test condicionales con if:

-d fichero : cierto si fichero existe y es un directorio
-e fichero : cierto si fichero existe, independientemente del tipo que sea
-f fichero : cierto si fichero existe y es un fichero normal
-r fichero : cierto si fichero existe y se puede leer
-s fichero : cierto si fichero existe y tiene tamaño mayor que cero
-w fichero : cierto si fichero existe y es se puede escribir sobre él
-x fichero : cierto si fichero existe y es ejecutable

Condicionales de dígitos:

n1 -eq n2 : cierto si los enteros n1 y n2 son iguales
n1 -ne n2 : cierto si los enteros n1 y n2 no son iguales
n1 -gt n2 : cierto si el entero n1 es mayor que n2
n1 -ge n2 : cierto si el entero n1 es mayor o igual que n2
n1 -lt n2 : cierto si el entero n1 es menor que n2
n1 -le n2 : cierto si el entero n1 es menor o igual que n2

Condicionales para cadena de caracteres:

s1 = s2 : cierto si las cadenas de texto s1 y s2 son idénticas
s1 != s2 : cierto si las cadenas de texto s1 y s2 no son idénticas

Nota: Podemos aplicar el signo de exclamación ‘!‘ a las condicionales de dígitos o de test de archivos para negar

s1 > s2 : cierto si la cadena de texto s1 es mayor que s2
s1 < s2 : cierto si la cadena de texto s1 es menor que s2
-n cadena : cierto si la longitud de la cadena de texto es distinta de cero

Condicionales con expresiones:

! expresion : cierto si expresion es falsa (negación)
expresion1 -a expresion2 : cierto si expresion1 y expresion2 son ciertas
expresion1 -o expresion2 : cierto si expresion1 o expresion2 son ciertas

Referencias:

http://blackshell.usebox.net/pub/shell/taller_sh/x214.html

Nota: Con && indicamos que se ejecute el siguiente comando en caso de que la ejecución del anterior haya sido correcta (ls -lt && echo “Listado del directorio”) o bien implicamos a que la condición sea verdadera solo si se cumplen todos los requisitos (como ya vimos en uno de los ejemplos anteriores). Con || estamos diciendo que si el último comando dió error, se ejecute el siguiente ( mkdi /opt/notfound || echo “El comando no está bien escrito y falló” ) o bien la condición será cierta si uno u otro de los requisitos es verdadero. Esto también lo vimos en un ejemplo superior.

Existe otra instrucción con la que podemos usar el valor de una variable o expresión y ejecutar una acción solo en el caso de que el valor o expresión coincidan con un patrón. Esta estructura es case:

case palabra in
      patrón1) comando(s);;
      patrón2) comando(s);;
esac

Los patrones se pueden ampliar utilizando comodines y reglas de expansión. Además es posible incluir una condición por defecto, es decir, en el caso de que palabra no coincida con ningún patrón, se ejecute una determinada acción. Esto lo conseguimos utilizando un * como patrón por lo que deberá de ir como última opción, de lo contrario se ejecutaría siempre.

Los bucles for, while y until

Los bucles son estructuras que le indican al script que realice la misma tarea repetidamente hasta que se cumpla (o hasta que deje de cumplirse) una determinada condición.

for

El bucle for se ejecuta una vez para cada elemento que pasamos (variable, lista de nombres, salida de un comando…). Cada elemento se le asigna como valor en cada iteracción o turno a una variable con la que se realizarán diferentes acciones. Veamos esto con un ejemplo:

for i in negro blanco azul
do
          echo "El color es $i"
done

Existe un comando muy útil a utilizar con for que nos permitirá crear una lista de número en función del o los parámetros que le pasemos. Puede usarse para generar un número y compararlo con otro y actuar de una determinada forma o compararlo con un parámetro pasado al script etc… se trata del comando seq y su sintaxis es seq(x [y z])

  • Si pasamos un solo parámetro a seq (for i in `seq 10`) se generará una lista de números que comenzará con 1 y terminará en el número indicado, 10 en nuestro caso.
  • Si pasamos dos parámetros a seq (for i in `seq 5 10`) se generará una lista de números que comenzará en 5 y terminará en el 10 para nuestro ejemplo. Esto es útil si queremos ir creando un sumatorio de $i con respecto al valor anterior.
  • Por último cabe la posibilidad de pasar tres parámetros como parámetros tal que así : for i in `seq 2 4 14` . El primer parámetro (2) indica el número por el que se comienza, el segundo parámetro indica el incremento (4) y el tercer y último parámetro indica el número final a mostrar. Nuestro ejemplo mostraría la siguiente columna de números (aquí la representamos en fila): 2 6 10 14

Nota: En estos ejemplos hemos usado la variable i pero podemos pasar cualquier palabra para usar luego como variable.

while

While es otro tipo de bucle que se ejecuta mientras la condición que le pasemos sea cierta. Es útil para comprobar la veracidad de reiteradas condiciones. Su forma básica es la siguiente:

while [ condición ]
do
          comandos
done

Un ejemplo del bucle while en el que se ejecutará una acción mientras n sea menor o igual a 10:

n=1
while [ "$n" -le 10 ]
do
          echo "$n"
          ((n++))
done

until

Para terminar con los bucles comentar until, que es igual que while pero al contrario, es decir, se ejecuta hasta que la condición sea verdadera. Su sintaxis es igual a la de while.

En este caso, a diferencia de while vamos a ejecutar una acción hasta que n sea mayor o igual a 11. El resultado es el mismo al del ejemplo anterior con while pero se interpreta al contrario:

n=1
until [ "$n" -ge 11 ]
do
        echo "$n"
        ((n++))
done

Existen tres comandos que nos pueden resultar útiles cuando trabajamos con bucles y estos son: break, continue y exit.

  • break : Termina el bucle. Si existe un bucle dentro de otro, break provoca que salga del bucle desde el que fue llamado pero no del bucle padre de este.
  • continue : Salta o continua con la siguiente iteracción del bucle en el momento en el que es llamado, es decir, no termina el bucle.
  • exit : Termina la ejecución del script. Suele usarse con el valor 0 o 1 como parámetro para devolver un código de retorno del propio script por si tuviese que ser evaluada su ejecución.

select

El bucle select nos permite mostrar un menú de forma fácil y poder interactuar con él. Es común el uso de select junto a case de manera que se nos presente un menú y en función de la opción elegida hagamos coincidir esa opción (patrón) con uno de las posibilidades de case y ejecutar una acción. Con el siguiente ejemplo veremos esto fácilmente:

select i in listado home backup quit
do
        case $i in
               listado) ls -lt /opt/archivos;;
               home) cd ~/; echo "Moviéndonos al directorio home...";;
               backup) tar -cpvzf ~/backup.tar.gz /opt/archivos/*;echo "Realizando backup de /opt/archivos...";;
               quit) echo "Saliendo del programa...";exit 0;;
        esac
done

 

Las funciones

Las funciones son muy útiles en la creación de shell script debido a que pueden ahorrarnos muchas líneas de código repetidas a lo largo del script. Podría definirse función como una parte del script que realiza una subtarea específica y que puede ser invocada por su nombre desde otra parte del script. La condición para usar una función es que siempre preceda a la palabra que lo llama. Esto hace que en numerosas ocasiones tras definir las variables de un script, se definan las funciones y a continuación se desarrolle el script, de manera que al ir leyendo linea a línea, cuando se llame a una función por su nombre el script se desplazará hacía la parte superior para llamar a la función, realizará las acciones pertinentes y volverá a la línea donde fue llamada con el valor de retorno. Vamos a ver esto con un ejemplo. Vamos a llamar una función a la que además se le va a pasar un argumento, esto no es necesario pero si útil en muchos casos. Para crear un ejemplo sencillo bastaría con no pasarle ningún parámetro:

retorna_valor() {
       if [ -d "$directorio" ]
       then
                 echo "El directorio $directorio existe"
       else
                 echo "El directorio $directorio no existe"
       fi
}

echo "Vamos a comprobar si existen una serie de directorios"

for directorio in "/home/a.coslada" "/home/p.merino" "/home/r.garcia"
do
          retorna_valor "$directorio"
done

  Notas del autor:

 

Licencia Creative Commons
Curso LPIC-1 400 Capítulo 9 por nebul4ck se distribuye bajo una Licencia Creative Commons Atribución-NoComercial-CompartirIgual 4.0 Internacional.

Pin It

Escribir un comentario


Código de seguridad
Refescar



Redes:



 

Suscribete / Newsletter

Suscribete a nuestras Newsletter y periódicamente recibirás un resumen de las noticias publicadas.

Donar a LinuxParty

Probablemente te niegues, pero.. ¿Podrías ayudarnos con una donación?


Tutorial de Linux

Filtro por Categorías

Nos obligan a moslestarte con la obviedad de que este sitio utiliza Cookies. Ver política