Scripts shell útiles en cualquier programa

Bash es un programa informático cuya función consiste en interpretar órdenes. Está basado en la shell de Unix y fue escrito para el proyecto GNU siendo el intérprete de comandos por defecto en la mayoría de las distribuciones de GNU/Linux. Su nombre es un acrónimo de Bourne-Again Shell (otro shell bourne), haciendo un juego de palabras (born-again significa renacimiento) sobre el Bourne shell (sh), que fue uno de los primeros intérpretes importantes de Unix.

Hoy vamos a mostrar algunos scripts de shell que pueden ser de gran utilidad para los desarrolladores. La mayoría funcionan en cualquier shell de Unix, aunque algunos requieren que sean ejecutados específicamente por Bash.

Evitar que usuarios sin privilegios ejecuten el script

Algunos scripts realizan tareas administrativas por lo cual podríamos querer que solo el usuario root ejecute el script. En ese caso podemos usar algo como esto:

#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "Este script debe ser ejecutado por el usuario root" 1>&2
exit 1
fi

Permitir la ejecución del script solo a un usuario específico

De manera similar al código anterior, podríamos querer que solo un usuario específico ejecute el script. Lo hacemos así:

#!/bin/bash
AUTHORIZED_USER="usuario_permitido"
if [ $USER != $AUTHORIZED_USER ]; then
echo "Este script debe ser ejecutado por el usuario $AUTHORIZED_USER" 1>&2
exit 1
fi

Verificar que un servicio/proceso se está ejecutando

Si queremos saber si existen procesos de algún servicio o programa ejecutándose podríamos usar este script (en este caso verifica que el demonio de Apache esté corriendo):

#!/bin/sh
SERVICE='httpd'
if ps ax | grep -v grep | grep $SERVICE > /dev/null
then
echo "El servicio $SERVICE esta ejecutandose"
else
echo "Chanfle! El servicio $SERVICE esta detenido"
fi

Crear un archivo de bloqueo

A veces debemos asegurarnos que el script no se ejecute dos o más veces simultáneas. Para ello podemos hacer uso de los archivos de bloqueo. Esta es una versión sencilla de un script que nos permite hacer esto:

#!/bin/bash
lockfile=/var/lock/loquesea.lock
if [ ! -e $lockfile ]; then
touch $lockfile
echo "hago muchas cosas importantes aqui"
rm $lockfile
else
echo "ya hay otro proceso corriendo"
fi

En este caso, se verifica que el archivo loquesea.lock exista. En caso de que exista, el script NO ejecuta sus tareas. Si no existe, crea el archivo, ejecuta las tareas que deba ejecutar y lo elimina. Pero, esto no es del todo fiable. ¿Qué pasaría si mientras nuestro script se está ejecutando es cerrado abruptamente?

En ese caso el archivo de bloqueo no se borraría, y por lo tanto, no nos permitiría ejecutar el script de nuevo. Para cubrir esos casos, podríamos hacer uso del comando trap que nos permite ejecutar comandos en caso que nuestro script termine de manera inesperada. Esta es una versión más avanzada que además guarda dentro del archivo de bloqueo el PID del script que lo ejecuta:

#!/bin/bash
lockfile=/var/lock/loquesea.lock
if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null;
then
trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
echo "hago muchas cosas aqui tranquilamente"
rm -f "$lockfile"
trap - INT TERM EXIT
else
echo "Ya hay otro proceso de este script ejecutandose"
echo "corriendo con el PID: $(cat $lockfile)"
fi

Entendamos un poco mejor el comando trap. La sintaxis del mismo es básicamente esta: trap comando signal [signal …]; donde signal es la señal de terminación que quieres atrapar. Si quieres ver una lista de los signals disponibles puedes ejecutar el comando kill -l. Para el caso anterior se usaron los signals INT (captura la terminación producida por un Ctrl+c), TERM (terminación producida por el comando kill) y EXIT (terminación normal de un script, bien sea porque ya no hay más líneas que ejecutar o porque se encuentra con el comando exit).

