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.
Índice
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, deja el tuyo
Joder están geniales O_O … ayudará un montón a mis cosillas que hago en Bash 😀
Estan super los scripts !que gran aporte en serio¡ justo lo que andaba buscando.
PD: El foro esta caído.
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.
Ah bueno esperemos que no sea nada grave.
¿Ese «chanfle» también estaba incluido en Code Ninja? XD
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.
Gracias, me gustaron mucho
La validación de los parámetros de entrada es muy útil. No sabia como hacer los menús =)
Genial…. ahora puedo darle algo de «dureza» a mis churros de scripts jejeje
Un gustazo ver como nuestro humilde trabajo en CodeNinja sirve de algo a la comunidad internacional de linux
Claro! 🙂
Todo sea por ayudar y aportar entre todos, y no por crear flames ¿o no? 😉
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»
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?
Instala el siguiente programa
aptitude install autolog
Y el archivo de configuracion lo tenes en /etc/autolog.conf
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? 🙁
Escríbeme a mi email (kzkggaara[at]desdelinux[dot]net) para hablar con más calma, te ayudo con mucho gusto 🙂
Genial gracias amigo, te pasaste!
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
excelente …me parece muy bueno para adentrarse en las shell
gracias
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 😀
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
Porque usas read foo cuando esta haciendo un menu ? repuestas rapida necesito