¿Arrancar el sistema Linux desde un subdirectorio en una partición?


11

Me gustaría intentar configurar una computadora para que tenga varias instalaciones de Linux en el mismo sistema de archivos. Por ejemplo, el sistema de ficheros tendría 3 carpetas: /Ubuntu_Precise, /Ubuntu_Oneiric, y /Ubuntu_Natty.

(Sé que puedes hacer esto con BTRFS y subvolúmenes, pero me gustaría usar EXT4 para la velocidad).

Una vez configuré varias instalaciones de diferentes distribuciones usando BTRFS, y al hacer que eso funcione, sé que Grub funciona bien al arrancar la imagen vmlinuz e initrd desde rutas 'no estándar'. Pero cuando estaba haciendo lo de BTRFS, estaba el rootflags=subvol=@<subvolume_name>que le decía al núcleo que montara ese subvolumen como / en el sistema de archivos. ¿Hay algún argumento de que podría pasar el kernel que lo obligaría a montar una subcarpeta en una partición como / y luego iniciar?

Creo que para las otras partes, estoy bastante cerca. Sé cómo especificar un montaje de enlace /etc/fstab. Además, desde que configuré mi sistema con múltiples instalaciones de Linux en subvolúmenes BTRFS, estoy acostumbrado a instalar una distribución en una VM y luego migrarla usando rsync, así que no estoy demasiado preocupado por lo que tendría que hacer para obtener la configuración correcta, solo estoy tratando de averiguar cuál sería la configuración correcta. Una vez que sepa eso, debería poder migrar a las subcarpetas y editar archivos con bastante facilidad.

Ya sé sobre virtualización y particiones, pero eso no es lo que estoy buscando. La computadora de destino no tiene suficiente potencia para realizar la virtualización y las particiones no comparten espacio libre. Estoy buscando configurar un sistema que dual / triple / quad / etc inicie las distribuciones de Linux, pero que lo haga con un sistema de archivos, de modo que no haya ningún caso de "¡Tengo espacio libre, pero está en la partición incorrecta!"

Si alguien tiene sugerencias sobre cómo editar mi pregunta o su título para que quede más claro, soy todo oídos.


1
No hay nada AFAIK integrado en el sistema. Lo que probablemente tendría que hacer es agregar otro parámetro de arranque y modificar sus initramfs para hacer chroot en el subdirectorio antes de ejecutar init
Ulrich Dangel

@UlrichDangel, eso es lo que iba a proponer. ¡Hazlo una respuesta!
Nils

@Nils ok, acabo de proporcionar una respuesta, tbh. No quería escribir uno al principio ya que no quería proporcionar el parche / script
Ulrich Dangel

Respuestas:


10

Respuesta corta: hasta donde yo sé, no existe una solución de trabajo lista para usar para sus requisitos específicos. Tendrá que ajustar cada initramfs de cada distribución para satisfacer sus necesidades específicas.

Respuesta larga: sí, es posible. Hoy en día, la mayoría de las distribuciones de Linux usan un initramfs que el gestor de arranque cargará en la memoria y luego el núcleo desempacará. Allí se ejecutará /sbin/initel responsable de configurar el espacio de usuario temprano (ejecutar udev, cargar módulos, iniciar plymouth, solicitar una frase de contraseña criptográfica, configurar la red para montajes de red, ... lo que sea). Como puede ejecutar sus propios scripts y evaluar parámetros de arranque personalizados.

Ejemplo para Debian

Si está utilizando Debian (debería ser lo mismo con Ubuntu), debería poder colocar un script en el /etc/initramfs-tools/scripts/init-bottom/que se ejecutará antes de iniciar init. Para obtener más información sobre el script, los diferentes directorios y el diseño tienen un vistazo a man initramfs-tools . Tendrá que ajustar rootmnty agregar el directorio de destino.

Script de muestra (no probado) que debe instalarse como /etc/initramfs-tools/scripts/local-bottom/00-myrooto /usr/share/initramfs-tools/scripts/init-top/00-myroot:

#!/bin/sh -e

PREREQS=""

prereqs() { echo "$PREREQS"; }

case "$1" in
  prereqs)
  prereqs
  exit 0
;;
esac

for opt in $(cat /proc/cmdline); do
  case $opt in
    rootdir=*)
      new_mntdir="${opt#rootdir=}"
      ;;
    esac
