1

Backup automatizado con fecha y compresión

Caso de uso: Copia de seguridad diaria de un directorio importante (p. ej. /var/www) en un .tar.gz con la fecha en el nombre, conservando solo los últimos 7 backups.

#!/bin/bash
# === Backup automatizado de /var/www ===
ORIGEN="/var/www"                       # qué respaldar
DESTINO="/backups"                       # dónde guardar
FECHA=$(date '+%Y-%m-%d_%H%M%S')         # marca temporal única
ARCHIVO="$DESTINO/www_$FECHA.tar.gz"

mkdir -p "$DESTINO"                       # asegura que exista el destino

# Comprime el origen; -c crear, -z gzip, -f fichero
if tar -czf "$ARCHIVO" "$ORIGEN" 2>/dev/null; then
  echo "[OK] Backup creado: $ARCHIVO"
else
  echo "[ERROR] Fallo al crear el backup" >&2
  exit 1
fi

# Conserva solo los 7 backups más recientes (borra el resto)
ls -1t "$DESTINO"/www_*.tar.gz | tail -n +8 | xargs -r rm --
echo "[OK] Rotación completada (se conservan 7)"
⏰ Programar con cron 0 2 * * * /opt/scripts/backup.sh # cada día a las 02:00
💡 Posibles mejoras Enviar el backup a un servidor remoto con rsync/scp; cifrar con gpg; registrar el resultado en un log; notificar por email si falla.
2

Monitor de espacio en disco con alerta

Caso de uso: Comprueba el uso de la partición raíz y, si supera un umbral, envía un aviso (aquí simulado por pantalla y log).

#!/bin/bash
# === Alerta de disco lleno ===
UMBRAL=85                                # % a partir del cual alertar
LOG="/var/log/disco_monitor.log"

# df de / ; quitamos cabecera y el símbolo %
USO=$(df -h / | awk 'NR==2 {gsub("%","",$5); print $5}')
FECHA=$(date '+%Y-%m-%d %H:%M:%S')

if [ "$USO" -ge "$UMBRAL" ]; then
  MSG="[$FECHA] ALERTA: disco / al ${USO}% (umbral ${UMBRAL}%)"
  echo "$MSG" | tee -a "$LOG"
  # Simulación de email (en real: mail -s ... admin@dominio)
  echo "$MSG" > /tmp/aviso_disco.mail
else
  echo "[$FECHA] OK: disco / al ${USO}%" >> "$LOG"
fi
⏰ Programar con cron */30 * * * * /opt/scripts/disco.sh # cada 30 minutos
💡 Posibles mejoras Revisar todas las particiones con un bucle sobre df; integrar mail real o webhook; distinguir warning/critical con dos umbrales.
3

Rotación manual de logs

Caso de uso: Para un log propio de una aplicación: lo archiva con fecha, lo comprime y crea uno nuevo vacío, manteniendo permisos.

#!/bin/bash
# === Rotación manual de un log ===
LOG="/var/log/miapp/app.log"
MAX=5                                    # cuántos comprimidos conservar

[ -f "$LOG" ] || { echo "No existe $LOG"; exit 0; }

FECHA=$(date '+%Y%m%d')
mv "$LOG" "${LOG}.$FECHA"                  # archiva el actual
gzip "${LOG}.$FECHA"                       # lo comprime
: > "$LOG"                                # crea uno nuevo vacío (truncate)
chmod 640 "$LOG"                          # restaura permisos

# Elimina los comprimidos más antiguos que superen MAX
ls -1t "${LOG}."*.gz 2>/dev/null | tail -n +$((MAX+1)) | xargs -r rm --
echo "[OK] Log rotado: ${LOG}.$FECHA.gz"
⏰ Programar con cron 0 0 * * 0 /opt/scripts/logrotate.sh # cada domingo a medianoche
💡 Posibles mejoras Usar logrotate del sistema con un fichero en /etc/logrotate.d/; enviar SIGHUP al servicio para que reabra el log; añadir fecha-hora si rota varias veces al día.
4

Creación masiva de usuarios desde CSV

Caso de uso: Da de alta usuarios leyendo un fichero CSV con formato usuario,grupo,nombre_completo, creando home y contraseña inicial.

#!/bin/bash
# === Alta masiva de usuarios desde CSV ===
CSV="${1:-usuarios.csv}"                  # fichero como argumento o por defecto

[ -f "$CSV" ] || { echo "No existe $CSV"; exit 1; }

# IFS=, separa por comas; read lee cada campo
while IFS=, read -r usuario grupo nombre; do
  [ -z "$usuario" ] && continue          # salta líneas vacías
  if id "$usuario" &>/dev/null; then
    echo "[SKIP] $usuario ya existe"
    continue
  fi
  groupadd -f "$grupo"                    # crea el grupo si no existe
  useradd -m -g "$grupo" -c "$nombre" "$usuario"
  echo "${usuario}:Cambiar123" | chpasswd # contraseña inicial
  passwd --expire "$usuario"              # forzar cambio al primer login
  echo "[OK] Creado $usuario (grupo $grupo)"
