Solución de problemas de servicios Linux con systemctl y journalctl

Un flujo de trabajo práctico para depurar servicios Linux fallidos o no saludables con systemctl y journalctl.

Solución de problemas de servicios Linux con systemctl y journalctl

Cuando un servicio de Linux falla, el camino más rápido no suele ser una búsqueda en la web. Son tres comprobaciones locales: qué piensa systemd que ocurrió, qué registró el servicio y qué cambió antes del fallo. systemctl y journalctl te dan esas respuestas sin adivinar.

Esta guía utiliza fallos comunes de servicios como ejemplos: un servicio que no arranca, un proceso que se ejecuta pero no realiza trabajo útil y un servicio que termina después de parecer saludable. Los comandos aplican a la mayoría de los servicios gestionados por systemd, pero los nombres exactos de las unidades y las ubicaciones de los registros varían según la distribución y el paquete.

Entendiendo systemctl y journalctl

Antes de sumergirnos en la solución de problemas, es crucial entender los roles de estas dos herramientas principales:

  • systemctl: Este comando es la utilidad central para controlar y consultar el sistema y el gestor de servicios systemd. Te permite iniciar, detener, reiniciar, verificar el estado y habilitar/deshabilitar servicios.
  • journalctl: Este comando se utiliza para consultar el diario de systemd, que es un sistema de registro centralizado. Recoge registros del kernel, servicios del sistema y aplicaciones, proporcionando una vista unificada de los eventos del sistema. journalctl es invaluable para entender por qué un servicio falló o se comportó inesperadamente.

Escenarios comunes de solución de problemas y soluciones

Exploremos problemas típicos y cómo abordarlos:

1. El servicio no pudo iniciarse

Este es quizás el problema más común. Intentas iniciar un servicio y falla inmediatamente.

Paso 1: Verificar el estado del servicio

Usa systemctl status para obtener una visión general inmediata del estado del servicio y las entradas de registro recientes.

sudo systemctl status apache2.service

Salida esperada (Ilustrativa - la tuya puede variar):

● apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
     Active: **failed** (result: exit-code) since Tue 2023-10-27 10:00:00 UTC; 1min ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 12345 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
   Main PID: 12345 (code=exited, status=1/FAILURE)

Oct 27 10:00:00 your-server systemd[1]: Starting The Apache HTTP Server...
Oct 27 10:00:00 your-server apachectl[12345]: AH00526: Syntax error on line 123 of /etc/apache2/apache2.conf:
Oct 27 10:00:00 your-server apachectl[12345]: Invalid Mutex directory in argument file: '/var/run/apache2/'
Oct 27 10:00:00 your-server systemd[1]: apache2.service: Main process exited, code=exited, status=1/FAILURE
Oct 27 10:00:00 your-server systemd[1]: **Failed** to start The Apache HTTP Server.
Oct 27 10:00:00 your-server systemd[1]: apache2.service: Unit entered failed state.

Análisis: La salida de systemctl status muestra claramente Active: failed y proporciona un fragmento del mensaje de error: Invalid Mutex directory in argument file: '/var/run/apache2/'. Esto sugiere un problema de configuración.

Paso 2: Investigar registros con journalctl

Para obtener información más detallada, usa journalctl para ver los registros específicamente del servicio fallido. La bandera -u especifica la unidad (servicio).

sudo journalctl -u apache2.service -xe
  • -u apache2.service: Filtra los registros para la unidad apache2.service.
  • -x: Añade explicaciones para algunos mensajes de registro.
  • -e: Salta al final del diario, mostrando las entradas más recientes.

Hallazgos potenciales: La salida de journalctl podría revelar más contexto sobre el error de configuración, problemas de permisos o problemas de dependencia.

Paso 3: Verificar archivos de configuración

Basado en el mensaje de error, examina los archivos de configuración relevantes. En el ejemplo anterior, apunta a /etc/apache2/apache2.conf y al directorio /var/run/apache2/.

sudo nano /etc/apache2/apache2.conf

Solución: Problemas como este a menudo provienen de un directorio de ejecución faltante, un cambio de empaquetado o un archivo de configuración que referencia una ruta que ya no existe. No crees directorios ciegamente a partir de un ejemplo de internet. Primero confirma lo que la aplicación espera en tu distribución, luego corrige la ruta faltante o la configuración. Una posible reparación podría verse así:

sudo mkdir -p /var/run/apache2/
sudo chown www-data:www-data /var/run/apache2/
sudo systemctl start apache2.service

Si el error menciona un problema de sintaxis, ejecuta la prueba de configuración propia de la aplicación antes de reiniciar nuevamente:

sudo apachectl configtest
sudo nginx -t
sudo sshd -t

Los validadores específicos de la aplicación detectan errores que systemd no puede entender. Systemd sabe si el proceso terminó. No sabe si tu bloque server de Nginx apunta al archivo de certificado incorrecto o si una directiva de Apache pertenece a un contexto diferente.

2. El servicio se está ejecutando pero no responde

