¿Te preguntas cómo gestionar los servicios en segundo plano o en el arranque?
Se ha cambiado el mecanismo de gestión e inicio de procesos en el arranque. Hasta RHEL/CentOS 6.x, se creaba un script en /etc/init.d/ y se habilitaba con la ayuda de chkconfig
pero las cosas son diferentes en RHEL 7.
Se sustituye por systemd
y puesto que es más o menos el gestor de procesos por defecto en las principales versiones de Linux, Administrador del sistema versados en otros sabores se sentirán como en casa. En este artículo, exploraremos qué systemd
es, cuáles fueron las razones para el 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 systemd
está al acecho. En mi sistema, obtengo lo siguiente:
~$ ps -ef | grep systemd root 1 0 0 Nov11 ? 00:01:02 /lib/systemd/systemd --system --deserialize 22 message+ 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-resolved 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 te diste cuenta al instante. el primer proceso de la lista se lanzó como el usuario root
y tiene el pid 1.
Efectivamente, este fue el primer proceso que el sistema lanzó al arrancar. Saluda a systemd
. 🙂
Así que, sencillamente, systemd
es el proceso "madre" que lanza, gestiona y finaliza otros procesos del sistema, además de proporcionar información sobre su registro, estado del sistema de archivos, etc.
Una nota sobre el nombre. En efecto, el nombre es systemd
y no System D ni ninguna otra cosa. La "d" significa demonio, un proceso estándar de Linux que trabaja (¿acecha?) en segundo plano y no está conectado a ninguna sesión de terminal.
¿Por qué RHEL ha cambiado 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é ha tomado RHEL esta decisión? Bueno, hay muy buenas razones para ello, así que echemos un vistazo rápido.
Inicialización paralela de servicios
No le gusta el SysV init
programa, systemd
es capaz de lanzar servicios en paralelo. El sitio init
por el contrario, los lanza uno a uno. En una época en la que incluso los dispositivos móviles tienen CPU multinúcleo, la falta de inicialización paralela es una gran desventaja.
Gestión dinámica de servicios (en caliente)
Si ha notado que las unidades USB deben montarse explícitamente en los sistemas Fedora anteriores, mientras que en Ubuntu y distribuciones similares se abren automáticamente, la razón es la siguiente systemd
. Es capaz de detectar en tiempo real cambios en el hardware y terminar o 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 del servicio
systemd
hace que los tiempos de arranque sean más cortos, ya que es capaz de aplazar el lanzamiento del servicio hasta el momento en que realmente se necesita. Un ejemplo sencillo son los servicios relacionados con el sistema de archivos de 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
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 obtener recursos de comunicación.
Reinicio automático
Si un servicio se bloquea, systemd
puede detectarlo e intentar reiniciarla. La mayoría de las veces, un simple reinicio es todo lo que se necesita para que una aplicación comience a funcionar de nuevo, a menos que haya problemas más fundamentales.
En fin, systemd
facilita la vida de un administrador de sistemas.
systemd en RHEL7 - ¿Qué cambia para los administradores de sistemas?
Si tiene la molesta sensación de que systemd
no va a ser todo campanas y silbatos, tienes razón. Hay algunas incompatibilidades importantes que pueden pillar por sorpresa a los administradores de sistemas de RHEL. Echemos un vistazo rápido.
Soporte limitado del nivel de ejecución
systemd
tiene un reconocimiento y una compatibilidad bastante mediocres con los niveles de ejecución. No todos los niveles de ejecución son compatibles, y para algunos objetivos puede que incluso no haya ninguno. En tales casos, systemd
devuelve "N" como respuesta a la pregunta runlevel
lo que significa que no tiene un nivel de ejecución correspondiente a este objetivo. En definitiva, Red Hat nos aconseja no utilizar (!) el comando runlevel
comandos.
Sin comandos personalizados
Esto va a doler. Una gran ventaja de SysV era la posibilidad de definir comandos personalizados para mejorar la funcionalidad de la gestión de procesos. Con systemd
no existe tal opción y se queda con start
, stop
, status
, restart
etc.
Familiar 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 iniciados 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 a cualquier esperanza de capturar la salida.
Sin contexto
A diferencia de init
servicios, los lanzados por systemd
no heredan ningún entorno de ningún usuario del sistema. En otras palabras, 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 buscas en Google "systemd sucks" encontrarás mucho material de lectura. 😉
¿Cómo iniciar el servicio automáticamente cuando está inactivo?
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
.
Ya que las conexiones websocket pueden llegar al servidor en cualquier momento, este proceso necesita estar activo todo el tiempo y monitorear las conexiones entrantes. No podemos tener el ciclo de vida tradicional de PHP aquí porque WebSockets son conexiones con estado, y si el script muere, la conexión es una lista. De todos modos, basta de websockets; veamos cómo vamos a hacer para daemonizar este script vía systemd
.
Todos systemd
residen en /etc/systemd/system, así que vamos a crear un archivo allí para describir nuestro script de servidor websocket. Asumiendo que has iniciado sesión como usuario root.
# vi /etc/systemd/system/chat_server.service
y entonces se necesita lo siguiente.
[Unidad] Descripción=Servicio de servidor de chat After=red.destino [Servicio] Tipo=simple Usuario=ankush ExecStart=php /home/ankush/servidor_chat/index.php Reiniciar=on-abort [Instalar] WantedBy=multi-user.target
Guarde el archivo y el siguiente paso es volver a cargar el demonio systemd
# systemctl daemon-reload
e iniciar el servicio que acabamos de crear:
# systemctl start chat_server
Si no ves ningún error, ¡ya está!
Veamos también qué significan las distintas directivas del archivo:
- En
[Unit]
parte define una nueva unidad de servicio parasystemd
. En elsystemd
todos los servicios se denominan unidades de servicio. - En
After
(como era de esperar) dicesystemd
para lanzar este servicio sólo después de que se lancen los servicios de red (de lo contrario, ¡¿quién hará el manejo de bajo nivel de las conexiones de socket?!). - En
Type=simple
dicesystemd
que se supone que este servicio no se bifurca 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 a "root", pero es muy poco recomendable desde el punto de vista de la seguridad.ExecStart
como puedes ver, es el comando a ejecutar.Restart=on-abort
significa que el servicio debe ser reiniciado cuando aborta. En PHP, los procesos de larga ejecución pierden memoria y eventualmente explotan, por lo que esto es necesario.- En
WantedBy=
indicasystemd
de qué objetivo (piensa en grupos) forma parte este servicio. Esto da lugar a enlaces simbólicos que se crean dentro de ese objetivo para apuntar al servicio.
Generalmente, esta cantidad 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 no es la única opción. Hay más y elegir en función de la necesidad.
- en caso de fallo - se reiniciará cuando el código de salida o la señal no sean limpios
- siempre - reanudar cuando se encuentra abajo, limpio o sucio señal
- on-abnormal - señal no limpia, watchdog o timeout
- sobre el éxito - sólo cuando se detuvo por una señal limpia o código de salida
Configurar el servicio para que se inicie al arrancar
Una vez que estés satisfecho con el script y te asegures de que funciona, lo siguiente es configurarlo para que se active al arrancar e iniciarse.
Ir a /etc/systemd/system y ejecute el siguiente comando enable (no olvide cambiar el nombre del fichero .service por el que tenga)
# systemctl enable chat_server.service
Verás una confirmación de que se ha creado un enlace simbólico.
Creado 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 en el arranque.
¡Eso fue fácil! ¿A que sí?
¡Ayuda! Estoy masivamente invertido en Upstart. 🙁
Entiendo que confíes en mí, tu caso es la norma más que la excepción. RHEL lleva tanto tiempo utilizando Upstart que el cambio casi parece 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 han creado un guía de migración que debería consultar.
Una gracia salvadora en todo esto es que systemd
es compatible con el SysV init
por lo que, en la mayoría de los casos, sólo tendrás que mover los archivos y poner en marcha los mismos servicios.
¿Le interesa saber más sobre la administración y resolución de problemas de Linux? Echa un vistazo a este curso en línea.