Manual Completo de Bash para Administración de Sistemas

Desde conceptos básicos hasta técnicas avanzadas de automatización

Tabla de Contenidos

1. Fundamentos de Bash

Variables y Entorno

variable="valor"
Asignación de variables (sin espacios alrededor del =).
echo $variable
Mostrar el valor de una variable.
export VARIABLE="valor"
Crear una variable de entorno.
env
Mostrar todas las variables de entorno.

Entrada/Salida

echo "texto"
Imprimir texto en la salida estándar.
printf "Formato" argumentos
Imprimir con formato (más potente que echo).
read variable
Leer entrada del usuario.
read -s -p "Prompt: " variable
Leer entrada silenciosa (para contraseñas).

Redirección

comando > archivo
Redirigir salida estándar a archivo (sobrescribe).
comando >> archivo
Redirigir salida estándar a archivo (concatena).
comando 2> archivo
Redirigir errores a archivo.
comando &> archivo
Redirigir salida estándar y errores a archivo.
comando1 | comando2
Pipe: pasar salida de comando1 como entrada a comando2.
comando < archivo
Redirigir archivo como entrada estándar.
comando << "EOF"
texto
EOF
Here document: pasar texto multilínea como entrada.

2. Manejo Avanzado de Archivos

Operaciones Batch

for archivo in *.txt; do
mv "$archivo" "${archivo%.txt}.bak"
done
Renombrar todos los archivos .txt a .bak.
find . -name "*.log" -exec rm {} \;
Eliminar todos los archivos .log recursivamente.
find /ruta -type f -mtime +30 -exec gzip {} \;
Comprimir archivos no modificados en 30 días.
rsync -avz --delete origen/ destino/
Sincronizar directorios (incluyendo eliminaciones).
parallel -j 4 convert {} -resize 800x600 {.}_resized.jpg ::: *.jpg
Procesar archivos en paralelo (requiere GNU Parallel).

Manipulación de Contenido

sed -i 's/foo/bar/g' archivo
Reemplazar texto en archivo (in-place).
awk '{print $1}' archivo
Imprimir primera columna de un archivo.
sort archivo | uniq -c | sort -nr
Contar y ordenar líneas únicas.
cut -d: -f1 /etc/passwd
Extraer nombres de usuario del archivo passwd.
join -t: -1 3 -2 3 archivo1 archivo2
Unir archivos por campo común (como SQL JOIN).

Manipulación Masiva Eficiente

# Mover miles de archivos eficientemente
find /origen -type f -name "*.dat" -print0 | xargs -0 -I {} mv {} /destino/
Mover muchos archivos evitando problemas con espacios en nombres.
# Procesar archivos en lotes de 100
ls *.log | split -l 100 -d - logs_
for lote in logs_*; do
while read archivo; do
process_file "$archivo"
done < "$lote"
done
Procesamiento por lotes para manejar grandes volúmenes.
# Renombrar archivos con contador
count=1
for archivo in *.jpg; do
mv "$archivo" "foto_$(printf "%04d" $count).jpg"
((count++))
done
Renumerar archivos con padding de ceros.

3. Expresiones Regulares

Conceptos Básicos

^[A-Za-z]+$
Coincide con cadenas que contienen solo letras (mayúsculas o minúsculas)
\d{3}-\d{2}-\d{4}
Coincide con números de seguro social (formato: 123-45-6789)
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
Validación básica de email

Uso en Herramientas

grep -E "pattern" archivo
Buscar patrones con regex extendidas.
sed -E 's/([0-9]{3})/\1-/g' archivo
Usar grupos de captura en sed.
awk '/^[A-Z]/ {print}' archivo
Imprimir líneas que comienzan con mayúscula.
[[ $var =~ ^[0-9]+$ ]] && echo "Es número"
Validar variable en Bash con regex.

Expresiones Avanzadas

(?<=prefix)pattern
Positive lookbehind (coincide solo si está precedido por "prefix")
pattern(?=suffix)
Positive lookahead (coincide solo si está seguido por "suffix")
(?:non-capturing)
Grupo sin captura (mejor rendimiento cuando no se necesita capturar)
# Extraer direcciones IP de logs
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" access.log | sort | uniq -c | sort -nr
Ejemplo práctico: extraer y contar IPs de un log.