done

if [ -n "$new_mntdir" ] ; then
  echo rootmnt="$rootmnt/$new_mntdir" >> /conf/param.conf
fi

La idea es ajustar rootmnt cuál se usa en el initscript initramfs para iniciar / ejecutar el init real. Como el dispositivo raíz ya está montado en la init-bootometapa, solo puede ajustar / modificar el directorio de destino.

Para usar este script simplemente agregue un nuevo parámetro de arranque, copie el script, hágalo ejecutable, regenere sus initramfs y agregue un parámetro de arranque para su distribución de Linux, por ejemplo rootdir=/Ubuntu_Precise.


También es probable que desee vincular el montaje de la raíz real en un subdirectorio de la raíz del sistema operativo para que pueda ver los otros archivos del sistema operativo desde el que arranca.
psusi

@psusi Puede hacerlo a través de fstab o simplemente directamente mount /dev/rootdevice /mountpointdespués de que el sistema se esté ejecutando
Ulrich Dangel

Me pregunto cuándo cambió eso. No podías volver a montar el mismo dispositivo de bloque; obtendrías una EBUSY.
psusi

1
@psusi no estoy seguro, pero probablemente con la introducción de monturas de unión
Ulrich Dangel

@UlrichDangel ¡Gracias por la respuesta (muy) detallada!
Azendale

2

Aquí hay dos formas que funcionan en ubuntu bionic (y posiblemente en otros lugares). no tengo suficiente representante para comentar, pero bionic: / usr / share / initramfs-tools / init busca en / etc / fstab / usr justo después de llamar a mountroot y antes de llamar a los scripts * -bottom, por lo que agrega un init- La secuencia de comandos inferior (como se sugiere en otra respuesta aquí) es "demasiado tarde". en cambio, recomiendo estos:

#!/bin/bash -f
#copyleft 2018 greg mott

#set a subdirectory as root (so multiple installs don't need partitions)
#these work in ubuntu bionic, could be different elsewhere
#1st choice:  tweak initramfs-tools/scripts/local
#   pro:  subdirectory becomes root directly, nothing gets any chance to see the partition root
#   con:  only works if the subdirectory's initramfs/initrd is tweaked and rebuilt
#2nd choice:  specify this script as init= on the kernel commandline
#   pro:  no need to rebuild initramfs
#   con:  if the partition root etc/fstab mounts /usr the initramfs will have already mounted it
#   con:  it's conceivable some initramfs script might still look in the partition root rather than your subdirectory
#   con:  this script requires bin/bash et al in the partition root

#for either choice copy /etc/grub.d/40_custom to /etc/grub.d/07_custom and add one or more menuentries that specify subroot:
#menuentry "subroot foo" {
#     echo "subroot foo"
#              sub=/foo
#              uuid=22e7c84a-a416-43e9-ae9d-ee0119fc3894        #use your partition's uuid
#     search --no-floppy --fs-uuid --set=root $uuid
#            linux $sub/vmlinuz ro root=UUID=$uuid subroot=$sub                                                                                         
#     echo "initrd $sub/initrd.img"
#           initrd $sub/initrd.img      #works in recent releases where the /initrd.img softlink is relative
#}

#to use this script, in addition to subroot= on the kernel commandline also specify:
#   init=/path/to/script        #pathname from partition root to this script (chmod 744)

#the tweak for bionic:/usr/share/initramfs-tools/scripts/local is replace:
#          mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt}
#          mountroot_status="$?"
#with:
#          set -x
#          karg=" $(cat<proc/cmdline) " m=${karg#* subroot=}
#          [ "$m" = "$karg" ]||subroot=${m%% *}                                         #extract subroot from kernel commandline
#          [ $subroot ]&&part=part||part=$rootmnt                                       #no subroot, just mount partition as root
#          mkdir part
#          mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} $part&&         #mount partition
#             if [ "$subroot" ]
#             then mount --bind part/$subroot $rootmnt&&                                #mount subroot
#                  umount part                       #&&sleep 15                        #unmount partition root (uncomment sleep for time to look)
#             fi
#          mountroot_status="$?"
#          [ $mountroot_status = 0 ]||sleep 90                                          #if error pause to look
#          set +x
#once you've edited /usr/share/initramfs-tools/scripts/local, update-initramfs -u will rebuild for the current kernel,
#and it will automatically build into every new kernel installed

