Scripts Bash para Administración de Servidores: Ejemplos Prácticos de Automatización
Introducción
Los scripts Bash son la habilidad fundamental para la administración de sistemas Linux y la automatización DevOps. Aunque herramientas modernas como Ansible y Terraform sobresalen en orquestación compleja, los scripts Bash siguen siendo esenciales para automatizaciones rápidas, tareas de mantenimiento del sistema y situaciones donde instalar herramientas adicionales no es práctico. Todo administrador de sistemas debe dominar los scripts Bash para automatizar tareas repetitivas, implementar soluciones de monitoreo y gestionar servidores de manera eficiente.
Esta guía completa presenta scripts Bash listos para producción para tareas comunes de administración de servidores. Cada script incluye manejo de errores, registro de eventos y mejores prácticas que los hacen adecuados para entornos de producción.
Requisitos Previos
- Conocimiento básico de la línea de comandos Linux/Unix
- Comprensión de permisos de archivos
- Familiaridad con comandos comunes de Linux
- Editor de texto (vim, nano o VS Code)
- Bash 4.0+ instalado
Plantilla Esencial de Script
#!/bin/bash
set -euo pipefail
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_FILE="/var/log/$(basename "$0" .sh).log"
# Logging functions
log_info() {
echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
}
log_error() {
echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE" >&2
}
# Error handling
error_exit() {
log_error "$1"
exit "${2:-1}"
}
# Main function
main() {
log_info "Script started"
# Your code here
log_info "Script completed"
}
main "$@"
Scripts de Monitoreo del Sistema
Verificación Completa de Salud
#!/bin/bash
# system-health-check.sh
set -euo pipefail
CPU_THRESHOLD=80
MEMORY_THRESHOLD=85
DISK_THRESHOLD=85
get_cpu_usage() {
top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1
}
get_memory_usage() {
free | grep Mem | awk '{printf("%.0f", ($3/$2) * 100)}'
}
get_disk_usage() {
df -h / | tail -1 | awk '{print $5}' | sed 's/%//'
}
check_metrics() {
local alerts=()
cpu=$(get_cpu_usage)
if (( $(echo "$cpu > $CPU_THRESHOLD" | bc -l) )); then
alerts+=("CPU: ${cpu}%")
fi
memory=$(get_memory_usage)
if (( memory > MEMORY_THRESHOLD )); then
alerts+=("Memory: ${memory}%")
fi
disk=$(get_disk_usage)
if (( disk > DISK_THRESHOLD )); then
alerts+=("Disk: ${disk}%")
fi
if [ ${#alerts[@]} -gt 0 ]; then
echo "ALERTS: ${alerts[*]}" | mail -s "System Alert" [email protected]
fi
}
check_metrics
Script de Respaldo Automatizado
#!/bin/bash
# automated-backup.sh
set -euo pipefail
BACKUP_SOURCE="/var/www /etc /home"
BACKUP_DEST="/backup"
RETENTION_DAYS=7
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_${TIMESTAMP}"
create_backup() {
mkdir -p "${BACKUP_DEST}/${BACKUP_NAME}"
for dir in $BACKUP_SOURCE; do
if [ -d "$dir" ]; then
tar -czf "${BACKUP_DEST}/${BACKUP_NAME}/$(basename $dir).tar.gz" \
"$dir" 2>&1 | tee -a /var/log/backup.log
fi
done
# MySQL backup
mysqldump --all-databases | gzip > "${BACKUP_DEST}/${BACKUP_NAME}/mysql.sql.gz"
# Create final archive
cd "$BACKUP_DEST"
tar -czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME"
rm -rf "$BACKUP_NAME"
}
cleanup_old_backups() {
find "$BACKUP_DEST" -name "backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete
}
main() {
echo "Starting backup at $(date)"
create_backup
cleanup_old_backups
echo "Backup completed at $(date)"
}
main
Scripts de Gestión de Usuarios
Aprovisionamiento de Usuarios
#!/bin/bash
# user-provisioning.sh
set -euo pipefail
create_user() {
local username=$1
local fullname=$2
local ssh_key=$3
if id "$username" &>/dev/null; then
echo "User $username already exists"
return 1
fi
useradd -m -s /bin/bash -c "$fullname" "$username"
usermod -aG sudo,developers "$username"
# Setup SSH
mkdir -p "/home/$username/.ssh"
echo "$ssh_key" > "/home/$username/.ssh/authorized_keys"
chmod 700 "/home/$username/.ssh"
chmod 600 "/home/$username/.ssh/authorized_keys"
chown -R "$username:$username" "/home/$username/.ssh"
echo "Created user: $username"
}
# Usage: ./user-provisioning.sh username "Full Name" "ssh-rsa AAA..."
create_user "$@"
Scripts de Seguridad
Auditoría de Seguridad
#!/bin/bash
# security-audit.sh
set -euo pipefail
REPORT="/var/log/security-audit-$(date +%Y%m%d).txt"
{
echo "Security Audit - $(date)"
echo "================================"
echo -e "\nUsers without password:"
awk -F: '($2 == "") {print $1}' /etc/shadow
echo -e "\nUsers with UID 0:"
awk -F: '($3 == 0) {print $1}' /etc/passwd
echo -e "\nWorld-writable files:"
find / -xdev -type f -perm -0002 2>/dev/null | head -20
echo -e "\nSUID files:"
find / -xdev -type f -perm -4000 2>/dev/null
echo -e "\nListening ports:"
ss -tuln
echo -e "\nFirewall status:"
ufw status verbose 2>/dev/null || iptables -L -n
} | tee "$REPORT"
echo "Audit complete: $REPORT"
Gestión de Registros
Script de Rotación de Registros
#!/bin/bash
# log-rotation.sh
set -euo pipefail
LOG_DIRS="/var/log/nginx /var/log/application"
COMPRESS_AGE=7
DELETE_AGE=30
for dir in $LOG_DIRS; do
if [ -d "$dir" ]; then
# Compress old logs
find "$dir" -name "*.log" -mtime +$COMPRESS_AGE ! -name "*.gz" -exec gzip {} \;
# Delete very old logs
find "$dir" -name "*.gz" -mtime +$DELETE_AGE -delete
fi
done
echo "Log rotation completed"
Monitoreo de Rendimiento
Monitor de Recursos
#!/bin/bash
# resource-monitor.sh
set -euo pipefail
ALERT_EMAIL="[email protected]"
check_resources() {
cpu=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
memory=$(free | grep Mem | awk '{printf("%.1f"), ($3/$2) * 100}')
disk=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
report="Resource Report for $(hostname)
CPU: ${cpu}%
Memory: ${memory}%
Disk: ${disk}%"
echo "$report"
# Alert if thresholds exceeded
if (( $(echo "$cpu > 80" | bc -l) )); then
echo "$report" | mail -s "High CPU Alert" "$ALERT_EMAIL"
fi
}
check_resources
Scripts de Despliegue
Despliegue de Aplicación
#!/bin/bash
# deploy-app.sh
set -euo pipefail
APP_DIR="/opt/myapp"
BACKUP_DIR="/opt/backups"
REPO_URL="https://github.com/company/app.git"
BRANCH="main"
deploy() {
# Backup current version
if [ -d "$APP_DIR" ]; then
tar -czf "${BACKUP_DIR}/app-$(date +%Y%m%d_%H%M%S).tar.gz" "$APP_DIR"
fi
# Deploy new version
if [ -d "$APP_DIR/.git" ]; then
cd "$APP_DIR"
git fetch origin
git checkout "$BRANCH"
git pull origin "$BRANCH"
else
git clone -b "$BRANCH" "$REPO_URL" "$APP_DIR"
fi
# Install dependencies
cd "$APP_DIR"
npm install --production
# Restart service
systemctl restart myapp
# Verify deployment
sleep 5
if curl -f http://localhost:3000/health; then
echo "Deployment successful"
else
echo "Deployment failed, rolling back"
# Rollback logic here
exit 1
fi
}
deploy
Herramientas de Red
Monitor de Conexión
#!/bin/bash
# network-monitor.sh
set -euo pipefail
HOSTS=("8.8.8.8" "1.1.1.1" "google.com")
LOG_FILE="/var/log/network-monitor.log"
check_connectivity() {
for host in "${HOSTS[@]}"; do
if ping -c 3 -W 2 "$host" &>/dev/null; then
echo "[$(date)] OK: $host" >> "$LOG_FILE"
else
echo "[$(date)] FAILED: $host" >> "$LOG_FILE"
echo "Network issue detected for $host" | mail -s "Network Alert" [email protected]
fi
done
}
check_connectivity
Mantenimiento de Bases de Datos
Respaldo y Optimización de Bases de Datos
#!/bin/bash
# db-maintenance.sh
set -euo pipefail
DB_USER="backup_user"
DB_PASS="password"
BACKUP_DIR="/backup/mysql"
RETENTION=7
# Backup all databases
backup_databases() {
mkdir -p "$BACKUP_DIR"
mysql -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" | \
grep -Ev "Database|information_schema|performance_schema|mysql" | \
while read -r db; do
mysqldump -u"$DB_USER" -p"$DB_PASS" \
--single-transaction \
"$db" | gzip > "${BACKUP_DIR}/${db}-$(date +%Y%m%d).sql.gz"
echo "Backed up: $db"
done
}
# Optimize tables
optimize_tables() {
mysql -u"$DB_USER" -p"$DB_PASS" -e "SHOW DATABASES;" | \
grep -Ev "Database|information_schema|performance_schema|mysql" | \
while read -r db; do
mysqlcheck -u"$DB_USER" -p"$DB_PASS" --optimize "$db"
done
}
# Cleanup old backups
cleanup() {
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$RETENTION -delete
}
main() {
backup_databases
optimize_tables
cleanup
}
main
Mejores Prácticas
Manejo de Errores
# Always use strict mode
set -euo pipefail
# Custom error handler
error_handler() {
echo "Error on line $1"
cleanup_function
exit 1
}
trap 'error_handler $LINENO' ERR
Validación de Entrada
validate_input() {
local input=$1
if [[ -z "$input" ]]; then
echo "Error: Input required"
return 1
fi
if [[ ! "$input" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "Error: Invalid characters"
return 1
fi
return 0
}
Registro de Eventos
LOG_FILE="/var/log/script.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
log "Starting process"
Conclusión
Los scripts Bash son esenciales para la automatización de la administración de sistemas. Estos ejemplos prácticos demuestran patrones comunes para monitoreo, respaldo, gestión de usuarios y tareas de mantenimiento. Siempre pruebe los scripts en entornos que no sean de producción primero, implemente un manejo de errores adecuado y siga las mejores prácticas de seguridad.
Conclusiones clave:
- Use
set -euo pipefailpara mayor seguridad - Implemente registros completos
- Agregue manejo de errores y validación
- Programe con cron o temporizadores systemd
- Controle las versiones de sus scripts
- Documente su código
- Pruebe exhaustivamente antes del uso en producción
Continúe mejorando sus habilidades Bash adaptando estos ejemplos a sus necesidades específicas y construyendo una biblioteca de scripts de automatización reutilizables.


