A lo largo de los artículos anteriores hemos usado comandos sueltos en la consola. Cuando una secuencia de comandos se repite, lo natural es meterla en un script bash para no tener que escribirla cada vez.
Un script bash es un archivo de texto que empieza con la línea:
#!/bin/bash
Esta primera línea (el «shebang») le dice al sistema qué intérprete usar. A continuación escribimos los comandos igual que en la consola.
Variables y condicionales
Un script que comprueba si un servicio está corriendo y lo arranca si no:
#!/bin/bash
SERVICIO="apache2"
if ! sudo service $SERVICIO status > /dev/null 2>&1; then
sudo service $SERVICIO start
echo "$SERVICIO arrancado"
fi
La variable SERVICIO hace el script reutilizable para cualquier servicio. La condición
usa ! para invertir el resultado: si status falla (servicio parado), entra en el bloque
y lo arranca.
Bucles
Un script que renombra en lote archivos .jpeg a .jpg en el directorio actual:
#!/bin/bash
for archivo in *.jpeg; do
[ -f "$archivo" ] || continue
nuevo="${archivo%.jpeg}.jpg"
mv "$archivo" "$nuevo"
echo "Renombrado: $archivo → $nuevo"
done
${archivo%.jpeg} elimina el sufijo .jpeg del nombre (una sustitución de parámetro
de bash que evita llamar a sed para algo tan simple).
Hacerlo ejecutable
chmod 755 mi-script.sh
Y para ejecutarlo:
./mi-script.sh
O copiarlo a /usr/local/bin/ para tenerlo disponible en cualquier directorio.
Códigos de salida
Cuando un script termina, devuelve un número al sistema: 0 significa éxito, cualquier otro
valor significa error. $? contiene el código del último comando ejecutado:
ls /etc/hosts > /dev/null 2>&1
echo $? # 0 (el archivo existe)
ls /no-existe > /dev/null 2>&1
echo $? # distinto de 0 (el archivo no existe)
En un script propio se usa exit para fijar el código explícitamente:
#!/bin/bash
ARCHIVO=$1
if [ ! -f "$ARCHIVO" ]; then
echo "Error: $ARCHIVO no existe" >&2
exit 1
fi
echo "OK: $ARCHIVO encontrado"
exit 0
exit 1 señala que algo falló; exit 0 confirma que todo fue bien. Esto permite encadenar
scripts con && o comprobar el resultado desde otro script.
Depuración
bash -x muestra cada comando antes de ejecutarlo, útil para entender qué va mal:
bash -x mi-script.sh
Para scripts en cron
Dos reglas imprescindibles si el script lo ejecuta
cron:
- Usar siempre rutas absolutas (cron tiene un
PATHreducido) - Redirigir errores si no queremos recibir correos:
comando 2>/dev/null