subroot(){ karg=" $(cat<proc/cmdline) " m=${karg#* subroot=}
           [ "$m" = "$karg" ]||subroot=${m%% *}                 #extract subroot from kernel commandline
           [ $subroot ]||return 0                               #no subroot, just proceed in partition root
           while read -r m r m
           do for m in $M x                                     #build list of what's already mounted
              do    [[ $r = $m* ]]&&break                       #exclude subtrees (ie dev/**)
              done||[[ $r = /   ]]||M=$M\ $r                    #exclude /
           done<proc/mounts
           (set -x;mount --bind $subroot mnt)||{ set -x         #mount subroot
                                                 sleep 30          #if not found pause to see error
                                                 return 0;}        #then reincarnate as partition root init
           for m in $M
           do (set -x;mount -n --move $m mnt$m)||return         #move listed mounts to subroot
           done
           set -x
           cd           mnt&&
           pivot_root . mnt&&                                   #subroot becomes root
           umount -l    mnt&&                                   #unmount partition root
          #sleep 15        &&                                   #so far so good?  uncomment for time to look
           exec chroot . init "$@"                              #reincarnate as subroot init
}
subroot "$@"&&exec init "$@"||exec bash                         #land in a shell if moves or pivot fail

Esto funcionó para mí
paultop6

1

Arrancar diferentes Linux sin jugar con la tabla de particiones es interesante para diferentes propósitos, una solución alternativa a un sistema de archivos compartido es usar volúmenes de bucle, aquí los pocos cambios necesarios suponiendo que tenga un / archivo de volumen / debian en el sistema de archivos / dev / sdb1 (Estoy usando GNU / Debian sid / inestable para los sistemas operativos principales y de bucle).

/etc/grub.d/40_custom: # outside from loop volume
menuentry 'label' --class gnu-linux --class gnu --class os {
    ...
    loopback loop (hd2,msdos1)/debian
    linux   (loop)/boot/vmlinuz root=/dev/sdb1 loop=/debian ro
    initrd  (loop)/boot/initrd
}

Los argumentos definidos en grub como línea de comando de linux se establecen en env por initrd / init, por lo que:

ROOT=/dev/sdb1
rootmnt=/root
loop=/debian 

el bucle permite montar el volumen sobre "sí mismo", el flujo de script predeterminado hace un mount /dev/sdb1 /rootopcionalmente solo volvemos a montar el / dev / sdb1 como rw si era ro y siempre agregamos a mount -o loop /root/debian /root.

/etc/initramfs-tools/scripts/local-bottom/loop: # inside the loop volume
#!/bin/sh

[ "$1" = "prereqs" ] && echo && exit 0

if [ -n "${loop}" ]; then
        if [ "${readonly}" = "y" ]; then
                roflag=-r
                mount -o remount,rw ${ROOT} ${rootmnt}
        else
                roflag=-w
        fi
        mount ${roflag} -o loop ${rootmnt}${loop} ${rootmnt}
fi

También necesita precargar algún módulo en el initram (luego no olvide ejecutar update-initramfs)

/etc/initramfs-tools/modules: # inside the loop volume
...
loop
ext4

No sé cuánto usar el rendimiento de la influencia del bucle o desperdiciar recursos, me pregunto si montar ext4 sobre ext4 duplica las probabilidades de una falla del sistema de archivos, pero supongo que se podría hacer un ajuste. Tal vez hay una mejor manera de usar el bucle, menos hack, si hay, por favor avíseme porque no lo he encontrado.


0

Esta no es una respuesta, pero quiero aclarar algún punto sobre la respuesta y los comentarios de Ulrich (no puedo comentar más arriba).

La solución que Ulrich propone "puede" funcionar (aún no se ha probado) pero luego obtendrá un sistema de archivos no desmontable . Como solución alternativa (en mi humilde opinión), puede montar el fs como rw antes del chrooting ( como se sugiere aquí ) pero tenga cuidado con los scripts de inicio rotos. Supongo que esta solución tiene más efectos secundarios (como fs rotos que intentan volver a montar ro y fallan).

Estoy usando el kernel 3.2 con ext4 y montar un desarrollador ya montado dentro del chroot todavía da EBUSY como comentó psusi.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.