#4sysadmins

Inicio » LPIC-1 Capítulo 9

LPIC-1 Capítulo 9

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

 

 

Correo electrónico

A diferencia de otros sistemas, en Linux el correo electrónico es uno de los servicios de red mas importantes. Linux hace uso del correo electrónico para muchas de sus tareas. Además de estar estrechamente ligado a las cuentas de los usuarios, el correo en Linux es utilizado por ejemplo para informar de sus actividades programadas con cron, o enviar notificaciones sobre operaciones realizadas por shell scripts, entre otras.  El servidor de correo contiene los mensajes entrantes de cada usuario, normalmente en /var/spool/mail, aunque como siempre, esto pueda variar en función de la distribución que estemos usando. Deberemos de tener un conocimiento básico sobre su funcionamiento, configuración y posibilidades (crear alias de correo, reenviar correos, configurar el correo en aplicaciones clientes, etc…).

Existen varios protocolos para administrar el correo electrónico, siendo el mas común SMTP (Simple Mail Transfer Protocol, Protocolo simple de transferencia de correo). En la mayoría de ocasiones se utiliza SMTP como sistema de entrega de correo, por estar diseñado como sistema push (el sistema emisor inicia la transferencia). No obstante en la etapa final del envío del correo se utilizan protocolos de tipo pull (el sistema receptor inicia la transferencia) como POP (Post Office Protocol, Protocolo de oficina de correos) o IMAP (Internet Message Access Protocol, Protocolo de acceso a mensajes de Internet). Estos protocolos son útiles sobre todo cuando el sistema receptor es el equipo de un usuario, el cual suele permanecer apagado en muchas ocasiones. La diferencia básica entre ambos protocolos es que con POP descargaremos los mensajes a nuestro equipo y con IMAP podremos leerlos desde el propio servidor.

 

Funcionamiento del correo electrónico

El método tradicional en Linux para enviar correo, es hacer que los programas locales se comuniquen con el servidor de correos local, quién a través del protocolo SMTP reenviará el correo hacia el destino. Los servidores SMTP son conocidos también como MTA, Agentes de Transferencias de Correos. De esta manera en caso de que el servidor de envío SMTP se encuentre offline, el correo se pondrá en cola y será enviado a sus destinos una vez que este vuelva a estar operativo. La mayoría de los clientes de correo (MUA, Agentes de usuario de correo) ofrecen la opción de contactar directamente con un servidor SMTP remoto al enviar el correo.

Un servidor SMTP puede hacer tanto de servidor (es decir recibe el correo de otro sistema) como de cliente (envía un correo a otro sistema).

El protocolo SMTP permite que un mensaje pase por un número arbitrario de ordenadores. Un usuario puede redactar un email que será enviado a su servidor SMTP local. Este servidor buscará a través de los servidores DNS el destino y una vez localizado se procederá a la entrega.

Cada servidor de la cadena de transmisión alterará el correo añadiendo un encabezado que proporcionará información sobre la ruta que ha tomado el correo. Los spammers y similares, falsifican los encabezados del correo complicando enormemente el análisis de seguimiento.

 

Configurar el correo electrónico

Aviso: Esta sección queda fuera del alcance del examen LPIC-1, aún así se cree conveniente añadir algunos comentarios o parámetros de configuración que nos permitan entendernos con un servidor de correo local, bien para enviar y recibir correos a usuarios de la misma máquina o red, o incluso hacer relay a un proveedor como gmail, de manera que podamos enviar mensajes al exterior a través de una cuenta de correos existente en un proveedor externo.

En un sistema de correo Linux totalmente funcional, probablemente se incluyan otros software. Lo normal es tener un servidor de correo saliente (push) y uno de correo entrante (pull), además de utilidades que nos ayuden a reorganizar el correo, a filtrarlo, a detener correo spam, etc…

Existen diferentes alternativas para servidores de correos de tipo push. Algunos de estos con formatos de configuración mas complejos, mientras que otros quizás estén mas orientado a proporcionar seguridad, o una configuración rápida y efectiva. Los servidores de correo mas populares en Linux son:

  • Sendmail: Durante muchos años fue el servidor de correo dominante en Internet. Es muy potente pero también difícil de configurar. Sus archivos de configuración pueden parecernos algo arcaicos.
  • Postfix: Diseñado como sustituto modular de sendmail ya que utiliza varios programas, controlando cada cual su pequeña tarea específica. Esto lo hace mas seguro y además suele ser mas fácil de configurar que sendmail. Es el servidor de correo por defecto en muchas distribuciones Linux. Será este el que usemos en los ejemplos de configuración que veremos en breves.
  • Exim: Al igual que sendmail, es un servidor monolítico pero su formato de configuración es mas sencillo por lo tanto mas fácil de configurar. Algunas distribuciones de Linux lo emplean como servidor de correo por defecto.
  • qmail: Es un servidor modular (como postfix) con la seguridad como principal objetivo. Es mas sencillo de configurar que sendmail, pero debido a su licencia, la cual complica su distribución en Linux, no se ofrece como servidor de correo por defecto.

Podemos averiguar de diferentes formas que servidor de correo instala nuestra distribución por defecto como por ejemplo mediante el comando ps o incluso mirando dentro de los directorios /usr/bin o /usr/sbin. Para ambos podemos aplicar filtros con grep como ya vimos en Capítulos anteriores. Por motivos de compatibilidad la mayoría de servidores de correo Linux incluyen un programa sendmail, por lo que este podría servir de patrón en nuestra búsqueda.

