El arranque en GNU/Linux.

Grub fue creado en 1995 por Erich Boleyn mientras intentaba poner en marcha Hurd, la eterna alternativa al nucle Linux que nunca terminó de arrancar. Erich modificó el código de arranque de FreeBSD (una distribución de Linux) para que soportase multiarranque. En 1999 Grub pasó a formar parte de GNU como paquete oficial, se expandió rápidamente, sustituyendo a Lilo, el gestor de arranque por excelencia hasta ese momento. Una de las ventajes que hizo que Grub sustituyese a Lilo, fue que era capaz de acceder al sistema de archivos, cosa que Lilo no podía hacer, ya que localizaba los archivos por posición física en disco (lo que quiere decir que cualquier variación en su posición física de disco impedía su localización).

En 2007, Grub2 se puso en marcha, y su adopción masiva por las principales distribuciones empezó en 2009.

Proceso de arranque con Grub2

Cuando un ordenador basado en BIOS arranca, lo primero en ejecutarse es el MBC (el Master Boot Code ubicado en la MBR). En concreto el MBC es muy pequeño (446 Bytes), y dado que Grub es de mayor tamaño, El proceso de arranque de grub se hace en fases. La primera fase es precisamente el MBC. El MBC carga a su vez el resto de fases que se encuentran ya en la partición donde esté los archivos de arranque de GNU/Linux.

Una vez que Grub se ha cargado, muestra el contenido del archivo grub.cfg donde se encuentran las diferentes opciones de arranque. El usuario termina seleccionando una de las entradas.

Suponiendo que se ha elegido una entrada de GNU/Linux, el proceso de arranque del sistema operativo se hace en varias fases:

  1. En primer lugar, el cargador de Grub carga el kernel de linux (archivo vmlinuz) y el ramdisk (archivo initrd) en memoria. El kernel realiza una inicilización básica (establece las tablas de paginación de memoria, detecta el tipo del CPU y funcionalidad adicional como capacidades de punto flotante), y después descomprime el archivo initrd, y lo monta como un sistema de archivos temporal (llamado ramdisk).
  2. initrd contiene programas y módulos del kernel necesarios para cargar drivers para poder inicializar los dispositivos que contienen el sistema de archivos real. Así que el kernel emplea initrd para montar un sistema de archivos virtual en memoria, y poder así cargar en memoria el software y los controladores necesarios para poder montar el sistema de archivos real y hacer funcionar correctamente el hardware. Una vez que el proceso ha terminado, el kernel sustituye (con las herramientas disponibles en memoria) el sistema de archivos temporal por el real, e initrd es borrado de memoria.
  3. Una vez que el kernel ha montado el sistema de archivos real, pasa el control al programa /sbin/init.
  4. Init (o bien upstart o bien systemd) consigue que todo funcione como debe, una vez que el kernel está totalmente en funcionamiento, estableciendo el espacio de usuario. Esto incluye la comprobación y montaje de sistemas de archivos, la puesta en marcha los servicios de usuario necesarios y cambiar al entorno de usuario cuando el inicio del sistema se ha completado. Init y upstart toman como parámetro el runlevel, conocido como nivel de ejecución, que tiene un valor entre 1 y 6, y que determina qué servicios se pondrán en funcionamiento. Systemd reune dichos servicios con otra denominación: en lugar de runlevel, los llama target, aunque el concepto es el mismo.

Trabajando con Grub2

Centos 7 incluye Grub2 como gestor de arranque. Grub2 lee su configuración desde el archivo /boot/grub2/grub.cfg. Este archivo contiene los menús que se muestran durante el inicio. A diferencia de la versión de Grub anterior, este archivo (grub.cfg) no está pensado para ser editado a mano, ya que se genera con la aplicación /usr/sbin/grub2-mkconfig, partiendo de:

  • los kernels Linux ubicados en /boot/,
  • las plantillas ubicadas en /etc/grub.d/,
  • y las configuraciones presentes en /etc/default/grub

Cada vez que se instala un nuevo kernel, el archivo de configuración grub.cfg se actualiza automáticamente.

Cualquier cambio realizado en /etc/default/grub requiere reconstruir grub.cfg, mediante la ejecución de grub2-mkconfig, del siguiente modo:

# grub2-mkconfig -o /boot/grub2/grub.cfg

Si abrimos el archivo grub.cfg lo veremos lleno de entradas de tipo menuentry. Cada una de estas entradas, representa una opción del menú que Grub2 muestra al encender el ordenador.

Actividad 1. Lo que se puede ver a continuación, es el archivo grub.cfg. Aunque no entiendas la mayor parte de lo que pone, sí que puedes identificar las entradas menuentry. Identifícalas y averigua el nombre con que se mostraría cada entrada en el menú de arranque de Grub2

Justifica en clase la razón de tu afirmación.

