Automatización de Red con Bash
La automatización de configuraciones de red es fundamental en entornos de producción donde se manejan múltiples servidores y configuraciones complejas. Con Bash podemos crear scripts robustos que configuren interfaces, establezcan rutas, gestionen servicios de red y mantengan la coherencia en toda la infraestructura.
En esta lección aprenderemos a crear scripts que automaticen tareas comunes de red, desde configuraciones básicas hasta implementaciones más complejas con validación de errores y logging avanzado.
Beneficios de la Automatización
- Consistencia: Elimina errores humanos en configuraciones repetitivas
- Escalabilidad: Permite gestionar cientos de servidores fácilmente
- Documentación: Los scripts sirven como documentación ejecutable
- Recuperación: Facilita la restauración rápida en caso de fallos
Configuración Automatizada de Interfaces
Script Base para Configuración de Interfaces
Script completo para configurar interfaces de red con validación y logging.
#!/bin/bash
# Script para Configuración Automatizada de Interfaces de Red
# Uso: ./configure_interface.sh -i interface -a address -m mask [-g gateway] [-d dns]
# Variables por defecto
SCRIPT_DIR=$(dirname "$0")
LOG_FILE="/var/log/network_config.log"
BACKUP_DIR="/etc/network/backups"
INTERFACE=""
IP_ADDRESS=""
NETMASK=""
GATEWAY=""
DNS_SERVERS=""
DHCP_MODE=false
# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Función de logging
log_message() {
local level=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
case $level in
ERROR) echo -e "${RED}[ERROR]${NC} $message" ;;
SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
WARNING) echo -e "${YELLOW}[WARNING]${NC} $message" ;;
INFO) echo -e "${BLUE}[INFO]${NC} $message" ;;
esac
}
# Función de ayuda
show_help() {
cat << EOF
Uso: $0 [OPCIONES]
OPCIONES:
-i, --interface INTERFACE Interfaz de red (ej: eth0, enp0s3)
-a, --address IP_ADDRESS Dirección IP
-m, --mask NETMASK Máscara de red (ej: 255.255.255.0 o /24)
-g, --gateway GATEWAY Gateway predeterminado
-d, --dns DNS_SERVERS Servidores DNS (separados por coma)
--dhcp Configurar interfaz para DHCP
-h, --help Mostrar esta ayuda
EJEMPLOS:
$0 -i eth0 -a 192.168.1.100 -m 255.255.255.0 -g 192.168.1.1 -d 8.8.8.8,8.8.4.4
$0 -i eth0 --dhcp
EOF
}
# Validar si se ejecuta como root
check_root() {
if [[ $EUID -ne 0 ]]; then
log_message "ERROR" "Este script debe ejecutarse como root"
exit 1
fi
}
# Validar parámetros
validate_parameters() {
if [[ -z "$INTERFACE" ]]; then
log_message "ERROR" "Debe especificar una interfaz con -i"
show_help
exit 1
fi
# Verificar si la interfaz existe
if ! ip link show "$INTERFACE" &>/dev/null; then
log_message "ERROR" "La interfaz $INTERFACE no existe"
exit 1
fi
# Validación para configuración estática
if [[ "$DHCP_MODE" == false ]]; then
if [[ -z "$IP_ADDRESS" || -z "$NETMASK" ]]; then
log_message "ERROR" "Para configuración estática necesita IP (-a) y máscara (-m)"
exit 1
fi
# Validar formato de IP
if ! [[ $IP_ADDRESS =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
log_message "ERROR" "Formato de IP inválido: $IP_ADDRESS"
exit 1
fi
fi
}
# Crear backup de configuración actual
backup_config() {
log_message "INFO" "Creando backup de configuración actual..."
mkdir -p "$BACKUP_DIR"
local backup_file="$BACKUP_DIR/interface_${INTERFACE}_$(date +%Y%m%d_%H%M%S).backup"
# Backup de configuración IP actual
ip addr show "$INTERFACE" > "$backup_file"
ip route show dev "$INTERFACE" >> "$backup_file"
log_message "SUCCESS" "Backup creado: $backup_file"
}
# Configurar interfaz estática
configure_static() {
log_message "INFO" "Configurando $INTERFACE con IP estática: $IP_ADDRESS"
# Limpiar configuración actual
ip addr flush dev "$INTERFACE"
# Asignar nueva IP
if ip addr add "$IP_ADDRESS/$NETMASK" dev "$INTERFACE"; then
log_message "SUCCESS" "IP $IP_ADDRESS asignada a $INTERFACE"
else
log_message "ERROR" "Falló la asignación de IP"
return 1
fi
# Activar interfaz
if ip link set "$INTERFACE" up; then
log_message "SUCCESS" "Interfaz $INTERFACE activada"
else
log_message "ERROR" "Falló la activación de interfaz"
return 1
fi
# Configurar gateway si se especificó
if [[ -n "$GATEWAY" ]]; then
if ip route add default via "$GATEWAY" dev "$INTERFACE" 2>/dev/null; then
log_message "SUCCESS" "Gateway $GATEWAY configurado"
else
log_message "WARNING" "Gateway ya existe o falló la configuración"
fi
fi
# Configurar DNS si se especificó
if [[ -n "$DNS_SERVERS" ]]; then
configure_dns
fi
}
# Configurar DHCP
configure_dhcp() {
log_message "INFO" "Configurando $INTERFACE para DHCP"
# Verificar si dhclient está disponible
if ! command -v dhclient &> /dev/null; then
log_message "ERROR" "dhclient no está instalado"
return 1
fi
# Liberar IP actual
dhclient -r "$INTERFACE" 2>/dev/null
# Obtener nueva IP vía DHCP
if dhclient "$INTERFACE"; then
log_message "SUCCESS" "DHCP configurado para $INTERFACE"
# Mostrar IP obtenida
local obtained_ip=$(ip addr show "$INTERFACE" | grep -oP 'inet \K[\d.]+')
if [[ -n "$obtained_ip" ]]; then
log_message "INFO" "IP obtenida vía DHCP: $obtained_ip"
fi
else
log_message "ERROR" "Falló la configuración DHCP"
return 1
fi
}
# Configurar DNS
configure_dns() {
log_message "INFO" "Configurando servidores DNS..."
# Backup de resolv.conf
cp /etc/resolv.conf /etc/resolv.conf.backup.$(date +%Y%m%d_%H%M%S)
# Agregar servidores DNS
IFS=',' read -ra DNS_ARRAY <<< "$DNS_SERVERS"
for dns in "${DNS_ARRAY[@]}"; do
dns=$(echo "$dns" | xargs) # Trim whitespace
echo "nameserver $dns" >> /etc/resolv.conf
log_message "INFO" "DNS agregado: $dns"
done
}
# Verificar configuración
verify_config() {
log_message "INFO" "Verificando configuración..."
# Mostrar configuración actual
echo -e "\n${BLUE}=== Configuración de $INTERFACE ===${NC}"
ip addr show "$INTERFACE"
echo -e "\n${BLUE}=== Rutas ===${NC}"
ip route show dev "$INTERFACE"
# Test de conectividad
if [[ -n "$GATEWAY" ]]; then
echo -e "\n${BLUE}=== Test de conectividad al gateway ===${NC}"
if ping -c 3 -W 5 "$GATEWAY" &>/dev/null; then
log_message "SUCCESS" "Conectividad al gateway OK"
else
log_message "WARNING" "Sin conectividad al gateway"
fi
fi
}
# Procesar argumentos
while [[ $# -gt 0 ]]; do
case $1 in
-i|--interface)
INTERFACE="$2"
shift 2
;;
-a|--address)
IP_ADDRESS="$2"
shift 2
;;
-m|--mask)
NETMASK="$2"
shift 2
;;
-g|--gateway)
GATEWAY="$2"
shift 2
;;
-d|--dns)
DNS_SERVERS="$2"
shift 2
;;
--dhcp)
DHCP_MODE=true
shift
;;
-h|--help)
show_help
exit 0
;;
*)
log_message "ERROR" "Opción desconocida: $1"
show_help
exit 1
;;
esac
done
# Función principal
main() {
log_message "INFO" "Iniciando configuración de interfaz de red..."
check_root
validate_parameters
backup_config
if [[ "$DHCP_MODE" == true ]]; then
configure_dhcp
else
configure_static
fi
verify_config
log_message "SUCCESS" "Configuración completada exitosamente"
}
# Ejecutar si es llamado directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
Gestión Automática de Rutas
Script para Configuración de Rutas Estáticas
Automatización de la configuración de rutas estáticas con validación y persistencia.
#!/bin/bash
# Script para Gestión Automatizada de Rutas
# Uso: ./manage_routes.sh [add|del|list|save|load] [opciones]
ROUTES_CONFIG_FILE="/etc/network/static-routes"
LOG_FILE="/var/log/route_management.log"
# Colores
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_message() {
local level=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
case $level in
ERROR) echo -e "${RED}[ERROR]${NC} $message" ;;
SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
WARNING) echo -e "${YELLOW}[WARNING]${NC} $message" ;;
INFO) echo -e "${BLUE}[INFO]${NC} $message" ;;
esac
}
# Verificar privilegios de root
check_root() {
if [[ $EUID -ne 0 ]]; then
log_message "ERROR" "Se requieren privilegios de root"
exit 1
fi
}
# Validar dirección de red
validate_network() {
local network=$1
if [[ ! $network =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
log_message "ERROR" "Formato de red inválido: $network"
return 1
fi
return 0
}
# Validar gateway
validate_gateway() {
local gateway=$1
if [[ ! $gateway =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
log_message "ERROR" "Formato de gateway inválido: $gateway"
return 1
fi
return 0
}
# Agregar ruta
add_route() {
local network=$1
local gateway=$2
local interface=$3
if ! validate_network "$network" || ! validate_gateway "$gateway"; then
return 1
fi
# Verificar si la ruta ya existe
if ip route show "$network" | grep -q "via $gateway"; then
log_message "WARNING" "La ruta $network via $gateway ya existe"
return 0
fi
# Agregar la ruta
local route_cmd="ip route add $network via $gateway"
if [[ -n "$interface" ]]; then
route_cmd="$route_cmd dev $interface"
fi
if eval "$route_cmd"; then
log_message "SUCCESS" "Ruta agregada: $network via $gateway"
# Guardar en archivo de configuración para persistencia
echo "$route_cmd" >> "$ROUTES_CONFIG_FILE"
return 0
else
log_message "ERROR" "Falló al agregar ruta: $network via $gateway"
return 1
fi
}
# Eliminar ruta
delete_route() {
local network=$1
local gateway=$2
if ! validate_network "$network" || ! validate_gateway "$gateway"; then
return 1
fi
# Eliminar la ruta
if ip route del "$network" via "$gateway"; then
log_message "SUCCESS" "Ruta eliminada: $network via $gateway"
# Remover del archivo de configuración
if [[ -f "$ROUTES_CONFIG_FILE" ]]; then
sed -i "\|$network via $gateway|d" "$ROUTES_CONFIG_FILE"
fi
return 0
else
log_message "ERROR" "Falló al eliminar ruta: $network via $gateway"
return 1
fi
}
# Listar rutas
list_routes() {
echo -e "${BLUE}=== Rutas actuales del sistema ===${NC}"
ip route show
echo -e "\n${BLUE}=== Rutas estáticas configuradas ===${NC}"
if [[ -f "$ROUTES_CONFIG_FILE" ]]; then
cat "$ROUTES_CONFIG_FILE"
else
echo "No hay rutas estáticas guardadas"
fi
}
# Guardar rutas actuales
save_routes() {
local save_file=${1:-"$ROUTES_CONFIG_FILE"}
log_message "INFO" "Guardando rutas actuales en $save_file"
# Crear directorio si no existe
mkdir -p "$(dirname "$save_file")"
# Guardar todas las rutas no predeterminadas
ip route show | grep -v '^default' | while read -r route; do
echo "ip route add $route"
done > "$save_file"
log_message "SUCCESS" "Rutas guardadas en $save_file"
}
# Cargar rutas desde archivo
load_routes() {
local load_file=${1:-"$ROUTES_CONFIG_FILE"}
if [[ ! -f "$load_file" ]]; then
log_message "ERROR" "Archivo de rutas no encontrado: $load_file"
return 1
fi
log_message "INFO" "Cargando rutas desde $load_file"
while IFS= read -r route_cmd; do
if [[ -n "$route_cmd" && ! "$route_cmd" =~ ^# ]]; then
if eval "$route_cmd"; then
log_message "SUCCESS" "Ruta cargada: $route_cmd"
else
log_message "ERROR" "Falló al cargar: $route_cmd"
fi
fi
done < "$load_file"
}
# Mostrar ayuda
show_help() {
cat << EOF
Uso: $0 COMANDO [OPCIONES]
COMANDOS:
add NETWORK GATEWAY [INTERFACE] - Agregar ruta estática
del NETWORK GATEWAY - Eliminar ruta estática
list - Listar todas las rutas
save [ARCHIVO] - Guardar rutas actuales
load [ARCHIVO] - Cargar rutas desde archivo
EJEMPLOS:
$0 add 192.168.2.0/24 192.168.1.1 eth0
$0 del 192.168.2.0/24 192.168.1.1
$0 list
$0 save /etc/network/my-routes
$0 load /etc/network/my-routes
EOF
}
# Función principal
main() {
check_root
case "${1:-}" in
add)
if [[ $# -lt 3 ]]; then
log_message "ERROR" "Uso: $0 add NETWORK GATEWAY [INTERFACE]"
exit 1
fi
add_route "$2" "$3" "$4"
;;
del|delete)
if [[ $# -lt 3 ]]; then
log_message "ERROR" "Uso: $0 del NETWORK GATEWAY"
exit 1
fi
delete_route "$2" "$3"
;;
list)
list_routes
;;
save)
save_routes "$2"
;;
load)
load_routes "$2"
;;
-h|--help|help)
show_help
exit 0
;;
*)
log_message "ERROR" "Comando desconocido: ${1:-}"
show_help
exit 1
;;
esac
}
# Ejecutar función principal
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
Configuración de Firewall Automatizada
Script para iptables
Automatización de reglas de firewall con templates y validación.
#!/bin/bash
# Script para Gestión Automatizada de Firewall (iptables)
# Uso: ./firewall_manager.sh [start|stop|status|reset|add-rule|save|load]
FIREWALL_CONFIG="/etc/iptables/rules.v4"
BACKUP_DIR="/etc/iptables/backups"
LOG_FILE="/var/log/firewall.log"
# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_message() {
local level=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
case $level in
ERROR) echo -e "${RED}[ERROR]${NC} $message" ;;
SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
WARNING) echo -e "${YELLOW}[WARNING]${NC} $message" ;;
INFO) echo -e "${BLUE}[INFO]${NC} $message" ;;
esac
}
check_root() {
if [[ $EUID -ne 0 ]]; then
log_message "ERROR" "Se requieren privilegios de root"
exit 1
fi
}
# Crear backup de reglas actuales
backup_rules() {
mkdir -p "$BACKUP_DIR"
local backup_file="$BACKUP_DIR/iptables_$(date +%Y%m%d_%H%M%S).backup"
iptables-save > "$backup_file"
log_message "SUCCESS" "Backup creado: $backup_file"
}
# Configuración básica del firewall
setup_basic_firewall() {
log_message "INFO" "Configurando reglas básicas del firewall..."
# Limpiar reglas existentes
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
# Políticas por defecto
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Permitir loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Permitir conexiones establecidas y relacionadas
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Permitir SSH (puerto 22) - IMPORTANTE para no perder acceso
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Permitir ping (ICMP)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
log_message "SUCCESS" "Reglas básicas configuradas"
}
# Agregar regla personalizada
add_custom_rule() {
local protocol=$1
local port=$2
local action=${3:-ACCEPT}
local source=${4:-"0.0.0.0/0"}
if [[ -z "$protocol" || -z "$port" ]]; then
log_message "ERROR" "Uso: add_rule PROTOCOL PORT [ACTION] [SOURCE]"
return 1
fi
# Validar protocolo
if [[ ! "$protocol" =~ ^(tcp|udp|icmp)$ ]]; then
log_message "ERROR" "Protocolo inválido. Use: tcp, udp, icmp"
return 1
fi
# Validar puerto
if [[ ! "$port" =~ ^[0-9]+$ ]] || [[ $port -lt 1 || $port -gt 65535 ]]; then
log_message "ERROR" "Puerto inválido: $port"
return 1
fi
# Agregar regla
local rule_cmd="iptables -A INPUT -p $protocol --dport $port -s $source -j $action"
if eval "$rule_cmd"; then
log_message "SUCCESS" "Regla agregada: $protocol/$port desde $source -> $action"
else
log_message "ERROR" "Falló al agregar regla"
return 1
fi
}
# Iniciar firewall
start_firewall() {
log_message "INFO" "Iniciando firewall..."
backup_rules
# Si existe configuración guardada, cargarla
if [[ -f "$FIREWALL_CONFIG" ]]; then
log_message "INFO" "Cargando configuración desde $FIREWALL_CONFIG"
if iptables-restore < "$FIREWALL_CONFIG"; then
log_message "SUCCESS" "Configuración cargada exitosamente"
else
log_message "WARNING" "Falló al cargar configuración, usando básica"
setup_basic_firewall
fi
else
log_message "INFO" "No se encontró configuración guardada, usando básica"
setup_basic_firewall
fi
# Habilitar firewall en systemd si está disponible
if command -v systemctl &> /dev/null; then
systemctl enable iptables 2>/dev/null || true
fi
log_message "SUCCESS" "Firewall iniciado"
}
# Detener firewall
stop_firewall() {
log_message "INFO" "Deteniendo firewall..."
# Cambiar políticas a ACCEPT
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# Limpiar todas las reglas
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
log_message "SUCCESS" "Firewall detenido (todas las reglas eliminadas)"
}
# Mostrar estado
show_status() {
echo -e "${BLUE}=== Estado del Firewall ===${NC}"
# Mostrar políticas
echo -e "\n${YELLOW}Políticas por defecto:${NC}"
iptables -L -n | head -3
# Mostrar reglas INPUT
echo -e "\n${YELLOW}Reglas INPUT:${NC}"
iptables -L INPUT -n --line-numbers
# Mostrar estadísticas
echo -e "\n${YELLOW}Estadísticas:${NC}"
iptables -L -n -v | head -10
}
# Guardar configuración actual
save_config() {
local save_file=${1:-"$FIREWALL_CONFIG"}
mkdir -p "$(dirname "$save_file")"
if iptables-save > "$save_file"; then
log_message "SUCCESS" "Configuración guardada en $save_file"
else
log_message "ERROR" "Falló al guardar configuración"
return 1
fi
}
# Resetear a configuración básica
reset_firewall() {
log_message "INFO" "Reseteando firewall a configuración básica..."
backup_rules
setup_basic_firewall
save_config
log_message "SUCCESS" "Firewall reseteado"
}
# Mostrar ayuda
show_help() {
cat << EOF
Uso: $0 COMANDO [OPCIONES]
COMANDOS:
start - Iniciar firewall con configuración guardada
stop - Detener firewall (permitir todo)
status - Mostrar estado actual
reset - Resetear a configuración básica
save [ARCHIVO] - Guardar configuración actual
add-rule PROTOCOL PORT [ACTION] [SOURCE]
- Agregar regla personalizada
EJEMPLOS:
$0 start
$0 add-rule tcp 80 ACCEPT
$0 add-rule tcp 443 ACCEPT 192.168.1.0/24
$0 save
$0 status
EOF
}
# Función principal
main() {
check_root
case "${1:-}" in
start)
start_firewall
;;
stop)
stop_firewall
;;
status)
show_status
;;
reset)
reset_firewall
;;
save)
save_config "$2"
;;
add-rule)
if [[ $# -lt 3 ]]; then
log_message "ERROR" "Uso: $0 add-rule PROTOCOL PORT [ACTION] [SOURCE]"
exit 1
fi
add_custom_rule "$2" "$3" "$4" "$5"
;;
-h|--help|help)
show_help
exit 0
;;
*)
log_message "ERROR" "Comando desconocido: ${1:-}"
show_help
exit 1
;;
esac
}
# Ejecutar función principal
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
Gestión de Servicios de Red
Script para Gestión de Servicios
Automatización del control de servicios de red comunes.
#!/bin/bash
# Script para Gestión de Servicios de Red
# Servicios: SSH, Apache, Nginx, NetworkManager, etc.
LOG_FILE="/var/log/network_services.log"
# Lista de servicios de red comunes
NETWORK_SERVICES=(
"ssh"
"apache2"
"nginx"
"NetworkManager"
"systemd-networkd"
"dnsmasq"
"bind9"
"openvpn"
)
# Colores
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_message() {
local level=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
case $level in
ERROR) echo -e "${RED}[ERROR]${NC} $message" ;;
SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
WARNING) echo -e "${YELLOW}[WARNING]${NC} $message" ;;
INFO) echo -e "${BLUE}[INFO]${NC} $message" ;;
esac
}
# Verificar si systemctl está disponible
check_systemctl() {
if ! command -v systemctl &> /dev/null; then
log_message "ERROR" "systemctl no está disponible"
exit 1
fi
}
# Obtener estado de un servicio
get_service_status() {
local service=$1
if systemctl is-active "$service" &>/dev/null; then
echo "running"
elif systemctl is-enabled "$service" &>/dev/null; then
echo "stopped"
else
echo "disabled"
fi
}
# Mostrar estado de todos los servicios
show_all_status() {
echo -e "${BLUE}=== Estado de Servicios de Red ===${NC}"
printf "%-20s %-10s %-10s %s\n" "SERVICIO" "ESTADO" "ENABLED" "DESCRIPCIÓN"
echo "────────────────────────────────────────────────────────────────"
for service in "${NETWORK_SERVICES[@]}"; do
# Verificar si el servicio existe
if systemctl list-unit-files | grep -q "^$service.service"; then
local status=$(get_service_status "$service")
local enabled="No"
if systemctl is-enabled "$service" &>/dev/null; then
enabled="Sí"
fi
# Obtener descripción corta
local description=$(systemctl show "$service" --property=Description --value 2>/dev/null | cut -c1-30)
# Colorear según estado
case $status in
running) printf "%-20s ${GREEN}%-10s${NC} %-10s %s\n" "$service" "$status" "$enabled" "$description" ;;
stopped) printf "%-20s ${YELLOW}%-10s${NC} %-10s %s\n" "$service" "$status" "$enabled" "$description" ;;
disabled) printf "%-20s ${RED}%-10s${NC} %-10s %s\n" "$service" "$status" "$enabled" "$description" ;;
esac
fi
done
}
# Controlar un servicio específico
control_service() {
local action=$1
local service=$2
if [[ -z "$service" ]]; then
log_message "ERROR" "Debe especificar un servicio"
return 1
fi
# Verificar si el servicio existe
if ! systemctl list-unit-files | grep -q "^$service.service"; then
log_message "ERROR" "El servicio $service no existe"
return 1
fi
case $action in
start)
if systemctl start "$service"; then
log_message "SUCCESS" "Servicio $service iniciado"
else
log_message "ERROR" "Falló al iniciar $service"
return 1
fi
;;
stop)
if systemctl stop "$service"; then
log_message "SUCCESS" "Servicio $service detenido"
else
log_message "ERROR" "Falló al detener $service"
return 1
fi
;;
restart)
if systemctl restart "$service"; then
log_message "SUCCESS" "Servicio $service reiniciado"
else
log_message "ERROR" "Falló al reiniciar $service"
return 1
fi
;;
enable)
if systemctl enable "$service"; then
log_message "SUCCESS" "Servicio $service habilitado al inicio"
else
log_message "ERROR" "Falló al habilitar $service"
return 1
fi
;;
disable)
if systemctl disable "$service"; then
log_message "SUCCESS" "Servicio $service deshabilitado del inicio"
else
log_message "ERROR" "Falló al deshabilitar $service"
return 1
fi
;;
status)
systemctl status "$service" --no-pager
;;
*)
log_message "ERROR" "Acción desconocida: $action"
return 1
;;
esac
}
# Reiniciar servicios de red críticos
restart_critical_services() {
local critical_services=("NetworkManager" "ssh" "systemd-networkd")
log_message "INFO" "Reiniciando servicios críticos de red..."
for service in "${critical_services[@]}"; do
if systemctl is-active "$service" &>/dev/null; then
log_message "INFO" "Reiniciando $service..."
if systemctl restart "$service"; then
log_message "SUCCESS" "$service reiniciado correctamente"
else
log_message "ERROR" "Falló al reiniciar $service"
fi
else
log_message "WARNING" "$service no está ejecutándose"
fi
done
}
# Diagnosticar problemas de servicios
diagnose_services() {
echo -e "${BLUE}=== Diagnóstico de Servicios de Red ===${NC}"
for service in "${NETWORK_SERVICES[@]}"; do
if systemctl list-unit-files | grep -q "^$service.service"; then
local status=$(get_service_status "$service")
if [[ "$status" == "disabled" ]] || ! systemctl is-active "$service" &>/dev/null; then
echo -e "\n${YELLOW}Analizando $service...${NC}"
# Mostrar últimos logs
echo "Últimos logs:"
journalctl -u "$service" --no-pager -n 5 --since "1 hour ago" 2>/dev/null || echo " Sin logs recientes"
# Verificar archivos de configuración principales
case $service in
ssh)
[[ -f /etc/ssh/sshd_config ]] && echo " Config: /etc/ssh/sshd_config existe" || echo " Config: /etc/ssh/sshd_config FALTA"
;;
apache2)
[[ -f /etc/apache2/apache2.conf ]] && echo " Config: /etc/apache2/apache2.conf existe" || echo " Config: /etc/apache2/apache2.conf FALTA"
;;
nginx)
[[ -f /etc/nginx/nginx.conf ]] && echo " Config: /etc/nginx/nginx.conf existe" || echo " Config: /etc/nginx/nginx.conf FALTA"
;;
esac
fi
fi
done
}
# Mostrar ayuda
show_help() {
cat << EOF
Uso: $0 COMANDO [OPCIONES]
COMANDOS:
status - Mostrar estado de todos los servicios
start|stop|restart|enable|disable SERVICE
- Controlar servicio específico
restart-critical - Reiniciar servicios críticos
diagnose - Diagnosticar problemas
EJEMPLOS:
$0 status
$0 start ssh
$0 restart nginx
$0 enable apache2
$0 restart-critical
$0 diagnose
EOF
}
# Función principal
main() {
check_systemctl
case "${1:-}" in
status)
show_all_status
;;
start|stop|restart|enable|disable)
control_service "$1" "$2"
;;
restart-critical)
restart_critical_services
;;
diagnose)
diagnose_services
;;
-h|--help|help)
show_help
exit 0
;;
*)
log_message "ERROR" "Comando desconocido: ${1:-}"
show_help
exit 1
;;
esac
}
# Ejecutar si es llamado directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
Ejercicio Práctico Avanzado
Proyecto: Script de Configuración de Red Completa
Crea un script maestro que integre todas las funcionalidades:
- Configuración de múltiples interfaces
- Configuración de rutas estáticas
- Configuración básica de firewall
- Gestión de servicios de red
- Validación y testing automático
- Logging centralizado
Precauciones Importantes
- Backup: Siempre hacer backup antes de cambios importantes
- Testing: Probar scripts en entornos de desarrollo primero
- SSH: Mantener acceso SSH activo durante cambios de red
- Rollback: Implementar mecanismos de rollback automático
Ejercicios Adicionales
- Modifica los scripts para trabajar con IPv6
- Integra notificaciones por email en caso de fallos
- Añade soporte para configuración desde archivos YAML/JSON
- Implementa un modo "dry-run" para simular cambios
- Crea templates para diferentes tipos de servidores (web, DB, etc.)