De igual modo que con el servidor push, dependiendo del modo en el que vayamos a configurar nuestra forma de recibir correos podremos optar por algunas opciones entre las que destacamos:

  • Servidores pull de correo: Los dos protocolos mas populares para este tipo de sistema son POP e IMAP y ya vimos la diferencia básica entre ellos. Algunas de las herramientas mas destacadas con las que podremos controlar la lectura del correo en nuestro Linux son: cyrus, dovecot y courier (los tres tienen su equivalente tanto para POP como IMAP).
  • Fetchmail: Si dependemos de un ISP externo para la distribución de correo, necesitaremos un programa que obtenga el correo utilizando POP o IMAP, y que después lo inserte en una cola de correo SMTP. Esta es la función principal de Fetchmail.
  • Lectores de correos: Son el último eslabón de la cadena de correo. Existen muchos y suelen venir incluidos con la aplicación cliente. Por nombrar algunos: Evolution, KMail, Thunderbird o mutt. Mientra los tres primeros son para GUI, mutt puede ser útil para leer el correo desde la línea de comando, posee una interfaz gráfica para la shell, es decir está basado en texto.

Alguna de las herramientas de las que podemos hacer uso para completar nuestro sistema de correos podrían ser:

  • d-push: Útil si queremos recuperar mediante push el correo en dispositivos móviles. Requiere de un servidor web como apache o nginx y de soporte para PHP.
  • procmail: Funciona como MDA (Mail Delivery Agent, Agente de entrega de correo). Sirve para filtrar y clasificar el correo de entrada. Permite a los usuarios definir reglas que filtren los email recibidos y realizar una serie de funciones como colocarlos en determinadas carpetas, clasificarlos, reenviarlos, etc…
  • spamassassin: Identifica el correo sospechoso o masivo añadiendo cabeceras a los mensajes de modo que pueda ser filtrados por el cliente de correo electrónico

En las dos próximas secciones abarcaremos una configuración básica para en reenvío de correo electrónico dentro de la red local o el propio sistema (algo que en muchas distribuciones viene por defecto) y como reenviar el correo a un proveedor externo. No vamos a abarcar la configuración de un servidor de correo totalmente funciona pues son muchas y diferentes configuraciones las que entran en juegos, pero para que quede una idea, podremos montar una infraestructura con:

  • Postfix quién hará de servidor SMTP enviando y recibiendo el correo
  • dovecot para recuperar el correo IMAP en aplicaciones clientes de los usuarios
  • spamassassin para controlar el spam
  • procmail para filtrar y clasificar el correo
  • d-push con el que recuperar los email en clientes móviles

Configuración básica local

Ahora que tenemos claro los conceptos vamos a proceder a configurar un servidor de correo de manera que el sistema pueda enviar y recibir email entre cuentas de usuarios, algo que en muchos sistemas viene configurado por defecto. Para ello vamos a usar Postfix como SMTP sobre la distribución Linux Mint 17.1 (derivado de Debian)

Nota: En distribuciones como CentOS o Fedora (derivados de Red Hat) este sistema viene ya preconfigurado para un funcionamiento a nivel local.

En caso de que ya tuviéramos postfix instalado (de lo contrario deberemos de buscarlo por ejemplo con aptitude search postfix, en caso de distribuciones derivadas de Debian, y posteriormente instalarlo con apt-get) pero no configurado haremos:

$ sudo dpkg-reconfigure postfix

Esto volverá a ejecutar el programa de configuración posterior a la instalación de postfix. En el se realizan una serie de preguntas a las que deberemos de responder y con estos datos se creará el archivo de configuración /etc/postfix/main.cf que en caso de tenerlo podemos ahorrarnos el pasar por esta interfaz de menú y editar el archivo directamente. Importante recargar el servicio tras su edición.

Otra manera de efectuar cambios sobre main.cf es a través de la herramienta postconf (herramienta de configuración de postfix) la cual además también nos sirve para ver el valor de los parámetros de configuración o modificarlos. Por ejemplo, para ver el valor de una directiva de main.cf  bastará con pasársela como argumento a postconf, Si queremos cambiarle su valor, lo haremos así ‘postconf -e <directiva=valor>‘. Si queremos ver el valor que trae por defecto cada directiva de main.cf bastará con pasarle el parámetro -d, o -n para listar todas aquellas que tenemos ya configuradas. Con -p  listaremos todas las directivas de configuración de postfix, tanto aquellas a las que no se les ha cambiado su valor como las que si se han modificado. Sobre-escribiremos el valor de una directiva usando -o como opción. Existe otro archivo igual de importante (o incluso mas) que configura el servidor postfix y es master.cf. Para mostrar su contenido usaremos -M,

Las preguntas a contestar (y sus respuestas para mi configuración personal básica) son:

  • Configuración base inicial: solo correo local
  • FQDN: En mi caso no dispongo de dominio así que ‘freeser‘ a secas será el nombre de mi host.
  • Alias para redireccionar el correo de postmaster y root: Yo lo redirecciono todo a mi usuario ‘nebul4ck
  • Lista de dominios separados por comas para los que actuará nuestro servidor: <ok>. Yo la dejo tal cual, básicamente con el nombre de mi host y si tuviese dominio pues lo pondría igualmente.
  • Sincronizar el correo de forma síncrona: <No>. Esto ralentiza el procesado del servicio de correo. Si tenemos un sistema de archivos con journal no tiene por que hacernos falta.
  • Configuración del bloque de red: Para enviar y recibir en equipos de la red sería algo parecido a 192.168.1.0/24 (podemos eliminar la IP IPv6 si no la vamos a utilizar). Yo dejo la que viene por defecto que es para gestionar solo el correo local (127.0.0.1/8)
  • Tamaño máximo del buzón de correo: 0 ilimitado, 51200000 el valor dado por el desarrollador. Esto no tiene que ver con la cuota de correo para cada usuario, para eso deberemos de usar el sistema de Quota Disk que ya hemos estudiado.
  • Elegir un caracter que defina la extensión de dirección local: ‘+ por defecto. Yo lo dejo en blanco.
  • Concretar el protocolo de IP a utilizar: IPv4 en mi caso

