Manual:X86/Trabajando/GuionesDeinicio
El contenido de esta página no se aplica a los usuarios que eligieron un perfil systemd en Elegir el perfil correcto.
Niveles de ejecución
Iniciando el sistema
Al iniciar, notará que pasará al frente suyo una gran cantidad de texto. Si pone atención, notará que estos textos son (normalmente) iguales cada vez que reinicie su sistema. La secuencia de todas estas acciones se llama la secuencia de inicio y es (más o menos) definido estáticamente.
En primer lugar, su gestor de arranque cargará en memoria la imagen del núcleo que definió en la configuración del gestor de arranque, después de lo cual, se indica a la CPU que debe ejecutar el núcleo. Al ser cargado y luego ejecutado inicializa todas las estructuras y tareas específicas del núcleo e inicia el proceso init.
Este proceso asegura que todos los sistemas de archivo (definidos en /etc/fstab) estén montados y listos para usar. Luego ejecuta varios guiones en /etc/init.d/, correspondientes a los servicios requeridos para tener un sistema correctamente iniciado.
Finalmente, al concluir la ejecución de los guiones, init activa los terminales (generalmente solo las consolas virtuales accesibles con Alt+F1, Alt+F2, etc.) fijándoles un proceso especial denominado agetty. Este proceso hará posible que pueda ingresar al sistema a través de uno de estos terminales ejecutando login.
Guiones de inicio
Ahora bien, init no solamente ejecuta los guiones contenidos en /etc/init.d/ de manera aleatoria. Aún más, no ejecuta todos los guiones del /etc/init.d/, solamente los que han sido seleccionados para ejecutar. Los guiones seleccionados para ejecutar se encuentran dentro del directorio /etc/runlevels/.
Primero, init ejecuta todos los guiones de /etc/init.d/ cuyos enlaces simbólicos se encuentran dentro de /etc/runlevels/boot/. Usualmente los iniciará en orden alfabético, pero algunos guiones tienen información relativa a dependencias, para lo cual otros guiones deben ser iniciados anteriormente.
Cuando se ejecuten todos los guiones referenciados en /etc/runlevels/boot/, init continua su trabajo con los guiones en /etc/runlevels/default/. Una vez más, usará el orden alfabético, salvo cuando hay dependencias, en cuyo caso es alterado el orden de inicio para realizar una secuencia válida de arranque. Esto último es también la razón por la que durante la instalación de Gentoo Linux se utiliza la opción default
(por defecto), como en rc-update add sshd default.
¿Cómo funciona init?
Por supuesto que init no decide todo eso por su cuenta. Requiere un archivo de configuración que especifica las acciones a tomar. Este archivo es /etc/inittab.
Si recuerda la secuencia de inicio que se ha explicado, recordará que la primera acción de init es montar todos los sistemas de archivo. Esto está definido en la siguiente línea de /etc/inittab:
si::sysinit:/sbin/openrc sysinit
Esa línea dice a init que debe ejecutar /sbin/openrc sysinit al iniciar el sistema. El guión /sbin/openrc se encargan de la inicialización, con lo que podríamos decir que init no hace mucho, delega la tarea de inicialización del sistema a otro proceso.
En segundo lugar, init ejecutó los guiones con enlaces simbólicos en /etc/runlevels/boot/. Esto se define en la siguiente línea:
rc::bootwait:/sbin/openrc boot
Una vez más, el guión OpenRC lleva a cabo las tareas necesarias. Note que la opción dada a OpenRC (boot) corresponde al subdirectorio en /etc/runlevels/ que será usado.
Ahora init revisa su archivo de configuración para ver que nivel de ejecución debe ejecutar. Para decidirlo, lee la siguiente línea de /etc/inittab:
id:3:initdefault:
En este caso (para la mayoría de usuarios Gentoo), el identificador del nivel de ejecución será el 3. Con esta información init revisa qué debe ejecutar para iniciar el nivel de ejecución 3:
l0:0:wait:/sbin/openrc shutdown
l1:S1:wait:/sbin/openrc single
l2:2:wait:/sbin/openrc nonetwork
l3:3:wait:/sbin/openrc default
l4:4:wait:/sbin/openrc default
l5:5:wait:/sbin/openrc default
l6:6:wait:/sbin/openrc reboot
La línea que define el nivel 3, de nuevo usa el guión openrc para iniciar los servicios (ahora con el parámetro por defecto default
). Note una vez más que el parámetro pasado al guión openrc corresponde al subdirectorio de /etc/runlevels/.
Al terminar OnpenRC, init decide qué consolas virtuales debe activar y qué órdenes se deben ejecutar para cada una:
c1:12345:respawn:/sbin/agetty 38400 tty1 linux
c2:12345:respawn:/sbin/agetty 38400 tty2 linux
c3:12345:respawn:/sbin/agetty 38400 tty3 linux
c4:12345:respawn:/sbin/agetty 38400 tty4 linux
c5:12345:respawn:/sbin/agetty 38400 tty5 linux
c6:12345:respawn:/sbin/agetty 38400 tty6 linux
Niveles de ejecución existentes
Ha visto que init utiliza un esquema de numeración para decidir cual nivel de ejecución debe activar. Un nivel de ejecución es un estado en el cual su sistema está corriendo y contiene guiones (del nivel de ejecución o initscripts) que serán ejecutados al ingresar o salir del nivel de ejecución.
En Gentoo, hay siete niveles de ejecución definidos: tres internos y cuatro definidos por el usuario. Los internos se llaman sysinit, shutdown y reboot y hacen exactamente lo que implican sus nombres: inicialización, apagado y reinicio del sistema.
Los niveles de ejecución definidos por el usuario están acompañados de un subdirectorio bajo /etc/runlevels/: boot, default, nonetwork y single. El nivel de ejecución boot inicia los servicios necesarios que requieren los demás niveles de ejecución. Los tres niveles de ejecución restantes difieren respecto a los servicios que inician: default es para uso diario, nonetwork en caso de no requerirse la red y single es utilizado en caso de necesitar arreglar el sistema.
Trabajando con los guiones de inicio
Los guiones iniciados por el proceso openrc son llamados guiones de inicio o init scripts. Cada guión en /etc/init.d/ puede ser ejecutado con los parámetros start
, stop
, restart
, zap
, status
, ineed
, iuse
, iwant
, needsme
, usesme
o wantsme
.
Para iniciar, parar o reiniciar un servicio (y sus respectivas dependencias), deben usarse start
, stop
y restart
:
root #
rc-service postfix start
Solo los servicios que necesiten del servicio nombrado serán parados o reiniciados. Los demás servicios, (aquellos que usen el servicio nombrado, pero que no lo necesiten) continuarán sin ser tocados.
Si desea parar un servicio, pero no los que dependan de el, puede usar la opción --nodeps
junto con el parámetro stop
:
root #
rc-service --nodeps postfix stop
Si desea ver el estado de un servicio (iniciado, parado, ...) puede usar el parámetro status
:
root #
rc-service postfix status
Si la respuesta a status indica que el servicio está corriendo, pero realmente no es así, puede reajustarlo manualmente con el parámetro zap
:
root #
rc-service postfix zap
Para preguntar por las dependencias que tiene un servicio, puede usar iwant
, iuse
o ineed
. Con ineed
puede ver qué servicios son realmente necesarios para el correcto funcionamiento del servicio nombrado. Por otra parte, iwant
o iuse
muestran los servicios que pueden ser usados por el servicio nombrado, pero que no son requeridos para su correcto funcionamiento.
root #
rc-service postfix ineed
De igual manera, puede indagar que servicios requieren el servicio nombrado (needsme
) o cuáles pueden usarlo (usesme
o wantsme
):
root #
rc-service postfix needsme
Modificar los niveles de ejecución
rc-update
El sistema de inicio de Gentoo usa un árbol de dependencias para decidir qué servicios deben iniciarse primero. Como ésta es una tarea tediosa, que no deseamos que nuestros usuarios tengan que hacer manualmente, hemos creado unas herramientas para facilitar la administración de los niveles de ejecución y los guiones de inicio.
Con rc-update puede añadir o quitar guiones de inicio a un nivel de ejecución. La herramienta rc-update automáticamente usará el guión depscan.sh para reconstruir el árbol de dependencias.
Añadir y quitar servicios
En instrucciones anteriores ya hemos agregado guiones de inicio al nivel de ejecución "por defecto" (default). Lo que quiere decir "por defecto" (default) se ha explicado antes en este documento. Junto al nivel de ejecucuión, el guión rc-update requiere un segundo parámetro que define la acción a llevar a cabo: add
, del
o show
para agregar, borrar o mostrar.
Para añadir o quitar un guión de inicio, use rc-update con el parámetro add
o del
, seguido por el nombre del guión de inicio y el nivel de ejecución, por ejemplo:
root #
rc-update del postfix default
La orden rc-update -v show mostrará todos los guiones de inicio con los niveles de ejecución donde ejecutarán:
root #
rc-update -v show
Es posible ejecutar también rc-update show (sin -v) simplemente para ver los guiones de inicio activos y sus respectivos niveles de ejecución.
Configurar los servicios
¿Por qué se necesita configuración adicional?
Los guiones de inicio pueden ser bastante complejos, por lo cual no es interesante que los usuarios modifiquen directamente el guión de inicio, ya que esto puede ser propenso a errores. Sin embargo es importante poder configurar estos servicios, en caso que se quieren dar más opciones al servicio.
Una segunda razón para mantener esta información fuera del guión de inicio es para poder actualizar estos guiones sin que los cambios de configuración sean perdidos.
El directorio conf.d
Gentoo provee una manera fácil de configurar estos servicios: cada guión de inicio configurable tiene un archivo dispuesto en /etc/conf.d/. Por ejemplo, el guión de inicio apache2 (llamado /etc/init.d/apache2) tiene un archivo de configuración de nombre /etc/conf.d/apache2, el cual contiene las opciones a pasar al servidor web Apache 2 en el momento de inicio:
APACHE2_OPTS="-D PHP5"
Este tipo de archivo de configuración contiene solamente variables (como en /etc/portage/make.conf), lo que facilita la configuración de servicios. También nos permite suministrar información adicional acerca de las variables (en forma de comentarios).
Crear guiones de inicio
Otro recurso útil es la guía de guiones de servicios de OpenRC.
¿Es necesario?
No, escribir un guión de inicio normalmente no hace falta, ya que Gentoo ofrece guiones listos para usar para todos los servicios suministrados. Sin embargo, puede haber instalado un servicio sin usar Portage, en cuyo caso probablemente tenga que crear un guión de inicio.
No utilice el guión de inicio proporcionado por el servicio si no está escrito explícitamente para Gentoo: ¡los scripts de inicio de Gentoo no son compatibles con los scripts de inicio utilizados por otras distribuciones! Es decir, a menos que la otra distribución esté utilizando OpenRC.
Esquema
El esquema básico de un guión de inicio se muestra a continuación.
#!/sbin/openrc-run
depend() {
# (Información acerca de las dependencias)
}
start() {
# (Órdenes requeridas para iniciar el servicio)
}
stop() {
# (Órdenes requeridas para parar el servicio)
}
#!/sbin/openrc-run
command=/usr/bin/foo
command_args="${foo_args} --bar"
pidfile=/var/run/foo.pid
name="Demonio FooBar"
description="FooBar es un demonio que bebe"
extra_started_commands="drink"
description_drink="Abre su boca y traga reflexivamente"
depend() {
# (Información de dependencias)
}
start_pre() {
# (Comandos necesarios para prepararse para iniciar el servicio)
# Asegurarse de que nuestros directorios son correctos
checkpath --directory --owner foo:foo --mode 0775 \
/var/run/foo /var/cache/foo
}
stop_post() {
# (Commandos necesarios para limpiar después del servicio)
# Limpiar todas las salpicaduras
rm -rf /var/cache/foo/*
}
drink() {
ebegin "Empezando a beber"
${command} --drink beer
eend $? "No he podido beberme ninguna cerveza :("
}
Cualquier guión de inicio requiere la definición de la función start()
o de la variable command. El resto de secciones son opcionales.
Dependencias
Existen tres ajustes relacionados con las dependencias que puede definir y que influyen en el arranque o secuenciación de los guiones de inicio: want
, use
y need
. Aparte de estas dos, existen también dos métodos, llamados before
y after
, que influyen en el orden . Estos últimos no son dependencias en sí mismos, no provocan el fallo del guión de inicio si el guión seleccionado no está programado para ser iniciado (o falla al iniciar).
- Los ajustes
use
informan al sistema de inicio que este guión utiliza funcionalidad ofrecida por el guión seleccionado, sin embargo no depende directamente de él. Un buen ejemplo seríause logger
ouse dns
. Si estos servicios están disponibles, se usarán de forma correcta, pero aunque no tenga instalado un programa de registro (logger) o servidor DNS, los servicios funcionarán de todos modos. Si estos servicios están presentes en su sistema, entonces se arrancarán antes del guión que los utiliza. - El ajuste
want
es similar ause
con una excepción.use
considera únicamente los servicios que se añadieron a un nivel de inicio.want
intentará iniciar cualquier servicio disponible incluso si no se ha añadido a un nivel de inicio. - El ajuste
need
es una dependencia inevitable. Esto significa que el guión que necesita otro guión, no podrá arrancar antes de que el otro guión se arranque de forma correcta. Si el otro guión es reiniciado, entonces el guión que depende de él será reiniciado igualmente. - Cuando se utiliza
before
, el guión dado es arrancado antes del guión seleccionado si el seleccionado forma parte del nivel de inicio. Por lo tanto, si el guión de inicio xdm definebefore alsasound
, será arrancado antes que el guión alsasound, pero solo si alsasound está también programado para ser arrancado en el mismo nivel de inicio. Si alsasound no está programado para arrancar, entonces este ajuste en particular no tiene efecto y el guión xdm será arrancado cuando el sistema de inicio lo juzgue apropiado. - De modo similar,
after
informa al sistema de inicio que el guión dado debería ser arrancado antes que el seleccionado si el guión seleccionado forma parte de nivel de inicio. En caso contrario, el ajuste no tiene efecto y el guión será arrancado por el sistema de inicio cuando éste lo juzgue apropiado.
Debería quedar claro una vez leido lo anterior, que need
es el único ajuste que define un "auténtica" dependencia ya que afecta al hecho de que el guión sea arrancado o no. Las demás son simplemente apuntes al sistema de inicio para clarificar el orden en el que los guiones deben (o deberían ser arrancados).
Si echa un vistazo al muchos de los guiones de inicio disponibles en Gentoo, observará que algunos tienen dependencias de objetos que no son guiones de inicio. Estos "objetos" son los llamados virtuals (virtuales).
Una dependencia virtual es una dependencia suministrada por un servicio, pero no únicamente por un servicio en concreto. Su guión de inicio puede depender de un gestor de registro de sistema, habiendo disponibilidad de varios (metalogd, syslog-ng, sysklogd, ...). Como no se necesitan todos (ningún sistema normal tiene todos estos gestores de registro instalados y corriendo) nos aseguramos que todos estos servicios provean una dependencia virtual.
A modo de ejemplo examinemos la información de dependencia del servicio postfix:
depend() {
need net
use logger dns
provide mta
}
Como podemos ver, el servicio postfix:
- requiere la dependencia (virtual) net (suministrada, por ejemplo por, /etc/init.d/net.eth0)
- usa la dependencia (virtual) logger (suministrada, por ejemplo por, /etc/init.d/syslog-ng)
- usa la dependencia (virtual) dns (suministrada por ejemplo por, /etc/init.d/named)
- provee la dependencia (virtual) mta (común a todos los servidores de correo electrónico)
Controlar la ordenación
Tal y como se ha descrito en la sección anterior, puede indicarle al sistema de inicio qué orden debe seguir para arrancar (o parar) los guiones. Este orden es manejado tanto por los ajustes de dependencia use y need, como por los ajustes de orden before y after. Como ya hemos descrito estos ajustes, echemos un vistazo al servicio portmap como ejemplo de guión de inicio.
depend() {
need net
before inetd
before xinetd
}
También puede usar el carácter que engloba "*" para referirse a todos los servicios, aunque no es aconsejable.
depend() {
before *
}
Si el servicio debe escribir en discos locales, necesitará localmount. Si coloca algo en /var/run/, como un archivo PID, entonces debe iniciarse después de bootmisc:
depend() {
need localmount
after bootmisc
}
Funciones estándar
Junto con la función depend()
, hará falta definir la función start()
, que contiene las órdenes necesarias para inicializar su servicio. Es aconsejable usar las funciones ebegin
y eend
para informarle al usuario acerca de lo que está ocurriendo:
start() {
if [ "${RC_CMD}" = "restart" ];
then
# Hacer algo en caso de que restart requiera algo más que parar y arrancar
fi
ebegin "Arrancando mi_servicio"
start-stop-daemon --start --exec /path/to/mi_servicio \
--pidfile /path/to/my_pidfile
eend $?
}
Ambos --exec
y --pidfile
deben usarse en las funciones start y stop. Si el servicio no crea un archivo pid, entonces use --make-pidfile
si es posible, aunque debe probar esto para estar seguro. De otra manera, no use archivos pid. Puede también agregar --quiet
a las opciones al start-stop-daemon, pero esto no es recomendado a no ser que el el servicio sea extremadamente verboso. Usando --quiet
puede interferir con la depuración si el servicio no logra arrancar.
Otro ajuste notable usado en el ejemplo anterior es la comprobación del contenido de la variable RC_CMD. Al contrario que el sistema de guiones de inicio anterior, el nuevo sistema OpenRC no soporta funcionalidad de reinicio específica de los guiones. En lugar de esto, el guión necesita comprobar el contenido de la variable RC_CMD para var si una función (sea start()
o stop()
) se llama como parte del reinicio o no.
Asegúrese que
--exec
efectivamente llame a un servicio y no solamente a un guión que lanza un servicio y termina -- después de todo, eso es lo que se espera que haga un guión de inicio.Si requiere más ejemplos de funciones start()
, favor leer directamente las fuentes de los guiones de inicio en su directorio /etc/init.d/.
Otra función que puede definir es stop()
. Sin embargo, ¡No está obligado a definir esta función! Nuestro sistema de inicio es lo suficientemente inteligente para rellenar esta función por sí mismo si utiliza start-stop-daemon.
stop() {
ebegin "Parando mi_servicio"
start-stop-daemon --stop --exec /path/to/mi_servicio \
--pidfile /path/to/my_pidfile
eend $?
}
Si el servicio ejecuta otro guión (por ejemplo, Bash, Python o Perl), y este guión cambia posteriormente de nombre (por ejemplo, foo.py a foo), entonces hará falta agregar --name
al start-stop-daemon. Debe especificar el nombre al cual cambiará el guión. En este ejemplo, un servicio inicia foo.py, el cual cambia de nombre a foo:
start() {
ebegin "Arrancando mi_guion"
start-stop-daemon --start --exec /path/to/mi_guion \
--pidfile /path/to/my_pidfile --name foo
eend $?
}
El start-stop-daemon tiene una excelente página man si requiere más información:
user $
man start-stop-daemon
La sintaxis de los guiones de inicio de Gentoo está basada en el intérprete de comandos POSIX, de manera que es libre de usar construcciones compatibles con sh dentro del guión de inicio. No utilice otras construcciones, por ejemplo las del tipo bash, en los guiones de inicio para asegurarse de que los guiones funcionen en el futuro incluso si se cambia el sistema de inicio de Gentoo.
Añadir opciones personalizadas
Si desea que su guión de inicio soporte un mayor número de opciones de las que hemos encontrado hasta ahora, debe agregar la opción a una de las siguientes variables y crear una función con el mismo nombre que la opción. Por ejemplo, para dar soporte a una opción llamada restartdelay
:
- extra_commands - El comando está disponible con el servicio en cualquier estado
- extra_started_commands - El comando está disponible cuando se arranca el servicio
- extra_stopped_commands - El comando está disponible cuando se para el servicio
extra_started_commands="restartdelay"
restartdelay() {
stop
sleep 3 # Esperar 3 segundos antes de iniciarse de nuevo
start
}
¡La función
restart()
no puede ser sobreescrita en OpenRC!Variables para la configuración de servicios
No hay que hacer nada para dar soporte a un archivo de configuración en /etc/conf.d/: si su guión de inicio se ejecuta, los siguientes archivos serán automáticamente leídos -sourced- (es decir, las variables estarán disponibles para ser usadas):
- /etc/conf.d/YOUR_INIT_SCRIPT
- /etc/conf.d/basic
- /etc/rc.conf
También, si su guión de inicio provee una dependencia virtual (como net), el archivo asociado a esa dependencia (el /etc/conf.d/net) será leído también.
Cambiar el comportamiento del nivel de ejecución
¿Quién se podría beneficiar?
Muchos usuarios de equipos portátiles conocen la situación: en casa necesita iniciar net.eth0 mientras que puede no querer iniciar net.eth0 mientras está de viaje (cuando no hay una red disponible). Con Gentoo puede modificar el comportamiento del nivel de ejecución para sus propios propósitos.
Por ejemplo puede crear un segundo nivel de ejecución "default" con el cual puede arrancar y que utiliza otros guiones de inicio que le han sido asignados. Puede seleccionar al arrancar que nivel de ejecución quiere utilizar.
Utilizar softlevel
Antes de nada, cree el directorio para su segundo nivel de ejecución "default". Como ejemplo vamos a crear el nivel de ejecución offline:
root #
mkdir /etc/runlevels/offline
Añada los guiones de inicio necesarios para el nuevo nivel de ejecución. Por ejemplo, si quiere una copia exacta de su actual "default" pero sin net.eth0:
root #
cd /etc/runlevels/default
root #
for service in *; do rc-update add $service offline; done
root #
rc-update del net.eth0 offline
root #
rc-update show offline
(Partial sample Output) acpid | offline domainname | offline local | offline net.eth0 |
Incluso aunque se haya eliminado net.eth0 del nivel de ejecución offline, puede que udev quiera intentar iniciar cualquier dispositivo que detecte y lanzar los servicios apropiados, una funcionalidad llamada hotplugging (enchufado en caliente). Por defecto Gentoo no habilita esta funcionalidad.
Si quiere habilitar el hotplugging pero solo para un conjunto seleccionado de guiones, utilice la variable rc_hotplug en /etc/rc.conf:
rc_hotplug="net.wlan !net.*"
Para más información sobre los servicios iniciados en función de dispositivos, consulte los comentarios del archivo /etc/rc.conf.
Ahora edite la configuración de su gestor de arranque y añada una nueva entrada para el nivel de ejecución offline. En dicha entrada, añada softlevel=offline
como parámetero de arranque.
Utilizar bootlevel
Utilizar bootlevel es completamente análogo a softlevel. La única diferencia es que se define un segundo nivel de ejecución "boot" en lugar de un segundo "default".