La terminal es la herramienta de diagnóstico definitiva: estos ejercicios son músculo, no teoría.
Ejercicio 1 — Anatomía de tus procesos
- El padre (arbiter) muestra el comando base
gunicorn config.wsgi --bind 127.0.0.1:8000; los workers muestran[1]/[2](o similar) tras el comando. El RSS del padre es pequeño; los workers cargan tu app (más memoria). - Con SIGTERM el worker termina educadamente (acaba la petición en curso) y el arbiter lo reemplaza con un PID nuevo: el servicio no deja de responder ni un instante. Es el mecanismo del reload sin downtime.
- Con SIGKILL el worker muere sin limpiar: la petición en curso se corta (el cliente ve conexión cerrada) y el arbiter detecta al muerto y levanta otro. Diferencia clave: SIGTERM respeta lo que estaba haciendo; SIGKILL ni pregunta. Por eso los despliegues usan TERM y los orquestadores (systemd, Docker) esperan un graceful timeout antes de mandar KILL.
Ejercicio 2 — Puertos y carga
- Gunicorn (o
runserver) en 8000; PostgreSQL en 5432; Redis en 6379. Si algo no aparece, ese es tu primer diagnóstico real. - El consumo se reparte entre los 2 workers (y el
runserversi no usaste Gunicorn: nota fina,runserveres de desarrollo y monohilo; los números no trasladan a producción). Loscurlcompiten entre sí; con 200 lanzados en paralelo verás contención en CPU o en la cola de aceptación del socket. - Los tres números son carga en 1, 5 y 15 min. En una máquina de n núcleos, carga > n significa trabajo en espera. Tendencia: si 1min > 15min, el sistema va a peor ahora; la lectura en tendencia importa más que el valor puntual.
Ejercicio 3 — El pipeline de logs
$9es el noveno campo del log de acceso combinado: el código de estado HTTP. El pipeline responde "¿cuántas respuestas de cada código tengo?" — en un incidente, la primera pregunta: ¿200s dominan (todo bien) o 500s se disparan (bug nuestro)?- Si el formato tiene la duración en el último campo (configurable en Nginx/Gunicorn):
awk '{print $NF, $7}' access.log | sort -rn | head -5(duración + ruta, ordenado descendente, top 5). Si tu log no tiene duración, añadirla es la mitad del ejercicio: sin dato no hay análisis — la misma idea que reaparece en la Lección 37 (perfilado).
Ejercicio 4 — Permisos de verdad
- Sí pudo: 644 da lectura a "otros", y
app_testes "otro". Cualquier usuario del sistema lee tus secretos. - Con 640 y grupo de la app: el dueño y ese grupo leen; el resto nada. Con 600: solo el dueño (más estricto: úsalo cuando no haya otra app del mismo grupo). La jerarquía que recordarás: cada bit que abres es un usuario del servidor que puede leer.
chmod 600.envy dueño = usuario que corre la app (no root). Y en elservicede systemd:User=ticketflow, así solo ese usuario (y root) puede leer el fichero.
Ejercicio 5 — El.env bien hecho
- Un
env.examplecompleto: los nombres son contratos; los valores, secretos. Sisettings.pypide una variable que no está en el example, el onboarding de un compañero se rompe sin motivo. git check-ignore -v.envdebe imprimir la regla que lo ignora (p. ej..gitignore:6:.env). Si no imprime nada, tu.enves un accidente esperando commit.- Si aparecieron secretos en el historial: rotar (cambiar la credencial en el proveedor) — borrar el commit no basta, el historial queda clonado. La rotación es la única reparación real. (Las herramientas para reescribir historia las verás en la Lección 06; la rotación sigue siendo imprescindible.)
Ejercicio 6 — SSH local
- Sí entró sin contraseña: tu pública quedó en
~/.ssh/authorized_keysy la privada demostró identidad. La contraseña dejan de pedirla (y puedes desactivarPasswordAuthenticationen el servidor: la puerta de fuerza bruta se cierra). ssh localtest hostnamefunciona igual: el config mapea apodos a host/usuario/clave. Con 3 servidores ya no vives sin él.- En el puerto 5433 escucha tu cliente ssh (proceso local), que reenvía lo que reciba por el túnel cifrado hasta el 5432 del servidor. Con una BD real remota: conectas tu psql/DBeaver a
localhost:5433y el tráfico viaja cifrado por SSH aunque la BD no esté expuesta a Internet — el patrón de depuración que usarás siempre.
Ejercicio 7 — El script de operación
- Con Gunicorn caído, el curl devuelve 000/refused → el script imprime FALLO y sale con exit 1 (que es lo que un monitor interpreta como alerta). Levantado: OK.
- Redis caído avisa pero no falla porque no tumba la web (la API sigue sirviendo; pierdes caché/cola, degradación no indisponibilidad). La API caída sí es fallo. Distinguir severidades es la diferencia entre un script y un instrumento de monitorización: el exit code es tu API con los sistemas de alerta.
- En producción: systemd timer (o cron) que ejecuta el script cada minuto y, si falla, un mecanismo de alerta (email, Slack, Prometheus — Lección 46).
watches el juguete; el timer es el juguete con logs, alerta y reinicio tras caída.
Resumen del profesor
- Los procesos se operan con señales: TERM educado, KILL último recurso; el arbiter de Gunicorn es tu primer ejemplo de resiliencia.
- Mínimo privilegio: usuario de sistema, 600 para secretos, y cada bit abierto es una puerta más.
- El pipeline de logs responde "¿qué está pasando y cuántas veces?" en una línea de shell.
- El entorno vive fuera del código; los secretos jamás en Git ni en logs; SSH con claves y túneles para depurar.
- Si lo hiciste tres veces a mano, ya es un script. Si corre solo, ya es operación.
Cuando entregues, cerramos la 05 y pasamos a la Lección 06 — Git profesional: rebase, conflictos y el flujo de equipo que sostiene todo lo demás.