Estas preguntas y respuestas lo que hacen es añadir/modificar las siguientes líneas del archivo main.cf, con las que tendremos un sistema igualmente funcional en caso de que queramos hacerlo editando el archivo directamente:

relayhost =
myhostname = freeser
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = nombredetuequipo
mynetworks = 127.0.0.1/8
mailbox_size_limit = 51200000
inet_interfaces = loopback-only
inet_protocols = ipv4

Una vez tenemos la configuración base para postfix vamos a crear un alias para root, recordar que en los pasos anteriores creamos un alias para nuestro usuario de manera que todo el correo de postmaster y root se redirigiera a nuestro usuario, pero al parecer, según el mensaje obtenido tras la configuración: WARNING: /etc/aliases exists, but does not have a root alias. root no tiene alias por lo que deberemos de redirigir todo el correo (incluido el de postmaster) hacia root y entonces el de root será redirigido a nosotros. Para ello editamos el archivo /etc/aliases. Bastará con escribir ‘root: nuestrousuario

Nota: En la sección «Administrando el correo electrónico» veremos como crear alias y redirigir el correo.

Ahora con el archivo /etc/aliases editado, necesitaremos ejecutar el comando newaliases para crear un binario que pueda ser leído por el sistema.

Con esta configuración ya podremos enviar correos entre los usuarios del sistema local o red si hemos configurado el bloque de red de la siguiente manera:

$ mail -s "Asunto" usuariodelsistema@nombredehost

Nota: Si el prompt devolviera el típico «mail: command not found» deberemos de instalar el paquete mailutils que es donde suele encontrarse la utilidad mail.

Tras introducir esta línea nos aparece ‘cc:‘ esto es por si queremos poner en copia a alguien, si no queremos pulsamos <Enter> y a continuación el prompt esperará que introduzcamos texto. Una vez terminado pulsamos Control+D y el email será enviado.

En la sección «Administrando el correo» veremos mas opciones de mail y aprenderemos a gestionar nuestro correo.

Configuración para reenviar correo a un proveedor como gmail

En la sección anterior hemos aprendido a configurar postfix para enviar correo desde una cuenta de nuestro sistema a otra cuenta del mismo sistema u otro dentro de nuestra red local. Lo que haremos ahora será configurar un relay en postfix de manera que podamos reenviar el correo desde nuestra cuenta del sistema a una cuenta propia en un servidor de correo externo como podría ser gmail (para nuestro ejemplo) y que sea esta la que envíe el correo al destinatario. Así podremos salir a Internet fácilmente a través de un proveedor externo.

Para pasar de la configuración de correo local a hacer relay contra por ejemplo gmail las líneas a tener en cuenta y que deberíamos de agregar en caso de no existir en main.cf serían las siguientes:

  • relayhost = [smtp.gmail.com]:587
  • smtp_sasl_auth_enable = yes
  • smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
  • smtp_sasl_security_options = noanonymous
  • smtp_tls_CAfile = /etc/postfix/cacert.pem
  • default_transport = smtp
  • relay_transport = relay

Las modificaciones han sido claras. Estamos indicando que queremos hacer relay contra el servidor SMTP de gmail por el puerto 587, hemos habilitado el mecanismo de autenticación sasl indicando que archivo es el que contiene las credenciales de la cuenta que vamos a usar para hacer el relay con la opción ‘noanonymous‘, se ha referenciado el PATH para el certificado de nuestra máquina y por último se han modificado las directivas default_transpor y relay_transport, ambas con el valor ‘error‘ en nuestra anterior configuración «solo correo local«.

Por lo general suelen existir las siguientes líneas en main.cf, de lo contrario (como por ejemplo en CentOS y Fedora) deberemos de añadirla nosotros para habilitar la capa SSL/TLS:

  • smtpd_use_tls = yes
  • smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
  • smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
  • smtp_tls_policy_maps = hash:/etc/postfix/tls_policy

Volviendo a las líneas anteriores, para crear el archivo de credenciales ‘sasl_passwd‘ y hacer que postfix lo reconozca haremos lo siguiente:

1. Crear el archivo con las credenciales:

$ sudo vi /etc/postfix/sasl_passw

2. Añadimos la línea a sasl_passw con los datos de la cuenta:

[smtp.gmail.com]:587 USERNAME@gmail.com:PASSWORD

3. Cambiamos el modo de acceso del archivo a solo lectura para root:

$ sudo chmod 400 /etc/postfix/sasl_passwd

4. Indicamos a postfix que utilice el archivo de credenciales:

$ sudo postmap /etc/postfix/sasl_passwd

Con el archivo de credenciales creado y reconocido por postfix, pasamos a generar un certificado. En Linux Mint contamos con bastantes certificados preinstalados. En concreto nosotros usaremos uno de los que son válidos para gmailThawte_Premium_Server_CA.pm‘:

