Cambiaste una configuración. Hiciste lo responsable. Incluso dejaste un comentario como “temporal” que sin duda seguirá ahí en 2027. Ahora el servicio no arranca, tu monitorización está avisando y systemctl status se muestra esquivo.
La buena noticia: Debian 13 junto con systemd te da todo lo necesario para resolver esto rápidamente—si dejas de leer las líneas de registro equivocadas. La mala noticia: la mayoría de la gente hace exactamente eso, se queda mirando las últimas tres líneas de salida y luego empieza sacrificios rituales a “la caché”. No lo hagas. Lee las líneas correctas, en el orden correcto, y lo solucionarás en minutos.
Caso n.º 1: cambio de configuración → el servicio no arranca (qué ocurrió realmente)
Este es el patrón más habitual que veo en sistemas Debian: un servicio está sano, alguien edita un archivo de configuración y luego reinicia el servicio. El reinicio falla. El responsable abre systemctl status, ve “failed with result ‘exit-code’” y empieza a adivinar.
La solución casi siempre está dentro de los registros, pero no en la parte que la gente lee primero. La línea útil suele ser:
- Anterior a la línea “Main process exited…”
- Proveniente de un proceso auxiliar (como
ExecStartPre) que probó la configuración y salió - O del propio demonio, emitida una vez y luego enterrada bajo la verborrea de systemd
Para el caso n.º 1, imagina un servicio típico con un paso de prueba de configuración:
ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on;ExecStart=/usr/sbin/nginx -g daemon on; master_process on;
El reinicio falla no porque systemd sea misterioso, sino porque la prueba previa detectó un error de sintaxis, una ruta de include inválida o un problema de permisos en un archivo referenciado. Las “líneas de registro correctas” son las que describen esa falla previa. Tu trabajo es extraerlas limpiamente, sin ahogarte en ruido no relacionado.
Broma #1 (corta y relevante): Un reinicio de servicio es como un paracaídas: si te saltas la inspección, igual descubrirás si funciona.
Algunos hechos e historia que explican por qué los registros se ven así
Entender por qué Debian 13 se comporta de esta manera te hace más rápido bajo presión. Aquí hay hechos concretos que importan cuando un servicio se niega a arrancar tras un cambio de configuración:
- systemd se convirtió en el sistema init por defecto de Debian en Debian 8 (Jessie). Esa decisión estandarizó la gestión de servicios y las expectativas de registro, pero también cambió dónde buscan errores las personas.
- journald no es un archivo de texto. Los registros se almacenan en un journal binario y se consultan con
journalctl. Aún puedes reenviarlos a syslog, pero la fuente canónica es el journal. systemctl statuses un resumen, no una investigación. Muestra una porción recortada de registros y el estado de la unidad a alto nivel. Sirve para apuntarte a consultas más profundas, no para sustituirlas.- Las unidades systemd pueden tener múltiples procesos antes de que arranque el “daemon” real.
ExecStartPre, generators, scripts wrapper y archivos de entorno pueden fallar antes de que exista siquiera el PID del servicio. - Los códigos de salida están estandarizados, pero a menudo son engañosos sin contexto. Un “exit status 1” puede significar “error de sintaxis”, “permiso denegado” o “puerto ya en uso”. Necesitas el mensaje que lo acompaña.
- Muchos demonios están diseñados para fallar rápido con configuración inválida. Nginx, Postfix, HAProxy y otros se niegan intencionadamente a arrancar si las pruebas de configuración fallan—porque ejecutar con configuración parcial/incorrecta es peor.
- El empaquetado de Debian tiende a añadir comprobaciones de seguridad. Los mantenedores frecuentemente incluyen validaciones previas en las unidades o scripts wrapper. Es buena ingeniería, pero significa que los errores pueden venir de scripts que no sabías que estaban en la ruta.
- El orden de los registros puede ser engañoso. journald usa marcas temporales, pero el arranque paralelo de unidades y múltiples procesos puede entrelazar entradas. La “última línea” no es siempre “la causa”.
- El limitador de tasa es real. journald puede limitar por tasa servicios que spamean; el primer error puede registrarse y los siguientes 500 resumirse. Si solo ves el resumen, te pierdes la primera pista.
Una idea para tener en mente, parafraseada correctamente y atribuida: Gene Kim (idea parafraseada): la fiabilidad mejora cuando construyes bucles de retroalimentación rápidos y acortas la distancia entre el cambio y el diagnóstico.
Guía rápida de diagnóstico (primeras/segundas/terceras comprobaciones)
Este es el orden que gana en producción. Está orientado a obtener la causa raíz en menos de cinco minutos, no a dar la sensación de estar ocupado.
Primero: confirma qué cree systemd que falló (visión a nivel de unidad)
- Obtén el estado de la unidad, el código de salida y en qué fase falló (pre-start vs inicio principal).
- Extrae la línea de comando exacta que systemd ejecutó (incluyendo
ExecStartPre).
Segundo: extrae el fragmento correcto del journal (por tiempo y por unidad)
- Consulta los registros de esa unidad, para el último arranque, con el menor ruido posible.
- Luego amplía el rango temporal si es necesario; no amplíes el ámbito primero.
- Busca la primera línea de error significativa, no la última línea “exited”.
Tercero: ejecuta la propia validación de configuración del demonio manualmente
- La mayoría de servicios tiene un modo “probar configuración y salir”.
- Ejecuta exactamente como lo haría systemd (mismo usuario, mismo entorno, misma ruta de configuración).
- Si la validación pasa manualmente pero falla bajo systemd, sospecha de permisos, archivos de entorno, AppArmor o diferencias en el directorio de trabajo.
Cuarto: decide entre arreglar, revertir o aplicar un bypass temporal
- Si es un error de sintaxis claro: arréglalo ahora y reinicia.
- Si es incierto y la producción está ardiendo: revierte a la última configuración conocida buena y reinicia.
- Evita bypass temporales como comentar pasos de validación a menos que entiendas el radio de impacto.
Tareas prácticas: comandos, salida esperada y decisiones (12+)
Estas tareas están escritas como trabaja realmente un SRE: ejecuta un comando, lee la salida, toma una decisión. Sin discursos motivacionales. Cada tarea incluye qué significa la salida y qué haces después.
Tarea 1: Comprueba el estado de la unidad (pero léelo correctamente)
cr0x@server:~$ systemctl status nginx.service --no-pager
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Mon 2025-12-30 10:14:03 UTC; 42s ago
Duration: 2.103s
Process: 21984 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
CPU: 29ms
Dec 30 10:14:03 server nginx[21984]: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Dec 30 10:14:03 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Dec 30 10:14:03 server systemd[1]: nginx.service: Failed with result 'exit-code'.
Dec 30 10:14:03 server systemd[1]: Failed to start nginx.service - A high performance web server and a reverse proxy server.
Qué significa: La falla ocurrió en ExecStartPre, antes del arranque del daemon nginx. Eso es una falla de prueba de configuración, no un crash en tiempo de ejecución.
Decisión: No persigas puertos, archivos PID o límites del kernel. Corrige la línea de configuración referenciada (app.conf:57) y vuelve a ejecutar la prueba de configuración.
Tarea 2: Muestra solo el journal para esta unidad (el último intento, limpio)
cr0x@server:~$ journalctl -u nginx.service -b --no-pager -n 60
Dec 30 10:14:03 server systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Dec 30 10:14:03 server nginx[21984]: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Dec 30 10:14:03 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Dec 30 10:14:03 server systemd[1]: nginx.service: Failed with result 'exit-code'.
Dec 30 10:14:03 server systemd[1]: Failed to start nginx.service - A high performance web server and a reverse proxy server.
Qué significa: El journal confirma el error de parseo exacto. No hace falta inferir.
Decisión: Abre el archivo, corrige la sintaxis y vuelve a probar la configuración antes de reiniciar.
Tarea 3: Extrae registros “desde el reinicio” cuando el arranque está ruidoso
cr0x@server:~$ systemctl show -p ActiveEnterTimestampMonotonic nginx.service
ActiveEnterTimestampMonotonic=81234567890
cr0x@server:~$ journalctl -u nginx.service -b --no-pager --since "2 min ago"
Dec 30 10:14:03 server systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Dec 30 10:14:03 server nginx[21984]: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Dec 30 10:14:03 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Dec 30 10:14:03 server systemd[1]: nginx.service: Failed with result 'exit-code'.
Qué significa: Estás acotando los registros por tiempo en lugar de vadear por todo el arranque.
Decisión: Si el error no está en esa ventana, amplía a 10 minutos; no quites todavía el filtro por unidad.
Tarea 4: Inspecciona la unidad en busca de comprobaciones previas e archivos de entorno
cr0x@server:~$ systemctl cat nginx.service
# /lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on;
ExecStart=/usr/sbin/nginx -g daemon on; master_process on;
ExecReload=/usr/sbin/nginx -g daemon on; master_process on; -s reload
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
Qué significa: La falla no está dentro del daemon de larga ejecución; está en el paso de validación. Además, no hay EnvironmentFile= aquí, por lo que hay menos variables ocultas.
Decisión: Ejecuta el comando exacto de pre-start manualmente para reproducirlo; si falla, arregla la configuración. Si tiene éxito, la falla es ambiental (permisos, AppArmor, rutas de include).
Tarea 5: Ejecuta la prueba de configuración del daemon manualmente (mismo comando)
cr0x@server:~$ sudo /usr/sbin/nginx -t -q -g "daemon on; master_process on;"
nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Qué significa: Este es un error determinista de parseo de configuración. No hay rareza de systemd.
Decisión: Corrige el archivo y la línea referenciada. No reinicies repetidamente esperando que “se arregle”. No lo hará.
Tarea 6: Localiza la línea ofensiva y valida la estructura de includes
cr0x@server:~$ nl -ba /etc/nginx/sites-enabled/app.conf | sed -n '45,70p'
45 server {
46 listen 443 ssl;
47 server_name app.example.internal;
48 include /etc/nginx/snippets/tls.conf;
49
50 location / {
51 proxy_pass http://127.0.0.1:8080;
52 proxy_set_header Host $host;
53 }
54
55 } # end server
56
57 }
Qué significa: Hay una llave de cierre extra en la línea 57.
Decisión: Elíminala, guarda, vuelve a ejecutar la prueba de configuración. Si ves desajustes de llaves a menudo, adopta una regla de estilo: un bloque por archivo, indentación consistente y un linter de configuración en CI.
Tarea 7: Valida de nuevo, luego reinicia (no omitas la validación)
cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Qué significa: Ahora es seguro reiniciar.
Decisión: Reinicia una vez. Si el reinicio falla ahora, es un problema distinto—no asumas que sigue siendo la sintaxis.
cr0x@server:~$ sudo systemctl restart nginx.service
cr0x@server:~$ systemctl is-active nginx.service
active
Qué significa: El servicio está en ejecución.
Decisión: Confirma que sirve tráfico (comprobación de salud local) y cierra el incidente correctamente.
Tarea 8: Cuando status no ayuda, muestra registros completos filtrando por prioridad
cr0x@server:~$ journalctl -u nginx.service -b -p warning --no-pager
Dec 30 10:14:03 server nginx[21984]: nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/app.conf:57
Qué significa: Filtraste a warnings y peores, así que no estás leyendo el relleno de “Started…”.
Decisión: Usa esto cuando una unidad es muy habladora. Si no aparece nada en warning/error, o registras en otro lugar o tienes una falla silenciosa antes de que el registro se inicialice.
Tarea 9: Confirma qué archivos de configuración cambiaron recientemente (caza al culpable real)
cr0x@server:~$ sudo find /etc/nginx -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort | tail -n 8
2025-12-30 10:12 /etc/nginx/sites-enabled/app.conf
2025-12-29 18:41 /etc/nginx/nginx.conf
2025-12-10 09:03 /etc/nginx/snippets/tls.conf
2025-11-21 15:22 /etc/nginx/mime.types
Qué significa: Puedes correlacionar la falla de arranque con la edición más reciente.
Decisión: Si el error referencia un archivo incluido, revisa también su mtime. “Solo cambié una línea” rara vez es toda la historia.
Tarea 10: Si no es sintaxis, comprueba permiso denegado (clásico tras “hardening”)
cr0x@server:~$ journalctl -u nginx.service -b --no-pager -n 30
Dec 30 10:20:11 server nginx[22310]: nginx: [emerg] open() "/etc/nginx/snippets/tls.conf" failed (13: Permission denied)
Dec 30 10:20:11 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
cr0x@server:~$ namei -l /etc/nginx/snippets/tls.conf
f: /etc/nginx/snippets/tls.conf
drwxr-xr-x root root /
drwxr-xr-x root root etc
drwxr-xr-x root root nginx
drwx------ root root snippets
-rw------- root root tls.conf
Qué significa: Los permisos del directorio impiden que nginx (que corre como www-data después del arranque) o su comprobación previa lean los includes.
Decisión: Corrige permisos al mínimo requerido. Normalmente: bit de ejecución en directorios para recorrido y lectura de archivo para el usuario o grupo del servicio.
Tarea 11: Valida el usuario de runtime y el sandboxing del servicio
cr0x@server:~$ systemctl show nginx.service -p User -p Group -p DynamicUser -p ProtectSystem -p ReadWritePaths
User=
Group=
DynamicUser=no
ProtectSystem=no
ReadWritePaths=
Qué significa: Esta unidad en particular no usa directivas de sandboxing de systemd. Si ves ProtectSystem=strict o ReadWritePaths restrictivos, las lecturas/escrituras de configuración pueden estar bloqueadas.
Decisión: Si el sandboxing está habilitado, alinéalo con las necesidades del daemon en lugar de desactivarlo a ciegas. Añade ReadOnlyPaths/ReadWritePaths explícitas en un override.
Tarea 12: Interpreta las razones de fallo desde la perspectiva de systemd (códigos y señales)
cr0x@server:~$ systemctl show nginx.service -p ExecMainStatus -p ExecMainCode -p Result
ExecMainStatus=1
ExecMainCode=exited
Result=exit-code
Qué significa: El proceso terminó normalmente con estado 1. No fue SIGKILL, ni OOM, ni timeout.
Decisión: Concéntrate en configuración, parámetros y permisos. Si ves ExecMainCode=killed o Result=timeout, esa es otra rama completamente distinta.
Tarea 13: Si el servicio está flapeando, detén el bucle de reinicios mientras lees los registros
cr0x@server:~$ sudo systemctl reset-failed nginx.service
cr0x@server:~$ sudo systemctl stop nginx.service
cr0x@server:~$ systemctl status nginx.service --no-pager
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: inactive (dead)
Qué significa: Evitas que systemd inunde con reinicios mientras depuras. Esto también hace que el journal sea más fácil de leer.
Decisión: Haz esto cuando Restart=always esté generando ruido y carga. Luego reinicia deliberadamente cuando tengas un arreglo.
Tarea 14: Compara cambios de configuración de forma segura con metadata de dpkg (revisión de empaquetado)
cr0x@server:~$ dpkg -S /etc/nginx/nginx.conf
nginx-common: /etc/nginx/nginx.conf
cr0x@server:~$ sudo ls -l /etc/nginx/nginx.conf*
-rw-r--r-- 1 root root 1492 Dec 29 18:41 /etc/nginx/nginx.conf
-rw-r--r-- 1 root root 1479 Nov 21 15:22 /etc/nginx/nginx.conf.dpkg-dist
Qué significa: Puede que tengas un archivo nuevo por defecto del distro o una fusión pendiente. Eso puede interactuar con tu cambio.
Decisión: Si el servicio empezó a fallar tras una actualización más un cambio de configuración, examina .dpkg-dist/.dpkg-old y reconcilia de forma intencional.
Tarea 15: Cuando faltan registros, confirma persistencia y limitador de journald
cr0x@server:~$ sudo grep -E '^(Storage|SystemMaxUse|RateLimitIntervalSec|RateLimitBurst)=' /etc/systemd/journald.conf | sed '/^#/d;/^$/d'
Storage=auto
RateLimitIntervalSec=30s
RateLimitBurst=1000
cr0x@server:~$ journalctl --disk-usage
Archived and active journals take up 384.0M in the file system.
Qué significa: Si Storage=volatile, pierdes registros al reiniciar. Si el limitador de tasa es bajo, podrías perder errores repetidos.
Decisión: En producción, persiste los logs en disco y asigna un tamaño apropiado. Para depuración, aumenta temporalmente los límites de tasa si un servicio spamea, pero arregla el spam después.
Broma #2 (corta y relevante): “Funcionó ayer” no es evidencia; es solo el testimonio de un testigo con mala memoria.
Tres micro-historias corporativas (y lo que enseñan)
Micro-historia 1: El incidente causado por una suposición errónea
El equipo tenía una flota Debian con una mezcla de servicios web y API. Una tarde, se desplegó un cambio rutinario de configuración: actualizar los cifrados TLS y estandarizar entre entornos. Alguien reinició nginx en un canario. Falló. Ejecutaron nginx -t manualmente; pasó. La suposición se formó al instante: “systemd está roto en este host”.
Se buceó en versiones de paquetes, parámetros del kernel e incluso en SELinux (que ni siquiera estaba activado). Mientras tanto, el tráfico se drenó del nodo y el autoscaler se puso nervioso. Siguieron reintentando reinicios “solo para ver”, que es una excelente manera de sobreescribir la única buena línea de error con una pila de reinicios.
La solución fue vergonzosamente simple: la unidad systemd usaba una ruta de configuración diferente a través de un archivo de entorno. No era malintencionado—solo histórico. El nginx -t manual probó /etc/nginx/nginx.conf; systemd probó /etc/nginx/nginx-canary.conf. El archivo canario incluyó un snippet que no existía en ese host.
La lección no es “no uses archivos de entorno”. Es: nunca asumas que tu reproducción manual coincide con el gestor de servicios. Extrae el ExecStartPre/ExecStart exacto de systemctl cat y ejecuta eso. Si existe un archivo de entorno, imprímelo y deja de adivinar.
Micro-historia 2: La optimización que salió mal
Un grupo de plataforma decidió “acelerar despliegues” cambiando de restart a reload cuando fuera posible. Reload es más barato: menos churn de conexiones, menos errores transitorios. Buena intención. Luego lo generalizaron a múltiples servicios con un script “one-size-fits-most”.
Un servicio, un broker de mensajes, aceptaba señales de reload pero solo recargaba parcialmente la configuración. Para algunas opciones requería un reinicio completo, pero el comando reload devolvía éxito de todas maneras. Con el tiempo, se acumuló drift de configuración: la configuración en memoria no coincidía con la del disco, y la gente dejó de confiar en ambas.
Finalmente, un cambio introdujo un parámetro que habría fallado la validación de un arranque limpio. El reload no hizo nada útil, dijo “OK” y el sistema siguió con la configuración antigua. Días después, un reinicio rutinario del host ocurrió. Ahora el servicio tenía que iniciar en frío, leyó la mala configuración y se negó a arrancar. Esta falla ocurrió durante una ventana de mantenimiento, que es donde vas a encontrarte con tus errores futuros.
La lección: reload no es gratis. Si eliges reload como optimización, también debes imponer la validación de configuración como parte del proceso de cambio y realizar reinicios controlados periódicamente para probar que la configuración realmente es arrancable.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día
Un servicio interno del área financiera corría en Debian, respaldado por una base de datos y un frontend web. Tenían una política de cambios poco glamurosa: cada edición de configuración debía ser commiteada en un repo, y las herramientas de despliegue siempre ejecutaban la prueba de configuración del servicio antes de tocar systemd. Si la prueba fallaba, el cambio simplemente no se desplegaba.
La gente se quejaba. “Nos ralentiza”. “Puedo probarlo en mi cabeza”. Lo usual. Pero llegó un día en que un ingeniero senior editó la configuración en vivo durante un incidente—porque el servicio se comportaba mal y necesitaban una mitigación rápida. La edición tenía un error sutil de comillas. El siguiente reinicio habría matado el servicio por completo.
La herramienta de despliegue se negó a aplicar el cambio sin pasar la prueba de configuración. Ese era el punto: guardarraíles cuando el estrés hace a todos descuidados. Arreglaron la comilla, volvieron a probar y luego reiniciaron con seguridad. Nadie recibió otra página.
La lección: la práctica aburrida no es el repo. Es la puerta de validación automática más una ruta de rollback predecible. Esas dos cosas evitan que pequeños errores se conviertan en incidentes.
Errores comunes: síntoma → causa raíz → solución
Aquí están los reincidentes. Si tu servicio no arranca tras un cambio de configuración, probablemente caerás en uno de estos grupos.
1) Síntoma: systemctl status muestra “failed (Result: exit-code)” sin error útil
Causa raíz: Solo estás viendo el resumen. La línea significativa está antes o está truncada.
Solución: Consulta el journal directamente y amplía el fragmento.
cr0x@server:~$ journalctl -u myservice.service -b --no-pager -n 200
...look for the first real error line...
2) Síntoma: el servicio falla instantáneamente tras reiniciar; los logs mencionan ExecStartPre
Causa raíz: La validación previa falló (sintaxis, include faltante, directiva inválida).
Solución: Ejecuta la misma validación manualmente y corrige la configuración antes de reiniciar.
cr0x@server:~$ systemctl cat myservice.service | sed -n '/ExecStartPre/p'
ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on;
3) Síntoma: la prueba de configuración pasa manualmente, falla bajo systemd
Causa raíz: Ruta de configuración diferente, usuario distinto, entorno distinto o restricciones del sandbox.
Solución: Extrae el comando y entorno exactos de la unidad; ejecútalo como el usuario del servicio.
cr0x@server:~$ systemctl show myservice.service -p Environment -p EnvironmentFiles
Environment=
EnvironmentFiles=/etc/default/myservice (ignore_errors=no)
4) Síntoma: “Permission denied” en includes, certificados, sockets, archivos PID
Causa raíz: Cambio de hardening (chmod/chown), nueva ruta con permisos restrictivos o desajuste del usuario del servicio.
Solución: Rastrea permisos con namei -l; corrige bits de ejecución de directorio y la legibilidad de archivos.
5) Síntoma: “Address already in use” tras cambiar la configuración
Causa raíz: Cambiaste bind/listen; otro servicio ya lo ocupa; o la instancia antigua no se detuvo limpiamente.
Solución: Identifica quién tiene el puerto; decide si revertir el puerto, detener el servicio en conflicto o arreglar la activación por socket.
cr0x@server:~$ sudo ss -ltnp | grep ':443 '
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("haproxy",pid=1203,fd=7))
6) Síntoma: la unidad muestra Result=timeout
Causa raíz: El daemon se queda colgado durante el arranque (esperando DNS, almacenamiento, migraciones) o el timeout de systemd es demasiado agresivo para un arranque en frío.
Solución: Lee los registros alrededor del bloqueo y ajusta TimeoutStartSec solo si el trabajo de inicio es legítimo y acotado.
7) Síntoma: tras un cambio de configuración, el servicio “arranca” pero no funciona
Causa raíz: Usaste reload y asumiste que aplicó todo; o la configuración fue aceptada pero es semánticamente incorrecta.
Solución: Ejecuta un chequeo de salud a nivel de aplicación y confirma la configuración activa con introspección del servicio si está disponible. Reinicia si es necesario.
8) Síntoma: el journal no tiene entradas para la unidad
Causa raíz: El servicio registra en archivo (o stdout está redirigido), journald es volátil, o la unidad nunca se ejecutó por una falla de dependencia.
Solución: Revisa systemctl list-dependencies y la configuración de journald; inspecciona archivos de log tradicionales si el servicio los usa.
Listas de verificación / plan paso a paso (correcciones seguras y rollback)
Paso a paso: diagnostica y arregla sin sobrecargar el sistema
- Detén el bucle de reinicios si está presente. Si la unidad está flapeando, pausa para poder leer registros estables.
- Lee el resumen de la unidad. Identifica si
ExecStartPrefalló o el proceso principal murió. - Consulta journald por unidad y por arranque. No comiences con registros globales.
- Extrae los comandos de arranque exactos. Lee
systemctl caty busca drop-ins. - Ejecuta la prueba de configuración del servicio manualmente. Mismos args, misma ruta de configuración.
- Corrige lo más pequeño que haga que arranque. Evita refactors durante la respuesta a un incidente.
- Reinicia una vez y verifica a nivel de aplicación. “active (running)” no es lo mismo que “sirviendo”.
- Escribe la línea de causa raíz. Pega la cadena de error exacta en la nota del incidente. El tú del futuro agradecerá al tú del presente.
Plan de rollback: cuando no estás seguro de que tu arreglo sea correcto
Si no puedes probar el arreglo rápidamente, haz rollback. No “iteres en producción” mientras suena el pager.
- Guarda la configuración rota. Cópiala con timestamp para análisis posterior.
- Restaura la última conocida buena desde el repo de configuración o backup.
- Valida la configuración. Siempre ejecuta el modo de prueba del daemon.
- Reinicia el servicio y verifica.
- Solo tras la recuperación: depura el cambio roto en un entorno controlado.
cr0x@server:~$ sudo cp -a /etc/nginx/sites-enabled/app.conf /root/app.conf.broken.$(date +%F-%H%M%S)
cr0x@server:~$ sudo cp -a /root/rollback/app.conf /etc/nginx/sites-enabled/app.conf
cr0x@server:~$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
cr0x@server:~$ sudo systemctl restart nginx.service
cr0x@server:~$ systemctl is-active nginx.service
active
Cuando debes mantener parcialmente el servicio en marcha (control de daños)
A veces no puedes arreglarlo completamente de inmediato, pero puedes reducir el impacto:
- Restaura una configuración mínima que sirva una página de mantenimiento.
- Deshabilita el virtual host roto mientras los demás siguen funcionando.
- Redirige tráfico fuera del nodo temporalmente, arregla en aislamiento y luego reintroduce.
No deshabilites pasos de validación para “hacer que arranque” a menos que estés seguro de que el daemon no arrancará en un estado corrupto. Ese camino conduce a pérdida de datos y no disfrutarás el postmortem.
Preguntas frecuentes
1) ¿Por qué no basta con systemctl status?
Porque es intencionalmente compacto. Muestra una pequeña cola de registros y un resumen del estado de la unidad. Úsalo para encontrar el nombre de la unidad, la fase de fallo y luego pivota a journalctl -u para el diagnóstico real.
2) ¿Cuál es el comando journalctl más útil para esta situación?
Normalmente:
cr0x@server:~$ journalctl -u myservice.service -b --no-pager -n 200
Si eso es ruidoso, añade -p warning o restringe por tiempo con --since.
3) ¿Cómo sé si la falla es de configuración o de runtime?
Busca ExecStartPre fallando (config/validación) frente al proceso principal que arranca y luego muere (runtime). systemctl status suele decirte qué proceso falló.
4) ¿Por qué a veces la prueba manual de configuración tiene éxito cuando systemd falla?
Entorno distinto. systemd puede usar un archivo de entorno, un directorio de trabajo distinto, sandboxing o un contexto de usuario diferente. Reproduce siempre usando la línea de comando exacta de la unidad.
5) ¿Cómo veo los drop-in overrides que podrían cambiar el comportamiento?
cr0x@server:~$ systemctl status myservice.service --no-pager
...look for "Drop-In:" lines...
cr0x@server:~$ systemctl cat myservice.service
...includes /etc/systemd/system/myservice.service.d/*.conf if present...
6) ¿Cuándo debo usar reload en lugar de restart?
Sólo cuando el servicio documente que reload aplica los cambios que hiciste y tengas un paso de validación. Si no estás seguro, reinicia en una ventana segura o tras drenar tráfico.
7) ¿Y si no hay registros en absoluto para la unidad?
Entonces o la unidad no se ejecutó, journald no retiene registros o los logs van a otro lugar (como /var/log/*). Revisa dependencias y ajustes de journald, e inspecciona logs basados en archivos si el servicio los usa.
8) ¿Cómo detecto rápidamente si es un problema de permisos?
Busca “Permission denied” en el journal y luego traza la ruta con namei -l. Los problemas de permisos suelen venir de bits de ejecución en directorios o cambios de hardening que olvidaron al usuario del servicio.
9) ¿Cuál es la forma más segura de prevenir esta clase de incidentes?
Automatiza la validación de configuración (modo test del daemon) antes de restart/reload, guarda las configuraciones en control de versiones y facilita el rollback. El objetivo es atrapar la línea rota antes de que llegue a systemd.
Conclusión: siguientes pasos para evitar incidentes recurrentes
Un servicio en Debian 13 que falla tras un cambio de configuración rara vez es un misterio. Suele ser una línea de error precisa que no extrajiste limpiamente. Lee la unidad para saber qué se ejecutó. Lee el journal acotado a la unidad para saber qué falló. Luego valida la configuración manualmente usando el comando exacto que systemd usa.
Pasos prácticos siguientes:
- Añade un paso de prueba de configuración previo al despliegue para cada servicio que lo soporte.
- Entrena a tu equipo para tratar
systemctl statuscomo un puntero, no como un diagnóstico. - Haz del rollback una operación de primera clase (copiar, restaurar, validar, reiniciar).
- Estandariza una guía de “diagnóstico rápido” y tenla cerca de la rotación del pager.
Haz eso, y la próxima vez que un servicio se niegue a arrancar, pasarás el tiempo arreglando el problema real—no discutiendo con una pantalla de resumen.