Systemd en Linux
Servicios, arranque, logs y automatización desde la terminal
Cuando utilizamos Linux normalmente ejecutamos comandos, abrimos aplicaciones y trabajamos con procesos sin preocuparnos demasiado por lo que ocurre detrás de ellos. Sin embargo, desde que encendemos el ordenador hasta que aparece nuestro escritorio, existe todo un sistema encargado de iniciar procesos, montar sistemas de archivos, levantar servicios, administrar dependencias, registrar errores y mantener funcionando determinados programas.
En la mayoría de distribuciones modernas ese trabajo está relacionado con systemd.
Systemd no es simplemente un programa para iniciar servicios. Es un system and service manager que, cuando se ejecuta como PID 1, actúa como el primer proceso del sistema y coordina gran parte del espacio de usuario. Además, trabaja con un modelo basado en unidades (units) y dependencias.
En este artículo veremos systemd desde cero hasta llegar a la creación de servicios y automatizaciones reales.
1. ¿Qué es systemd?
systemd es el sistema de inicialización y administrador de servicios utilizado por muchas distribuciones Linux modernas.
Cuando Linux termina de cargar el kernel, necesita iniciar el resto del sistema:
Kernel
│
▼
systemd (PID 1)
│
├── Servicios
├── Montajes
├── Dispositivos
├── Timers
├── Sockets
├── Targets
└── Otros componentes
Podemos comprobar si nuestro sistema utiliza systemd con:
ps -p 1 -o pid,comm,args
Un resultado típico sería:
PID COMMAND COMMAND
1 systemd /sbin/init
El dato importante es:
PID = 1
PID 1 es un proceso especial. Es el proceso que inicia y supervisa el espacio de usuario.
También podemos ejecutar:
systemctl --version
Por ejemplo:
systemd 259
+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK
+SECCOMP +GCRYPT +GNUTLS +OPENSSL
...
La versión exacta dependerá de nuestra distribución.
2. ¿Por qué systemd es importante?
Una de las tareas principales de systemd es administrar servicios.
Por ejemplo:
NetworkManager
sshd
bluetooth
docker
cups
postgresql
nginx
Todos ellos pueden ser administrados mediante systemd.
En lugar de ejecutar manualmente:
./servidor &
podemos crear un servicio:
mi-servidor.service
y permitir que systemd se encargue de:
- iniciarlo;
- detenerlo;
- reiniciarlo;
- supervisarlo;
- registrar sus logs;
- controlar sus dependencias;
- iniciarlo automáticamente durante el boot;
- reiniciarlo si falla, cuando así se configure.
3. El concepto fundamental: Units
Antes de aprender systemctl, hay que entender qué es una unit.
Systemd utiliza diferentes tipos de unidades para representar recursos o mecanismos que necesita administrar. Entre ellas existen:
.service
.socket
.target
.device
.mount
.automount
.swap
.timer
.path
.slice
.scope
Por ejemplo:
nginx.service
docker.service
sshd.service
backup.timer
multi-user.target
Cada extensión representa un tipo diferente de unidad.
Las más importantes para comenzar son:
| Unit | Función |
|---|---|
.service | Gestiona servicios/procesos |
.timer | Programa la activación de unidades |
.target | Agrupa unidades y representa estados del sistema |
.socket | Gestiona sockets y activación por socket |
.mount | Gestiona puntos de montaje |
.path | Puede activar unidades cuando cambia un archivo/directorio |
4. ¿Qué es un .service?
Un archivo:
algo.service
describe cómo systemd debe ejecutar y controlar un servicio.
Por ejemplo:
mi-servidor.service
podría decir:
Descripción:
Mi servidor web
Programa:
/usr/bin/python
Argumentos:
/home/user/server.py
Usuario:
user
Reinicio:
si falla
Los archivos de unidades utilizan secciones como:
[Unit]
[Service]
[Install]
Cada sección tiene una responsabilidad diferente.
5. La arquitectura básica de un servicio
Un servicio sencillo puede tener esta estructura:
[Unit]
Description=Mi servidor Python
After=network.target
[Service]
ExecStart=/usr/bin/python /home/user/server.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
Vamos a analizarlo.
[Unit]
Contiene información general y dependencias.
[Unit]
Description=Mi servidor Python
After=network.target
Description proporciona una descripción legible.
After= define un orden.
En este caso:
After=network.target
significa que systemd debe ordenar este servicio después de network.target.
Esto no significa por sí solo que network.target sea iniciado por este servicio. Las relaciones de dependencia y las relaciones de orden son conceptos diferentes.
6. [Service]
Esta sección define cómo se ejecutará el programa.
Por ejemplo:
[Service]
ExecStart=/usr/bin/python /home/user/server.py
Restart=on-failure
ExecStart indica qué programa debe ejecutarse.
Restart=on-failure indica que systemd puede intentar reiniciar el servicio si termina debido a un fallo.
También podemos especificar el usuario:
User=geremy
y el directorio de trabajo:
WorkingDirectory=/home/geremy/app
Por ejemplo:
[Service]
User=geremy
WorkingDirectory=/home/geremy/app
ExecStart=/usr/bin/python /home/geremy/app/server.py
Restart=on-failure
Esto es preferible a ejecutar automáticamente todo como root cuando no existe una necesidad real de privilegios.
7. [Install]
Esta sección determina cómo puede integrarse la unidad con otros targets cuando utilizamos operaciones como:
systemctl enable
Por ejemplo:
[Install]
WantedBy=multi-user.target
Esto permite habilitar el servicio para que sea incorporado al conjunto de unidades asociadas con multi-user.target.
Los target funcionan como agrupaciones y puntos de sincronización dentro del modelo de dependencias de systemd. Son una evolución más flexible de los antiguos runlevels de SysV init.
8. systemctl: el controlador de systemd
El comando principal que utilizamos para comunicarnos con systemd es:
systemctl
Podemos pensar en él como el cliente que envía instrucciones al administrador de servicios.
Por ejemplo:
systemctl status
muestra información general del estado del sistema.
Para trabajar con un servicio:
systemctl status nginx
9. Ver el estado de un servicio
Ejecutemos:
systemctl status sshd
Podríamos obtener algo parecido a:
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled)
Active: active (running) since Mon 2026-09-28 18:21:03 AST
Main PID: 842 (sshd)
Tasks: 1
Memory: 4.8M
CPU: 32ms
Hay varias líneas importantes.
Loaded
Loaded: loaded
significa que systemd encontró y cargó la unidad.
También puede aparecer:
enabled
Esto indica que la unidad está habilitada para ser incorporada mediante su mecanismo de instalación correspondiente.
Active
Active: active (running)
indica que actualmente está funcionando.
Otros estados comunes incluyen:
active
inactive
failed
activating
deactivating
Main PID
Main PID: 842
nos muestra el PID principal asociado al servicio.
10. Iniciar un servicio
Podemos iniciar un servicio con:
sudo systemctl start nginx
Después comprobamos:
systemctl status nginx
Si todo funciona correctamente veremos:
Active: active (running)
11. Detener un servicio
Para detenerlo:
sudo systemctl stop nginx
Y:
systemctl status nginx
podría mostrar:
Active: inactive (dead)
12. Reiniciar un servicio
Podemos reiniciarlo:
sudo systemctl restart nginx
Esto detiene y vuelve a iniciar el servicio.
Es especialmente útil después de realizar cambios de configuración.
13. Recargar la configuración
Existe una diferencia importante entre:
restart
y:
reload
Un servicio que soporte recarga puede utilizar:
sudo systemctl reload nginx
La idea es aplicar cambios sin necesariamente reiniciar completamente el proceso.
No todos los servicios soportan reload.
Podemos consultar qué ofrece una unidad mediante:
systemctl cat nginx
o:
systemctl show nginx
14. enable vs start
Esta es una de las diferencias más importantes de systemd.
systemctl start nginx
significa:
Inicia nginx ahora.
Mientras:
systemctl enable nginx
significa:
Configura la unidad para que sea incorporada automáticamente al arranque según sus relaciones de instalación.
Por lo tanto:
start ≠ enable
Podemos tener:
START
↓
ejecutar ahora
y:
ENABLE
↓
preparar para arranque automático
También podemos hacer ambas cosas:
sudo systemctl enable --now nginx
Esto habilita el servicio y lo inicia inmediatamente.
15. Deshabilitar un servicio
Para evitar que una unidad habilitada sea incorporada automáticamente al arranque:
sudo systemctl disable nginx
Si además queremos detenerla ahora:
sudo systemctl disable --now nginx
16. Comprobar si un servicio está habilitado
systemctl is-enabled nginx
Resultado:
enabled
o:
disabled
También podemos preguntar si está activo:
systemctl is-active nginx
Resultado:
active
Esto resulta muy útil para scripts.
Por ejemplo:
if systemctl is-active --quiet nginx; then
echo "Nginx está funcionando"
else
echo "Nginx está detenido"
fi
17. Listar servicios
Podemos consultar las unidades activas:
systemctl list-units --type=service
Ejemplo:
UNIT LOAD ACTIVE SUB DESCRIPTION
dbus.service loaded active running D-Bus System Message Bus
NetworkManager.service loaded active running Network Manager
sshd.service loaded active running OpenSSH server daemon
systemd-journald.service loaded active running Journal Service
Para incluir unidades que no están activas:
systemctl list-units --type=service --all
18. Buscar servicios fallidos
Una de las herramientas más útiles para diagnosticar un sistema es:
systemctl --failed
Podríamos obtener:
UNIT LOAD ACTIVE SUB DESCRIPTION
● example.service loaded failed failed Example Service
Si aparece algo en esta lista, tenemos un punto de partida para investigar.
19. Inspeccionar una unidad
Podemos utilizar:
systemctl cat sshd
Esto muestra el contenido de la unidad y, cuando corresponde, sus fragmentos relacionados.
También podemos utilizar:
systemctl show sshd
que devuelve propiedades internas de la unidad.
Por ejemplo:
Id=sshd.service
Type=notify
Restart=on-failure
ExecStart={ path=/usr/bin/sshd ; argv[]=/usr/bin/sshd -D ; ... }
User=root
systemctl show es especialmente útil cuando queremos obtener información que pueda ser procesada por scripts.
20. ¿Dónde están los archivos .service?
Systemd tiene diferentes ubicaciones para las unidades.
Las unidades proporcionadas por paquetes suelen encontrarse en:
/usr/lib/systemd/system/
Mientras que las unidades creadas por el administrador normalmente se colocan en:
/etc/systemd/system/
Para servicios propios, una ubicación habitual es:
/etc/systemd/system/
Por ejemplo:
/etc/systemd/system/quantlab.service
La búsqueda de unidades de systemd utiliza diferentes rutas y prioridades; no debemos asumir que todos los archivos estarán en un único directorio.
21. Crear nuestro primer servicio
Vamos a crear un servicio sencillo.
Nuestro programa será:
/usr/bin/bash
y simplemente escribirá un mensaje en el journal.
Primero creamos:
sudo nano /etc/systemd/system/hello.service
Contenido:
[Unit]
Description=Mi primer servicio systemd
[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c 'echo "Hola desde systemd"'
[Install]
WantedBy=multi-user.target
Guardamos el archivo.
Ahora debemos informar a systemd de que existe una nueva unidad:
sudo systemctl daemon-reload
Este paso es importante después de crear o modificar archivos de unidades.
22. Ejecutar nuestro servicio
Ahora:
sudo systemctl start hello.service
Comprobamos:
systemctl status hello.service
Podríamos ver:
● hello.service - Mi primer servicio systemd
Loaded: loaded (/etc/systemd/system/hello.service)
Active: inactive (dead)
Puede parecer extraño.
¿Por qué dice inactive si funcionó?
Porque utilizamos:
Type=oneshot
El proceso ejecuta su tarea y termina.
No es un daemon que permanezca ejecutándose.
23. Ver el resultado con journalctl
Aquí aparece otra pieza fundamental de systemd:
journalctl
Ejecutemos:
journalctl -u hello.service
Podríamos obtener:
Sep 30 20:14:31 linux bash[1234]: Hola desde systemd
El journal almacena registros gestionados por systemd-journald, y journalctl permite consultarlos y filtrarlos.
24. ¿Qué es journald?
systemd-journald es el servicio responsable de recopilar y gestionar registros del sistema.
En lugar de tener que buscar manualmente cada log, podemos utilizar:
journalctl
para consultar el journal.
Por ejemplo:
journalctl
muestra los registros disponibles a los que nuestro usuario tenga acceso.
25. Ver los logs de un servicio específico
Esta es probablemente una de las opciones más importantes:
journalctl -u nginx
O explícitamente:
journalctl -u nginx.service
Para nuestro ejemplo:
journalctl -u hello.service
Esto evita tener que buscar entre todos los logs del sistema.
26. Ver solamente los logs recientes
Podemos utilizar:
journalctl -u nginx -n 50
Esto muestra las últimas 50 entradas relacionadas con nginx.
También:
journalctl -n 100
muestra las últimas 100 entradas generales.
27. Seguir los logs en tiempo real
Una de las opciones más útiles:
journalctl -u nginx -f
La opción:
-f
significa seguir el journal.
Es similar al comportamiento de:
tail -f
Podríamos ver:
Sep 30 20:20:01 server nginx[1234]: request received
Sep 30 20:20:02 server nginx[1234]: request completed
Sep 30 20:20:05 server nginx[1234]: request received
Y las nuevas entradas aparecerán automáticamente.
Para salir:
Ctrl + C
28. Buscar errores
Podemos filtrar por prioridad.
Por ejemplo:
journalctl -p err
o:
journalctl -p warning
También podemos combinarlo con un servicio:
journalctl -u nginx -p err
Esto resulta extremadamente útil cuando un servicio falla.
29. Ver los logs del boot actual
Podemos utilizar:
journalctl -b
Esto muestra los registros relacionados con el arranque actual.
Para consultar el boot anterior:
journalctl -b -1
Otro anterior:
journalctl -b -2
Esto es especialmente útil cuando el ordenador tuvo problemas después de reiniciarse.
30. Ver los logs del kernel
Podemos utilizar:
journalctl -k
Esto filtra los mensajes relacionados con el kernel.
También podemos utilizar:
dmesg
aunque journalctl -k resulta especialmente conveniente en sistemas que utilizan journald.
31. Logs desde una fecha determinada
Podemos filtrar por tiempo:
journalctl --since "2026-09-30 18:00:00"
También:
journalctl --since today
o:
journalctl --since yesterday
Y podemos especificar un intervalo:
journalctl \
--since "2026-09-30 18:00:00" \
--until "2026-09-30 20:00:00"
Esto resulta muy útil cuando sabemos aproximadamente cuándo ocurrió un problema.
32. ¿Dónde se almacenan los logs?
El journal puede utilizar almacenamiento persistente o volátil.
Cuando existe:
/var/log/journal/
se puede utilizar almacenamiento persistente, dependiendo de la configuración de journald.
Sin almacenamiento persistente, el journal puede almacenarse bajo:
/run/log/journal/
y esos registros pueden perderse al reiniciar.
Podemos comprobar:
ls -lah /var/log/journal/
Si queremos configurar almacenamiento persistente, una opción habitual es crear el directorio:
sudo mkdir -p /var/log/journal
y posteriormente permitir que systemd configure correctamente los permisos:
sudo systemd-tmpfiles --create --prefix /var/log/journal
33. ¿Qué ocurre durante el boot?
Ahora podemos entender una parte fundamental.
Un esquema simplificado sería:
UEFI / BIOS
│
▼
Bootloader
│
▼
Linux Kernel
│
▼
systemd (PID 1)
│
▼
default.target
│
├── servicios
├── mounts
├── sockets
├── timers
└── otros targets
Durante el arranque, systemd activa default.target, que normalmente apunta a un target como graphical.target o multi-user.target, dependiendo de la configuración.
34. ¿Qué es un target?
Un target no es necesariamente un programa.
Podemos entenderlo como una agrupación lógica de unidades y un punto de sincronización.
Algunos targets importantes son:
basic.target
multi-user.target
graphical.target
network.target
network-online.target
timers.target
shutdown.target
reboot.target
Por ejemplo:
graphical.target
│
├── display-manager.service
├── servicios
├── network
└── otros componentes
Los targets permiten construir relaciones de dependencia entre diferentes unidades.
35. Ver el target predeterminado
Podemos ejecutar:
systemctl get-default
Un sistema gráfico podría devolver:
graphical.target
Un servidor podría utilizar:
multi-user.target
También podemos consultar:
systemctl list-dependencies graphical.target
Esto permite explorar qué unidades están relacionadas con ese target.
36. Iniciar automáticamente nuestro servicio
Volvamos a:
hello.service
Tenemos:
[Install]
WantedBy=multi-user.target
Ahora podemos ejecutar:
sudo systemctl enable hello.service
Esto configura el servicio para que sea incorporado al arranque mediante la relación declarada en [Install].
Podemos comprobarlo:
systemctl is-enabled hello.service
Resultado esperado:
enabled
Para habilitarlo y arrancarlo inmediatamente:
sudo systemctl enable --now hello.service
37. Dependencias: una de las grandes ventajas de systemd
Systemd no solamente sabe:
"Ejecuta este programa."
También puede saber:
"Ejecuta este programa después de que otro recurso esté disponible."
Por ejemplo:
[Unit]
Description=Servidor web
After=network-online.target
Wants=network-online.target
Aquí aparecen dos conceptos diferentes:
After=
establece orden.
Mientras:
Wants=
establece una relación de dependencia más débil.
Una forma sencilla de visualizarlo:
network-online.target
│
│ After=
▼
myserver.service
Las dependencias son una parte central del modelo de systemd. Las unidades pueden formar relaciones complejas y systemd utiliza esas relaciones para construir y ordenar los trabajos que debe ejecutar.
38. Requires= vs Wants=
También podemos encontrar:
Requires=network-online.target
y:
Wants=network-online.target
Conceptualmente:
Wants
Wants=algo.service
expresa:
Quiero que esta otra unidad también sea activada.
Pero su fallo no implica necesariamente que nuestra unidad deba fallar.
Requires
Requires=algo.service
establece una relación más fuerte.
En configuraciones reales debemos estudiar también After=, Before=, BindsTo=, PartOf= y otras directivas antes de asumir exactamente cómo reaccionará una unidad ante el fallo de otra.
39. Crear un servicio real
Ahora vamos a crear algo más interesante.
Supongamos que tenemos:
/home/user/myapp/server.py
y queremos que se ejecute automáticamente.
Podemos crear:
sudo nano /etc/systemd/system/myapp.service
Contenido:
[Unit]
Description=Mi aplicación Python
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=user
WorkingDirectory=/home/user/myapp
ExecStart=/usr/bin/python /home/user/myapp/server.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Hay que sustituir:
user
por el usuario real del sistema.
40. Aplicar el servicio
Después de guardar:
sudo systemctl daemon-reload
Luego:
sudo systemctl start myapp.service
Comprobamos:
systemctl status myapp.service
Si funciona:
● myapp.service - Mi aplicación Python
Loaded: loaded (/etc/systemd/system/myapp.service)
Active: active (running)
Main PID: 1452 (python)
Ahora podemos habilitarlo:
sudo systemctl enable myapp.service
o directamente:
sudo systemctl enable --now myapp.service
41. ¿Qué pasa si nuestro programa falla?
Supongamos que server.py se cierra.
Tenemos:
Restart=on-failure
RestartSec=5
Por lo tanto, systemd puede detectar la terminación por fallo y volver a intentar iniciar el servicio después de cinco segundos.
Podemos observar esto con:
journalctl -u myapp.service -f
Podríamos observar:
server started
application error
Main process exited
Scheduled restart job
Starting service
server started
Esta supervisión es una de las razones por las que resulta mejor utilizar un service manager que simplemente ejecutar un proceso con:
python server.py &
42. Automatización con systemd timers
Hasta ahora hemos utilizado servicios.
Pero systemd tiene otro componente extremadamente interesante:
.timer
Un timer unit permite activar otra unidad basándose en condiciones temporales.
Un timer normalmente activa un .service correspondiente. Por ejemplo:
backup.timer
│
▼
backup.service
Por convención, si tenemos:
backup.timer
systemd puede activar:
backup.service
cuando el timer expira.
43. Crear nuestro primer timer
Vamos a crear un pequeño sistema de backup.
Primero:
sudo nano /etc/systemd/system/backup.service
Contenido:
[Unit]
Description=Backup automático
[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c 'echo "Backup ejecutado: $(date)"'
Ahora:
sudo nano /etc/systemd/system/backup.timer
Contenido:
[Unit]
Description=Ejecutar backup periódicamente
[Timer]
OnBootSec=5min
OnUnitActiveSec=1h
Unit=backup.service
[Install]
WantedBy=timers.target
44. ¿Qué significa OnBootSec?
OnBootSec=5min
significa que el timer puede activar el servicio cinco minutos después del arranque.
Por otro lado:
OnUnitActiveSec=1h
indica un intervalo de una hora respecto a la activación de la unidad correspondiente.
Los timers disponen de diferentes mecanismos de programación, incluyendo OnCalendar= para horarios basados en calendario.
45. Activar el timer
Después de crear los archivos:
sudo systemctl daemon-reload
Luego:
sudo systemctl enable --now backup.timer
Podemos comprobar:
systemctl status backup.timer
Y también:
systemctl list-timers
Podríamos ver:
NEXT LEFT LAST
Thu 2026-10-01 21:00:00 AST 42min Thu 2026-10-01 20:00:00 AST
La columna importante es:
NEXT
porque indica cuándo está programada la siguiente activación.
46. Automatización con OnCalendar
Para tareas más precisas podemos utilizar:
OnCalendar=daily
Por ejemplo:
[Timer]
OnCalendar=daily
Persistent=true
Esto puede utilizarse para ejecutar un servicio diariamente.
También podemos utilizar expresiones más específicas, por ejemplo:
OnCalendar=*-*-* 03:00:00
para programarlo alrededor de las 03:00.
La sintaxis exacta de OnCalendar= permite construir programaciones mucho más complejas.
Podemos consultar cómo interpreta systemd una expresión con:
systemd-analyze calendar "daily"
Ejemplo:
Normalized form: daily
Next elapse: Thu 2026-10-01 00:00:00 AST
Esta herramienta es excelente para comprobar una expresión antes de ponerla en producción.
47. Persistent=true
Existe una opción particularmente útil:
Persistent=true
Supongamos que tenemos:
[Timer]
OnCalendar=daily
Persistent=true
y el ordenador estaba apagado cuando correspondía ejecutar la tarea.
Con Persistent=true, systemd puede ejecutar el servicio al activarse nuevamente el timer si la ejecución programada se perdió bajo las condiciones descritas por systemd.
Esto hace que los timers sean muy interesantes para tareas como:
backups
limpieza
reportes
sincronización
mantenimiento
48. Ver todos los timers
Podemos ejecutar:
systemctl list-timers
o:
systemctl list-timers --all
Un resultado puede parecerse a:
NEXT LEFT LAST
Thu 2026-10-01 21:00:00 AST 30min Thu 20:00:00
Fri 2026-10-02 00:00:00 AST 3h Thu 00:00:00
UNIT
backup.timer
log-cleanup.timer
49. Cron vs systemd timers
Linux tradicionalmente utiliza cron para automatizaciones.
Por ejemplo:
0 3 * * * /home/user/backup.sh
Systemd ofrece otra alternativa:
backup.service
+
backup.timer
Una ventaja de utilizar timers es que la tarea queda integrada en el ecosistema de systemd.
Podemos consultar:
systemctl status backup.service
y:
journalctl -u backup.service
Por lo tanto, la automatización tiene:
programación
↓
timer
↓
service
↓
ejecución
↓
journal
Esto proporciona una forma coherente de programar y posteriormente investigar las ejecuciones.
50. Diagnosticar un servicio que falla
Imaginemos:
systemctl status myapp
y obtenemos:
● myapp.service
Loaded: loaded
Active: failed
No debemos comenzar a modificar archivos aleatoriamente.
Podemos seguir una metodología.
Paso 1: estado
systemctl status myapp
Paso 2: logs
journalctl -u myapp -n 100
Paso 3: logs recientes
journalctl -u myapp --since "10 minutes ago"
Paso 4: configuración
systemctl cat myapp
Paso 5: propiedades
systemctl show myapp
Paso 6: comprobar el ejecutable
Si tenemos:
ExecStart=/usr/bin/python /home/user/myapp/server.py
comprobamos:
ls -l /usr/bin/python
y:
ls -l /home/user/myapp/server.py
51. Un error muy común: ExecStart
Supongamos que tenemos:
ExecStart=python server.py
Dependiendo del servicio y del entorno, esto puede provocar problemas.
Es preferible utilizar rutas explícitas:
ExecStart=/usr/bin/python /home/user/myapp/server.py
Esto evita depender del PATH interactivo de nuestro usuario.
Systemd no debe asumirse como equivalente a ejecutar un comando desde nuestra shell interactiva.
52. Otro error común: variables de entorno
Desde nuestra terminal puede funcionar:
python app.py
pero systemd puede fallar.
¿Por qué?
Porque nuestro shell interactivo puede tener variables como:
PATH
HOME
API_KEY
VIRTUAL_ENV
que no existen de la misma forma en el entorno del servicio.
Podemos declarar variables mediante:
Environment="MODE=production"
Por ejemplo:
[Service]
Environment="MODE=production"
Environment="PORT=8080"
ExecStart=/usr/bin/python /home/user/app/server.py
Para configuraciones más grandes puede utilizarse:
EnvironmentFile=/etc/myapp/environment
53. Seguridad: no ejecutar todo como root
Un error frecuente al crear servicios es:
User=root
para absolutamente todo.
Si la aplicación no necesita privilegios administrativos, es preferible ejecutar:
User=usuario
Por ejemplo:
[Service]
User=geremy
ExecStart=/usr/bin/python /home/geremy/app/server.py
De esta manera, si la aplicación tiene una vulnerabilidad, el proceso no necesariamente tendrá todos los privilegios de root.
Systemd además proporciona diferentes mecanismos de aislamiento y restricciones de recursos que pueden utilizarse para endurecer servicios.
54. Analizar el boot
Systemd también proporciona herramientas para estudiar el arranque.
Podemos utilizar:
systemd-analyze
Ejemplo:
Startup finished in 3.201s (firmware) + 1.102s (loader)
+ 2.421s (kernel) + 4.873s (userspace)
= 11.597s
graphical.target reached after 4.812s in userspace
Esto nos permite saber aproximadamente cuánto tardó cada etapa.
55. ¿Qué servicio está tardando demasiado?
Podemos utilizar:
systemd-analyze blame
Ejemplo:
2.812s NetworkManager-wait-online.service
1.421s systemd-udev-settle.service
0.842s docker.service
0.412s systemd-logind.service
Esto nos muestra unidades que consumieron tiempo durante el arranque.
Pero hay que tener cuidado:
systemd-analyze blameno significa automáticamente que el servicio de la primera línea sea "la causa" de un boot lento.
Las relaciones de dependencia y el paralelismo de systemd hacen que interpretar el tiempo de arranque requiera más contexto.
56. Visualizar la cadena de dependencias
Otra herramienta interesante:
systemd-analyze critical-chain
Podemos obtener algo parecido a:
graphical.target
└─multi-user.target
└─docker.service
└─network-online.target
└─NetworkManager.service
Esto ayuda a entender qué unidades forman parte de la cadena crítica del arranque.
57. El modelo mental completo
Después de conocer todas estas herramientas podemos visualizar systemd así:
SYSTEMD
│
▼
┌──────────────┐
│ Units │
└──────────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
.service .timer .target
│ │ │
│ │ │
▼ ▼ ▼
proceso schedule agrupación
│ │ │
└────────────┬────┘ │
▼ │
ejecución │
│ │
▼ │
journald │
│ │
▼ │
journalctl │
Y systemctl es nuestra interfaz principal para administrar esas unidades:
systemctl
│
├── start
├── stop
├── restart
├── reload
├── enable
├── disable
├── status
├── cat
├── show
└── list-units
58. Chuleta de comandos
Servicios
systemctl status servicio
sudo systemctl start servicio
sudo systemctl stop servicio
sudo systemctl restart servicio
sudo systemctl reload servicio
sudo systemctl enable servicio
sudo systemctl disable servicio
sudo systemctl enable --now servicio
sudo systemctl disable --now servicio
Estado
systemctl is-active servicio
systemctl is-enabled servicio
systemctl --failed
systemctl list-units --type=service
systemctl list-units --type=service --all
Configuración
systemctl cat servicio
systemctl show servicio
sudo systemctl daemon-reload
Logs
journalctl
journalctl -u servicio
journalctl -u servicio -f
journalctl -u servicio -n 50
journalctl -u servicio -p err
journalctl -b
journalctl -b -1
journalctl -k
journalctl --since today
Timers
systemctl list-timers
systemctl list-timers --all
systemctl status backup.timer
systemd-analyze calendar "daily"
Boot
systemd-analyze
systemd-analyze blame
systemd-analyze critical-chain
systemctl get-default
systemctl list-dependencies graphical.target
59. Flujo recomendado para trabajar con systemd
Cuando creemos un servicio nuevo, podemos seguir siempre este procedimiento:
1. Crear .service
↓
2. Guardar en /etc/systemd/system/
↓
3. daemon-reload
↓
4. start
↓
5. status
↓
6. journalctl
↓
7. corregir errores
↓
8. enable
Por ejemplo:
sudo nano /etc/systemd/system/myapp.service
Después:
sudo systemctl daemon-reload
Luego:
sudo systemctl start myapp.service
Comprobar:
systemctl status myapp.service
Logs:
journalctl -u myapp.service -n 100
Y finalmente:
sudo systemctl enable myapp.service
60. Conclusión
Systemd puede parecer complicado al principio porque no es simplemente un comando para iniciar servicios. Es un sistema completo de administración de unidades, dependencias, procesos, arranque, logs y automatización.
Sus componentes principales pueden resumirse así:
systemd
│
├── systemctl
│ └── administrar unidades
│
├── .service
│ └── ejecutar y supervisar procesos
│
├── .timer
│ └── automatizar ejecuciones
│
├── .target
│ └── agrupar unidades
│
├── journald
│ └── recopilar logs
│
├── journalctl
│ └── consultar logs
│
└── systemd-analyze
└── analizar el sistema y el boot
Una vez entendido este modelo, muchas tareas que parecen independientes comienzan a tener sentido.
Un servidor web puede ser:
nginx.service
Una aplicación Python:
myapp.service
Un backup automático:
backup.timer
↓
backup.service
Los logs de todo ello:
journalctl
Y la administración:
systemctl
La idea fundamental es que systemd convierte procesos y tareas del sistema en unidades administrables, establece relaciones entre ellas y proporciona una infraestructura común para iniciarlas, detenerlas, supervisarlas, automatizarlas y diagnosticar sus problemas.
Por eso aprender systemd no consiste solamente en memorizar:
systemctl start
systemctl stop
systemctl restart
sino en aprender a pensar en términos de:
UNITS
↓
DEPENDENCIES
↓
JOBS
↓
SERVICES
↓
LOGS
↓
AUTOMATION
Ese modelo mental permite pasar de simplemente "usar Linux" a administrar y automatizar un sistema Linux de forma profesional.