$ ls -lt /etc/ssl/certs |grep Thawte
 Thawte_Premium_Server_CA.pem -> /usr/share/ca-certificates/mozilla/Thawte_Premium_Server_CA.crt

Por lo que podremos generarlo de la siguiente manera:

$ cat /etc/ssl/certs/Thawte_Premium_Server_CA.pem | sudo tee -a /etc/postfix/cacert.pem

Importante: Igualmente podríamos haber creado nuestro propio certificado, algo que no será útil por ejemplo en CentOS (entre otras) donde no contamos con estos certificados preinstalados. Para crear nuestro propio certificado haremos:

# cd /etc/pki/tls/certs
# make <nombre_host>.pem

Se nos hará una serie de preguntas a las que deberemos de responder, como el País, la Ciudad o Estado, email, etc… luego ya podremos generar nuestro certificado:

# cp /etc/pki/tls/certs/<nombre_host>.pem /etc/postfix/cacert.pem

Nota: Si hemos tenido que crear nuestro propio certificado normalmente en estas distribuciones tendremos que crear un archivo /etc/postfix/tls_policy y seguir los mismos pasos realizados con el archivo /etc/postfix/sasl_passwd solo que el contenido a añadir será:

[smtp.gmail.com]:587     encrypt

Ahora, como ya sabemos, cada vez que modificamos main.cf toca recargar el archivo de configuración o incluso reiniciar el servicio, así que:

$ sudo service postfix reload | restart

Hasta aquí debe de estar todo listo para poder hacer el reenvío. Antes comentamos alguna forma de enviar un correo desde la línea de comandos con mail, aquí mostramos esta otra:

$ echo "Este es mi tercer email" | mail -s "Mi tercer" nebul4ck@gmail.com

Para ver lo que ha ocurrido como siempre visitaremos nuestro mejor amigo /var/log/mail.log o /var/log/maillog

Podremos encontrar mucha información sobre como configurar el servidor postfix en /usr/share/doc/postfix/

Los servidores de correo proporcionan una amplia variedad de opciones avanzadas para priorizar el envío de correos, aceptar mensajes por la línea de comandos, borrar mensajes específicos de la cola, depurar conexiones de correos y otras muchas opciones que no se han abarcado en esta sección por no extender en demasía el Capítulo, además de no ser el propósito de esta guía de estudios para LPIC-1.

Proteger el servidor

En esta sección no se desarrollarán métodos sobre como securizar nuestro servidor de correos, pero si alguna información importante a tener en cuenta y herramientas que pueden hacernos la vida menos complicada en lo referente a nuestro servidor de correos. Por ejemplo algo con lo que estar familiarizado deben de ser los bugs del propio servidor de correos o herramientas que usemos para dar de alguna forma asistencia o complementación a nuestro servicio de correo. Los bugs pueden poner en peligro el sistema permitiendo a alguien obtener acceso y enviar correos, o como vimos en el Capítulo anterior sobre el diagnóstico de la red, conectándose al puerto 25 (SMTP) mediante un cliente Telnet y escribiendo comandos SMTP para aprovechar la vulnerabilidad. Es por esto que muchas distribuciones de Linux reducen el acceso exclusivamente al ordenador local. Es muy importante instalar los parches que puedan surgir a raíz de bugs encontrados y actualizar el sistema constantemente.

Otro aspecto a tener en cuenta es la configuración. Deberemos de ser conocedores de que parámetros son los que estamos configurando y que valor le estamos dando. Existen configuraciones defectuosas que permiten a spammers utilizar su servidor de correos para enviar email masivos por lo que no tardarán en bloquear nuestra IP o añadirla a listas negras (blacklist). A este tipo de configuraciones se las llama open relay (transmisiones abiertas). La mayoría de distribuciones Linux configuran el servidor de manera que no permita el open relay por lo que de cierta manera podemos andar tranquilos. No obstante deberemos de revisar de que nosotros tenemos la configuración apropiada. Existen varias maneras o sitios en Internet en los que podremos comprobar esto como por ejemplo desde la web http://www.spamhelp.org/shopenrelay, o bien mediante conexión Telnet, conectando a nuestro servidor SMTP por su IP y puerto 25 y enviando comandos SMTP.

Algunas herramientas útiles de cara a la seguridad en sistemas totalmente funcionales de correo electrónico pueden ser: spamassassin (herramienta open source que utiliza una extensa serie de test o reglas tanto a nivel local como de red para identificar firmas de spam en los correos electrónicos.), smapd o greylist (ambas orientadas a reducir el correo spam).

 

Administrar el correo electrónico

Hasta aquí hemos visto algunos aspectos básicos sobre la configuración de un servidor postfix SMTP, de manera que podamos enviar y recibir correos en nuestra máquina local o aquellas que pertenecen a nuestra red, y además como reenviar correo desde nuestra cuenta del sistema hacia una cuenta en un proveedor externo (en nuestro caso gmail) para que sea esta quien entregue el correo del sistema a través de Internet. En las siguientes secciones aprenderemos un uso básico sobre la administración del correo de manera local, como el envío y lectura del correo a través de la línea de comandos, ver la cola de correo y eliminar alguno o todos los correos existente en ella, además de como redirigir el correo entre usuarios de una máquina mediante alias de correo.

Enviar y recibir correo desde la línea de comandos

