systemd no solo arranca y detiene servicios: también sabe en qué estado está cada uno, cuánta CPU y memoria consume, cuántas veces se ha reiniciado y qué ha escrito en el journal. En este tutorial usarás esas capacidades en Ubuntu 24.04 para revisar el estado de un servicio, medir sus recursos, hacer que se reinicie solo cuando falle y recibir un aviso cuando systemd deje de intentarlo. Como ejemplo se usa Nginx, pero todo aplica a cualquier unidad .service.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Los comandos funcionan igual en Debian 12 y Rocky Linux 9, que también usan systemd.
  • Un usuario no root con privilegios sudo.
  • Nginx instalado como servicio de ejemplo. Si no lo tienes, instálalo con sudo apt install nginx.

Paso 1: Consultar el estado de un servicio

El punto de partida es systemctl status, que resume en una pantalla el estado, el PID principal, los recursos consumidos y las últimas líneas del log:

systemctl status nginx --no-pager
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-09-24 10:12:03 UTC; 2h 5min ago
       Docs: man:nginx(8)
   Main PID: 1234 (nginx)
      Tasks: 3 (limit: 2267)
     Memory: 4.1M (peak: 4.6M)
        CPU: 52ms
     CGroup: /system.slice/nginx.service
             ├─1234 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             └─1235 "nginx: worker process"

Fíjate en tres líneas:

  • Loaded indica si la unidad está habilitada (enabled) para arrancar con el sistema.
  • Active muestra el estado: active (running) en marcha, inactive (dead) detenido, failed si terminó con error.
  • Tasks, Memory y CPU salen de la contabilidad de cgroups que systemd mantiene por servicio.

Para scripts y comprobaciones rápidas, usa las variantes is-*, que devuelven una sola palabra y un código de salida:

systemctl is-active nginx
systemctl is-enabled nginx
active
enabled

Si quieres valores concretos, systemctl show con -p y --value imprime propiedades de la unidad sin formato adicional:

systemctl show nginx -p ActiveState -p SubState -p MainPID -p ActiveEnterTimestamp
MainPID=1234
ActiveState=active
SubState=running
ActiveEnterTimestamp=Thu 2026-09-24 10:12:03 UTC

Paso 2: Localizar servicios fallidos

Un servidor sano no debería tener unidades en estado failed. Este comando las lista todas:

systemctl --failed
  UNIT LOAD ACTIVE SUB DESCRIPTION

0 loaded units listed.

Si aparece alguna, systemctl show te dice por qué terminó. La propiedad Result puede valer exit-code, signal, core-dump, timeout o start-limit-hit, y ExecMainStatus guarda el código de salida del proceso:

systemctl show nombre_del_servicio -p Result -p ExecMainStatus

Una vez corregido el problema, limpia el estado de fallo para que la unidad deje de aparecer en la lista:

sudo systemctl reset-failed nombre_del_servicio

Paso 3: Revisar los logs del servicio con journalctl

Todo lo que un servicio escribe en la salida estándar o de error acaba en el journal, etiquetado con su unidad. Filtra por unidad con -u y muestra solo las últimas líneas con -n:

journalctl -u nginx -n 20 --no-pager

Para ver únicamente errores de la última hora, combina -p err con --since:

journalctl -u nginx -p err --since "1 hour ago" --no-pager
-- No entries --

Y para seguir el log en tiempo real mientras reproduces un problema, usa -f y pulsa Ctrl+C para salir:

journalctl -u nginx -f

journalctl -u incluye también los mensajes que escribe el propio systemd sobre la unidad, así que puedes ver el historial de arranques, paradas y fallos buscando esas líneas con -g:

journalctl -u nginx -g "Started|Stopped|Failed" --no-pager

Paso 4: Medir CPU, memoria y tareas por servicio