Menú de opciones

Para hacer un menú en donde permitimos al usuario seleccionar una serie de opciones podemos usar el siguiente esquema:

#!/bin/bash
clear
while :
do
echo " Escoja una opcion "
echo "1. quien soy?"
echo "2. cuanto espacio tengo"
echo "3. que es esto?"
echo "4. Salir"
echo -n "Seleccione una opcion [1 - 4]"
read opcion
case $opcion in
1) echo "este eres:";
whoami;;
2) echo "tienes esto";
df;;
3) uname -r;;
4) echo "chao";
exit 1;;
*) echo "$opc es una opcion invalida. Es tan dificil?";
echo "Presiona una tecla para continuar...";
read foo;;
esac
done

Pedir confirmación antes de ejecutar un script

A veces es útil hacer que el usuario confirme la ejecución de un lote de sentencias, es decir, el típico mensaje que pide al usuario escribir yes o no. Esto lo podemos hacer así:

#!/bin/bash
while true; do
echo
read -p "esta seguro de hacer lo que sea que vaya a hacer " yn
case $yn in
yes ) break;;
no ) exit;;
* ) echo "por favor responda yes o no";;
esac
done
echo "si se ejecuta esto es que aceptaste"

Fin del artículo. Sencillamente genial 😀

Edito: Hay que tener cuidado con los espacios y tabulaciones, que por algún motivo, no me están saliendo ¬¬