Linux dispone de una amplia gama de aplicaciones de correo cliente o MUA (Mail User Agent) con las que poder administrar una cuenta. Alguna de estas pudiesen ser Geary, sistema cliente básico para principiantes, Thunderbird, Evolution y KMail, todas ellas disponibles para GUI y orientadas a usuarios mas avanzados, Zimbra, para acceder vía web. Además Zimbra es un paquete Open Source con el que podremos crear y gestionar un servidor funcional completo de correos (SMTP, POP, IMAP…) que incluye otras funcionalidades como la Agenda y el Calendario. Otro cliente con el que podremos enviar y recibir correo pero esta vez desde la línea de comandos es mutt. Mutt es un MUA que soporta protocolos como IMAP y POP para la lectura del correo, así como SMTP para la transferencia. Es bastante configurable y su interfaz está basada totalmente en texto. No obstante en esta sección nos vamos a centrar en la ya mencionada herramienta mail con la que podremos envía correo desde la línea de comandos e incluso leerlos.

La sintaxis básica de mail es la siguiente:

  •  Para enviar un correo:

mai [-v] [-s «asunto»] [-c «dirección con-copia» | -b «dirección con copia oculta»] dirección destinatario

Nota: La opción -c no trabaja en todas las versiones de mail

Anteriormente ya vimos dos formas de enviar un email, bien escribiendo la línea del comando mail la cual nos desplegará un prompt donde introducir texto y finalizar con Control+D o bien mediante el comando echo redireccionado a mail. Otras dos formas de enviar un correo serían:

1. Enviar el contenido de un archivo como correo:

mail -s "Lista de invitados para la fiesta!!" < /home/party/listainvitados.txt invitados@4sysadmins.es

2. Es igual a la opción básica pero en vez de usar Control+D para finalizar, utilizamos una palabra:

mail -s "Tareas por hacer" nebul4ck@4sysadmins.es << EOF
Aqui escribiremos todo lo que queramos
El correo terminará cuando repitamos la palabra con
la que abrimos el contenido de este email
EOF

Nota: Esta última forma es muy útil en correos enviados desde shell scripts.

  • Para leer un correo:

mail  [-v] [-f «/var/mail/<usuario>» | -u <usuario>]

Con -f indicaremos el nombre del archivo de correo de un determinado usuario o bien con -u pasamos directamente el nombre de ese usuario. Otras formas de leer el correo es desplegando el contenido del archivo de correo de un usuario mediante un paginador de archivo o cat, o bien utilizando mail de forma interactiva lo cual conseguiremos llamando a mail sin parámetros.

Cuando usamos mail de forma interactiva lo que hace es desplegar una serie de líneas de resúmenes de mensajes (un resumen de mensaje por línea) con el siguiente formato:

<nº de mensaje> <remitente> <fecha> <nº de líneas>/<nº de bytes> <Asunto>

Deberemos de prestar atención al número de mensaje pues es el que deberemos de introducir para desplegar su contenido. Posteriormente podremos eliminar el mensaje con d o responder a este con r.

Comprobar la cola de correo

El programa mailq es la principal herramienta para administrar la cola de correo. Originalmente este programa formaba parte del paquete sendmail, es por ello que usar sendmail -bp es equivalente a mailq. El comando básico (sin opciones) muestra el contenido de la cola de correo de todos los sistemas.

Podremos vaciar una cola de correos con sendmail -q, postqueue (postfix) o runq (exim). Además en postfix contamos con la utilidad postsuper con la que podremos eliminar toda la cola de correos con ‘-d ALL’ o un solo correo con ‘-d <nº de correo>

Redirigir el correo

Por regla general los servidores de correo mantienen una cuenta propietaria que en la mayoría de los casos se nombra postmaster a la que se le es enviado el correo y cuyo contenido solo debería de ser leído por el administrador del sistema (root). Existe una manera con la que el correo es direccionado o redirigido a otro usuario con el fin de que este pueda leerlo. Para hacer posible esto se cuenta con el archivo aliases que suele encontrarse bajo /etc/ o bajo /etc/mail y que posee un formato sencillo pero eficaz.

Si abriésemos este archivo veríamos una lista de líneas con un formato parecido al siguiente:

# Basic system aliases -- these MUST be present.
mailer-daemon: postmaster
postmaster: root
# General redirections for pseudo accounts.
bin: root
daemon: root
adm: root
...

Este sería el caso mas simple en el que se nombra a postmaster como mailer-daemon y seguidamente se crea el primer alias en el que el correo de postmaster será redirigido a root (postmaster: root). Las siguientes líneas (y algunas mas que faltan) por lo general lo que hacen es que el correo enviado a las cuentas de servicios o programas del sistema sea redirigido a root, de manera que el administrador cuente con la información de todos ellos. Al final de de este archivo podríamos añadir la siguiente línea:

root: nuestrousuario

con lo que estaríamos diciendo que una vez que todo el correo del sistema (servicios y programas) haya sido enviado a root, este sea su vez reenviado a nuestro usuario, con el fin de mantener un control de esta información sin llegar a ser superusuario o poseer los permisos de este.

Además de usar un nombre de usuario del sistema al que redirigir el correo, podremos utilizar un comando por el que canalizar los mensajes ( | ), el nombre de un archivo en el que se encuentran añadidos una serie de direcciones o incluso una cuenta de correo como nebul4ck@4sysadmins.es.

En la mayoría de servidores de correos es un requisito el compilar /etc/aliases a un archivo binario de manera que  pueda ser procesado mas rápidamente. Para esto usaremos el comando ya visto newaliases

