Systemd es un software creado por Lennart Poettering y Kay Sievers en 2010 que tiene mucha polémica y controversia detrás. Cuenta con muchos detractores debido a su estructura compleja que a todas luces parece ir en contra de la filosofía GNU/Linux y Unix; pero tanto si lo odias como si lo amas, la realidad es que a día de hoy, la mayoría de distribuciones lo han implantado.
Por este motivo y para que podáis exprimirlo un poco más os presento una pequeña guía para que le deis una oportunidad y comencéis a usarlo en el día a día si no lo hacéis ya.
¿Qué es Systemd?
Systemd es un software que se encarga de iniciar el sistema así como de gestionar todo el sistema. Es el sucesor de otros software de inicio como SysVinit o Upstart entre otras muchas cosas.
Las unidades
En comparación con SysVinit que funciona con scripts, Systemd trabaja con unidades (units). Hay unidades de muchos tipos: device, mount, service, socket, target, timer, etc.
Cada unidad no es más que un fichero de texto en el que la extensión del fichero define el tipo de unidad (.target, .service, etc…).
Dependiendo de la distribución y del modo de ejecución (system o user) podemos encontrar estos archivos en:
- Rutas de ejecución en System Mode:
/usr/lib/systemd/system/: Unidades instaladas por el gestor de paquetes
/usr/local/lib/systemd/system/: Unidades instaladas por el administrador
/etc/systemd/system/: Unidades generadas de por administrador (la mayoría son enlaces a /usr/lib/systemd/system/)
/run/systemd/system/: Unidades de Runtime - Rutas de ejecución en User Mode:
/usr/lib/systemd/user/: Unidades instaladas por el gestor de paquetes
/usr/local/lib/systemd/user/: Unidades instaladas por el administrador
/etc/systemd/user/: Unidades generadas de por administrador
/run/systemd/user/: Unidades de Runtime
Para conocer todas las rutas podemos ver las páginas man de systemd.unit o aquí.
De esta forma si echamos un vistazo a /lib/systemd/system/ veremos las unidades hay dentro y lo mismo pasa con /etc/systemd/system/.

Si miramos el contenido de uno de estos archivos, por ejemplo ssh.service:

Veamos los bloques que definen el archivo:
- [Unit]: Define la unidad en sí (nombre, descripción,…). Define también las condiciones, dependencias y restricciones necesarias para ejecutar la unidad: unidades que es necesario cargar antes o después y el orden de ejecución de todas las unidades necesarias.
- [Service]: Aquí se definen las acciones que realiza la unidad cuando se inicia, para, recarga o muere.
- [Install]: Define en qué escenarios se cargará automáticamente esta unidad. En el caso de la imagen, cuando se cargue el multi-user.target se cargará también ssh.service. También define Alias para el servicio.
Los tipos de unidades que veremos con más frecuencia son los targets, services y timers:
- Target: Son los escenarios en los que se ejecuta el sistema. Son los antiguos runlevels. No me voy a extender en esto, pero dejo abajo una imagen con la correspondencia entre runlevels y targets.
- Service: Son los servicios propiamente dichos. Pueden residir en memoria o ejecutarse una sola vez cuando sea necesario.
- Timer: Son tareas programadas para la ejecución de otras unidades. Similar a cron.
Hablar con Systemd: systemctl
Una vez que sabemos a grandes rasgos que son las unidades y sus tipos, debemos interactuar con Systemd para pedirle información o que haga cosas por nosotros. El principal comando para esto será systemctl.
Obtener información de las unidades
Listar unidades activas
systemctl list-units: Lista todas las unidades activas. Al ejecutarlo veremos algo similar a esto (sólo pongo unos pocos):
root:~# systemctl list-units accounts-daemon.service loaded active running Accounts Service alsa-restore.service loaded active exited Save/Restore Sound Car apparmor.service loaded active exited Load AppArmor profiles avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stac binfmt-support.service loaded active exited Enable support for add bluetooth.service loaded active running Bluetooth service colord.service loaded active running Manage, Install and Ge console-setup.service loaded active exited Set console font and k cpufrequtils.service loaded active exited LSB: set CPUFreq kerne cron.service loaded active running Regular background pro cups-browsed.service loaded active running Make remote CUPS print cups.service loaded active running CUPS Scheduler dbus.service loaded active running D-Bus System Message B exim4.service loaded active running LSB: exim Mail Transpo gdm.service loaded active running GNOME Display Manager
Si usamos -t podemos filtrar un tipo de unidad concreto, también podemos pasarle un patrón para filtrar por palabras. Si añadimos –all vemos también los inactivos.
Listar todas las unidades
systemctl list-unit-files: Muestra no sólo los activos, sino todos los archivos de unidades que hay en el sistema, cargados o no. Es interesante destacar la opción –state= con la que podremos ver las unidades con cierto estado, como enabled, disabled, masked, etc.
root:~# systemctl list-unit-files --state=enabled UNIT FILE STATE accounts-daemon.service enabled anacron.service enabled apparmor.service enabled autovt@.service enabled avahi-daemon.service enabled binfmt-support.service enabled bluetooth.service enabled console-setup.service enabled cron.service enabled cups-browsed.service enabled cups.service enabled
Listar dependencias
systemctl list-dependencies: Muestra el árbol de dependencias para una unidad. Es decir todas aquellas que estén relacionadas mediante las condiciones requires, wants, wantedby, after, berfore, etc.

