Responder al comentario

Oct 28 21:31

Modificando upstart para elegir un nivel u otro de arranque desde grub

La imaginativa configuración de los niveles de inicio sumado a la posibilidad de seleccionar uno u otro en tiempo de arranque abre un mundo de posibilidades no solo destinado a los administradores de sistemas sino también a usuarios de escritorio.


El siguiente documento se cede al dominio público, según la licencia
CC Reconocimiento-NoComercial-CompartirIgual 2.5 España

 



Capítulo 1. Guía Rápida

Para los impacientes y para los que conocen la intención de este documento no me andaré por las ramas y explicaré la solución porpuesta.


Requisitos

Ubuntu Edgy, Feisty o superior, o cualquier distribución que use Upstart como demonio init funcionando como wrapper (envoltorio) a SysVinit.

Grub como Boot Loader.


El efecto conseguido

Podemos indicar el runlevel con el que arrancar indicándolo como parámetro en el comando de entrada de menú kernel de Grub:

  • Escribiéndolo directamente en el fichero /boot/grub/menu.lst

  • En boot-time desde el menú de Grub usando la línea de comandos de éste.

Aquí un ejemplo de como quedaría una entrada de menú Grub que arranca en runlevel 3

  
title Ubuntu, kernel 2.6.17-11-386
root (hd0,0)
kernel /boot/vmlinuz-2.6.17-11-386 root=/dev/sda1 ro quiet splash runlevel=3
initrd /boot/initrd.img-2.6.17-11-386
savedefault
boot

Procediendo

Sustituir el fichero /etc/event.d/rc-default por lo siguiente:

  
# rc - runlevel compatibility
#
# This task guesses what the "default runlevel" should be and starts the
# appropriate script.
#
# (c) J. Félix Ontañón 2007. Distribuido con licencia GPLv2
#
# Modificado para correr uno u otro nivel de inicio según lo que indique el
# parámetro "runlevel" pasado al kernel por la cmd-line en tiempo de arranque.
#
start on rcS/stop

script
runlevel --reboot || true

RUNLEVEL=2

