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:
Loadedindica si la unidad está habilitada (enabled) para arrancar con el sistema.Activemuestra el estado:active (running)en marcha,inactive (dead)detenido,failedsi terminó con error.Tasks,MemoryyCPUsalen 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
Notala guía de journalctl de esta misma sección explica en detalle los filtros por tiempo, prioridad y arranque, y cómo configurar la retención de logs.
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.StartLimitIntervalSecyStartLimitBurst: si el servicio arranca más de 5 veces en 300 segundos, systemd deja de intentarlo y lo marca comofailedcon el resultadostart-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 editno 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 discardedse 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 superadoStartLimitBurst. Corrige la causa revisandojournalctl -u nombre_del_servicio, ejecutasudo systemctl reset-failed nombre_del_servicioy arráncalo de nuevo.- No llega el aviso: ejecuta
sudo systemctl status [email protected]yjournalctl -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=oCPUQuota=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.