A veces, systemctl status muestra un servicio como active (running), pero no está realizando su función prevista (por ejemplo, un servidor web no está sirviendo páginas).

Paso 1: Verificar el estado del servicio y el PID

Confirma que realmente se está ejecutando y tiene un ID de proceso (PID).

sudo systemctl status nginx.service

Si muestra active (running), anota el PID.

Paso 2: Examinar los registros del servicio en busca de errores

Incluso si se está ejecutando, el servicio podría encontrar errores internos que impiden que funcione correctamente.

sudo journalctl -u nginx.service -f
  • -f: Sigue la salida del registro en tiempo real. Esto es útil si puedes desencadenar el problema (por ejemplo, intenta acceder a la página web) mientras journalctl se está ejecutando.

Paso 3: Verificar registros específicos de la aplicación

Muchos servicios escriben sus propios registros además del diario de systemd. Para servidores web como Nginx o Apache, verifica sus ubicaciones de registro típicas (por ejemplo, /var/log/nginx/error.log, /var/log/apache2/error.log).

sudo tail -n 50 /var/log/nginx/error.log

Paso 4: Verificar la utilización de recursos

Un sistema sobrecargado puede hacer que los servicios no respondan.

 top
 htop
 free -h

Busca alto uso de CPU, memoria o E/S de disco por parte de los procesos del servicio.

También verifica si el servicio está escuchando donde esperas:

sudo ss -ltnp
sudo ss -lunp

Para un servicio web, ver nginx activo en systemctl es solo la mitad de la historia. Aún necesitas saber si está vinculado a 0.0.0.0:80, 127.0.0.1:8080, un socket IPv6 o ningún socket en absoluto. Una regla de firewall, un desajuste de proxy inverso o una dirección de enlace incorrecta pueden hacer que un proceso saludable parezca roto desde el exterior.

Solución: Si los registros indican problemas o los recursos están tensos, es posible que necesites:

  • Optimizar configuraciones.
  • Reiniciar el servicio (sudo systemctl restart <nombre_del_servicio>.service).
  • Investigar problemas subyacentes de recursos del sistema.
  • Aumentar los recursos del sistema si es necesario.

3. El servicio se detiene inesperadamente

Si un servicio que se estaba ejecutando previamente se detiene repentinamente, a menudo se debe a una excepción no manejada o a un tiempo de espera de vigilancia.

Paso 1: Verificar el historial reciente con journalctl

Usa journalctl para ver qué sucedió justo antes de que el servicio se detuviera. Las banderas --since y --until pueden ser útiles si conoces la hora aproximada.

sudo journalctl -u <nombre_del_servicio>.service --since "1 hour ago"

O, para ver todos los registros relacionados con el servicio desde el último arranque:

sudo journalctl -u <nombre_del_servicio>.service -b

Paso 2: Buscar volcados de núcleo o informes de fallo

Si el servicio falló, el sistema podría haber generado un volcado de núcleo o un informe de fallo.

ls -l /var/crash/

Paso 3: Revisar el archivo de unidad de servicio de systemd

Examina el archivo de unidad del servicio (generalmente en /etc/systemd/system/ o /lib/systemd/system/) en busca de directivas Restart= y configuraciones WatchdogSec=. Una configuración Restart= incorrecta o un WatchdogSec= demasiado corto podrían causar reinicios o fallos inesperados.

systemctl cat <nombre_del_servicio>.service

Solución: Aborda la causa raíz identificada en los registros. Esto podría implicar corregir errores de código, ajustar parámetros del archivo de unidad de systemd o aumentar los límites de recursos.

Si ves reinicios repetidos, verifica si systemd ha limitado la tasa de la unidad:

systemctl status <nombre_del_servicio>.service
journalctl -u <nombre_del_servicio>.service --since "30 minutes ago"

Los mensajes sobre Start request repeated too quickly generalmente significan que el servicio falló varias veces en un período corto. Después de solucionar el problema subyacente, limpia el estado fallido:

sudo systemctl reset-failed <nombre_del_servicio>.service
sudo systemctl start <nombre_del_servicio>.service

4. Problemas con systemctl enable o systemctl disable

Aunque no es un fallo en tiempo de ejecución, pueden ocurrir problemas al habilitar o deshabilitar servicios.

Problema: Un servicio está habilitado pero no se inicia al arrancar, o viceversa.

Verificar estado:

sudo systemctl is-enabled <nombre_del_servicio>.service

Este comando mostrará enabled o disabled.

Solución de problemas:

  • Asegúrate de que el archivo de unidad del servicio en sí sea válido y esté colocado correctamente (por ejemplo, /etc/systemd/system/).
  • Después de hacer cambios en un archivo de unidad, siempre ejecuta sudo systemctl daemon-reload.
  • Verifica los registros del servicio (journalctl -u <nombre_del_servicio>.service) en busca de errores de inicio que podrían impedir que se active incluso si está habilitado.