for x in $(cat /proc/cmdline); do
case $x in
runlevel=*)
RUNLEVEL=${x#runlevel=}
;;
esac
done

telinit $RUNLEVEL

end script

Capítulo 2. Motivación

Sabemos que como estándar de facto se usan 8 niveles de incio con SysVinit: desde rc0 a rc6 mas rcS. De esos niveles de inicio 3 son reservados:

  • 0. Halt

  • 1. Single-mode user

  • 6. Reboot

El resto de niveles de inicio, son los llamados user-definible runlevels.

A lo largo del tiempo los administradores de sistemas han sacado partido a estos runlevels definiendo que procesos iniciar o parar en cada uno de ellos para conseguir llevar a la máquina a uno u otro estado. Las distribuciones también han hecho uso de estos niveles para definir que niveles de arranque multiusuario, con o sin entorno gráfico, por ejemplo.

No obstante las distribuciones mas orientadas a escritorio han ido despreocupándose progresivamente de la utilidad que niveles de arranque pueden tener para sus usuarios finales, de modo que, algo tan particular como la elección de un nivel de arranque u otro en boot-time parece haber caido en el olvido y la documentación al respecto es realmente escasa.

Mas aún, con la prometedora llegada de Upstart, por parte de Ubuntu desde su versión 6.10 (Edgy Eft), y los cambios que esta trae consigo, la información buscada es nula.


Posibilidades

La imaginativa configuración de los niveles de inicio sumado a la posibilidad de seleccionar uno u otro en tiempo de arranque abre un mundo de posibilidades no solo destinado a los administradores de sistemas sino también a usuarios de escritorio.

Esta podría ser una curiosa propuesta:

  • Runlevel 2: Arranque por defecto.

    Modo multiusuario con entorno gráfico. Un runlevel con la configuración por defecto de la distribución.

  • Runlevel 3: Media Center.

    Modo monousuario que inicia lo mínimo necesario arrancar a pantalla completa un media center (o multimedia center) como Freevo, Elisa o Linux Media Center (LMC).

  • Runlevel 4: Modo ahorro de recursos.

    Iniciar el sistema librándonos de la mayoría de servicios pesados con el fin de tener un sistema con los mínimos recursos consumidos. Ideal para jugones.

Para cada nivel se podría crear una entrada de menú en Grub que el usuario podría elegir.


Capítulo 3. Explicación paso a paso

Línea de comandos de Kernel

El núcleo puede aceptar parámetros en tiempo de arranque. Un par de parámetros populares que sirven para ilustrarnos son:

  • root=/dev/dispositivo

  • vga=ext

Una vez montado el sistema de ficheros virtual proc podemos ver los parámetros pasados como argumento en la línea de comandos del kernel en /proc/cmdline.

En la actualidad la línea de comandos del núcleo es también usada indicar otras opciones de arranque. InitramFS (imagen initrd) parsea la línea de comandos en busca de parámetros, y así, por ejemplo, se procede a la identificación de unidades de disco por UUID.

En este caso hemos definido un nuevo parámetro en la kernel cmdline con el acertado nombre runlevel


Upstart

Upstart es un init daemon creado por el Ubuntu-team que pretende ser sustituto del init de System V. Es el único proceso que arranca el núcleo y encargado de llamar al resto de programas/servicios del sistema. En Linux, todo proceso es hijo de init.

Ciertamente Upstart presenta interesantes mejoras respecto del init de System V: Arranque de servicios en paralelo, guiado por eventos, servicios que se rearrancan automáticamente si mueren, etc ... Sin embargo, por el momento (este documento fue escrito en Agosto 2007) las únicas distribuciones que lo implementan son Ubuntu (Edgy/Feisty) y Debian Experimental. Es mas, toda la potencia de Upstart no es aprovechada pues, por retrocompatibilidad con los scripts de sysvinit, upstart solo se acaba comportando como un wrapper de éste.

En /etc/event.d/ tenemos los ficheros de configuración de upstart que, podríamos decir, funcionan como si del fichero /etc/inittab se tratase:

  • Ficheros ttyX: que llaman a la creación de las terminales con getty.

  • Ficheros rcX: que acaban ajustando el runlevel y llamando a /etc/init.d/rc para ejecutar los scripts del nivel de arranque correspondiente.

  • Otros ficheros como ctrl-alt-del que mapea dicha combinación al reincio ordenado del equipo, o rc-default que define el nivel de inicio por defecto.

Es este último fichero, rc-default, es el objeto de nuestro estudio.


Fichero /etc/event.d/rc-default

Originalmente, Ubuntu Edgy y Feisty, define este fichero como sigue:

  
# rc - runlevel compatibility
#
# This task guesses what the "default runlevel" should be and starts the
# appropriate script.

start on rcS/stop

script
runlevel --reboot || true

if grep -q -w -- "-s\|single\|S" /proc/cmdline; then
telinit S
elif [ -r /etc/inittab ]; then
RL="$(sed -n -e "/^id:[0-9]*:initdefault:/{s/^id://;s/:.*//;p}" /etc/inittab || true)"
if [ -n "$RL" ]; then
telinit $RL
else
telinit 2
fi
else
telinit 2
fi
end script

Aquel que conozca bash-scripting puede darse cuenta rápidamente que el script busca en la línea de comandos del núcleo la directiva single para arrancar en single-mode user, caso contrario busca en /etc/inittab el runlevel por defecto (retrocompatibilidad con sysvinit) y si no hay ninguno definido se toma el runlevel 2 como nivel de inicio.

Vemos pues que incluso este script parsea la línea de comandos del kernel, en busca de parámetros para iniciar el single-user mode, si procede. No es, por tanto, mucho mas dificil imaginar como modificar dicho script para que se parsee la línea de comandos del núcleo en busca de nuestro parámetro runlevel.

La aproximación seguida, aunque no la mejor, es la siguiente:

  
# rc - runlevel compatibility
#
# This task guesses what the "default runlevel" should be and starts the
# appropriate script.
#
# (c) J. Félix Ontañón 2007. Distribuido con licencia GPLv2
#
# Modificado para correr uno u otro nivel de inicio según lo que indique el
# parámetro "runlevel" pasado al kernel por la cmd-line en tiempo de arranque.
#
start on rcS/stop

script
runlevel --reboot || true

RUNLEVEL=2

for x in $(cat /proc/cmdline); do
case $x in
runlevel=*)
RUNLEVEL=${x#runlevel=}
;;
esac
done

telinit $RUNLEVEL

end script

Sencillo y funcional: extrae el nivel de arranque de la línea de comandos del núcleo y ajusta el runlevel 2 por defecto. Podríamos complicarlo un poco mas determinando el nivel de arranque por defecto extrayéndolo del /etc/inittab si hubiere.

Además, por haberse construido con un bloque case este script es fácilmente extensible para añadir nuevos parámetros.


Capítulo 4. Bibliografía

Espero que este humilde artículo haya sido de vuestro agrado y podáis sacar mas partido a los niveles de arranque. Para mas información:

Responder

El contenido de este campo se mantiene privado y no se mostrará públicamente.
  • Etiquetas HTML permitidas: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd><img>
  • Saltos automáticos de líneas y de párrafos.
  • Las direcciones de las páginas web y las de correo se convierten en enlaces automáticamente.

Más información sobre opciones de formato

By submitting this form, you accept the Mollom privacy policy.