Ubuntu 24.04 usa cgroups v2 con contabilidad de CPU, memoria y tareas activada por defecto, así que systemd sabe exactamente cuánto consume cada servicio, incluidos todos sus procesos hijos. Para una vista en vivo, similar a top pero agrupada por servicio, usa systemd-cgtop:

sudo systemd-cgtop

Dentro del programa, pulsa c para ordenar por CPU, m por memoria, t por número de tareas y q para salir. Si solo quieres una foto puntual, por ejemplo para pegarla en un ticket, usa el modo batch con una iteración:

sudo systemd-cgtop -b -n 1 | head -15

Para un servicio concreto, consulta las propiedades de consumo. MemoryCurrent está en bytes y CPUUsageNSec en nanosegundos de CPU acumulados desde el último arranque:

systemctl show nginx -p MemoryCurrent -p CPUUsageNSec -p TasksCurrent
MemoryCurrent=4308992
CPUUsageNSec=52187000
TasksCurrent=3

Si prefieres la memoria en un formato legible, numfmt (incluido en coreutils) hace la conversión:

systemctl show nginx -p MemoryCurrent --value | numfmt --to=iec
4.2M

Paso 5: Reiniciar el servicio automáticamente cuando falle

Por defecto, muchas unidades no se reinician si el proceso muere. La directiva Restart=on-failure hace que systemd lo vuelva a arrancar cuando termina con un código distinto de cero, por una señal, por un timeout o por el watchdog, pero no cuando lo paras tú con systemctl stop.

No edites el archivo del paquete en /usr/lib/systemd/system/, porque una actualización lo sobrescribiría. Crea un override con systemctl edit, que abre un archivo en /etc/systemd/system/nginx.service.d/override.conf:

sudo systemctl edit nginx

Añade este bloque en la zona indicada del editor, entre los comentarios:

[Unit]
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Restart=on-failure
RestartSec=5s

Qué hace cada línea:

  • Restart=on-failure: reinicia el servicio si termina de forma anómala.
  • RestartSec=5s: espera cinco segundos antes de cada reintento, para no entrar en un bucle inmediato.
  • StartLimitIntervalSec y StartLimitBurst: si el servicio arranca más de 5 veces en 300 segundos, systemd deja de intentarlo y lo marca como failed con el resultado start-limit-hit. Estas dos directivas van en la sección [Unit].

Guarda y cierra el editor. systemctl edit recarga la configuración de systemd al salir, así que puedes comprobar directamente que los valores se han aplicado:

systemctl show nginx -p Restart -p RestartUSec -p StartLimitBurst
Restart=on-failure
RestartUSec=5s
StartLimitBurst=5

Probar el reinicio automático

Simula un fallo matando el proceso principal con SIGKILL, que es lo que ocurriría si el kernel lo terminase por falta de memoria:

sudo kill -9 "$(systemctl show nginx -p MainPID --value)"

Espera unos segundos y consulta el contador de reinicios automáticos, NRestarts:

sleep 6; systemctl show nginx -p NRestarts -p ActiveState
NRestarts=1
ActiveState=active

El journal también refleja lo ocurrido:

journalctl -u nginx -n 5 --no-pager
Sep 24 12:20:14 web01 systemd[1]: nginx.service: Main process exited, code=killed, status=9/KILL
Sep 24 12:20:14 web01 systemd[1]: nginx.service: Failed with result 'signal'.
Sep 24 12:20:19 web01 systemd[1]: nginx.service: Scheduled restart job, restart counter is at 1.
Sep 24 12:20:19 web01 systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Sep 24 12:20:19 web01 systemd[1]: Started nginx.service - A high performance web server and a reverse proxy server.

Paso 6: Recibir un aviso con OnFailure

Reiniciar solo resuelve fallos puntuales. Si el servicio no consigue arrancar y agota el límite de reintentos, necesitas enterarte. La directiva OnFailure= arranca otra unidad cuando la primera entra en estado failed. Crearás una unidad plantilla que envía un aviso con el nombre del servicio caído.