Otra manera de redirigir el correo es hacerlo a nivel de usuario, es decir, editando el archivo ~/.forward del directorio principal del usuario de manera que el correo que es enviado a este, sea reenviado a otra cuenta. Para hacer esto basta con editar el archivo con tan solamente el nombre de usuario al que queremos redirigir el correo o bien una cuenta de correo electrónico completa. Este sistema tiene varias ventajas como por ejemplo, el administrador del sistema podría crear por ejemplo una cuenta ‘correos‘ y avisar a todos los usuarios del sistema que hagan el reenvío de su correo a esta cuenta, de forma que el administrador pueda tener el correo de los usuarios de una forma controlada, o bien los usuarios podrán reenviar el correo de varias de sus cuentas a una sola cuenta de usuario o correo sin tener que molestar al administrador.

 

 

Administrar datos con SQL

En las siguientes secciones hablaremos sobre el Lenguaje de consulta estructurado o SQL (Structured Query Languaje) que como su nombre indica es utilizado para obtener datos de una base de datos. Para comenzar a utilizar SQL deberemos de disponer de algún paquete de software que lo implemente. En Linux disponemos de algunos, siendo los mas habituales:

  • MySQL: Este paquete nos ofrece un servidor de BBDD, un cliente para conectar con estas y herramientas de desarrollo. Es un software en propiedad de Oracle el cual se distribuye bajo GPL. La mayoría de las distribuciones de Linux incluyen a MySQL en sus repositorios oficiales.
  • PostgreSQL: Disponible bajo licencia BSD y es una evolución del software Ingres inicial. El nombre de PostgreSQL es la compresión de Post-Ingres SQL. Al igual que MySQL, se encuentra disponible en los repositorios oficiales de las distribuciones Linux.
  • SQLite: Es una biblioteca que implementa SQL. No se trata de un gestor de BBDD independiente, mas bien un procedimiento o medio que permite a un programa almacenar datos utilizando una interfaz SQL del propio programa. Si desea escribir un programa que acceda a BBDD pero instalar un software pesado como MySQL o PostgreSQL resulta excesivo, quizás SQLite sea su solución.

 

Fundamentos de SQL

Desde LPI.org se está planteando la posibilidad de prescindir del contenido sobre gestión de bases de datos y mas concretamente de la herramienta SQL con la que acceder a BBDD relacionales. Es por ello que nos hemos extendido un poco mas en el software del correo electrónico y lo haremos de forma mas breve con respecto a SQL.

SQL permite la gestión de varias BBDD, a su vez estás están formadas por una o mas tablas construidas por filas (tuplas) y columnas (atributos o campos).

Las columnas de una base de datos contienen tipos de datos específicos, ya que no es lo mismo indicar un color (rojo) que un precio (1.99€). Usaremos los tipos de datos específicos para crear restricciones relacionadas, llamadas «dominio» o «tipo de datos«.

Algunos de estos tipos de datos son:

  • INTEGER (INT): Valor entero de cuatro bytes.
  • SMALLINT: Valor entero de dos bytes
  • DECIMAL o NUMERIC: Almacenamiento preciso de valores decimales
  • FLOAT: Número de coma flotante
  • DOUBLE PRECISION: Número de coma flotante almacenado con el doble de precisión que con el que lo hace FLOAT
  • DATETIME: Una fecha y una hora
  • DATE: Una fecha
  • TIME: Una hora en formato HH:MM:SS
  • CHAR: Uno o mas caracteres
  • VARCHAR: Un número variable de caracteres
  • ENUM: Una lista enumerada de datos como pequeño, mediano y grande
  • SET: Datos que pueden tener cero o más valores. Como para un yogurt de macedonia: fresa, plátano, melocotón y pera.

Los datos de una tabla no están ordenados, pero podremos devolver el contenido de una consulta realizada con SQL de forma ordenada y filtrada como veremos en breves.

 

Primeros pasos en una base de datos

Lo primero que debemos de hacer para aprender a utilizar SQL es tener acceso a una base de datos SQL. Nosotros en nuestro ejemplo vamos a utilizar el motor MySQL. Aquí vamos a suponer que tenemos ya instalado el paquete mysql en el que se incluye servidor, cliente y herramientas, y además lo tenemos en ejecución (esto se hace de la misma forma que el resto de servicios Linux).

Para iniciar el cliente mysql basta con llamar a mysql sin parámetro alguno. Esto nos introducirá en un prompt (mysql> ) que al igual que bash esperará a que introduzcamos comandos. Los comandos SQL se suelen escribir en mayúsculas. No es obligación pero si una forma de simplificar o clarificar la lectura de los comandos que normalmente ocupan mas de una línea. Una vez en el prompt de mysql lo primero que debemos de hacer es mostrar las bases de datos existentes. Lo normal es que no haya ninguna creada, pero mysql muy amigo nuestro nos tiene una preparada llamada test con la que podremos iniciarnos.

mysql> SHOW DATABASES;

Es importante fijarnos en como terminamos la línea de comandos. El caracter punto y coma ‘;‘ es el que indica que hemos terminado la línea de comandos, por lo que mientras que este no sea indicado se entenderá que la línea de consulta sigue abierta.

Si queremos crear una base de datos utilizaremos el comando CREATE DATABASE seguido por el nombre de la base de datos:

mysql> CREATE DATABASE animales;

Ahora podremos empezar a usar la tabla con el comando USE:

mysql> USE animales;

Como acabamos de crear la base de datos no existe ninguna tabla. Por ello vamos a crear una tabla con cuatro columnas o campos que servirán para diferenciar unas filas o tuplas de otras que iremos almacenando posteriormente. Por ejemplo:

