systemctl es la herramienta de línea de comandos que te permite hablar con el demonio systemd (PID 1). No es un envoltorio cosmético: cada subcomando que ejecutas se traduce en una llamada D-Bus al proceso init, que responde con estado, ejecuta cambios o persiste configuración en disco. Entender esta distinción —que systemctl es un cliente y systemd el servidor— explica por qué ciertos cambios requieren pasos explícitos como daemon-reload: el cliente no sabe automáticamente que los archivos en disco cambiaron, hay que decírselo.

El diseño de systemctl separa intencionalmente dos ejes ortogonales: el estado en tiempo de ejecución (activo/inactivo ahora mismo) y el estado persistente en el arranque (habilitado/deshabilitado para futuros boots). Mezclarlos mentalmente es la fuente de la mayoría de errores de configuración: un servicio puede estar corriendo ahora y no arrancar en el próximo boot, o estar habilitado y estar caído en este momento. Cada eje se gestiona con verbos distintos.

Úsalo siempre que necesites arrancar, detener, inspeccionar o configurar unidades de systemd —servicios, timers, sockets, mounts—. Si estás escribiendo un script de automatización o de despliegue, los subcomandos is-active e is-enabled te devuelven exit codes limpios (0 = sí, distinto de 0 = no) sin texto que parsear, lo que los hace ideales para condicionales de shell.

Lo que se rompe si no conoces bien esta herramienta es predecible: reinicias un servicio cuando solo necesitabas recargar su configuración (interrumpiendo conexiones activas), olvidas daemon-reload tras editar un unit file y te quedas preguntando por qué systemd ignora tus cambios, o habilitas un servicio sin arrancarlo esperando que ya esté activo.

# Escenario: instalar nginx, ajustar su configuración y dejarlo
# correctamente gestionado en producción.

# 1. Instalar nginx (crea el unit file en /lib/systemd/system/nginx.service)
apt install -y nginx

# 2. Habilitar E arrancar en un solo paso.
#    --now equivale a: enable + start en una sola llamada.
systemctl enable --now nginx

# Verificar estado completo: muestra si está activo, enabled,
# el PID, uso de memoria, y los últimos logs del journal.
systemctl status nginx

# 3. Editar la configuración de nginx y recargar SIN cortar conexiones.
#    reload le manda SIGHUP al proceso; nginx recarga sus workers.
#    Solo funciona si el servicio implementa recarga — no todos lo hacen.
nano /etc/nginx/sites-available/default
nginx -t                  # validar antes de aplicar
systemctl reload nginx

# 4. Si cambiaste el unit file mismo (no la config de la aplicación),
#    systemd necesita releer el disco antes de cualquier otra operación.
#    Sin este paso, systemd opera con la definición anterior en memoria.
nano /lib/systemd/system/nginx.service   # hipotético — en producción usa override
systemctl daemon-reload
systemctl restart nginx   # stop + start completo; corta conexiones activas

# 5. Crear un override drop-in sin tocar el unit file original.
#    Abre $EDITOR con una plantilla en /etc/systemd/system/nginx.service.d/override.conf
#    Al guardar, el archivo queda en disco pero aún no está activo.
systemctl edit nginx
systemctl daemon-reload   # siempre después de editar unit files o drop-ins
systemctl restart nginx

# 6. Checks programáticos — útiles en scripts de despliegue.
#    Exit code 0 = condición verdadera; cualquier otro valor = falsa.
systemctl is-active nginx   && echo "nginx está corriendo"
systemctl is-enabled nginx  && echo "nginx arranca en el boot"

# 7. Ver todos los servicios cargados y su estado actual.
systemctl list-units --type=service

# 8. Si necesitas sacarlo del arranque sin detenerlo ahora:
systemctl disable nginx

# Y si quieres pararlo y deshabilitarlo de una vez:
systemctl disable --now nginx

Qué está pasando en cada paso

El paso 2 con enable --now es el más importante de aprender. enable por sí solo crea un symlink en el target de arranque correspondiente —típicamente /etc/systemd/system/multi-user.target.wants/nginx.service— pero no toca el proceso en ejecución. --now añade el start implícito. Sin --now, tras un apt install el servicio normalmente ya está corriendo (el paquete Debian lo arranca en el postinst), pero no está habilitado para el siguiente boot. Con --now consolidas ambas cosas.

reload en el paso 3 merece atención especial. nginx implementa recarga limpia: cuando recibe SIGHUP, el proceso maestro valida la nueva configuración, lanza workers nuevos y espera a que los viejos terminen sus conexiones activas antes de matarlos. restart no hace eso —mata el proceso y lo vuelve a crear—, lo que genera un hueco de disponibilidad aunque sea de milisegundos. En un balanceador de carga eso puede pasar desapercibido; en un servicio que gestiona estado en memoria, puede ser catastrófico. La regla: si el servicio soporta reload, úsalo.

El daemon-reload del paso 4 es un error clásico omitir. systemd mantiene en memoria las definiciones de las unidades que ya ha procesado. Si editas /lib/systemd/system/nginx.service o creas un drop-in en /etc/systemd/system/nginx.service.d/, systemd no detecta ese cambio automáticamente —no hay inotify watch sobre esos directorios en este contexto—. daemon-reload fuerza la relectura. Hasta que no lo ejecutas, cualquier restart o start posterior usa la definición antigua.

El paso 5 con systemctl edit es la forma correcta de personalizar un unit file en Debian. Los archivos en /lib/systemd/system/ son propiedad del paquete y el próximo apt upgrade puede sobreescribirlos. systemctl edit crea automáticamente /etc/systemd/system/nginx.service.d/override.conf con una plantilla vacía. Solo escribes las directivas que quieres sobreescribir —por ejemplo LimitNOFILE=65536 o Environment=NGINX_ENVVAR=valor—; el resto hereda del unit original. Después del daemon-reload, systemd fusiona el drop-in sobre la definición base.

Los checks del paso 6 son los que separan los scripts que funcionan de los que funcionan a veces. Parsear la salida de systemctl status en un script es frágil: el formato puede cambiar entre versiones, el texto varía con el locale, y capturar la salida completa es innecesariamente costoso. is-active y is-enabled devuelven un exit code limpio y además imprimen el estado en una palabra (active, inactive, enabled, disabled) por si quieres usarlo con $(...). En un health check de un script de despliegue, el patrón es simplemente systemctl is-active nginx || systemctl start nginx.

list-units --type=service en el paso 7 muestra por defecto solo las unidades cargadas —las que systemd tiene en memoria, ya sea porque están activas, porque fallaron, o porque fueron activadas en esta sesión—. Si quieres ver todas las definidas en disco, incluyendo las deshabilitadas que nunca se han cargado, añade --all. Añade --state=failed para ver solo las que tienen problemas, que es el primer lugar donde mirar en un sistema con comportamiento extraño al arranque.

66