done < "$CSV"
⏰ Programar con cron # Normalmente se ejecuta a mano: ./usuarios_csv.sh altas_septiembre.csv
💡 Posibles mejoras Validar formato de cada línea; generar contraseñas aleatorias; registrar en log quién se creó; soportar una columna de shell.
5

Auditoría de usuarios del sistema

Caso de uso: Informe rápido de seguridad: usuarios con shell de login, cuentas con UID 0 (peligrosas) y usuarios sin contraseña.

#!/bin/bash
# === Auditoría básica de usuarios ===
echo "=== Usuarios con shell de login ==="
grep -E '/(bash|sh|zsh)$' /etc/passwd | cut -d: -f1

echo
echo "=== Cuentas con UID 0 (deberían ser solo root) ==="
awk -F: '$3 == 0 {print $1}' /etc/passwd

echo
echo "=== Usuarios SIN contraseña (campo 2 vacío en shadow) ==="
sudo awk -F: '($2 == "" ) {print $1}' /etc/shadow

echo
echo "=== Últimos accesos ==="
last -n 5
⏰ Programar con cron 0 7 * * 1 /opt/scripts/auditoria.sh > /var/log/audit_users.txt # lunes 07:00
💡 Posibles mejoras Comparar contra una lista blanca de cuentas esperadas; alertar si aparece un nuevo UID 0; exportar a CSV/JSON para un panel.
6

Monitor de proceso con reinicio automático

Caso de uso: Vigila que un servicio crítico (p. ej. nginx) siga vivo y, si no, lo reinicia y lo registra. Útil como red de seguridad básica.

#!/bin/bash
# === Vigilante de proceso ===
PROCESO="nginx"
LOG="/var/log/watchdog.log"
FECHA=$(date '+%Y-%m-%d %H:%M:%S')

# pgrep devuelve 0 si el proceso está vivo
if pgrep -x "$PROCESO" > /dev/null; then
  echo "[$FECHA] $PROCESO OK" >> "$LOG"
else
  echo "[$FECHA] $PROCESO CAÍDO -> reiniciando" >> "$LOG"
  systemctl restart "$PROCESO"
  if pgrep -x "$PROCESO" > /dev/null; then
    echo "[$FECHA] $PROCESO reiniciado correctamente" >> "$LOG"
  else
    echo "[$FECHA] ERROR: no se pudo reiniciar $PROCESO" >> "$LOG"
  fi
fi
⏰ Programar con cron */5 * * * * /opt/scripts/monitor_proc.sh # cada 5 minutos
💡 Posibles mejoras Limitar el número de reinicios por hora para no enmascarar un fallo grave; notificar al administrador; usar el propio systemd (Restart=on-failure) cuando sea posible.
7

Limpieza de ficheros temporales antiguos

Caso de uso: Borra de un directorio temporal los ficheros con más de N días sin modificar, liberando espacio de forma segura.

#!/bin/bash
# === Limpieza de temporales > N días ===
DIR="/tmp/miapp"
DIAS=7                                    # antigüedad mínima para borrar
LOG="/var/log/limpieza_tmp.log"
FECHA=$(date '+%Y-%m-%d %H:%M:%S')

[ -d "$DIR" ] || { echo "No existe $DIR"; exit 0; }

# find: -type f ficheros, -mtime +N modificados hace más de N días
N=$(find "$DIR" -type f -mtime +$DIAS | wc -l)
find "$DIR" -type f -mtime +$DIAS -print -delete >> "$LOG"
echo "[$FECHA] Eliminados $N ficheros de más de $DIAS días" >> "$LOG"
⏰ Programar con cron 30 3 * * * /opt/scripts/limpieza_tmp.sh # cada día a las 03:30
💡 Posibles mejoras Probar primero sin -delete (solo -print) en modo simulacro; excluir ficheros importantes con -not -name; mover a papelera en vez de borrar.
8

Generador de informe del sistema

Caso de uso: Genera un resumen del estado del servidor (uptime, carga, memoria, disco, top de procesos) en un fichero con fecha, ideal para revisión diaria.

#!/bin/bash
# === Informe diario del sistema ===
FECHA=$(date '+%Y-%m-%d %H:%M:%S')
OUT="/var/log/informe_$(date '+%Y%m%d').txt"

{
  echo "===== INFORME DEL SISTEMA — $FECHA ====="
  echo; echo "--- Uptime y carga ---"; uptime
  echo; echo "--- Memoria ---"; free -h
  echo; echo "--- Disco ---"; df -h
  echo; echo "--- Top 5 procesos por CPU ---"
  ps aux --sort=-%cpu | head -n 6
  echo; echo "--- Top 5 procesos por memoria ---"
  ps aux --sort=-%mem | head -n 6
} > "$OUT"

echo "[OK] Informe generado en $OUT"
⏰ Programar con cron 0 8 * * * /opt/scripts/informe.sh # cada día a las 08:00
💡 Posibles mejoras Enviar el informe por email/Telegram; añadir comprobación de servicios con systemctl is-active; comparar con el día anterior para detectar anomalías.
← Dashboard 🖥️ Sandbox 📚 Glosario