Saltar al contenido
Open Security
Linux Real Intermedio · 25 min

systemd y journalctl: por qué un servicio no arranca

Un servicio falla y el reflejo es reiniciar a ciegas. Acá aprendés a leer el estado real con systemctl y a encontrar la causa en los logs con journalctl.

#linux#systemd#debugging

Antes de empezar necesitás

  • Una terminal en Linux (con systemd) o WSL2 con systemd activado
  • Saber moverte por el filesystem y leer permisos

Al terminar vas a poder

  • Leer el estado de un servicio con systemctl status y entender cada campo
  • Encontrar la causa de una falla en journalctl, no adivinarla
  • Distinguir 'no arrancó' de 'arrancó y se murió' de 'está deshabilitado'
  • Filtrar logs por unidad, por tiempo y por prioridad

Un servicio no levanta y el reflejo es restart una y otra vez, como quien golpea la tele. systemd ya te está diciendo qué pasó: el problema es que casi nadie lee la respuesta completa. Este lab es sobre leerla.

Paso 1: leer el estado, no inventarlo

systemctl status no es solo un “verde o rojo”. Cada línea importa:

vt@labs:~
systemctl status nginx --no-pager
● nginx.service - A high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Tue 2026-06-24 18:02:11; 5s ago
    Process: 5821 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
  • Loaded: si la unit existe y si está enabled (arranca sola al bootear) o disabled.
  • Active: el estado real. active (running), failed, inactive (dead), activating.
  • Process / ExecStartPre: qué comando corrió y con qué código salió. status=1/FAILURE es la pista grande.

Paso 2: la causa está en el journal

status te muestra las últimas líneas. Para la historia completa de esa unit:

vt@labs:~
# Logs de un servicio, solo del boot actual (-b), sin paginador
journalctl -u nginx -b --no-pager

# Las últimas 50 líneas y seguir en vivo mientras reintentás
journalctl -u nginx -n 50 -f

La clave es -u <unit>: filtra el ruido de todo el sistema y te deja solo lo del servicio. Ahí suele estar la línea real, del tipo bind() to 0.0.0.0:80 failed (98: Address already in use) o permission denied.

Paso 3: un caso clásico para reproducir

Creá un servicio de juguete que apunte a un binario que no existe y mirá cómo systemd lo reporta:

vt@labs:~
# Unit mínima que va a fallar a propósito
sudo tee /etc/systemd/system/roto.service >/dev/null <<'EOF'
[Service]
ExecStart=/usr/local/bin/no-existe-este-binario
EOF

sudo systemctl daemon-reload
sudo systemctl start roto.service     # no va a levantar
systemctl status roto.service --no-pager
journalctl -u roto.service -b --no-pager

Vas a ver algo como status=203/EXEC: systemd no pudo ejecutar el binario. El código te dice la familia del problema sin que adivines.

203/EXEC      no pudo ejecutar el binario (no existe, sin permiso, mal path)
200/CHDIR     el WorkingDirectory no existe
1/FAILURE     el programa arrancó y salió con error (mirá su log)

El criterio

Debuggear un servicio es un flujo corto y repetible:

1. systemctl status <unit>   → ¿failed, inactive o disabled? ¿qué exit code?
2. journalctl -u <unit> -b   → ¿qué línea explica el fallo?
3. arreglo el origen          (path, permiso, puerto, config)
4. systemctl restart <unit>  → y verifico con status, no por fe

Lo que practicás en este lab

Llevátelo a tu repo si querés, pero no es obligatorio: es tu aprendizaje.

  • La salida de systemctl status del servicio fallando, con la línea que explica por qué
  • El comando de journalctl que usaste para aislar el error
  • Writeup de 2 líneas: cuál era la causa y cómo la confirmaste en los logs

Reto

Tomá un servicio que falle (o creá uno de juguete que apunte a un binario inexistente). Usá systemctl + journalctl para encontrar la causa exacta. Escribí dos líneas: qué decía el log y qué cambiarías para arreglarlo.

Resolvelo y escribí dos líneas explicando qué pasó. Con eso lo fijás.

¿Hiciste el lab?

Si querés, guardá lo que hiciste (comandos, notas, un repo) para volver después. Y si encontrás un error o querés mejorar este lab, contribuí al repo. El progreso se guarda solo en tu navegador.