# # DO NOT EDIT THIS FILE # # It is automatically generated by grub2-mkconfig using templates # from /etc/grub.d and settings from /etc/default/grub # ### BEGIN /etc/grub.d/00_header ### set pager=1 if [ -s $prefix/grubenv ]; then load_env fi if [ "${next_entry}" ] ; then set default="${next_entry}" set next_entry= save_env next_entry set boot_once=true else set default="${saved_entry}" fi if [ x"${feature_menuentry_id}" = xy ]; then menuentry_id_option="--id" else menuentry_id_option="" fi export menuentry_id_option if [ "${prev_saved_entry}" ]; then set saved_entry="${prev_saved_entry}" save_env saved_entry set prev_saved_entry= save_env prev_saved_entry set boot_once=true fi function savedefault { if [ -z "${boot_once}" ]; then saved_entry="${chosen}" save_env saved_entry fi } function load_video { if [ x$feature_all_video_module = xy ]; then insmod all_video else insmod efi_gop insmod efi_uga insmod ieee1275_fb insmod vbe insmod vga insmod video_bochs insmod video_cirrus fi } terminal_output console if [ x$feature_timeout_style = xy ] ; then set timeout_style=menu set timeout=5 # Fallback normal timeout code in case the timeout_style feature is # unavailable. else set timeout=5 fi ### END /etc/grub.d/00_header ### ### BEGIN /etc/grub.d/10_linux ### menuentry 'CentOS Linux, with Linux 3.10.0-123.el7.x86_64' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-123.el7.x86_64-advanced-b7c67778-c967-4e13-9bda-f04a12b3959b' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' b7c67778-c967-4e13-9bda-f04a12b3959b else search --no-floppy --fs-uuid --set=root b7c67778-c967-4e13-9bda-f04a12b3959b fi linux16 /boot/vmlinuz-3.10.0-123.el7.x86_64 root=UUID=b7c67778-c967-4e13-9bda-f04a12b3959b ro crashkernel=auto vconsole.keymap=es vconsole.font=latarcyrheb-sun16 rd.lvm.lv=centos_centos-filesvr/swap rhgb quiet LANG=es_ES.UTF-8 initrd16 /boot/initramfs-3.10.0-123.el7.x86_64.img } menuentry 'CentOS Linux, with Linux 0-rescue-417106a52aab474d9ac9eb973bf4ad7f' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-417106a52aab474d9ac9eb973bf4ad7f-advanced-b7c67778-c967-4e13-9bda-f04a12b3959b' { load_video insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' b7c67778-c967-4e13-9bda-f04a12b3959b else search --no-floppy --fs-uuid --set=root b7c67778-c967-4e13-9bda-f04a12b3959b fi linux16 /boot/vmlinuz-0-rescue-417106a52aab474d9ac9eb973bf4ad7f root=UUID=b7c67778-c967-4e13-9bda-f04a12b3959b ro crashkernel=auto vconsole.keymap=es vconsole.font=latarcyrheb-sun16 rd.lvm.lv=centos_centos-filesvr/swap rhgb quiet initrd16 /boot/initramfs-0-rescue-417106a52aab474d9ac9eb973bf4ad7f.img } if [ "x$default" = 'CentOS Linux, with Linux 3.10.0-123.el7.x86_64' ]; then default='Advanced options for CentOS Linux>CentOS Linux, with Linux 3.10.0-123.el7.x86_64'; fi; ### END /etc/grub.d/10_linux ### ### BEGIN /etc/grub.d/20_linux_xen ### ### END /etc/grub.d/20_linux_xen ### ### BEGIN /etc/grub.d/20_ppc_terminfo ### ### END /etc/grub.d/20_ppc_terminfo ### ### BEGIN /etc/grub.d/30_os-prober ### ### END /etc/grub.d/30_os-prober ### ### BEGIN /etc/grub.d/40_custom ### # This file provides an easy way to add custom menu entries. Simply type the # menu entries you want to add after this comment. Be careful not to change # the 'exec tail' line above. ### END /etc/grub.d/40_custom ### ### BEGIN /etc/grub.d/41_custom ### if [ -f ${config_directory}/custom.cfg ]; then source ${config_directory}/custom.cfg elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then source $prefix/custom.cfg; fi ### END /etc/grub.d/41_custom ###

Configurar el menú de Grub2

Grub2 es capaz por sí mismo de localizar los sistemas operativos en el ordenador donde se ejecuta, y añadirlos al menú de inicio. Sin embargo el usuario puede querer crear una nueva entrada, o tener las entradas en un orden específico.

Grub2 usa una serie de scripts para crear el menú de unicio, que están en /etc/grub.d/. Se trata de los siguientes archivos.

  • 00_header - carga la configuración de Grub2 desde el archivo /etc/default/grub.
  • 01_users - se crea cuando se asigna una contraseña al gestor de arranque.
  • 10_linux - localiza los kernels en la partición por defecto de CentOS
  • 30_os-prober - crea entradas para los sistemas operativos encontrados en otras particiones.
  • 40_custom - en esta plantilla se pueden añadir entradas adicionales.

