Práctica 6 — Software, Tiempo y Automatización
Setup — ejecutar una sola vez
Sección titulada “Setup — ejecutar una sola vez"mkdir -p ~/practica6/{work,entrega}sudo apt updateTodo lo que se pida “guardar” debe ir dentro de ~/practica6/entrega/.
Ejercicio 6.1 — Gestión avanzada de paquetes con apt
Sección titulada “Ejercicio 6.1 — Gestión avanzada de paquetes con apt"Contexto
Sección titulada “Contexto"El repositorio de Debian/Ubuntu es la única fuente de software de confianza para un sysadmin LFCS. Aquí practicarás el ciclo completo: buscar, instalar, inspeccionar dependencias, gestionar repositorios y recuperarte de paquetes rotos.
- Audita el estado inicial del sistema de paquetes antes de modificar nada:
# Número total de paquetes instaladosdpkg -l | grep "^ii" | wc -l
# Ver las fuentes de repositorios activascat /etc/apt/sources.listls /etc/apt/sources.list.d/ 2>/dev/null
# Paquetes con actualizaciones pendientesapt list --upgradable 2>/dev/null | head -15Guarda la salida en ~/practica6/entrega/61_estado_inicial.txt. Identifica con comentarios # qué repositorios tiene activos el sistema.
- Diferencia entre
dpkgyapt. Instala y compara el nivel de información de cada herramienta:
# Instala dos herramientas útilessudo apt install -y htop tree
# dpkg: información de bajo nivel del paquete instaladodpkg -l htopdpkg -L htop # archivos que instaló este paquete
# apt-cache: búsqueda en los repositoriosapt-cache show htop | head -20apt-cache depends htop # dependencias del paqueteapt-cache rdepends --installed htop | head -10 # qué paquetes dependen de htopGuarda en ~/practica6/entrega/61_dpkg_vs_apt.txt. Añade un comentario # explicando la diferencia entre dpkg (gestión local) y apt (gestión con repositorios).
- Practica el ciclo completo de instalación y eliminación:
# Instala curlsudo apt install -y curl
# Verifica que está instalado y su versióncurl --version | head -1dpkg -l curl | grep "^ii"
# Elimina pero conserva la configuraciónsudo apt remove curldpkg -l curl | grep "^rc" # "rc" = eliminado pero con configuraciónls /etc/curl* 2>/dev/null || echo "(no hay ficheros de configuración de curl)"
# Elimina también la configuración (purge)sudo apt purge curldpkg -l curl 2>/dev/null | grep curl || echo "curl eliminado completamente"
# Limpia paquetes huérfanos que ya no son necesariossudo apt autoremove -yGuarda en ~/practica6/entrega/61_ciclo_paquete.txt.
- Instala un paquete
.debmanualmente condpkg:
# Descarga bat (cat mejorado con sintaxis coloreada) como .debwget "https://github.com/sharkdp/bat/releases/download/v0.24.0/bat_0.24.0_amd64.deb" \ -O /tmp/bat.deb
# Instala con dpkgsudo dpkg -i /tmp/bat.deb
# Si falla por dependencias, corrígelas automáticamente:sudo apt install -f -y
# Prueba que funcionabat /etc/hostsGuarda en ~/practica6/entrega/61_dpkg_manual.txt.
- Añade un repositorio externo con clave GPG (práctica real de producción):
# Inspecciona el fichero sources.list actualcat /etc/apt/sources.list
# Crea un fichero de repositorio personalizado (usando el repositorio stable de Debian como ejemplo)# En producción añadirías aquí repositorios de terceros (Docker, NodeJS, etc.)cat /etc/apt/sources.list | grep "^deb " | head -3
# Comprueba la integridad de los repositorios actualessudo apt-get update 2>&1 | grep -E "error|warning|OK" | head -10Guarda en ~/practica6/entrega/61_repositorios.txt. Explica con un comentario # por qué es peligroso añadir repositorios de terceros sin verificar su clave GPG.
Ejercicio 6.2 — Compilación de software desde el código fuente
Sección titulada “Ejercicio 6.2 — Compilación de software desde el código fuente"Contexto
Sección titulada “Contexto"Cuando un paquete no existe en los repositorios o necesitas una versión específica, compilas desde el código fuente. El ciclo GNU (./configure → make → make install) es una habilidad clave del examen LFCS.
Setup — herramientas de compilación
Sección titulada “Setup — herramientas de compilación"sudo apt install -y build-essential libssl-dev wget- Audita las herramientas de compilación disponibles:
# Versión del compilador Cgcc --version
# Make: el orquestador de compilaciónmake --version | head -2
# Ver las librerías dinámicas del sistemaldconfig -p | wc -lGuarda en ~/practica6/entrega/62_entorno_compilacion.txt.
- Descarga y prepara el código fuente de
htop(versión de referencia desde código):
# Crea un directorio de trabajo limpiomkdir -p ~/practica6/work/compilacioncd ~/practica6/work/compilacion
# Descarga el tarball del código fuente de htopwget "https://github.com/htop-dev/htop/releases/download/3.3.0/htop-3.3.0.tar.xz" \ -O htop-3.3.0.tar.xz
# Extrae el tarballtar xf htop-3.3.0.tar.xz
# Inspecciona la estructura del proyecto descargadols -lacd htop-3.3.0ls -laGuarda la estructura del directorio en ~/practica6/entrega/62_estructura_fuente.txt. Identifica con comentarios # para qué sirven los ficheros configure, Makefile.am y README.
- Ejecuta el ciclo de compilación GNU completo:
cd ~/practica6/work/compilacion/htop-3.3.0
# Paso 1: configure — detecta el entorno y crea el Makefile definitivo# --prefix define dónde se instalará (aquí usamos /usr/local para no contaminar el sistema)sudo apt install -y libncurses-dev libnl-3-dev libnl-genl-3-dev libsensors-dev./configure --prefix=/usr/local 2>&1 | tail -10
# Paso 2: make — compila el código fuente en binarios# -j$(nproc) usa todos los núcleos disponibles para acelerar la compilaciónmake -j$(nproc) 2>&1 | tail -5
# Paso 3: make install — copia los binarios compilados al destinosudo make install 2>&1 | tail -5
# Verifica que se instaló correctamentewhich htop/usr/local/bin/htop --versionGuarda la salida de los tres pasos en ~/practica6/entrega/62_compilacion.txt.
- Inspecciona las dependencias de librerías dinámicas con
ldd:
# ldd muestra qué librerías .so necesita el binario en tiempo de ejecuciónldd /usr/local/bin/htop
# Compara con el htop del sistema (si existe)ldd /usr/bin/htop 2>/dev/null || echo "htop del sistema no encontrado"
# Si una librería aparece como "not found", el binario no podrá ejecutarse# ldconfig actualiza la caché de librerías dinámicassudo ldconfigGuarda en ~/practica6/entrega/62_ldd.txt. Explica con un comentario # qué significa “not found” en la salida de ldd y cómo se resolvería.
- Desinstala el programa compilado manualmente:
cd ~/practica6/work/compilacion/htop-3.3.0
# make uninstall solo funciona si el Makefile lo soportasudo make uninstall 2>&1 | head -10 || echo "Uninstall no soportado"
# Alternativa manual: eliminar los ficheros copiados por make installsudo rm -f /usr/local/bin/htopsudo rm -f /usr/local/share/man/man1/htop.1which htop && echo "htop sigue instalado" || echo "htop eliminado correctamente"Guarda en ~/practica6/entrega/62_desinstalacion.txt. Añade un comentario # sobre por qué la compilación manual complica la gestión de actualizaciones frente a apt.
Ejercicio 6.3 — Sincronización de tiempo (NTP)
Sección titulada “Ejercicio 6.3 — Sincronización de tiempo (NTP)"Contexto
Sección titulada “Contexto"Un servidor con la hora incorrecta es un servidor enfermo. Los certificados TLS fallan, los logs son inútiles para forensics y las bases de datos distribuidas pueden corromperse. Aquí aprenderás a diagnosticar y corregir la sincronización horaria.
- Audita el estado actual del tiempo en el sistema:
# Muestra hora del sistema, zona horaria y estado de sincronizacióntimedatectl status
# Diferencia entre reloj hardware (BIOS) y reloj del sistema (kernel)sudo hwclock --show # reloj BIOSdate # reloj del sistema
# Ver la zona horaria actualls -la /etc/localtimeGuarda la salida en ~/practica6/entrega/63_tiempo_inicial.txt. Identifica con comentarios # si el sistema ya está sincronizando NTP y con qué servicio.
- Cambia la zona horaria del sistema:
# Lista las zonas disponibles de Europatimedatectl list-timezones | grep Europe
# Cambia temporalmente a Madrid (o mantén la tuya si ya es correcta)sudo timedatectl set-timezone Europe/Madrid
# Verifica el cambiotimedatectl status | grep "Time zone"date
# Opcional: vuelve a la zona original después de documentar# sudo timedatectl set-timezone Europe/LondonGuarda en ~/practica6/entrega/63_timezone.txt.
- Instala y configura
chronycomo servidor NTP:
# Instala chronysudo apt install -y chrony
# Verifica que el servicio arrancósystemctl status chrony --no-pager | head -10
# Estado de sincronización: muestra los servidores NTP y el offset actualchronyc tracking
# Fuentes NTP actuales y su calidad (Poll, Reach, LastRx, Offset)chronyc sources -vGuarda en ~/practica6/entrega/63_chrony_tracking.txt.
- Configura
chronycon servidores NTP españoles:
# Edita la configuración de chronysudo nano /etc/chrony/chrony.confSustituye los servidores pool existentes por los servidores de España:
# Servidores NTP del pool español (alta disponibilidad)pool es.pool.ntp.org iburstserver 0.es.pool.ntp.org iburstserver 1.es.pool.ntp.org iburst# Recarga la configuraciónsudo systemctl restart chrony
# Fuerza la sincronización inmediata (útil si el reloj lleva mucho tiempo mal)sudo chronyc makestep
# Verifica las nuevas fuenteschronyc sources -vGuarda los cambios del fichero de configuración y la salida de sources en ~/practica6/entrega/63_chrony_config.txt.
- Compara los dos mecanismos de sincronización NTP disponibles en Debian:
# Muestra el estado de systemd-timesyncd (alternativa más ligera a chrony)systemctl status systemd-timesyncd --no-pager | head -8
# En sistemas con chrony activo, timesyncd queda desactivadotimedatectl show-timesync 2>/dev/null || echo "timesyncd no activo"
# Muestra qué servicio gestiona el NTP ahora mismotimedatectl status | grep NTPGuarda en ~/practica6/entrega/63_comparativa_ntp.txt. Explica con un comentario # cuándo usarías chrony frente a systemd-timesyncd.
Ejercicio 6.4 — Automatización con cron y systemd timers
Sección titulada “Ejercicio 6.4 — Automatización con cron y systemd timers"Contexto
Sección titulada “Contexto"Un sysadmin que trabaja manualmente en tareas repetibles está haciendo mal su trabajo. Cron y systemd timers son las dos herramientas de automatización del examen LFCS. Aquí dominarás ambas y comprenderás cuándo usar cada una.
Setup — script base para automatizar
Sección titulada “Setup — script base para automatizar"# Crea un script de limpieza de logs de pruebasudo nano /usr/local/bin/limpia_logs.shEscribe:
#!/bin/bash# limpia_logs.sh — elimina logs de /tmp mayores de 7 díasLOGFILE="/var/log/limpieza.log"FECHA=$(date '+%Y-%m-%d %H:%M:%S')ELIMINADOS=$(find /tmp -name "*.log" -mtime +7 -type f 2>/dev/null | wc -l)
find /tmp -name "*.log" -mtime +7 -type f -delete 2>/dev/null
echo "[$FECHA] Limpieza completada. Ficheros eliminados: $ELIMINADOS" >> "$LOGFILE"sudo chmod +x /usr/local/bin/limpia_logs.sh
# Prueba manualsudo /usr/local/bin/limpia_logs.shcat /var/log/limpieza.logTarea 1 — Cron: automatización clásica
Sección titulada “Tarea 1 — Cron: automatización clásica"# Inspecciona los crontabs del sistemals -la /etc/cron.{d,daily,weekly,monthly}/ 2>/dev/nullcat /etc/crontab
# Abre el crontab personal del usuario actualcrontab -eAñade las siguientes tareas al crontab (usa el editor que se abra):
# Sintaxis: minuto hora día-mes mes día-semana comando# m h dom mon dow command
# Ejecuta el script de limpieza cada día a las 3:00 AM0 3 * * * /usr/local/bin/limpia_logs.sh
# Ejecuta una verificación de disco cada lunes a las 8:000 8 * * 1 df -h / >> /var/log/disco_semanal.log
# Ejecuta un backup de /etc cada domingo a las 23:000 23 * * 0 tar czf /tmp/backup_etc_$(date +\%Y\%m\%d).tar.gz /etc 2>/dev/nullVerifica el crontab:
# Lista todas las tareas del usuario actualcrontab -l
# Lista el crontab del sistema (root)sudo crontab -l 2>/dev/null || echo "sin crontab de root"Guarda la salida de crontab -l en ~/practica6/entrega/64_crontab.txt.
Tarea 2 — at: ejecución diferida única
Sección titulada “Tarea 2 — at: ejecución diferida única"# Instala at si no está disponiblesudo apt install -y atsudo systemctl enable --now atd
# Programa una tarea para ejecutarse en 2 minutosecho "df -h / >> /var/log/disco_at.log && date >> /var/log/disco_at.log" | at now + 2 minutes
# Lista las tareas programadas con atatq
# Espera 2 minutos y verifica la ejecuciónsleep 120cat /var/log/disco_at.log 2>/dev/null || echo "El fichero aún no existe"Guarda en ~/practica6/entrega/64_at.txt. Explica con un comentario # la diferencia entre at y cron.
Tarea 3 — systemd timer: la alternativa moderna
Sección titulada “Tarea 3 — systemd timer: la alternativa moderna"Crea una unidad de servicio y su timer correspondiente:
sudo nano /etc/systemd/system/limpia-logs.service[Unit]Description=Limpieza automática de logs de /tmpAfter=local-fs.target
[Service]Type=oneshotExecStart=/usr/local/bin/limpia_logs.sh
[Install]WantedBy=multi-user.targetsudo nano /etc/systemd/system/limpia-logs.timer[Unit]Description=Timer para limpieza diaria de logs (3:00 AM)
[Timer]OnCalendar=*-*-* 03:00:00Persistent=true
[Install]WantedBy=timers.targetsudo systemctl daemon-reloadsudo systemctl enable limpia-logs.timersudo systemctl start limpia-logs.timer
# Verifica el estado y la próxima ejecuciónsystemctl status limpia-logs.timer --no-pagersystemctl list-timers | grep limpia
# Fuerza ejecución inmediata para probarsudo systemctl start limpia-logs.servicejournalctl -u limpia-logs.service -n 10 --no-pagerGuarda en ~/practica6/entrega/64_timer.txt:
{ echo "--- Estado del timer ---" systemctl status limpia-logs.timer --no-pager echo "" echo "--- Próxima ejecución ---" systemctl list-timers | grep limpia echo "" echo "--- Log de ejecución ---" journalctl -u limpia-logs.service -n 5 --no-pager echo "" echo "--- Unidad service ---" cat /etc/systemd/system/limpia-logs.service echo "" echo "--- Unidad timer ---" cat /etc/systemd/system/limpia-logs.timer} > ~/practica6/entrega/64_timer.txtEjercicio 6.5 — Scripting Bash para sysadmins
Sección titulada “Ejercicio 6.5 — Scripting Bash para sysadmins"Contexto
Sección titulada “Contexto"Un sysadmin que no sabe Bash es un sysadmin lento. Los scripts automatizan diagnósticos, informes y respuestas a incidentes. Aquí construirás un script de informe completo paso a paso, incorporando las estructuras de control que aparecen en el examen LFCS.
Tarea 1 — Variables y argumentos de línea de comandos
Sección titulada “Tarea 1 — Variables y argumentos de línea de comandos"sudo nano /usr/local/bin/info_sistema.shEmpieza con las bases:
#!/bin/bash# info_sistema.sh — Informe modular del servidor# Uso: info_sistema.sh [--detalle] [--servicio nombre]
# Variables de entorno del sistemaHOSTNAME=$(hostname)FECHA=$(date '+%Y-%m-%d %H:%M:%S')USUARIO_ACTUAL=$(whoami)KERNEL=$(uname -r)
# Variables con valores por defectoMODO_DETALLE=falseSERVICIO_A_REVISAR=""
# Procesar argumentos de línea de comandoswhile [[ $# -gt 0 ]]; do case "$1" in --detalle) MODO_DETALLE=true shift ;; --servicio) SERVICIO_A_REVISAR="$2" shift 2 ;; *) echo "Opción desconocida: $1" exit 1 ;; esacdone
echo "=== INFORME DEL SERVIDOR ==="echo "Hostname: $HOSTNAME"echo "Fecha: $FECHA"echo "Usuario: $USUARIO_ACTUAL"echo "Kernel: $KERNEL"sudo chmod +x /usr/local/bin/info_sistema.sh
# Prueba básica/usr/local/bin/info_sistema.sh
# Con argumentos/usr/local/bin/info_sistema.sh --detalleTarea 2 — Condicionales y funciones
Sección titulada “Tarea 2 — Condicionales y funciones"Amplía el script añadiendo estas funciones (edita el mismo fichero):
sudo nano /usr/local/bin/info_sistema.shAñade después de las variables:
# =========================================================# FUNCIONES# =========================================================
comprobar_disco() { local PUNTO_MONTAJE="${1:-/}" local USO_PORCENTAJE USO_PORCENTAJE=$(df "$PUNTO_MONTAJE" | tail -1 | awk '{print $5}' | tr -d '%')
echo "" echo "--- Disco ($PUNTO_MONTAJE) ---" df -h "$PUNTO_MONTAJE" | tail -1
if [[ "$USO_PORCENTAJE" -ge 90 ]]; then echo "ALERTA CRÍTICA: disco al ${USO_PORCENTAJE}% — acción inmediata necesaria" elif [[ "$USO_PORCENTAJE" -ge 80 ]]; then echo "ADVERTENCIA: disco al ${USO_PORCENTAJE}% — revisar pronto" else echo "Estado: OK (${USO_PORCENTAJE}% usado)" fi}
comprobar_servicio() { local NOMBRE="$1" echo "" echo "--- Servicio: $NOMBRE ---"
if systemctl is-active --quiet "$NOMBRE"; then echo "Estado: ACTIVO" systemctl status "$NOMBRE" --no-pager | grep -E "Active:|Main PID:|Memory:" else echo "Estado: CAÍDO — revisando logs..." journalctl -u "$NOMBRE" -n 5 --no-pager 2>/dev/null fi}
mostrar_memoria() { echo "" echo "--- Memoria ---" free -h | grep -E "Mem:|Swap:"
local LIBRE_MB LIBRE_MB=$(free -m | awk '/^Mem:/{print $4}') if [[ "$LIBRE_MB" -lt 100 ]]; then echo "ALERTA: menos de 100 MB de RAM libre (${LIBRE_MB} MB)" fi}
# =========================================================# CUERPO PRINCIPAL# =========================================================
comprobar_disco "/"mostrar_memoria
if [[ "$MODO_DETALLE" == true ]]; then comprobar_disco "/var" comprobar_disco "/tmp"fi
if [[ -n "$SERVICIO_A_REVISAR" ]]; then comprobar_servicio "$SERVICIO_A_REVISAR"fi# Prueba con diferentes argumentos/usr/local/bin/info_sistema.sh/usr/local/bin/info_sistema.sh --detalle/usr/local/bin/info_sistema.sh --servicio ssh/usr/local/bin/info_sistema.sh --detalle --servicio nginxGuarda la salida de cada ejecución en ~/practica6/entrega/65_script_pruebas.txt.
Tarea 3 — Bucles y generación de informes
Sección titulada “Tarea 3 — Bucles y generación de informes"Añade un bucle que compruebe múltiples servicios de una vez:
sudo nano /usr/local/bin/informe_diario.sh#!/bin/bash# informe_diario.sh — Informe completo del servidor con bucles
LOGFILE="/var/log/informes/informe_$(date '+%Y-%m-%d').log"mkdir -p /var/log/informes
SERVICIOS_CRITICOS=("ssh" "cron" "networking")
{ echo "============================================" echo "INFORME DIARIO — $(date '+%Y-%m-%d %H:%M:%S')" echo "Servidor: $(hostname)" echo "============================================" echo ""
echo "## ESTADO DE SERVICIOS CRÍTICOS" for SERVICIO in "${SERVICIOS_CRITICOS[@]}"; do if systemctl is-active --quiet "$SERVICIO" 2>/dev/null; then ESTADO="OK" else ESTADO="CAÍDO" fi printf " %-20s %s\n" "$SERVICIO" "$ESTADO" done echo ""
echo "## USO DE DISCO" df -h | grep -v tmpfs | grep -v "Filesystem" echo ""
echo "## MEMORIA" free -h echo ""
echo "## CARGA DEL SISTEMA" uptime echo ""
echo "## ÚLTIMOS ERRORES (últimas 6 horas)" journalctl -p err --since "6 hours ago" --no-pager -n 10 2>/dev/null \ || echo "(sin errores recientes)" echo ""
echo "============================================" echo "Fin del informe"} | tee "$LOGFILE"
echo "Informe guardado: $LOGFILE"sudo chmod +x /usr/local/bin/informe_diario.sh
# Ejecuta y verificasudo /usr/local/bin/informe_diario.sh
# Lee el informe guardadols -la /var/log/informes/cat /var/log/informes/informe_$(date '+%Y-%m-%d').logGuarda la salida en ~/practica6/entrega/65_informe_diario.txt.
Tarea 4 — Manejo de errores y exit codes
Sección titulada “Tarea 4 — Manejo de errores y exit codes"sudo nano /usr/local/bin/backup_seguro.sh#!/bin/bash# backup_seguro.sh — Script con manejo de errores robustoset -euo pipefail # e=salir en error, u=variables no definidas son error, o=pipefail
# ConfiguraciónORIGEN="${1:?ERROR: debes proporcionar el directorio de origen}"DESTINO="/tmp/backups"TIMESTAMP=$(date '+%Y%m%d_%H%M%S')FICHERO_BACKUP="$DESTINO/backup_${TIMESTAMP}.tar.gz"
# Función de limpieza en caso de errorlimpiar_en_error() { echo "ERROR: backup interrumpido. Limpiando archivos parciales..." rm -f "$FICHERO_BACKUP" 2>/dev/null exit 1}trap limpiar_en_error ERR
# Verificaciones previasif [[ ! -d "$ORIGEN" ]]; then echo "ERROR: el directorio '$ORIGEN' no existe" exit 1fi
mkdir -p "$DESTINO"
echo "Iniciando backup de '$ORIGEN'..."tar czf "$FICHERO_BACKUP" "$ORIGEN" 2>/dev/null
# Verifica que el backup no está vacíoTAMANO=$(du -sh "$FICHERO_BACKUP" | cut -f1)echo "Backup completado: $FICHERO_BACKUP ($TAMANO)"sudo chmod +x /usr/local/bin/backup_seguro.sh
# Prueba con directorio válido/usr/local/bin/backup_seguro.sh /etc/apt
# Prueba con directorio inválido (debe mostrar error limpio)/usr/local/bin/backup_seguro.sh /directorio/inexistente || true
# Sin argumento (debe mostrar error)/usr/local/bin/backup_seguro.sh || true
ls -lh /tmp/backups/ 2>/dev/nullGuarda en ~/practica6/entrega/65_backup_script.txt. Explica con un comentario # para qué sirve set -euo pipefail y qué hace trap.
📤 Bloque de entrega
Sección titulada “📤 Bloque de entrega"Guarda la verificación del estado antes de empaquetar:
mkdir -p ~/practica6/entrega{ echo "=== ENTREGA PRÁCTICA 6 ===" echo ""
echo "--- 6.1: Paquetes instalados ---" dpkg -l | grep "^ii" | wc -l echo ""
echo "--- 6.1: Estado de htop ---" dpkg -l htop | grep "^ii" || echo "htop no instalado por apt" /usr/local/bin/htop --version 2>/dev/null && echo "(htop compilado disponible)" || true echo ""
echo "--- 6.2: Compilación htop ---" ls ~/practica6/work/compilacion/htop-3.3.0/ 2>/dev/null | head -5 || echo "directorio no encontrado" echo ""
echo "--- 6.3: Sincronización NTP ---" timedatectl status | grep -E "Local time|Time zone|NTP" chronyc tracking 2>/dev/null | grep -E "System time|Stratum" || echo "chrony no activo" echo ""
echo "--- 6.4: Crontab activo ---" crontab -l 2>/dev/null || echo "(sin crontab personal)" echo ""
echo "--- 6.4: Timer activo ---" systemctl status limpia-logs.timer --no-pager | grep -E "Active:|Next" echo ""
echo "--- 6.4: Próxima ejecución ---" systemctl list-timers | grep limpia echo ""
echo "--- 6.5: Scripts creados ---" ls -la /usr/local/bin/info_sistema.sh /usr/local/bin/informe_diario.sh /usr/local/bin/backup_seguro.sh echo ""
echo "--- 6.5: Último informe generado ---" ls -la /var/log/informes/ 2>/dev/null tail -5 /var/log/informes/informe_$(date '+%Y-%m-%d').log 2>/dev/null || echo "(sin informe hoy)"} > ~/practica6/entrega/verificacion.txt
cat ~/practica6/entrega/verificacion.txtPara empaquetar y enviar, sigue las instrucciones comunes: Cómo entregar las prácticas (usa N = 6).
🧨 Desafíos extra (MUY DIFÍCILES) — Troubleshooting de automatización
Sección titulada “🧨 Desafíos extra (MUY DIFÍCILES) — Troubleshooting de automatización"Estos ejercicios están diseñados para ser difíciles. No hay pista directa: tendrás que leer los logs, analizar la sintaxis y reproducir el fallo.
Reglas:
- Solo puedes usar comandos de terminal y herramientas del módulo 6.
- No se permite recrear desde cero sin entender el error.
- Todo el trabajo se documenta en
~/practica6/entrega/.
Ejercicio 6.6 ⚡ EXTRA — Reparar un crontab y un timer rotos
Sección titulada “Ejercicio 6.6 ⚡ EXTRA — Reparar un crontab y un timer rotos"Setup (ejecuta UNA sola vez)
Sección titulada “Setup (ejecuta UNA sola vez)"bash -lc 'set -euo pipefail
# Crea un script que el cron intentará ejecutarsudo tee /usr/local/bin/monitor_practica.sh > /dev/null << '"'"'EOF'"'"'#!/bin/bashecho "$(date): monitor ejecutado" >> /var/log/monitor_practica.logEOF
# Error 1: el script no tiene permisos de ejecuciónsudo chmod 644 /usr/local/bin/monitor_practica.sh
# Crea un crontab de sistema con sintaxis incorrectasudo tee /etc/cron.d/practica6-roto > /dev/null << '"'"'EOF'"'"'# Error 2: la hora "25" no existe (válido: 0-23)0 25 * * * root /usr/local/bin/monitor_practica.shEOF
# Crea un timer rotosudo tee /etc/systemd/system/monitor-practica.service > /dev/null << '"'"'EOF'"'"'[Unit]Description=Monitor de práctica
[Service]Type=oneshotExecStart=/usr/local/bin/monitor_practica.sh
[Install]WantedBy=multi-user.targetEOF
sudo tee /etc/systemd/system/monitor-practica.timer > /dev/null << '"'"'EOF'"'"'[Unit]Description=Timer del monitor de práctica
[Timer]# Error 3: OnCalendar con formato incorrecto (falta el año)OnCalendar=*-* 06:00:00Persistent=true
[Install]WantedBy=timers.targetEOF
sudo systemctl daemon-reloadecho "Escenario 6.6 creado con 3 errores sembrados"'Objetivo
Sección titulada “Objetivo"Conseguir que:
cron.d/practica6-rotoejecute el script sin errores cada día a las 6:00 AM (no a las 25:00)/usr/local/bin/monitor_practica.shsea ejecutablemonitor-practica.timeractive y muestre la próxima ejecución correctamente
Proceso de diagnóstico
Sección titulada “Proceso de diagnóstico"# Intenta arrancar el timer y observa el errorsudo systemctl start monitor-practica.timersystemctl status monitor-practica.timer --no-pager
# Verifica la sintaxis del timersystemd-analyze verify /etc/systemd/system/monitor-practica.timer 2>&1 || true
# Inspecciona el crontab del sistemasudo cat /etc/cron.d/practica6-roto
# Intenta ejecutar el script manualmente/usr/local/bin/monitor_practica.sh 2>&1 || echo "Error al ejecutar"Pista: hay exactamente 3 errores. Localiza y corrige cada uno antes de seguir al siguiente.
Guarda en ~/practica6/entrega/66_solucion.txt:
{ echo "=== DIAGNÓSTICO Y SOLUCIÓN 6.6 ===" echo "" echo "--- Crontab corregido ---" sudo cat /etc/cron.d/practica6-roto echo "" echo "--- Permisos del script ---" ls -la /usr/local/bin/monitor_practica.sh echo "" echo "--- Timer corregido y activo ---" systemctl status monitor-practica.timer --no-pager echo "" echo "--- Próxima ejecución ---" systemctl list-timers | grep monitor-practica} > ~/practica6/entrega/66_solucion.txt