mysql> CREATE TABLE gatos (nombre VARCHAR(30), raza  VARCHAR(20), fech_nac DATE, precio DECIMAL (4,2));

Con este comando crearemos la tabla ‘gatos‘ como hemos dicho de cuatro campos | id | nombre | raza | fecha de nacimiento | precio |, en la que los dos primeros campos usan un tipo de datos de caracter variable, es decir podrán tener un máximo de 30 y 20 caracteres respectivamente. Si hubiésemos utilizado CHAR tanto los nombres de los gatos como sus razas deberían de tener exactamente 30 y 20 caracteres respectivamente. Para la fecha de nacimiento usamos el tipo DATE y algo a tener en cuenta en el campo ‘precio‘ es que podríamos haber usado el tipo FLOAT pero sin duda para un campo en el que vamos a definir algo tan importante y exacto como es un precio, es preferible utilizar el tipo DECIMAL (mas exacto que FLOAT) con el que se indica los dígitos que irán delante de la coma (4 en este caso) y cuantos decimales tras la coma (2 para nuestro ejemplo). En otros motores de bases de datos existe el tipo MONEY pero MySQL no lo soporta.

Antes de pasar a almacenar datos en la tabla vamos a ver como mostrar las tablas que forma la base de datos:

mysql> SHOW TABLES;

Una vez localizada que tablas forman una base de datos podremos ver los campos que construyen a cada tabla. Vamos a ver por ejemplo que campos (nombre, raza, fecha de nacimiento y precio en nuestro ejemplo)  son la base de la tabla gatos.

mysql> DESCRIBE gatos;

Bueno ahora que hemos localizado nuestra base de datos, hemos creado una tabla y hemos mostrado que campos son los que finalmente hemos añadido, vamos a pasar a almacenar información dentro de estos. Para insertar una tupla en una tabla usaremos el comando INSERT INTO de la siguiente manera:

mysql> INSERT INTO gatos
-> values ('rigodón', 'europeo', '2009-02-28', 23,4);

Bueno ahora supongamos que hemos insertado un dato erróneo, por lo que vamos a actualizar los datos de la tabla con el valor correcto:

mysql> UPDATE gatos SET precio=12.99 WHERE nombre='rigodon';

Esto buscará la tupla que tiene como nombre rigodon y volverá a setear el valor de precio pero esta vez con el valor 12.99. Si existiesen mas de una tupla con nombre rigodon deberemos de añadir mas criterios de filtrado. Podemos conseguir esto con AND y OR. Por ejemplo, vamos a suponer que existen dos filas con el valor rigodon en el campo nombre pero solo una con la fecha de nacimiento 2009-02-28, para localizar esta tupla usaremos la siguiente línea:

mysql> UPDATE gatos SET precio=12.99 WHERE nombre='rigodon' AND fech_nac='2009-02-28';

Como últimos comandos a estudiar en esta sección y no por ello menos importantes son DELETE  y DROP con los que podremos eliminar algunos o todos los datos de una tabla o eliminar la tabla competa respectivamente.

Si queremos eliminar todos los datos de una tabla haremos uso del comodín ‘*‘:

mysql> DELETE * FROM gatos;

Podemos eliminar solo datos específicos así:

mysql> DELETE FROM gatos
-> WHERE raza='persa' OR precio > 21,99;

Nota: Esto eliminará toda las tuplas pertenecientes a gatos cuya raza es ‘persa‘ o tienen un precio superior a 21,99

En ocasiones lo que querremos será borrar una tabla completa (tuplas y campos) ya porque esta no sirva o porque haya tantos datos erróneos o desfasados que ya no nos interesen. En este caso usaremos DROP de la siguiente manera:

mysq> DROP TABLE gatos;

Entre las numerosas posibilidades de manipulación de datos con las que cuenta SQL tenemos la de recuperar datos de distintas tablas y combinarlos, dando como salida una única tabla con los datos necesitados. Para lograr esto, las tablas a combinar deben de tener todas ellas un campo común que pueda ser utilizado para conectarlas y además cada tabla igualmente deberá de tener un campo cuyo valor identifique inequívocamente a cada tupla. A este campo se le llama PK (Primary Key, Clave Primaria).

Antes de nada debemos de conocer el comando SELECT. SELECT nos permite realizar consultas en una base de datos. Será el comando que nos ofrezca la posibilidad de recuperar los datos de las distintas tablas para posteriormente manipularlos o simplemente obtener la información deseada.

La sintaxis básica para SELECT es la siguiente:

SELECT campo(s) FROM tabla [ WHERE condiciones ] [ ORDER BY campo ]

Vamos a recuperar todos los datos de la tabla gatos:

mysql> SELECT * FROM gatos;

Podemos seleccionar uno o varios campos de la siguiente manera:

mysql> SELECT nombre, raza FROM gatos;

Y de la misma manera que ya hemos visto podemos filtrar la consulta con WHERE y ser mas específicos con AND, OR o NOT:

mysql> SELECT * FROM gatos WHERE raza='persa' OR fech_nac>'2008-11-29' AND NOT raza='europeo';

Podemos incluso ordenar la salida por un campo en orden ascendente (ASC) o descendente (DESC). Igualmente podemos sumar (SUM) todos los valores de un campo. Esto último es útil por ejemplo si queremos sumar el precio de todas las mascotas.

mysql> SELECT raza,precio FROM gatos WHERE precio>15.99 GROUP BY precio ASC

