Creando una Aplicación del Mundo Real
Ahora que hemos aprendido sobre variables, variables no definidas, expansión de parámetros y modo estricto, combinemos todos estos conceptos en un script práctico. Crearemos una utilidad simple de copia de seguridad de archivos que demuestra las mejores prácticas para manejar variables en Bash.
Planificando Nuestro Script de Copia de Seguridad
Nuestro script de copia de seguridad:
- Tomará un directorio de origen y un destino de copia de seguridad como entradas
- Permitirá la configuración a través de variables de entorno o argumentos de línea de comandos
- Manejará los errores con elegancia usando el modo estricto
- Proporcionará comentarios útiles al usuario
Creando el Script de Copia de Seguridad
- Crea un nuevo archivo llamado
backup.sh con el siguiente contenido:
#!/bin/bash
## ====================================
## File Backup Utility
## ====================================
## --- Strict mode ---
set -euo pipefail
## --- Script metadata ---
SCRIPT_NAME="$(basename "$0")"
SCRIPT_VERSION="1.0.0"
## --- Default configuration ---
SOURCE_DIR=${SOURCE_DIR:-"$(pwd)"}
BACKUP_DIR=${BACKUP_DIR:-"/tmp/backups"}
BACKUP_NAME=${BACKUP_NAME:-"backup_$(date +%Y%m%d_%H%M%S)"}
EXCLUDE_PATTERN=${EXCLUDE_PATTERN:-"*.tmp"}
VERBOSE=${VERBOSE:-"false"}
## --- Helper functions ---
log() {
if [[ "$VERBOSE" == "true" ]]; then
echo "$(date "+%Y-%m-%d %H:%M:%S") - $1"
fi
}
error() {
echo "ERROR: $1" >&2
exit 1
}
usage() {
cat << EOF
Usage: $SCRIPT_NAME [options]
A simple file backup utility.
Options:
-s, --source DIR Source directory to backup (default: current directory)
-d, --destination DIR Backup destination directory (default: /tmp/backups)
-n, --name NAME Name for the backup archive (default: backup_YYYYMMDD_HHMMSS)
-e, --exclude PATTERN Files to exclude (default: *.tmp)
-v, --verbose Enable verbose output
-h, --help Show this help message and exit
Environment variables:
SOURCE_DIR Same as --source
BACKUP_DIR Same as --destination
BACKUP_NAME Same as --name
EXCLUDE_PATTERN Same as --exclude
VERBOSE Set to 'true' to enable verbose output
EOF
}
## --- Process command line arguments ---
while [[ $## -gt 0 ]]; do
case $1 in
-s | --source)
SOURCE_DIR="$2"
shift 2
;;
-d | --destination)
BACKUP_DIR="$2"
shift 2
;;
-n | --name)
BACKUP_NAME="$2"
shift 2
;;
-e | --exclude)
EXCLUDE_PATTERN="$2"
shift 2
;;
-v | --verbose)
VERBOSE="true"
shift
;;
-h | --help)
usage
exit 0
;;
*)
error "Unknown option: $1"
;;
esac
done
## --- Main function ---
main() {
## Validate source directory
if [[ ! -d "$SOURCE_DIR" ]]; then
error "Source directory does not exist: $SOURCE_DIR"
fi
## Create backup directory if it doesn't exist
if [[ ! -d "$BACKUP_DIR" ]]; then
log "Creating backup directory: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR" || error "Failed to create backup directory"
fi
## Full path for the backup file
BACKUP_FILE="$BACKUP_DIR/$BACKUP_NAME.tar.gz"
log "Starting backup from $SOURCE_DIR to $BACKUP_FILE"
log "Excluding files matching: $EXCLUDE_PATTERN"
## Create the backup
tar -czf "$BACKUP_FILE" \
--exclude="$EXCLUDE_PATTERN" \
-C "$(dirname "$SOURCE_DIR")" "$(basename "$SOURCE_DIR")" \
|| error "Backup failed"
## Check if backup was created
if [[ -f "$BACKUP_FILE" ]]; then
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo "Backup completed successfully: $BACKUP_FILE ($BACKUP_SIZE)"
else
error "Backup file was not created"
fi
}
## --- Run main function ---
main
- Haz que el script sea ejecutable:
chmod +x backup.sh
- Ejecuta el script con la configuración predeterminada:
./backup.sh
Deberías ver un mensaje confirmando que la copia de seguridad se creó correctamente.
- Revisa el archivo de copia de seguridad:
ls -lh /tmp/backups/
- Intenta ejecutar el script con diferentes opciones:
./backup.sh --source ~/project --destination ~/backups --name my_project_backup --verbose
Si el directorio ~/backups no existe, el script lo creará. Podrías ver un error si no tienes permisos de escritura para crear ese directorio.
Probando el Manejo de Errores en Nuestro Script de Copia de Seguridad
Probemos cómo nuestro script maneja los errores:
- Intenta hacer una copia de seguridad de un directorio que no existe:
./backup.sh --source /path/that/does/not/exist
Deberías ver un mensaje de error como:
ERROR: Source directory does not exist: /path/that/does/not/exist
- Intenta establecer un destino de copia de seguridad no válido (donde no tienes permisos de escritura):
./backup.sh --destination /root/backups
Deberías ver un mensaje de error que indica que el script no pudo crear el directorio de copia de seguridad.
Creando un Entorno de Prueba
Creemos un entorno de prueba para demostrar nuestro script de copia de seguridad:
- Crea una estructura de directorio de prueba:
mkdir -p ~/project/test_backup/{docs,images,code}
touch ~/project/test_backup/docs/{readme.md,manual.pdf}
touch ~/project/test_backup/images/{logo.png,banner.jpg}
touch ~/project/test_backup/code/{script.sh,data.tmp,config.json}
- Ejecuta el script de copia de seguridad en este directorio de prueba:
./backup.sh --source ~/project/test_backup --exclude "*.tmp" --verbose
- Enumera los archivos en la copia de seguridad:
tar -tvf /tmp/backups/backup_*.tar.gz | sort
Deberías ver todos los archivos excepto aquellos que coinciden con el patrón de exclusión (*.tmp).
Este script de copia de seguridad demuestra todos los conceptos que hemos cubierto:
- Establecer valores predeterminados para las variables usando la expansión de parámetros
- Usar el modo estricto para detectar errores
- Manejar argumentos de línea de comandos y variables de entorno
- Proporcionar comentarios al usuario y mensajes de error
- Validar entradas y manejar casos extremos
Con estas técnicas, puedes escribir scripts de Bash robustos que manejen variables no definidas con elegancia y proporcionen una mejor experiencia de usuario.