Actividad 2. Visualiza cada uno de los archivos mencionados anteriormente.

Observa que, aunque no entiendas los scripts, puedes acceder a ellos y leerlos en texto plano. Esta es una de las características diferenciadoras de GNU/Linux. Los archivos de configuración, así como los scripts son legibles y modificables con un simple editor de textos.

Cambiar la entrada por defecto de Grub

Por defecto, la variable GRUB_DEFAULT dentro del archivo /etc/default/grub tiene el valor saved. Este valor se utiliza para indicar a Grub2 que cargue la entrada indicada en el archivo /boot/grub2/grubenv. Para que la opción por defecto del menú sea otra, debemos usar el comando grub2-set-default que actualizará el archivo /boot/grub2/grubenv. Por ejemplo:

# grub2-set-default 2 NOTA: el número 2 indica la tercera entrada, ya que empezamos por 0.

Cualquier cambio requiere la reconstrucción de grub.cfg del siguiente modo:

# grub2-mkconfig -o /boot/grub2/grub.cfg

Actividad 3. Ahora conoces la estructura de Grub2. Supón la siguiente situación:

Añades a una máquina virtual con CentOS 7 instalado un disco con Windows, de forma que no aparece entre las opciones de arranque de Grub2. Busca en Internet instrucciones para añadir una nueva entrada para el menú de Grub2, de forma que te ofrezca la posibilidad de arrancar Windows desde el menú de Grub2.

Explica la solución que has encontrado y demuestra como la máquina es capaz de arrancar Windows desde Grub2.

NOTA: Para el ejercicio anterior, bastaría con hacer grub2-mkconfig -o /boot/grub/grub.cfg para se añadieran automáticamente las nuevas entradas. Entiéndase el ejercicio anterior como práctica para seleccionar de diferentes fuentes documentales la opción que parece más adecuada y ponerla en práctica, creando una entrada manualmente en el archivo de configuración 40_custom.

Reinstalar Grub2

La reinstalación de Grub2 puede ser útil para reparar problemas relacionados con una instalación defectuosa de Grub2, archivos perdidos, etc. Otras opciones para reinstalar Grub2 pueden ser:

  • Actualizar de Grub a Grub2
  • Desaparición de Grub2 debido a que otro gestor de arranque lo ha destruido
  • Añadir la información de arranque a otro disco diferente

Cuando se usa el comando grub2-install la información de arranque se actualiza. Observa el siguiente ejemplo:

# grub2-install /dev/sda

Este método se puede usar mientras los archivos de configuración de Grub2 están íntegros (/etc/grub.d/* y /etc/sysconfig/grub). Pero si dichos archivos están corruptos, contienen entradas erróneas, etc., no funcionará. Para ello podemos usar otro procedimiento: borrar y reinstalar Grub2.

Actividad 4. Reinstala Grub2 en el disco.

Muestra al profesor la consola donde has hecho todas las operaciones.

Borrar y reinstalar Grub2

El siguiente método borra todos los archivos de configuración de Grub2, y después devuelve la configuración de Grub2 a la configuración por defecto. Este método resuelve problemas causados por archivos corruptos y configuraciones incorrectas. Seguimos el siguiente procedimiento:

# rm /etc/grub.d/* # rm /etc/sysconfig/grub # yum reinstall grub2-tools # grub2-mkconfig -o /boot/grub2/grub.cfg

Actividad 5. Realiza el procedimiento anterior, y comprueba que puedes volver a arrancar.

Muestra al profesor cómo llevas a cabo el borrado de los archivos de configuración de Grub2 y cómo tras reinstalarlo, puedes volver a arrancar.

Algunos comentarios sobre UEFI

Aparentemente, durante la instalación de Linux, no hay ninguna diferencia entre un sistema BIOS y otro UEFI. En éste último no habrá necesidad de crear una partición extendida, ya que UEFI soporta 128 particiones. A diferencia de BIOS, UEFI no instala parte de Grub en la MBR y el resto en el sector de la partición de arranque. En lugar de esto coloca los archivos necesarios (el binario de Grub compilado como aplicación UEFI, el archivo de configuración grub.cfg y los módulos de Grub) en la partición ESP (Efi System Partition). A continuación se muestran algunos comandos útiles para el trabajo sobre Grub en UEFI:

Para reconstruir la configuración de Grub

grub2-mkconfig -o /boot/efi/EFI/ubuntu/grub.cfg

Para reinstalar los binarios de Grub en la ESP

# mkdir /boot/efi # mount /dev/sda1 /boot/efi suponiendo que la ESP está en /dev/sda1 # sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=nuevo-grub --recheck bootloader-id da nombre al directorio donde se almacenará grub

Actividad 6. Reinstala Grub2 en la partición ESP en un directorio llamado nuevo-grub. Comprueba que el nuevo gestor de arranque está disponible cuando arrancas la interfaz de UEFI

Entrega una captura donde se pueda ver que aparece el nuevo gestor de arranque al iniciar la interfaz de UEFI.