Una vez que conocemos el uso básico de SELECT será suficiente para poder combinar la salida de por ejemplo dos tablas. Para combinar tablas podemos usar el mismo comando SELECT aunque se suele emplear JOIN. A continuación veremos un ejemplo, pero antes vamos a hacer un uso sencillo de otro de los comandos que nos ofrece SQL y es ALTER TABLE. Este comando nos permite modificar la estructura de una tabla ya existente, por ejemplo, añadir nuevas columnas o eliminar otras o bien, crear y borrar restricciones. Para ello se permite el uso de palabras reservadas como ADD (añade o modifica una columna), DROP (elimina una columna o restricciones sobre ella), UNIQUE (los datos de cada tupla de la columna serán únicos), PRIMARY KEY (esta columna hará de clave primaria para cada tupla) y CONSTRAINT (añade o elimina una restricción) . ¿ Porque comentamos esto aquí ? – pues porque si hubiésemos seguido los ejemplos que hemos ido realizando, nos daríamos cuenta (en caso de que no hayamos eliminado ya la tabla o base de datos) que cuando creamos la tabla gatos no creamos el campo/columna ‘id’ el cual nos permitirá combinar tablas con SELECT o JOIN. La sintaxis de ALTER es la siguiente:

  • Añadir una columna (para eliminarla usamos la misma sentencia pero cambiamos ADD por DROP):

ALTER TABLE <tabla> ADD [COLUMN] <nombre_columna> <tipo>

  • Añadir una columna con restricciones:

ALTER TABLE <tabla> ADD [COLUMN] <nom_column> <tipo> RESTRICCIONES

  • Añadir restricciones a una columna ya existente:

ALTER TABLE <tabla> ADD [COLUMN] RESTRICCIONES <columna>

Nota: Para eliminar una restricción usamos la sintaxis anterior pero cambiamos ADD por DROP

Antes de pasar al ejemplo que comentábamos sobre la combinación de tablas con SELECT y JOIN vamos a crear definitivamente nuestro campo id en la tabla gatos con las siguientes restricciones: el campo no podra ser nulo (NOT NULL) y nos valdrá como clave primaria (PRIMARY KEY). Será de tipo entero y con un máximo de cuatro dígitos de longitud:

mysql> ALTER TABLE gatos ADD COLUMN id INTEGER(4) NOT NULL PRIMARY KEY;

Aviso: El ejemplo anterior solo ha servidor para mostrar como crear una columna con un nombre y tipo y dos restricciones pero en la práctica obtendremos un error diciendo que no podemos hacer el campo id PK. Esto es porque al ser NOT NULL se le ha asignado el valor 0 a todos y al ser repetido es imposible que sea una clave primaria. Por ello anularemos el PRIMARY KEY, le daremos un valor diferente a cada tupla y a continuación usaremos la siguiente sentencia:

mysq> ALTER TABLE gatos ADD PRIMARY KEY (id);

Ahora que ya tenemos nuestro campo id en la tabla gatos volvamos al ejemplo de combinación de tablas:

Ejemplo: Un veterinario nos pide que saquemos los números de contacto de todos los gatos mayores de cinco años que tienen implantado el chip de reconocimiento y que además estén vacunados.

Lo primero que haremos será localizar las tablas que tengan campos en común y posean el campo PK. Además de esto las tablas deberán de tener la información de si se encuentran vacunados, si existe un número de contacto y la fecha de nacimiento. Vamos a suponer que ya hemos dado con dos tablas que nos serán útiles.

  • La tabla gatos tiene los siguientes campos: id | nombre | raza | fech_nac | precio |
  • La tabla identificación está formada por: num_chip | nombre | vacunado | contacto |

Sabemos que las PK de ambas tablas son ‘id‘ y ‘num_chip‘ y el campo común es ‘nombre‘. Para obtener la información que nos ha pedido el veterinario haremos lo siguiente:

mysql> SELECT gatos.nombre, gatos.fech_nac, identificacion.vacunado, identificacion.contacto
-> FROM gatos, identificacion
-> WHERE gatos.nombre=identificacion.nombre AND gatos.fech_nac<'2010-01-01' AND identificacion.vacunado='si';

Si queremos combinar de la misma forma pero usando JOIN solo existe la diferencia de que una tabla es especificada con FROM y la otra con JOIN:

mysql> SELECT gatos.nombre, gatos.fech_nac, identificacion.vacunado, identificacion.contacto
-> FROM gatos
-> JOIN identificacion
-> WHERE gatos.nombre=identificacion.nombre AND gatos.fech_nac<'2010-01-01' AND identificacion.vacunado='si';

Y hasta aquí todo lo relacionado con la administración de bases de datos. Ha sido un mini tutorial pero como ya indicamos al principio de la sección, este contenido puede quedar obsoleto con respecto a la certificación LPI-1


 

Capítulo 9

 

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.


3 comentarios

  1. […] script está bastante comentado ya que se creó como ejercicio de práctica del Capítulo -9 El entorno de Consola, Shell Scripts, el Correo Electrónico y uso básico de SQL. Podemos descargarlo […]

    Me gusta

  2. […] motivo de estas tres entradas es poner en práctica los conocimientos obtenidos en el Capítulo 9 – El entorno de consola, shell scripts, el correo electrónico y uso básico de SQL de la guía de estudios para LPIC-1 400, así como la creación de usuarios Capítulo 7 – […]

    Me gusta

  3. […] LPIC-1 Capítulo 9. Administrar y configurar el entorno de consola, desarrollo de Shell Scripts (Variables, expresiones condiciones, funciones), Configurar servidor de correo electrónico y SQL […]

    Me gusta

Deja un comentario, Gracias!