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.
N° 66