El Sistema de Init y Gestión de Servicios
Systemd es el sistema de init estándar en la gran mayoría de distribuciones Linux modernas: Debian, Ubuntu, Fedora, Arch, RHEL, CentOS, openSUSE. Reemplaza a SysVinit y Upstart, y va mucho más allá de arrancar servicios: gestiona el proceso de boot, los logs del sistema, los timers, los sockets, los dispositivos y los namespaces de procesos.
¿Qué gestiona systemd?
| Componente | Función | Herramienta |
|---|---|---|
| Servicios | Arrancar, parar y supervisar daemons (nginx, sshd, mysql...) | systemctl |
| Logs | Recopilar y almacenar los logs del kernel y de todos los servicios | journalctl |
| Timers | Ejecutar tareas programadas — alternativa moderna a cron | systemctl + archivos .timer |
| Sockets | Activar servicios bajo demanda cuando llega una conexión | Archivos .socket |
| Montajes | Gestionar puntos de montaje (alternativa a /etc/fstab) | Archivos .mount |
| Targets | Agrupar unidades — equivalente a los runlevels de SysVinit | Archivos .target |
| Dispositivos | Gestionar eventos de hardware (udev integration) | Archivos .device |
Systemd vs SysVinit
| Aspecto | SysVinit | Systemd |
|---|---|---|
| Arranque de servicios | Secuencial — un servicio a la vez | Paralelo — todos los que pueden a la vez |
| Tiempo de boot | Lento | Rápido gracias a la paralelización |
| Scripts de inicio | Scripts bash en /etc/init.d/ | Archivos de unidad declarativos .service |
| Logs | Archivos de texto en /var/log/ | Journal binario estructurado con metadatos |
| Dependencias | Orden numérico (S01, S02...) | Declaradas explícitamente (After=, Requires=) |
| Reinicio automático | No nativo — requiere supervisord | Nativo con Restart= en el service file |
Todo lo que gestiona systemd se expresa como una "unidad" (unit). Cada unidad es un archivo de texto con extensión que indica su tipo. Conocer los tipos principales es el primer paso para trabajar con systemd.
| Extensión | Tipo | Para qué sirve | Ejemplo |
|---|---|---|---|
.service | Servicio | Gestionar un daemon o proceso en segundo plano | nginx.service, sshd.service |
.timer | Timer | Ejecutar tareas en momentos específicos — alternativa a cron | backup.timer, logrotate.timer |
.socket | Socket | Activar un servicio cuando llega una conexión por socket | sshd.socket, cups.socket |
.target | Target | Agrupar unidades — equivalente a runlevels | multi-user.target, graphical.target |
.mount | Montaje | Gestionar puntos de montaje de sistemas de archivos | home.mount, tmp.mount |
.path | Path | Vigilar un archivo o directorio y activar una unidad al cambiar | cups.path |
.slice | Slice | Agrupar procesos para gestionar recursos con cgroups | system.slice, user.slice |
.device | Dispositivo | Representar dispositivos de hardware detectados por udev | dev-sda1.device |
Ubicaciones de los archivos de unidad
# Prioridad de mayor a menor (la primera encontrada gana) /etc/systemd/system/ ← unidades del administrador (mayor prioridad) /run/systemd/system/ ← unidades creadas en tiempo de ejecución /usr/local/lib/systemd/system/ ← paquetes instalados manualmente /usr/lib/systemd/system/ ← unidades de paquetes del sistema (menor prioridad) # Ver todas las unidades disponibles y su ubicación systemctl show nginx.service -p FragmentPath FragmentPath=/usr/lib/systemd/system/nginx.service # Listar todos los archivos de unidad disponibles systemctl list-unit-files systemctl list-unit-files --type=service # Ver la ruta exacta de una unidad systemctl cat nginx.service # muestra el contenido del archivo
systemctl es la herramienta principal para interactuar con systemd. Permite arrancar, parar, reiniciar, habilitar y consultar el estado de cualquier unidad. Es el comando que más usarás como administrador Linux.
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2024-01-15 14:32:01 UTC; 2h 15min ago
Process: 1234 ExecStartPre=/usr/bin/nginx -t (code=exited, status=0/SUCCESS)
Main PID: 1235 (nginx)
Tasks: 3 (limit: 4915)
Memory: 6.2M
CPU: 42ms
CGroup: /system.slice/nginx.service
├─1235 "nginx: master process /usr/sbin/nginx"
└─1236 "nginx: worker process"
Jan 15 14:32:01 servidor nginx[1234]: nginx: configuration file /etc/nginx/nginx.conf test is OK
## CONTROL DE SERVICIOS systemctl start nginx # arrancar ahora (no persiste tras reinicio) systemctl stop nginx # parar el servicio systemctl restart nginx # parar y arrancar systemctl reload nginx # recargar config sin parar (si el servicio lo soporta) systemctl reload-or-restart nginx # reload si puede, restart si no ## HABILITAR / DESHABILITAR (persistencia entre reinicios) systemctl enable nginx # arrancar automáticamente al iniciar el sistema systemctl disable nginx # no arrancar automáticamente systemctl enable --now nginx # habilitar Y arrancar ahora (lo más común) systemctl disable --now nginx# deshabilitar Y parar ahora systemctl mask nginx # impedir completamente que arranque (ni manual) systemctl unmask nginx # revertir el mask ## CONSULTAR ESTADO systemctl status nginx # estado detallado con últimas líneas de log systemctl is-active nginx # active / inactive (ideal para scripts) systemctl is-enabled nginx # enabled / disabled systemctl is-failed nginx # true si el servicio falló ## LISTAR UNIDADES systemctl list-units # unidades activas systemctl list-units --all # todas (activas e inactivas) systemctl list-units --type=service # solo servicios systemctl list-units --state=failed # solo los que fallaron systemctl list-unit-files # todos los archivos de unidad instalados ## RECARGAR CONFIGURACIÓN tras crear o editar un unit file systemctl daemon-reload # releer todos los archivos de unidad desde disco ## APAGAR Y REINICIAR EL SISTEMA systemctl poweroff # apagar systemctl reboot # reiniciar systemctl suspend # suspender systemctl hibernate # hibernar
Un archivo .service es la descripción declarativa de cómo systemd debe gestionar un proceso: qué ejecutar, con qué usuario, cuándo arrancar, qué hacer si falla. Es la pieza central del trabajo con systemd.
Estructura de un archivo .service
[Unit]
Description=Mi Aplicación Web
Documentation=https://mi-app.com/docs
After=network.target postgresql.service
Requires=postgresql.service
# Sección [Service] — cómo ejecutar el proceso
[Service]
Type=simple
User=webapp
Group=webapp
WorkingDirectory=/opt/mi-app
EnvironmentFile=/etc/mi-app/env
ExecStartPre=/opt/mi-app/bin/check-config
ExecStart=/opt/mi-app/bin/servidor --port 8080
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
TimeoutStartSec=30
StandardOutput=journal
StandardError=journal
# Sección [Install] — en qué target se activa
[Install]
WantedBy=multi-user.target
Opciones clave de [Service]
| Opción | Valores / Ejemplo | Qué hace |
|---|---|---|
Type= | simple, forking, oneshot, notify, idle | Define cómo systemd sabe que el servicio arrancó. simple: el ExecStart es el proceso principal. forking: el proceso hace fork y el padre sale (daemons tradicionales). oneshot: se ejecuta y termina. notify: el proceso avisa a systemd cuando está listo. |
ExecStart= | /usr/bin/nginx -g "daemon off;" | Comando a ejecutar para arrancar el servicio. Ruta absoluta obligatoria. |
ExecStartPre= | /usr/bin/nginx -t | Comando a ejecutar antes de ExecStart. Si falla, el servicio no arranca. |
ExecStop= | /bin/kill -TERM $MAINPID | Comando para parar el servicio. Si no se especifica, systemd envía SIGTERM. |
Restart= | no, on-failure, on-abnormal, always | Cuándo reiniciar el servicio si se para. on-failure: si sale con código != 0 o por señal. always: siempre, incluso si se para limpiamente. |
RestartSec= | 5s, 30 | Tiempo de espera antes de reiniciar. |
User= / Group= | www-data, nobody | Usuario y grupo con los que se ejecuta el proceso. Si no se especifica, corre como root. |
WorkingDirectory= | /opt/mi-app | Directorio de trabajo del proceso. |
Environment= | NODE_ENV=production PORT=3000 | Variables de entorno inline. |
EnvironmentFile= | /etc/mi-app/env | Cargar variables de entorno desde un archivo (formato KEY=VALUE). |
TimeoutStartSec= | 30, infinity | Tiempo máximo para que el servicio arranque antes de que systemd lo declare fallido. |
Laboratorio completo: crear un archivo .service desde cero, habilitarlo y diagnosticar su funcionamiento. Este es el flujo que usarás en la vida real para desplegar aplicaciones propias como servicios.
# Crear usuario del sistema para el servicio sudo useradd --system --no-create-home --shell /usr/sbin/nologin webapp # Crear directorios necesarios sudo mkdir -p /opt/mi-app /var/log/mi-app /etc/mi-app sudo chown webapp:webapp /opt/mi-app /var/log/mi-app # Crear un script de ejemplo (la aplicación) sudo tee /opt/mi-app/servidor.sh << 'EOF' #!/bin/bash echo "Servidor arrancando en puerto ${PORT:-8080}" while true; do echo "$(date): Servidor ejecutándose" >> /var/log/mi-app/app.log sleep 10 done EOF sudo chmod +x /opt/mi-app/servidor.sh sudo chown webapp:webapp /opt/mi-app/servidor.sh
# Crear el archivo de variables de entorno sudo tee /etc/mi-app/env << 'EOF' PORT=8080 NODE_ENV=production DATABASE_URL=postgresql://localhost/miapp EOF sudo chmod 640 /etc/mi-app/env sudo chown root:webapp /etc/mi-app/env # solo webapp puede leerlo
/etc/systemd/system/ — nunca en /usr/lib/systemd/system/ que es para paquetes del sistema.sudo tee /etc/systemd/system/mi-app.service << 'EOF'
[Unit]
Description=Mi Aplicación Web
Documentation=https://mi-app.com/docs
After=network.target
Wants=network.target
[Service]
Type=simple
User=webapp
Group=webapp
WorkingDirectory=/opt/mi-app
EnvironmentFile=/etc/mi-app/env
ExecStart=/opt/mi-app/servidor.sh
Restart=on-failure
RestartSec=5s
TimeoutStartSec=30
TimeoutStopSec=20
StandardOutput=journal
StandardError=journal
SyslogIdentifier=mi-app
# Seguridad básica
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ReadWritePaths=/var/log/mi-app
[Install]
WantedBy=multi-user.target
EOF# Releer los archivos de unidad desde disco (SIEMPRE tras crear o editar) sudo systemctl daemon-reload # Habilitar y arrancar en un solo comando sudo systemctl enable --now mi-app.service # Verificar que está corriendo systemctl status mi-app.service ● mi-app.service - Mi Aplicación Web Loaded: loaded (/etc/systemd/system/mi-app.service; enabled) Active: active (running) since Mon 2024-01-15 14:32:01 UTC; 3s ago Main PID: 5678 (servidor.sh) CGroup: /system.slice/mi-app.service └─5678 /bin/bash /opt/mi-app/servidor.sh # Ver los logs en tiempo real journalctl -u mi-app.service -f
Los targets son el equivalente a los runlevels de SysVinit. Definen el estado del sistema — qué servicios están activos. El target activo determina si el sistema arranca en modo texto, con entorno gráfico, en modo de rescate, etc.
Equivalencia con runlevels SysVinit
| Runlevel SysV | Target systemd | Descripción |
|---|---|---|
| 0 | poweroff.target | Apagar el sistema |
| 1 | rescue.target | Modo de rescate — usuario único, sin red |
| 2, 3, 4 | multi-user.target | Sistema multiusuario sin entorno gráfico — el estándar en servidores |
| 5 | graphical.target | Sistema multiusuario con entorno gráfico (escritorio) |
| 6 | reboot.target | Reiniciar el sistema |
# Ver el target activo por defecto (el que arranca el sistema) systemctl get-default multi-user.target # Cambiar el target por defecto (p. ej. para añadir entorno gráfico) sudo systemctl set-default graphical.target # Cambiar al target de rescate SIN reiniciar (sesión actual) sudo systemctl isolate rescue.target # Ver qué servicios están habilitados en un target systemctl list-dependencies multi-user.target # Ver las dependencias de un servicio systemctl list-dependencies nginx.service # Arrancar en modo emergencia (mínimo absoluto — solo root) sudo systemctl isolate emergency.target
Systemd gestiona las dependencias entre unidades de forma explícita y declarativa. Entender las diferencias entre Requires, Wants, After y Before es fundamental para escribir unit files correctos.
| Directiva | Sección | Comportamiento |
|---|---|---|
Requires= | [Unit] | Dependencia fuerte — si la unidad requerida falla o se para, esta también se para |
Wants= | [Unit] | Dependencia débil — intenta arrancar la otra unidad, pero si falla esta sigue funcionando |
After= | [Unit] | Orden — esta unidad arranca DESPUÉS de la especificada (no implica dependencia) |
Before= | [Unit] | Orden — esta unidad arranca ANTES de la especificada |
Conflicts= | [Unit] | Conflicto — si esta arranca, la especificada se para, y viceversa |
BindsTo= | [Unit] | Como Requires pero más fuerte — si la otra unidad se para, esta también se para inmediatamente |
PartOf= | [Unit] | Si la unidad padre se para o reinicia, esta también lo hace (pero no al revés) |
After= solo define el orden — no activa la dependencia. Requires= define la dependencia pero no el orden. Para decir "necesito que B esté activo Y debo arrancar después de B", necesitas AMBOS: Requires=B y After=B. En la práctica casi siempre se usan juntos.# Servicio web que necesita base de datos [Unit] Description=Aplicación Web After=network.target postgresql.service redis.service Requires=postgresql.service # si postgres falla, esta app también Wants=redis.service # intenta redis, pero funciona sin él # Verificar dependencias en tiempo real systemctl list-dependencies mi-app.service --all systemd-analyze critical-chain mi-app.service # cadena crítica de arranque
journald es el sistema de logging de systemd. Captura la salida estándar de todos los servicios, los logs del kernel y los mensajes del sistema en un journal binario estructurado. journalctl es la herramienta para consultarlo.
## LOGS DE UN SERVICIO ESPECÍFICO journalctl -u nginx.service # todos los logs de nginx journalctl -u nginx.service -f # seguir en tiempo real (como tail -f) journalctl -u nginx.service -n 50 # últimas 50 líneas journalctl -u nginx.service --no-pager # sin paginador (útil para scripts) ## FILTRAR POR TIEMPO journalctl -u nginx --since "2024-01-15 14:00" journalctl -u nginx --since "1 hour ago" journalctl -u nginx --since today journalctl -u nginx --since "2024-01-15" --until "2024-01-16" ## FILTRAR POR PRIORIDAD (nivel de severidad) journalctl -p err # solo errores (err, crit, alert, emerg) journalctl -p warning # warnings y superior journalctl -u nginx -p err -f # errores de nginx en tiempo real # Niveles disponibles: debug, info, notice, warning, err, crit, alert, emerg ## BOOT ACTUAL Y ANTERIORES journalctl -b # logs del boot actual journalctl -b -1 # boot anterior journalctl --list-boots # lista de todos los boots guardados ## LOGS DEL KERNEL journalctl -k # kernel messages (como dmesg) journalctl -k -b -1 # kernel del boot anterior ## SALIDA EN DISTINTOS FORMATOS journalctl -u nginx -o json # JSON estructurado journalctl -u nginx -o json-pretty # JSON formateado journalctl -u nginx -o short-precise # timestamp con microsegundos journalctl -u nginx -o cat # solo el mensaje, sin metadatos ## GESTIÓN DEL ESPACIO EN DISCO journalctl --disk-usage # ver espacio usado por el journal journalctl --vacuum-size=500M # reducir a máximo 500 MB journalctl --vacuum-time=30d # eliminar logs de más de 30 días
Configurar journald
# /etc/systemd/journald.conf [Journal] Storage=persistent # guardar en /var/log/journal (persiste entre boots) Compress=yes # comprimir entradas antiguas SystemMaxUse=2G # máximo 2GB en disco SystemKeepFree=1G # mantener al menos 1GB libre MaxRetentionSec=30day # retener logs máximo 30 días MaxFileSec=1week # rotar archivos semanalmente ForwardToSyslog=no # no reenviar a syslog clásico RateLimitIntervalSec=30s RateLimitBurst=10000 # max 10000 mensajes cada 30s por servicio # Aplicar cambios sudo systemctl restart systemd-journald
Cuando un servicio falla, systemd y journald proporcionan toda la información necesaria para diagnosticar el problema. Este es el flujo de investigación estándar.
## PASO 1: ver servicios fallidos systemctl list-units --state=failed UNIT LOAD ACTIVE SUB DESCRIPTION ● mi-app.service loaded failed failed Mi Aplicación Web ## PASO 2: status detallado del servicio systemctl status mi-app.service ● mi-app.service - Mi Aplicación Web Active: failed (Result: exit-code) since Mon 2024-01-15 14:35:22 UTC Process: 5678 ExecStart=/opt/mi-app/servidor.sh (code=exited, status=1/FAILURE) Main PID: 5678 (code=exited, status=1/FAILURE) Jan 15 14:35:22 servidor servidor.sh[5678]: Error: no se puede leer /etc/mi-app/env ## PASO 3: logs completos del servicio journalctl -u mi-app.service -n 100 --no-pager journalctl -u mi-app.service -b -p err # solo errores del boot actual ## PASO 4: herramientas de análisis systemd-analyze # tiempo total de arranque Startup finished in 1.234s (kernel) + 3.456s (userspace) = 4.690s systemd-analyze blame # servicios ordenados por tiempo de arranque 3.234s postgresql.service 1.123s NetworkManager.service 0.456s mi-app.service systemd-analyze critical-chain # cadena crítica del boot systemd-analyze verify mi-app.service # validar el unit file sin arrancarlo ## PASO 5: ver el unit file activo (con overrides aplicados) systemctl cat mi-app.service ## PASO 6: ver las propiedades del servicio systemctl show mi-app.service systemctl show mi-app.service -p Restart,RestartSec,ExecStart ## REINTENTAR tras corregir el problema sudo systemctl reset-failed mi-app.service # limpiar el estado de fallo sudo systemctl start mi-app.service
Los timers de systemd son la alternativa moderna a crontab. Ofrecen más control, logging integrado en journald, la posibilidad de capturar el estado de la última ejecución y activación al arranque si se perdió una ejecución.
journalctl), soportan OnBootSec para ejecutar X tiempo después del arranque, y permiten ver la próxima ejecución con systemctl list-timers. La desventaja: requieren dos archivos en lugar de una línea de crontab.Crear un timer: backup diario
Description=Backup diario de base de datos
After=postgresql.service
[Service]
Type=oneshot
User=postgres
ExecStart=/usr/bin/pg_dump mibd | gzip > /backup/mibd-$(date +%%Y%%m%%d).sql.gz
StandardOutput=journal
Description=Ejecutar backup diariamente a las 02:00
[Timer]
OnCalendar=*-*-* 02:00:00 # todos los días a las 2AM
Persistent=true # ejecutar si se perdió la última vez
RandomizedDelaySec=10min # añadir hasta 10min de delay aleatorio
[Install]
WantedBy=timers.target
# Activar el timer (no el .service directamente) sudo systemctl daemon-reload sudo systemctl enable --now backup.timer # Ver todos los timers activos y cuándo se ejecutarán systemctl list-timers NEXT LEFT UNIT ACTIVATES Mon 2024-01-16 02:03:42 UTC 11h left backup.timer backup.service # Ver logs de las últimas ejecuciones journalctl -u backup.service ## SINTAXIS OnCalendar — ejemplos OnCalendar=daily → cada día a las 00:00 OnCalendar=weekly → cada lunes a las 00:00 OnCalendar=monthly → primer día de mes a las 00:00 OnCalendar=hourly → cada hora OnCalendar=*:0/15 → cada 15 minutos OnCalendar=Mon..Fri 09:00 → lunes a viernes a las 9AM OnCalendar=*-*-* 02:00:00 → todos los días a las 2AM OnCalendar=Sat *-*-* 03:30:00 → cada sábado a las 3:30AM ## TIMERS RELATIVOS AL ARRANQUE OnBootSec=5min → 5 minutos después del boot OnActiveSec=1h → 1 hora después de que el timer se activó OnUnitActiveSec=1day → 1 día después de la última activación # Verificar sintaxis de la expresión systemd-analyze calendar "Mon..Fri 09:00" Original form: Mon..Fri 09:00 Normalized form: Mon..Fri *-*-* 09:00:00 Next elapse: Mon 2024-01-15 09:00:00 UTC
La activación por socket permite arrancar un servicio solo cuando llega la primera conexión, en lugar de tenerlo corriendo siempre. Systemd gestiona el socket, y cuando llega una conexión, arranca el servicio y le pasa el socket. Reduce el consumo de recursos y acelera el boot.
Description=Socket para Mi API
[Socket]
ListenStream=8080 # escuchar en el puerto 8080
Accept=no # pasar el socket al servicio (no por conexión)
[Install]
WantedBy=sockets.target
# Habilitar el socket (no el servicio — systemd lo arranca al primer acceso) sudo systemctl enable --now mi-api.socket # Ver sockets activos systemctl list-sockets # Usos comunes de socket activation SSH: sshd.socket → sshd.service (activa sshd al primer intento de conexión) DBus: dbus.socket → dbus.service Printing: cups.socket → cups.service Docker: docker.socket → docker.service
Systemd incluye un sistema de sandboxing muy potente para aislar servicios y limitar su acceso al sistema. Añadir estas directivas a cualquier service file reduce drásticamente el impacto de un compromiso.
[Service] # --- DIRECTIVAS ESENCIALES (bajo coste, alto impacto) --- NoNewPrivileges=yes # el proceso no puede ganar más privilegios (setuid, etc.) PrivateTmp=yes # /tmp privado — no compartido con otros servicios ProtectSystem=strict # /usr, /boot y /etc son read-only ProtectHome=yes # /home, /root y /run/user son inaccesibles # --- CONTROL DE SISTEMA DE ARCHIVOS --- ReadWritePaths=/var/lib/mi-app /var/log/mi-app # solo estos directorios son escribibles ReadOnlyPaths=/etc/mi-app # acceso de solo lectura a la configuración InaccessiblePaths=/root /home # completamente inaccesibles PrivateDevices=yes # solo /dev/null, /dev/zero, /dev/random (sin acceso a hardware) # --- NAMESPACES Y AISLAMIENTO --- ProtectKernelTunables=yes # no puede modificar parámetros del kernel (/proc/sys, /sys) ProtectKernelModules=yes # no puede cargar módulos del kernel ProtectControlGroups=yes # no puede modificar cgroups RestrictNamespaces=yes # no puede crear namespaces LockPersonality=yes # no puede cambiar la personalidad del proceso (ABI) # --- LLAMADAS AL SISTEMA --- SystemCallFilter=@system-service # permitir solo syscalls típicas de servicios SystemCallErrorNumber=EPERM # devolver EPERM en vez de SIGSYS si intenta syscall no permitida # --- RED --- PrivateNetwork=yes # sin acceso a red (para servicios que no necesitan red) RestrictAddressFamilies=AF_INET AF_INET6 # solo IPv4 e IPv6
# Ver la puntuación de seguridad de un servicio systemd-analyze security nginx.service NAME DESCRIPTION EXPOSURE ✗ PrivateNetwork= Service has access to the host network 0.5 ✗ PrivateTmp= Service has access to other units' /tmp 0.1 ✓ NoNewPrivileges= Service cannot gain new privileges ... → Overall exposure level for nginx.service: 7.2 MEDIUM # Puntuación 0 = máxima seguridad, 10 = sin restricciones # Objetivo recomendado: por debajo de 4 (OK) o 2 (bueno)
Los overrides permiten personalizar un unit file de un paquete del sistema sin editarlo directamente. Al actualizar el paquete, el unit file original se sobreescribe pero el override se mantiene. Es la forma correcta de modificar servicios del sistema.
# Forma 1 — systemctl edit (abre el editor automáticamente) sudo systemctl edit nginx.service # Crea /etc/systemd/system/nginx.service.d/override.conf # Solo hay que añadir las directivas que quieres cambiar # Ejemplo de override: añadir límites de memoria y reinicio más agresivo sudo tee /etc/systemd/system/nginx.service.d/override.conf << 'EOF' [Service] Restart=always RestartSec=3s MemoryMax=512M CPUQuota=50% Environment=EXTRA_VAR=valor EOF # Forma 2 — systemctl edit --full (edita una copia completa del unit file) sudo systemctl edit --full nginx.service # CUIDADO: este se sobreescribe al actualizar el paquete — usar solo si necesitas cambios mayores # Aplicar los cambios sudo systemctl daemon-reload sudo systemctl restart nginx # Ver el unit file final con los overrides aplicados systemctl cat nginx.service # /usr/lib/systemd/system/nginx.service ← archivo original [Unit] ... # /etc/systemd/system/nginx.service.d/override.conf ← override [Service] Restart=always # Eliminar un override sudo systemctl revert nginx.service # O borrar el directorio manualmente sudo rm -rf /etc/systemd/system/nginx.service.d/ sudo systemctl daemon-reload
Los comandos más usados en el trabajo diario con systemd.
systemctl — Referencia rápida
- Arrancar:
systemctl start nombre.service - Parar:
systemctl stop nombre.service - Reiniciar:
systemctl restart nombre.service - Recargar config:
systemctl reload nombre.service - Habilitar y arrancar:
systemctl enable --now nombre.service - Estado:
systemctl status nombre.service - Recargar unit files:
systemctl daemon-reload - Servicios fallidos:
systemctl list-units --state=failed
journalctl — Referencia rápida
- Logs de un servicio:
journalctl -u nombre.service - Seguir en tiempo real:
journalctl -u nombre.service -f - Solo errores:
journalctl -u nombre.service -p err - Boot actual:
journalctl -b - Desde hace 1 hora:
journalctl -u nombre --since "1 hour ago" - Espacio en disco:
journalctl --disk-usage - Limpiar logs:
journalctl --vacuum-time=30d
Comandos de diagnóstico
## ANÁLISIS DE ARRANQUE systemd-analyze # tiempo total de boot systemd-analyze blame # servicios más lentos systemd-analyze critical-chain # cadena crítica systemd-analyze security nombre.service # puntuación de seguridad systemd-analyze verify nombre.service # validar sintaxis del unit file ## INSPECCIONAR UNIDADES systemctl cat nombre.service # ver el contenido del unit file systemctl show nombre.service # todas las propiedades systemctl show nombre.service -p Restart # propiedad específica systemctl list-dependencies nombre # árbol de dependencias ## TIMERS systemctl list-timers # ver todos los timers y próxima ejecución systemd-analyze calendar "daily" # verificar expresión de calendario ## OVERRIDES systemctl edit nombre.service # crear/editar override systemctl revert nombre.service # eliminar override ## TARGETS systemctl get-default # target de arranque systemctl set-default multi-user.target # cambiar target de arranque systemctl isolate rescue.target # cambiar target ahora
Flujo estándar para crear un nuevo servicio
- Crear usuario del sistema sin shell:
useradd --system --no-create-home --shell /usr/sbin/nologin nombre - Crear el archivo .service en
/etc/systemd/system/ - Validar la sintaxis:
systemd-analyze verify nombre.service - Recargar la configuración:
systemctl daemon-reload - Habilitar y arrancar:
systemctl enable --now nombre.service - Verificar estado:
systemctl status nombre.service - Ver logs:
journalctl -u nombre.service -f - Auditar seguridad:
systemd-analyze security nombre.service