4. Scripting Avanzado

Estructuras de Control

if [[ condición ]]; then
comandos
elif [[ condición ]]; then
comandos
else
comandos
fi
Estructura condicional if-elif-else.
case $variable in
patrón1) comandos ;;
patrón2) comandos ;;
*) comandos_default ;;
esac
Estructura switch-case.
for item in lista; do
comandos
done
Bucle for.
while [[ condición ]]; do
comandos
done
Bucle while.
until [[ condición ]]; do
comandos
done
Bucle until (ejecuta hasta que condición sea verdadera).

Funciones

function nombre_funcion {
comandos
return valor
}
Definición de función.
nombre_funcion() {
comandos
return valor
}
Sintaxis alternativa para funciones.
local variable="valor"
Variables locales en funciones.

Manejo de Errores

set -e
Terminar script si algún comando falla.
set -o pipefail
Considerar error si algún comando en un pipe falla.
trap 'cleanup_function' EXIT
Ejecutar función al salir del script (incluso por error).
if ! comando; then
echo "Falló comando" >&2
exit 1
fi
Manejo explícito de errores.

Arrays y Estructuras

array=(elemento1 elemento2 elemento3)
Crear array.
echo "${array[1]}"
Acceder a elemento del array (índice comienza en 0).
echo "${array[@]}"
Expandir todos los elementos.
echo "${#array[@]}"
Número de elementos en el array.
declare -A dict
dict[key]="value"
Diccionarios/arrays asociativos (Bash 4+).

5. Automatización

Cron y Programación

crontab -e
Editar tareas programadas del usuario actual.
# Ejemplo de entrada crontab
0 3 * * * /ruta/script.sh > /ruta/log.log 2>&1
Ejecutar script diariamente a las 3 AM, redirigiendo salida.
@reboot /ruta/script.sh
Ejecutar script al arrancar el sistema.
anacron -t /etc/anacrontab -d
Alternativa a cron para sistemas que no están siempre encendidos.

Systemd Timers

# /etc/systemd/system/mitarea.timer
[Unit]
Description=Ejecutar mi tarea diariamente

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
Ejemplo de timer para systemd (más moderno que cron).
systemctl enable --now mitarea.timer
Activar y empezar timer.

Automatización Compleja

# Script de backup con rotación
BACKUP_DIR="/backups"
MAX_BACKUPS=30
DATE=$(date +%Y%m%d_%H%M%S)

# Crear nuevo backup
tar -czf "$BACKUP_DIR/backup_$DATE.tar.gz" /datos

# Rotar backups antiguos
ls -t "$BACKUP_DIR"/backup_*.tar.gz | tail -n +$((MAX_BACKUPS + 1)) | xargs rm -f
Ejemplo de script de backup con rotación automática.
# Monitoreo de servicio con reinicio automático
SERVICE="nginx"
MAX_RESTARTS=3
LOG_FILE="/var/log/service_monitor.log"

if ! systemctl is-active --quiet "$SERVICE"; then
echo "$(date) - $SERVICE caído" >> "$LOG_FILE"
systemctl restart "$SERVICE"
echo "$(date) - $SERVICE reiniciado" >> "$LOG_FILE"
fi
Script básico de monitoreo y recuperación de servicios.

6. CI/CD con Bash

Integración Continua Básica

#!/bin/bash
# Script de build básico

set -e # Fallar en cualquier error

# Instalar dependencias
apt-get update
apt-get install -y build-essential

# Ejecutar tests
if ! make test; then
echo "Tests fallaron" >&2
exit 1
fi

# Crear artefacto
make package

# Subir artefacto
scp package.tar.gz deploy@server:/releases/
Ejemplo básico de script de CI.

Despliegue Continuo

#!/bin/bash
# Script de despliegue

APP_DIR="/var/www/myapp"
BACKUP_DIR="/backups/myapp"
RELEASE=$(date +%Y%m%d_%H%M%S)

# Crear directorio de release
mkdir -p "$APP_DIR/releases/$RELEASE"
tar -xzf package.tar.gz -C "$APP_DIR/releases/$RELEASE"