Primero, el script que manda la notificación. Este ejemplo publica el mensaje en un tema de ntfy, que acepta un simple POST con el texto en el cuerpo, y además lo deja registrado en el journal. Sustituye your_ntfy_topic_url por la URL de tu tema (por ejemplo https://ntfy.sh/un-nombre-dificil-de-adivinar) o por el webhook que ya uses:

sudo nano /usr/local/bin/notify-unit-failure
#!/usr/bin/env bash
set -euo pipefail

unit="$1"
host="$(hostname -f)"
url="your_ntfy_topic_url"

message="$(printf '%s ha fallado en %s\n\n%s' \
  "$unit" "$host" \
  "$(journalctl -u "$unit" -n 15 --no-pager -o cat)")"

logger -t unit-failure "Unidad fallida: $unit"
curl -fsS --max-time 10 -H "Title: Servicio caído en $host" -d "$message" "$url" > /dev/null

Hazlo ejecutable:

sudo chmod 755 /usr/local/bin/notify-unit-failure

Ahora crea la unidad plantilla. El @ en el nombre permite pasarle el servicio afectado como instancia, que llega al script a través de %i:

sudo nano /etc/systemd/system/[email protected]
[Unit]
Description=Aviso de fallo para %i

[Service]
Type=oneshot
ExecStart=/usr/local/bin/notify-unit-failure %i

Prueba la unidad de aviso directamente, sin esperar a un fallo real:

sudo systemctl daemon-reload
sudo systemctl start [email protected]
journalctl -t unit-failure -n 1 --no-pager
Sep 24 12:31:02 web01 unit-failure[5120]: Unidad fallida: nginx

Deberías recibir también la notificación en tu tema de ntfy. Cuando funcione, engancha el aviso al servicio abriendo de nuevo su override:

sudo systemctl edit nginx

Añade OnFailure= a la sección [Unit] que ya tenías. El especificador %N se sustituye por el nombre de la unidad sin el sufijo (nginx), de modo que se arrancará [email protected]:

[Unit]
StartLimitIntervalSec=300
StartLimitBurst=5
OnFailure=notify-failure@%N.service

[Service]
Restart=on-failure
RestartSec=5s

Comprueba que la dependencia está registrada:

systemctl show nginx -p OnFailure

Puedes reutilizar la misma plantilla en cualquier otro servicio añadiendo la misma línea OnFailure=notify-failure@%N.service a su override.

Solución de problemas

  • systemctl edit no guarda nada: el contenido debe ir entre las líneas de comentario que marca el editor. Todo lo que escribas debajo de ### Edits below this comment will be discarded se descarta.
  • El servicio no se reinicia tras un systemctl stop: es el comportamiento esperado. Restart= solo actúa cuando el proceso termina por sí mismo o por una señal externa.
  • Start request repeated too quickly: el servicio ha superado StartLimitBurst. Corrige la causa revisando journalctl -u nombre_del_servicio, ejecuta sudo systemctl reset-failed nombre_del_servicio y arráncalo de nuevo.
  • No llega el aviso: ejecuta sudo systemctl status [email protected] y journalctl -u [email protected] para ver el error del script, normalmente una URL mal copiada o sin salida a Internet.

Conclusión

Has usado systemctl, journalctl y systemd-cgtop para revisar el estado, los logs y el consumo de un servicio, has configurado reinicios automáticos con un límite razonable y has enlazado un aviso que se dispara cuando systemd se rinde. Todo con herramientas que ya vienen en Ubuntu 24.04.

Como siguientes pasos puedes:

  • Configurar la retención y el almacenamiento persistente del journal para conservar más historial.
  • Limitar recursos por servicio con directivas como MemoryMax= o CPUQuota= en el mismo override.
  • Añadir una herramienta de monitorización externa (Prometheus con node_exporter, Zabbix) para tener métricas históricas y vigilar varios servidores a la vez.