Recientemente encontré dos problemas diferentes en dos hosts Linux diferentes. Cada uno requería una elusión única porque todavía tengo que encontrar una solución real. Sin embargo, el método para realizar cada elusión era el mismo:ejecutar un comando durante o poco después del inicio de Linux.
El rc.local
El archivo era, y en algunos casos sigue siendo, el lugar para que los administradores de sistemas de Linux coloquen los comandos que deben ejecutarse al inicio. Uso del rc.local
El archivo no solo está en desuso, sino que después de un par de horas de intentos, no funcionaba en ningún caso. Esto a pesar del hecho de que systemd
la documentación menciona el uso de un "generador" que genera systemd
servicios desde un rc.local
archivo si existe. (Esa parece ser una buena manera de hacer cumplir la desaprobación, hacer que no funcione).
Los detalles de mi problema específico no son particularmente relevantes para esta discusión, por lo que usaré un comando simple y fácil de rastrear como contenido de nuestro archivo de inicio local. Agregaremos una línea con fecha a un archivo de registro local para verificar que el programa Bash que necesitamos ejecutar al inicio realmente funciona.
Arranque vs. inicio
Comprender el proceso de inicio y arranque de Linux es importante para configurar Linux y resolver problemas de inicio. En realidad, hay dos secuencias de eventos que se requieren para arrancar una computadora Linux y hacerla utilizable:arranque e inicio. La secuencia de inicio comienza cuando se enciende la computadora y finaliza cuando se inicializa el kernel y systemd
es lanzado. Luego, el proceso de inicio toma el control y finaliza la tarea de poner la computadora Linux en un estado operativo.
En general, el proceso de inicio y arranque de Linux es bastante simple de entender. Se compone de los siguientes pasos, que se describirán más adelante con más detalle:
- Prueba automática de encendido (POST) del BIOS
- Cargador de arranque (GRUB2)
- Núcleo
systemd
Para obtener una descripción mucho más detallada de las secuencias de arranque e inicio, consulte mi artículo Introducción a los procesos de arranque e inicio de Linux.
Inicio local
Los administradores de sistemas a veces agregan comandos a la secuencia de inicio que son localmente útiles. Estas adiciones pueden tener como objetivo iniciar o ejecutar procesos locales que no forman parte del estándar systemd
puesta en marcha. Es posible agregar un nuevo systemd
unidad de servicio para iniciar cada programa necesario al inicio, pero el antiguo rc.local
El método proporcionó un único archivo ejecutable para todas y cada una de las necesidades de inicio locales. Nosotros también podemos usar este enfoque de archivo único con systemd
. La elegancia de esta solución es que facilita agregar más comandos de inicio en un momento posterior, sin necesidad de agregar más unidades de servicio a systemd
.
Nuestra solución es crear un único systemd
unidad de servicio y coloque los comandos de Linux necesarios en el archivo ejecutable. Hay dos partes en esta solución. Una es obvia:necesitamos un archivo ejecutable. Y dos, necesitamos crear una unidad de servicio para systemd
que ejecuta el ejecutable.
Crear el archivo ejecutable
Este es un ejercicio trivial para cualquier administrador de sistemas familiarizado con la programación Bash. De hecho, crearemos un programa Bash y lo colocaremos en la ubicación del estándar jerárquico del sistema de archivos de Linux (FHS) para archivos ejecutables locales, /usr/local/bin
. Se podría hacer un argumento para colocar este archivo ejecutable en otra ubicación, pero /usr/local/bin
es el que tiene más sentido para mí, ya que esta ubicación facilita que el administrador del sistema ejecute el script desde la línea de comandos si es necesario. El /usr/local/bin
El directorio siempre está en el $PATH
de cada usuario , incluido el del usuario root.
Crea el mystartup.sh
archivo que se muestra aquí y colóquelo en /usr/local/bin
(asegúrese de hacerlo ejecutable). Asegúrese de utilizar la ubicación para Bash que sea correcta para su distribución. Por ejemplo, las distribuciones basadas en Debian ubican a Bash en /bin/bash
.
#!/usr/bin/bash
################################################################################
# mystartup.sh
#
# This shell program is for testing a startup like rc.local using systemd.
# By David Both
# Licensed under GPL V2
#
################################################################################
# This program should be placed in /usr/local/bin
################################################################################
# This is a test entry
echo `date +%F" "%T` "Startup worked" >> /root/mystartup.log
Asegúrese de probar este ejecutable ejecutándolo desde la línea de comandos. La primera vez que ejecute este script de shell, debería ver un nuevo archivo, /root/mystartup.log
, con una hora y fecha junto con el texto, "Startup worked"
. Creamos este archivo de registro y le agregamos líneas cada vez que se ejecuta el script como una prueba simple para asegurarnos de que nuestro script funciona.
Ejecute el script un par de veces más. Tus resultados deberían ser similares a los que se muestran aquí:
[root@testvm1 ~]# mystartup.sh
[root@testvm1 ~]# cat mystartup.log
2019-09-12 19:58:00 Startup worked
2019-09-12 19:58:17 Startup worked
2019-09-12 19:58:54 Startup worked
2019-09-12 19:59:00 Startup worked
2019-09-12 20:01:08 Startup worked
2019-09-12 20:04:01 Startup worked
2019-09-12 20:04:13 Startup worked
2019-09-12 20:06:11 Startup worked
2019-09-12 20:06:28 Startup worked
2019-09-16 09:51:21 Startup worked
2019-09-16 09:51:51 Startup worked
Eso es todo lo que tenemos que hacer para crear el archivo que eventualmente puede contener nuestros comandos de inicio locales. Simplemente agregue cualquier cosa que necesite ejecutarse al inicio de este archivo.
Crear el servicio systemd
La unidad de servicio que crearemos ahora es un systemd
estándar archivo de la unidad de servicio. Este archivo simple se usa solo para ejecutar mystartup.sh
secuencia de comandos al inicio.
Cree un nuevo archivo, /usr/local/lib/systemd/system/mystartup.service
y agregue los contenidos que se muestran a continuación:
################################################################################
# mystartup.service
#
# This service unit is for testing my systemd startup service
# By David Both
# Licensed under GPL V2
#
################################################################################
# This program should be placed in /usr/local/lib/systemd/system/.
# Create a symlink to it from the /etc/systemd/system directory.
################################################################################
[Unit]
Description=Runs /usr/local/bin/mystartup.sh
[Service]
ExecStart=/usr/local/bin/mystartup.sh
[Install]
WantedBy=multi-user.target
Este archivo no necesita ser ejecutable. Este archivo también podría estar ubicado en /etc/systemd/system
, pero como archivo local está mejor ubicado en /usr/local
rama de la estructura del directorio, con un enlace desde /etc/systemd.system
.
Ahora, ve a /etc/systemd/system
y cree el enlace simbólico en el archivo de la unidad de servicio:
[root@testvm1 system]# ln -s /usr/local/lib/systemd/system/mystartup.service
Probar la unidad de servicio
Deberíamos probar el archivo de la unidad de servicio final antes de reiniciar el host de Linux para la prueba final. Primero, verifiquemos que systemd
ve el servicio:
[root@testvm1 ~]# systemctl status mystartup
● mystartup.service - Runs /usr/local/bin/mystartup.sh
Loaded: loaded (/usr/local/lib/systemd/system/mystartup.service; linked; vendor preset: disabled)
Active: inactive (dead)
[root@testvm1 ~]#
Este resultado nos dice que el servicio es reconocido por systemd
. Ahora, comencemos el servicio. Si lo hace, se ejecutará el script, pero no se configurará el nuevo servicio para que se ejecute en el momento del arranque:
[root@testvm1 ~]# systemctl start mystartup
Verifique el contenido del archivo de registro para verificar que se agregó la nueva línea.
Habilitar el servicio
Todo lo que queda es habilitar el servicio para que se ejecute al inicio:
[root@testvm1 ~]# systemctl enable mystartup
Created symlink /etc/systemd/system/multi-user.target.wants/mystartup.service →
/usr/local/lib/systemd/system/mystartup.service.
[root@testvm1 ~]#
Prueba final
Antes de reiniciar, veamos el journalctl
comando y cómo podemos usarlo para ver las entradas del diario que se relacionan con mystartup.service
. También podemos usar el journalctl
comando para verificar esto porque systemd
lleva un diario de todo lo que hace.
En el siguiente comando, -u
La opción muestra solo entradas para mystartup
unidad:
[root@testvm1 ~]# journalctl -u mystartup
-- Logs begin at Mon 2019-04-15 22:50:27 EDT, end at Mon 2019-09-16 11:44:30 EDT. --
Sep 16 11:09:28 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]#
Ahora, reinicie el host de Linux y verifique el archivo de registro para asegurarse de que se haya agregado una nueva línea:
[root@testvm1 ~]# systemctl status mystartup
● mystartup.service - Runs /usr/local/bin/mystartup.sh
Loaded: loaded (/usr/local/lib/systemd/system/mystartup.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2019-09-16 11:45:59 EDT; 1min 30s ago
Process: 819 ExecStart=/usr/local/bin/mystartup.sh (code=exited, status=0/SUCCESS)
Main PID: 819 (code=exited, status=0/SUCCESS)
Sep 16 11:45:55 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]# journalctl -u mystartup
-- Logs begin at Mon 2019-04-15 22:50:27 EDT, end at Mon 2019-09-16 11:47:45 EDT. --
Sep 16 11:09:28 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
-- Reboot --
Sep 16 11:45:55 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]#
Conclusión
El script de shell Bash que hemos creado para este experimento se ejecuta una vez al inicio y luego se cierra. No permanece en la memoria como un demonio porque no fue diseñado para hacerlo.
En caso de que no lo hayas notado, el procedimiento que usamos para crear nuestro servicio de inicio local también se puede usar para crear cualquier servicio nuevo para systemd
. No es tan difícil una vez que sabemos cómo hacerlo.
Actualizar
Poco después de la publicación de este artículo, recibí un correo electrónico de Tom Murphy quien me informó de la existencia del rc-local
. servicio que es parte de systemd
. Agradezco ese correo electrónico porque no conocía ese servicio, así que aprendí algo nuevo.
Es posible agregar soporte para el antiguo rc.local
archivo habilitando el servicio con el comando, systemctl enable rc-local
. Los comandos en el archivo rc.local se ejecutarán en el siguiente arranque. Por supuesto, puede usar systemctl enable rc-local
para ejecutar rc.local
inmediatamente.
Sin embargo, sigue siendo cierto que rc.local está obsoleto. La página man para systemd-rc-local-generator
dice:“Soporte para /etc/rc.local se proporciona solo para compatibilidad con sistemas System V específicos. Sin embargo, se recomienda encarecidamente evitar hacer uso de este script hoy y, en su lugar, proporcionar archivos unitarios adecuados con dependencias apropiadas para que los scripts se ejecuten durante el proceso de arranque”.
Recursos
-
Libro de datos estándar jerárquico del sistema de archivos (FHS) de Linux para Linux
-
información GNU GRUB
-
Manual de GNU GRUB
-
Registro de arranque maestro
-
Especificación de arranque múltiple
-
información del sistema
-
proceso de arranque systemd
-
systemd índice de páginas man
-
Una introducción a los procesos de inicio y arranque de Linux
[¿Quiere probar Red Hat Enterprise Linux? Descárguelo ahora gratis.]