Consejos para una solución de problemas efectiva

  • Comienza con systemctl status: Siempre empieza aquí. Proporciona una instantánea rápida y a menudo te señala la dirección correcta.
  • Usa journalctl -u <servicio>: Esta es tu herramienta principal para entender por qué está sucediendo algo.
  • Bandera -f con journalctl: Extremadamente útil para monitoreo en tiempo real al intentar reproducir un problema.
  • systemctl restart <servicio>: Después de hacer cambios de configuración, siempre reinicia el servicio para aplicarlos.
  • systemctl daemon-reload: Crucial después de modificar cualquier archivo de unidad .service.
  • Verificar dependencias: A veces un servicio falla porque un servicio del que depende no se ha iniciado o está fallando. systemctl status a menudo mostrará esto.
  • Permisos: Muchos fallos de servicio se deben a permisos incorrectos de archivos o directorios. Asegúrate de que el usuario bajo el cual se ejecuta el servicio tenga el acceso necesario.
  • Problemas de red: Si el servicio depende de la red, verifica la conectividad de red, las reglas del firewall y la disponibilidad de puertos.

Un orden de solución de problemas que se mantiene

Cuando la presión está presente, usa el mismo orden cada vez:

systemctl status <servicio>.service
journalctl -u <servicio>.service -b --no-pager
systemctl cat <servicio>.service
systemctl list-dependencies <servicio>.service

Comienza con el estado actual, luego lee los registros del arranque actual, luego inspecciona la unidad exactamente como la ve systemd, luego verifica las dependencias. Si el servicio está orientado a la red, añade ss -ltnp y una prueba local con curl o un cliente. Si lee un archivo de configuración, ejecuta el validador de configuración propio del servicio.

El punto es evitar reinicios aleatorios. Reiniciar puede ser una solución válida después de un cambio de configuración o un proceso atascado, pero también destruye evidencia. Lee suficiente del diario primero para saber qué estás cambiando y por qué.

Leyendo la salida del diario sin perderse

journalctl puede ser ruidoso, especialmente en servidores ocupados. Comienza de manera estrecha, luego amplía solo cuando sea necesario.

Para un servicio en el arranque actual:

journalctl -u <servicio>.service -b --no-pager

Para los últimos minutos:

journalctl -u <servicio>.service --since "15 minutes ago" --no-pager

Para el arranque anterior:

journalctl -u <servicio>.service -b -1 --no-pager

Esa vista del arranque anterior es útil cuando un servicio falló durante el inicio y luego se recuperó, o cuando toda la máquina se reinició antes de que pudieras inspeccionarla. Puedes listar los arranques con:

journalctl --list-boots

Si el servicio registra campos estructurados o líneas largas, usa marcas de tiempo ISO cortas:

journalctl -u <servicio>.service -o short-iso --no-pager

Cuando necesites compartir registros, elimina secretos, tokens, nombres de host internos y datos del cliente. Los registros de servicio a menudo incluyen configuraciones derivadas del entorno, URLs, encabezados o cadenas de conexión. Un hábito limpio de solución de problemas incluye la redacción antes de pegar la salida en cualquier lugar.

Cuando systemctl dice "Active" pero los usuarios aún ven fallos

Un estado active (running) solo significa que systemd tiene un proceso que coincide con las expectativas de la unidad. No prueba que la aplicación esté saludable. Una aplicación web puede estar ejecutándose mientras devuelve HTTP 500. Un trabajador puede estar activo mientras está atascado en un mensaje de cola defectuoso. Un proxy de base de datos puede estar ejecutándose mientras todas las conexiones de backend fallan.

Para servicios de red, prueba desde las mismas capas de las que dependen tus usuarios:

curl -v http://127.0.0.1:8080/health
curl -v http://localhost/health
curl -v https://service.example.com/health

Esas tres comprobaciones responden a diferentes preguntas. La primera verifica el puerto de la aplicación local. La segunda puede incluir un proxy inverso local. La tercera verifica DNS, TLS, enrutamiento, reglas de firewall y la ruta de cara al público.

Para servicios de trabajadores, mira lo que consumen o producen. Un trabajador de cola puede necesitar una verificación de profundidad de cola. Un servicio de respaldo puede necesitar un archivo de salida reciente. Un recolector de métricas puede necesitar una consulta contra el backend de métricas. systemctl te dice si la supervisión está funcionando; las comprobaciones de la aplicación te dicen si el servicio es útil.

Arregla una variable a la vez

Cuando una unidad falla después de un despliegue, es tentador cambiar varias cosas y reiniciar. Eso puede ocultar la causa real. Prefiere un cambio a la vez:

systemctl cat my-app.service
journalctl -u my-app.service --since "30 minutes ago" --no-pager
sudo systemctl edit my-app.service
sudo systemctl daemon-reload
sudo systemctl restart my-app.service

Luego verifica el resultado antes de cambiar la siguiente cosa. Si el fallo es un archivo faltante, corrige la ruta del archivo. Si es un error de permiso, corrige la propiedad o el modo. Si es una dependencia, corrige la relación de la unidad o el comportamiento de reintento de la aplicación. La solución de problemas lenta y aburrida es a menudo más rápida que un bucle de reinicio con cinco ediciones no rastreadas.