# Backup de la versión actual
if [ -L "$APP_DIR/current" ]; then
cp -a "$APP_DIR/current" "$BACKUP_DIR/$RELEASE"
fi

# Cambiar symlink a nueva versión
ln -sfn "$APP_DIR/releases/$RELEASE" "$APP_DIR/current"

# Reiniciar servicios
systemctl restart myapp
Script de despliegue con rollback implícito (via symlink).

Integración con Git

#!/bin/bash
# Git post-receive hook para despliegue automático

while read oldrev newrev refname; do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "$branch" = "main" ]; then
# Pull en el servidor
unset GIT_DIR
cd /var/www/myapp || exit
git pull origin main
make install
fi
done
Hook de Git para despliegue automático al hacer push.

Pipeline Completo

#!/bin/bash
# Pipeline CI/CD completo

# Variables
PROJECT="myapp"
VERSION=$(git describe --tags)
ARTIFACT="$PROJECT-$VERSION.tar.gz"

# Fases
build() {
make clean
make all
}

test() {
make test
make lint
}

package() {
tar -czf "$ARTIFACT" bin/
}

deploy() {
scp "$ARTIFACT" deploy@prod:/releases/
ssh deploy@prod "/opt/scripts/deploy.sh $ARTIFACT"
}

# Ejecutar pipeline
build && test && package && deploy || exit 1
Pipeline completo con funciones para cada etapa.

7. Administración de iptables

Conceptos Básicos

iptables -L
Listar reglas actuales.
iptables -L -n -v
Listar reglas con información numérica y detallada.
iptables -F
Flush (borrar todas las reglas).

Configuración Básica

iptables -P INPUT DROP
Política por defecto DROP para tráfico entrante.
iptables -A INPUT -i lo -j ACCEPT
Permitir tráfico localhost.
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Permitir conexiones establecidas.
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
Permitir SSH.

Script de Firewall

#!/bin/bash
# Script completo de firewall

# Resetear reglas
iptables -F
iptables -X
iptables -Z

# Políticas por defecto
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Permitir localhost
iptables -A INPUT -i lo -j ACCEPT

# Permitir conexiones establecidas
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Servicios permitidos
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # HTTPS

# Protección básica
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 30 -j DROP
iptables -A INPUT -m state --state INVALID -j DROP

# Logging
iptables -N LOGGING
iptables -A INPUT -j LOGGING
iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: "
iptables -A LOGGING -j DROP
Script completo de firewall con políticas básicas y protección.

Persistencia

iptables-save > /etc/iptables.rules
Guardar reglas actuales.
iptables-restore < /etc/iptables.rules
Cargar reglas guardadas.
# Para hacerlas persistentes en reboot (Debian/Ubuntu)
apt install iptables-persistent
netfilter-persistent save
Hacer reglas persistentes entre reinicios.

8. Gestión de Procesos

Monitoreo

ps aux --sort=-%cpu | head
Procesos ordenados por uso de CPU.
ps aux --sort=-%mem | head
Procesos ordenados por uso de memoria.
top -b -n 1 | head -20
Salida no interactiva de top para scripts.

Prioridades

nice -n 10 comando
Ejecutar comando con prioridad baja.
renice 15 -p PID
Cambiar prioridad de proceso existente.

Administración

kill -9 PID
Terminar proceso forzosamente.
pkill -f "patron"
Terminar procesos por patrón en línea de comandos.
timeout 10s comando_largo
Ejecutar comando con límite de tiempo.

Script de Monitoreo

#!/bin/bash
# Monitoreo de procesos

THRESHOLD_CPU=90
THRESHOLD_MEM=80
LOG_FILE="/var/log/process_monitor.log"

# Obtener procesos problemáticos
PS_OUTPUT=$(ps -eo pid,%cpu,%mem,cmd --sort=-%cpu | awk -v cpu="$THRESHOLD_CPU" -v mem="$THRESHOLD_MEM" '
NR>1 && ($2 > cpu || $3 > mem) {print $0}'
)