22 comentarios

  1.   KZKG^Gaara dijo

    Joder están geniales O_O … ayudará un montón a mis cosillas que hago en Bash 😀

  2.   ren434 dijo

    Estan super los scripts !que gran aporte en serio¡ justo lo que andaba buscando.

    PD: El foro esta caído.

    1.    KZKG^Gaara dijo

      Sí, el servidor donde está montado el foro está offline, ni idea del por qué… le escribimos un email al amigo que se encarga de eso, a ver qué nos responde 🙂

      Saludos.

  3.   ren434 dijo

    Ah bueno esperemos que no sea nada grave.

  4.   zurdo dijo

    ¿Ese “chanfle” también estaba incluido en Code Ninja? XD

  5.   taregon dijo

    Me gusta el poder del bash 😉 y eso que me decían que para que servía el lenguaje C…, pues en shell script hay muchos comandos familiares.

  6.   Christopher dijo

    Gracias, me gustaron mucho

  7.   angelblade dijo

    La validación de los parámetros de entrada es muy útil. No sabia como hacer los menús =)

  8.   Hyuuga_Neji dijo

    Genial…. ahora puedo darle algo de “dureza” a mis churros de scripts jejeje

  9.   raven dijo

    Un gustazo ver como nuestro humilde trabajo en CodeNinja sirve de algo a la comunidad internacional de linux

    1.    KZKG^Gaara dijo

      Claro! 🙂
      Todo sea por ayudar y aportar entre todos, y no por crear flames ¿o no? 😉

  10.   diego dijo

    El script de proceso que esta corriendo podrias mejorarlo un poco poniendo la opcion para elegir el proceso del cual queres saber, quedaria algo asi:

    #!/bin/bash
    echo “Elija un servicio”
    read SERVICE
    #SERVICE=’mysql’
    if ps ax | grep -v grep | grep $SERVICE > /dev/null
    then
    echo “El servicio $SERVICE esta ejecutandose”
    else
    echo “El servicio $SERVICE esta detenido”

  11.   Jua Carlos C dijo

    Muy practico sus scripts, pero ando buscando un script en especial para resolver un problema que tengo que es el siguiente: Tenemos en la Compañia un servidor de aplicaciones que los usuarios internos acceden a el por telnet, y ejecutan una aplicacion en especial que esta limitado por licencias, los usuarios abusan y abren mas de un telnet para adueñarse de 2 o mas licencias, entonces el script que he pensado es que por algun metodo revise que proceso telnet esta inactivo por mas de 2 horas y por consiguiente envie un kill a ese pid, me podria ayudar?

    1.    diego dijo

      Instala el siguiente programa

      aptitude install autolog

      Y el archivo de configuracion lo tenes en /etc/autolog.conf

  12.   Tito dijo

    Genial, amigo, puedo hacerte una consulta, necesito un script shell con opciones y lo he basado en el tuyo y va genial, pero una de las opciones tiene que enviar correos (usando postifix), pide por pantalla asunto, texto y destinatarios y lo envia y comprueba que se envie correctamente, con el mailq puedo ver la cola y ver si se envio, ¿pero como envio los correos por comando usando las variables que recibieron asunto,texto y destinatarios? 🙁

    1.    KZKG^Gaara dijo

      Escríbeme a mi email (kzkggaara[at]desdelinux[dot]net) para hablar con más calma, te ayudo con mucho gusto 🙂

      1.    Tito dijo

        Genial gracias amigo, te pasaste!

  13.   Fer dijo

    Hola, buenos.
    Me he encontardo con estos excelentes ejemplos justo cuando necesitaba un menu.
    Me he puesto a ello y no consigo hacerlo funcionar (en los pasos previos).
    Tengo 247 elementos, que se refiren a los distintos dominios territoriales.
    Lo que necesito es un meno desde donde elejir el pais:
    #!/bin/bash
    clear
    while :
    do
    echo ” Escoja el pais tratar ”
    echo “1. Afghanistán(AF) ”
    echo “2. Albania(AL) ”
    echo “3. Alemania(DE) ”
    echo “5. Angola(AO) ”
    echo “6. Anguilla(AI) ”
    .. y continua hasta 247

    echo -n “Seleccione una opcion [1 – 247]”
    read opcion
    case $opcion in
    1) echo “este eres:”;whoami;;
    2) echo “tienes esto”;df;;
    3) echo “”; uname -r;;
    4) echo “chao”;exit 1;;
    5) echo “este eres:”;whoami;;
    6) echo “este eres:”;whoami;;
    …y continua hasta 247
    *) echo “$opc es una opcion invalida. Es tan dificil?”;
    echo “Presiona una tecla para continuar…”;
    read foo;;
    esac
    done

    El comportamiento es el siguiente:
    Cualquier opcion menos la 4, que es la salida borra el numero introducido y se queda a la espera de un nuevo numero.
    Al meter 4 sale.
    Si pongo el codigo del 4 en cualquier otra linea (digamos la 150) sale igualmente sin problemas.
    Tambien he probado a poner el codigo con este formato:
    151) echo “este eres:”;
    whoami;;
    con identico resultado.
    Me pregunto si para un menu tan largo hay mejores opciones y desde luego tambien que estoy haciendo mal.
    Una ayuda seria muy agradecida, gracias

  14.   Solo Raul dijo

    excelente …me parece muy bueno para adentrarse en las shell

    gracias

  15.   marcos dijo

    genial, oye como puedo hacer que mi bash trabaje con un archivo
    ejemplo:

    upload.sh fotodelavecina.jpg

    pensando que mi script en bash “upload.sh” tiene la información de acceso a mi ftp

    saludos y gracias 😀

  16.   Netzulo ntx dijo

    Bua tio, muchisimas gracias por todos los scripts, he montado un servidor CentOS y no sabeslo bien que me vienen estas plantillas, por favor, contacta conmigo por email. Que quiero proponerte algo

  17.   Gabriel Balderramos dijo

    Porque usas read foo cuando esta haciendo un menu ? repuestas rapida necesito

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

*

  1. Responsable de los datos: Miguel Ángel Gatón
  2. Finalidad de los datos: Controlar el SPAM, gestión de comentarios.
  3. Legitimación: Tu consentimiento
  4. Comunicación de los datos: No se comunicarán los datos a terceros salvo por obligación legal.
  5. Almacenamiento de los datos: Base de datos alojada en Occentus Networks (UE)
  6. Derechos: En cualquier momento puedes limitar, recuperar y borrar tu información.