¿Se pregunta cómo gestionar los servicios en segundo plano o en el arranque?
El mecanismo para gestionar e iniciar procesos en el arranque ha cambiado. Hasta RHEL/CentOS 6.x, habría creado un script en /etc/init.d/ y habilitado con la ayuda de chkconfig
pero las cosas son diferentes en RHEL 7.
Ha sido reemplazado por systemd
y dado que es más o menos el gestor de procesos por defecto en las principales versiones de Linux, los administradores de sistemas versados en otros sabores se sentirán como en casa. En este artículo, exploraremos qué es systemd
, cuáles fueron las razones del cambio y cómo utilizar systemd
para configurar, ejecutar y gestionar procesos en segundo plano con él.
¿Qué es systemd?
Dado que todos los procesos en Linux son transparentemente visibles, veamos dónde se esconde systemd
. En mi sistema, obtengo lo siguiente
~$ ps -ef | grep systemd root 1 0 0 Nov11 ? 00:01:02 /lib/systemd/systemd --system --deserialize 22 mensaje 768 1 0 Nov11 ? 00:05:46 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only root 805 1 0 Nov11 ? 00:10:22 /lib/systemd/systemd-logind ankush 1132 1 0 Nov11 ? 00:00:00 /lib/systemd/systemd --user ankush 1176 1132 0 Nov11 ? 00:04:50 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only ankush 9772 20029 0 21:11 pts/6 00:00:00 grep --color=auto systemd systemd 17298 1 0 Nov19 ? 00:00:12 /lib/systemd/systemd-resuelto systemd 17303 1 0 Nov19 ? 00:00:00 /lib/systemd/systemd-timesyncd root 17307 1 0 Nov19 ? 00:00:02 /lib/systemd/systemd-journald root 18182 1 0 Nov19 ? 00:00:00 /lib/systemd/systemd-udevd
Apuesto a que se ha dado cuenta al instante. El primer proceso del listado se inició como usuario root
y tiene el pid 1.
Efectivamente, este fue el primer proceso que el sistema lanzó al arrancar. Salude a systemd
. 🙂
Así que, sencillamente, systemd
es el proceso «madre» que lanza, gestiona y termina otros procesos en el sistema, además de proporcionar información sobre su registro, estados del sistema de archivos, etc.
Una nota sobre el nombre, sin embargo. El nombre es efectivamente systemd
y no System D o cualquier otro. La «d» significa demonio, un proceso estándar de Linux que trabaja (¿acecha?) en segundo plano y no está unido a ninguna sesión de terminal.
¿Por qué RHEL cambió a systemd?
Como ya hemos comentado, systemd es un gestor de sistemas y procesos y, en RHEL 7, sustituye al conocido programa Upstart. ¿Por qué RHEL tomó esta decisión? Bueno, hay muy buenas razones para ello, así que echemos un vistazo rápido.
Inicialización paralela de servicios
A diferencia del programa init
de SysV, systemd
es capaz de lanzar servicios en paralelo. El programa init
, por el contrario, los lanza uno a uno. En una era en la que incluso los dispositivos móviles tienen CPUs multinúcleo, la falta de inicialización paralela es una gran desventaja.
Gestión dinámica (en caliente) de servicios
Si ha notado que las unidades USB necesitan ser montadas explícitamente en los sistemas Fedora anteriores mientras que se abrían automáticamente en Ubuntu y distribuciones similares, la razón es systemd
. Es capaz de detectar cambios en vivo en el hardware y terminar/lanzar servicios según sea necesario. Algunos pueden argumentar que es innecesario, pero para muchos, cualquier cosa que reduzca la carga cognitiva es bienvenida.
Lanzamiento diferido de servicios
systemd
hace que los tiempos de arranque sean más cortos, ya que es capaz de aplazar el lanzamiento de servicios hasta el momento en que realmente se necesitan. Un ejemplo sencillo son los servicios relacionados con el sistema de archivos en red. Si no hay disco de red disponible, no tiene sentido tener un servicio en marcha.
Comunicación de procesos más rápida
Las capacidades paralelas de systemd
se trasladan a la comunicación entre procesos. systemd
es capaz de ofrecer acceso paralelo a los sockets y al bus del sistema, reduciendo significativamente los tiempos de espera de los procesos para los recursos de comunicación.
Reinicio automático
Si un servicio se bloquea, systemd
puede detectarlo e intentar reiniciarlo. La mayoría de las veces, un simple reinicio es todo lo que se necesita para que una aplicación empiece a funcionar de nuevo, a menos que haya problemas más fundamentales.
En cualquier caso, systemd
facilita aquí la vida de un administrador de sistemas.
systemd en RHEL7 – ¿Qué cambia para los administradores de sistemas?
Si tiene la persistente sensación de que systemd
no va a ser todo campanas y silbatos, está en lo cierto. Hay algunas incompatibilidades significativas que pueden pillar por sorpresa a los sysadmin de RHEL. Echemos un vistazo rápido.
Soporte limitado de runlevel
systemd
tiene un reconocimiento y soporte de los niveles de ejecución bastante limitado. No todos los niveles de ejecución están soportados, y para algunos objetivos puede que incluso no haya ninguno. En tales casos, systemd
devuelve «N» como respuesta a los comandos runlevel
, lo que significa que no tiene ningún runlevel correspondiente a este objetivo. En definitiva, Red Hat nos aconseja no utilizar (!) los comandos runlevel
.
Sin comandos personalizados
Esto va a doler. Una gran ventaja con SysV era la posibilidad de definir comandos personalizados para proporcionar una mejor funcionalidad para la gestión de procesos. Con systemd
, no hay tal opción y usted está atascado con start
, stop
, status
, restart
, etc.
Sólo para la familia y no interactivo
systemd
(por supuesto) mantiene un registro de los procesos que ha lanzado y almacena sus PID. El reto, sin embargo, es que systemd
no puede ocuparse de procesos no lanzados por él. Además, no es posible que un usuario interactúe con un proceso iniciado por systemd
. Toda la salida va a /dev/null
, poniendo fin de forma efectiva a cualquier esperanza que pudiera haber tenido de capturar la salida.
Sin contexto
A diferencia de los servicios init
, los lanzados por systemd
no heredan ningún entorno de ningún usuario del sistema. En otras palabras, la información como PATH
y otras variables del sistema no están disponibles, y cada nuevo proceso se lanza en un contexto vacío.
Si esta lista de limitaciones le hace llorar, de nuevo, no está solo. systemd
ha sido una fuerza polarizadora en el mundo Linux, y si busca en Google «systemd apesta» encontrará mucho material de lectura. 😉
¿Cómo iniciar el servicio automáticamente cuando está caído?
He aquí un caso de uso bastante común en los despliegues. Necesitamos daemonizar un programa en un lenguaje que no tiene procesos de larga ejecución: ¡PHP! Supongamos que escribo un script PHP para manejar las conexiones websocket entrantes (¡después de todo construimos una aplicación de chat!) y el script se coloca en /home/ankush/chat_server/index.php
.
Dado que las conexiones websocket pueden llegar al servidor en cualquier momento, este proceso necesita estar activo en todo momento y monitorizar las conexiones entrantes. No podemos tener el ciclo de vida tradicional de PHP aquí porque los WebSockets son conexiones con estado, y si el script muere, la conexión es una lista. De todos modos, suficiente sobre websockets; veamos como haremos para daemonizar este script a través de systemd
.
Todos los servicios systemd
residen en /etc/systemd/system, así que vamos a crear un archivo allí para describir nuestro script de servidor websocket. Asumiendo que ha iniciado sesión como usuario root.
# vi /etc/systemd/system/chat_server.service
y se necesita lo siguiente.
[Unidad] Descripción=Servicio de servidor de chat Después=network.target [Servicio] Tipo=simple Usuario=ankush ExecStart=php /home/ankush/servidor_chat/index.php Reiniciar=on-abortar [Instalar] WantedBy=multi-user.target
Guarde el archivo y el siguiente paso es recargar el demonio systemd
# systemctl daemon-reload
y arrancar el servicio que acabamos de crear
# systemctl start chat_server
Si no ve ningún error, ¡ya está!
Echemos también un vistazo rápido a lo que significan las distintas directivas del archivo:
- La parte
[Unidad
] define una nueva unidad de servicio parasystemd
. En la jerga desystemd
, todos los servicios se conocen como unidades de servicio. - La directiva
After
(predeciblemente) le dice asystemd
que lance este servicio sólo después de que se lancen los servicios de red (de lo contrario, ¡¿quién se encargará del manejo de bajo nivel de las conexiones de socket?!). - El
Type=simple
le dice asystemd
que este servicio no debe bifurcarse a sí mismo. En otras palabras, sólo se ejecutará una instancia en un momento dado. User=ankush
significa que este servicio se ejecutará como el usuario «ankush». Podríamos cambiarlo por «root», pero es muy poco recomendable desde el punto de vista de la seguridad.ExecStart
, como puede deducir, es el comando real a ejecutar.Restart=on-abort
significa que el servicio debe reiniciarse cuando aborte. En PHP, los procesos de larga ejecución pierden memoria y eventualmente explotan, por lo que esto es necesario.- La directiva
WantedBy=
indica asystemd
de qué objetivo (piense en grupos) forma parte este servicio. Esto hace que se creen enlaces simbólicos dentro de ese objetivo para apuntar al servicio.
Generalmente, esto es suficiente para ejecutar procesos en segundo plano utilizando systemd
en RHEL 7.
Más opciones para la lógica de reinicio
En el ejemplo anterior, he configurado Restart=on-abort
pero esa no es la única opción. Hay más y elija en función de sus necesidades.
- on-failure – se reiniciará cuando no se encuentre limpio el código de salida o la señal
- always – se reiniciará cuando se encuentre abajo, señal limpia o unclean
- on-abnormal – señal no limpia, watchdog o timeout
- on-success – sólo cuando se detuvo por una señal limpia o código de salida
Configuración del servicio para que se inicie al arrancar
Una vez que esté satisfecho con el script y se asegure de que funciona, lo siguiente es configurarlo para que se active al arrancar y se inicie.
Vaya a /etc/systemd/system y ejecute el siguiente comando enable (no olvide cambiar el nombre del archivo .service por el que tenga)
# systemctl enable chat_server.service
Verá una confirmación de que se ha creado un enlace simbólico.
Se ha creado un enlace simbólico de /etc/systemd/system/multi-user.target.wants/chat_server.service a /etc/systemd/system/chat_server.service.
Reinicie su servidor y debería ver que el servicio se inicia al arrancar.
Ha sido fácil ¿Verdad que sí?
¡Ayuda! Estoy masivamente invertido en Upstart. 🙁
Le entiendo confíe en mí, su caso es la norma más que la excepción. RHEL ha estado utilizando Upstart durante tanto tiempo que el cambio casi se siente como una traición. Pero bueno, los sistemas siguen cambiando y no deberíamos discutir por nimiedades. Red Hat reconoce que mucha gente está atascada con versiones anteriores y ha creado una guía de migración que sin duda debería consultar.
Una gracia salvadora en todo esto es que systemd
es compatible con los scripts de init
de SysV, así que en su mayor parte, simplemente tendrá que mover sus archivos y conseguir que se ejecuten los mismos servicios.
¿Está interesado en aprender más sobre la administración y resolución de problemas de Linux? Eche un vistazo a este curso en línea.