if [[ -n "$PS_OUTPUT" ]]; then
echo "$(date) - Procesos excediendo umbrales:" >> "$LOG_FILE"
echo "$PS_OUTPUT" >> "$LOG_FILE"
# Opcional: enviar alerta por email
echo "$PS_OUTPUT" | mail -s "Alerta de procesos" admin@example.com
fi
Script para monitorear procesos que exceden umbrales de CPU/memoria.

9. Administración de Redes

Diagnóstico

ip a
Mostrar interfaces de red.
ss -tulnp
Mostrar puertos abiertos y procesos asociados.
traceroute ejemplo.com
Trazar ruta a un host.
mtr ejemplo.com
Combinación de ping y traceroute en tiempo real.

Configuración

ip addr add 192.168.1.100/24 dev eth0
Asignar dirección IP a interfaz.
ip route add default via 192.168.1.1
Agregar ruta por defecto.
nmcli connection show
Mostrar conexiones de red (NetworkManager).

Script de Configuración

#!/bin/bash
# Configuración de red avanzada

INTERFACE="eth0"
IP_ADDR="192.168.1.100"
NETMASK="24"
GATEWAY="192.168.1.1"
DNS_SERVERS="8.8.8.8 8.8.4.4"

# Configurar IP estática
ip addr flush dev "$INTERFACE"
ip addr add "$IP_ADDR/$NETMASK" dev "$INTERFACE"
ip link set dev "$INTERFACE" up

# Configurar gateway
ip route replace default via "$GATEWAY" dev "$INTERFACE"

# Configurar DNS
echo "nameserver ${DNS_SERVERS// /$'\nnameserver '}" > /etc/resolv.conf

# Verificar conexión
if ! ping -c 1 "$GATEWAY"; then
echo "Error configurando red" >&2
exit 1
fi
Script completo para configuración de red estática.

10. Seguridad y Monitoreo

Auditoría

last
Mostrar últimos inicios de sesión.
lastb
Mostrar intentos fallidos de inicio de sesión.
grep "Failed password" /var/log/auth.log
Buscar intentos fallidos de autenticación.
find / -type f -perm -4000 -o -perm -2000 -ls
Buscar archivos con bits SUID/SGID.

Script de Auditoría

#!/bin/bash
# Script de auditoría de seguridad

AUDIT_DIR="/var/log/audit"
REPORT="$AUDIT_DIR/security_report_$(date +%Y%m%d).txt"

mkdir -p "$AUDIT_DIR"

{
echo "=== Reporte de Seguridad $(date) ==="
echo -e "\nUsuarios con shell:"
grep -v "/nologin$\|/false$" /etc/passwd

echo -e "\nUsuarios con sudo:"
grep -Po '^sudo.+:\K.*$' /etc/group | tr ',' '\n'

echo -e "\nArchivos SUID/SGID:"
find / -type f -perm -4000 -o -perm -2000 2>/dev/null

echo -e "\nConexiones de red activas:"
ss -tulnp

echo -e "\nIntentos fallidos de login recientes:"
lastb | head -20
} > "$REPORT"

chmod 600 "$REPORT"
Script para generar reporte de seguridad básico.

11. Mejores Prácticas

Scripts Robustos

#!/bin/bash
# Encabezado recomendado para scripts
set -euo pipefail
IFS=$'\n\t'

# Variables en mayúsculas, locales en funciones
readonly CONFIG_FILE="/etc/miapp.conf"

# Manejo de errores
trap 'cleanup' EXIT ERR

# Funciones antes del flujo principal
validate_config() {
local config_file="$1"
[[ -f "$config_file" ]] || { echo "Archivo no existe: $config_file" >&2; return 1; }
}

# Documentación
usage() {
echo "Uso: ${0##*/} [opciones] argumentos"
echo "Descripción breve del script"
}

# Procesar argumentos
while getopts ":hv" opt; do
case "$opt" in
h) usage; exit 0 ;;
v) VERBOSE=true ;;
\?) echo "Opción inválida: -$OPTARG" >&2; exit 1 ;;
esac
done
shift $((OPTIND-1))

# Flujo principal
main() {
validate_config "$CONFIG_FILE"
# Resto del código...
}

main "$@"
Plantilla de script Bash con mejores prácticas.

Consejos Clave