Normalmente list-dependencies sigue recursivamente las dependencias de tipo requies, wants, etc. Podemos hacer que sigua las de tipo inverso, es decir, requiredby, wantedbym etc con –reverse. También podemos decirle que muestre las dependencias después de las cuales nuestro servicio debe ejecutarse con –after o las dependencias antes de las cuales nuestro servicio debe ejecutarse con –before.
Mostrar contenido
systemctl cat: Muestra el contenido del archivo de una unidad. Es lo mismo que usar cat pero no tenemos que indicar la ruta del archivo, sólo su nombre. En el resultado veremos un comentario con la ruta del archivo.
El resultado es el mismo que vimos al examinar el archivo ssh.service más arriba.
systemctl cat ssh.service # /lib/systemd/system/ssh.service [Unit] Description=OpenBSD Secure Shell server After=network.target auditd.service ConditionPathExists=!/etc/ssh/sshd_not_to_be_run [Service] EnvironmentFile=-/etc/default/ssh ExecStartPre=/usr/sbin/sshd -t ExecStart=/usr/sbin/sshd -D $SSHD_OPTS ExecReload=/usr/sbin/sshd -t ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure [Install] WantedBy=multi-user.target Alias=sshd.service
Cambiando de target
Como hemos visto más arriba los targets sustituyen a los runlevels. Podemos ver la correspondencia entre ambos en la siguiente imagen:

Saber el target por defecto
systemctl get-default: Nos dice que target se carga por defecto al arrancar el sistema.
root:~# systemctl get-default graphical.target
Cambiar el target por defecto
systemctl set-default: Cambia el target por defecto.
Cambiar de target (aislar unidad)
systemctl isolate [target]: Inicia la unidad especificada y todas sus pendencencias y además para todas las unidades que no sean dependencia de esta. Esto nos permite cambiar al target que especifiquemos.
root:~# systemctl isolate rescue.target
Se puede abreviar quitando isolate y poniendo sólo el nombre del target:
root:~# systemctl rescue
Saber el target actual
Para saber en que target nos encontramos sigue siendo más rápido usar el comando runlevel, esto nos dará el número de runlevel con el que podremos saber el target mirando la imagen de correspondencia entre ambos. Pero si quisiéramos saberlo con systemd, podemos filtrar los targets activos con list-units.
Vamos a decirle a systemd que nos liste todas las unidades activas (list-units) de tipo (-t) target y las filtramos con egrep para que sólo muestre las que empiecen por res (rescue), mu (multi-user) o gra (graphical):
systemctl list-units -t target | egrep ‘res|mu|gra’ (list-units se puede omitir).
root:~# systemctl -t target | egrep 'res|mu|gra' graphical.target loaded active active Graphical Interface multi-user.target loaded active active Multi-User System
Podemos ver que hay dos activos. Debemos tener en cuenta la jerarquía, es decir, multi-user.target es necesario como base para correr graphical.target. Por tanto graphical será target actual.
Gestión de servicios
Arrancar y parar servicios
systemctl:
- start: Arranca un servicio
- stop: Para un servicio
- restart: Reinicia un servicio
Ver el estado
systemctl status: Muestra el estado de un servicio. Además, indica información interesante como si está activo, habilitado, si ha dado algún error, etc.
root:~# systemctl status ssh.service ● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/lib/systemd/system/ssh.service; disabled; vendor preset: enabled) Active: inactive (dead) Docs: man:sshd(8) man:sshd_config(5)
Recargar un servicio
Algunos servicio permiten modificar su configuración sin tener que parar el servicio. La configuración no se aplica justo después de modificarla sino que habría que parar y arrancar de nuevo el servicio. Con systemctl reload se aplica la nueva configuración sin tener que parar el servicio.
Habilitar o deshabilitar
systemctl enable/disable: Habilita o deshabilita un servicio para que se ejecute al inicio del sistema. Sin embargo, un servicio con estado «disabled»se puede ejecutar manualmente con la orden start.
Enmascarar o desenmascarar
systemctl mask/unmask: Enmascara o desenmascara un servicio. Un servicio enmascarado no puede ser ejecutado, ni automáticamente ni manualmente, por ningún usuario.
Tareas programadas y trabajos
Los timers son un tipo de unidades que están activas y programadas para ejecutar un servicio en un momento determinado.
Listar timers
Podemos listar los timers activos y ver desde cuando están activos, la última vez que se ejecutaron y cuando se volverán a ejecutar.
systemctl list-timers: Lista todos los timers activos. Se le puede añadir un patrón para listar sólo los que coincidan con el patrón. Si añadimos –all vemos también los inactivos.
root:~# systemctl list-timers NEXT LEFT LAST PASSED UNIT 2020-01-25 27min left 2020-01-25 35min ago anacron.time 2020-01-25 12h 40min left 2020-01-24 1 day 2h ago apt-daily.ti 2020-01-26 10h left 2020-01-25 2h 29min ago exim4-base.t 2020-01-27 1 day 10h left 2020-01-20 5 days ago fstrim.timer 4 timers listed. Pass --all to see loaded but inactive timers, too.
Cada unidad timer tiene asociada otra con el mismo nombre pero service. De esta forma el timer lanza el servicio que tenga su mismo nombre.
Vamos a ver como ejemplo fstrim.timer. Si vemos su contenido:
root:~# systemctl cat fstrim.timer # /lib/systemd/system/fstrim.timer [Unit] Description=Discard unused blocks once a week Documentation=man:fstrim [Timer] OnCalendar=weekly AccuracySec=1h Persistent=true [Install] WantedBy=timers.target
Vemos que se ejecuta semanalmente y además es persistente. Esto significa que si el equipo está apagado en el momento en el que debería ejecutarse el timer, este se ejecutará la próxima vez que se encienda el equipo.
Veamos ahora su servicio asociado, es decir fstrim.service:
root:~# systemctl cat fstrim.service # /lib/systemd/system/fstrim.service [Unit] Description=Discard unused blocks on filesystems from /etc/fstab Documentation=man:fstrim(8) [Service] Type=oneshot ExecStart=/sbin/fstrim --fstab --verbose --quiet ProtectSystem=strict ProtectHome=yes PrivateDevices=no PrivateNetwork=yes PrivateUsers=no ProtectKernelTunables=yes ProtectKernelModules=yes ProtectControlGroups=yes MemoryDenyWriteExecute=yes SystemCallFilter=@default @file-system @basic-io @system-service
ExecStart indica lo que hace el servicio al ser lanzado.
Si quisiéramos crear nosotros un timer, tendríamos que crear ambos archivos (timer y service), copiarlos en alguna de las rutas donde systemd busca las unidades y activar el timer con systemctl enable. Para conocer estas rutas podemos ver las páginas man de systemd.unit.
Listar trabajos en curso
systemctl list-jobs: Lista todos los trabajos en progreso.
Los registros: journalctl
Otra de las tareas que hace Systemd es anotar todo lo que pasa en el sistema. Vamos, los logs de siempre. Para obtenerlos usaremos journalctl.
- -S y -U: Con esta opciones pediremos los registros desde (since) una fecha determinada o hasta (until) una fecha determinada.
El formato de la fecha será: YYYY-MM-DD [HH:MM:SS], yesterday, today, tomorrow, ‘N day ago’, -/+ NhMmin (-3h10min, -2h, -15min, …).
- -k y -b: -k muestra sólo los mensajes del Kernel y -b muestra sólo los mensajes del arranque. Por tanto -kb sería el equivalente a dmseg.
- -p: Filtra por tipos (info, err, warn, etc).
- -u: Filtra por tipo de unidad.
- PARAM=VALUE: Podemos indicar algunos parámetros como _PID (PID del proceso), _UID (UID de usuario), _COMM (comando), etc. Para saber más podemos consultar los manuales de systemd.journal-fields.
En fin, creo con esto ya tenéis una buena base para empezar y trabajar con Systemd. Siempre podéis profundizar más, leyendo las páginas man de cada comando. También hay una documentación muy interesante en https://systemd.io/.
Espero que os haya gustado el artículo y nos vemos en el próximo.
Si os gustó este artículo podéis echar un vistazo a Reinstalando GRUB de forma indolora, Hablemos de Rsync o Jugando con la Raspberry Pi: Configuración inicial
Saludos linuxeros.