Загрузите систему Linux из подкаталога раздела?

11

Я хотел бы попытаться настроить компьютер так, чтобы на нем было несколько установок Linux в одной файловой системе. Например, filesytem будет иметь 3 папки: /Ubuntu_Precise, /Ubuntu_Oneiricи /Ubuntu_Natty.

(Я знаю, что вы можете сделать это с BTRFS и вложенными томами, но я хотел бы использовать EXT4 для скорости).

Однажды я установил несколько установок разных дистрибутивов, используя BTRFS, и, получив это, я знаю, что Grub отлично справляется с загрузкой образа vmlinuz и initrd из «нестандартных» путей. Но когда я занимался BTRFS, было то, rootflags=subvol=@<subvolume_name>что ядро ​​указывало монтировать этот подобъем как / в файловой системе. Есть ли какой-либо аргумент, что вы можете передать ядру, которое заставит его связать, смонтировать подпапку в разделе как / и затем загрузиться?

Я думаю, что для других частей, я довольно близок. Я знаю, как определить привязку в /etc/fstab. Кроме того, с тех пор, как я установил свою систему с несколькими установками linux в подобъемах BTRFS, я привык устанавливать дистрибутив на ВМ, а затем переносить его с помощью rsync, поэтому я не слишком беспокоюсь о том, что мне нужно сделать, чтобы получить правильную конфигурацию, я просто пытаюсь выяснить, какая будет правильная конфигурация. Как только я это узнаю, я смогу достаточно легко выполнить миграцию в подпапки и редактирование файлов.

Я уже знаю о виртуализации и разделах, но это не то, что я ищу. Целевой компьютер не обладает достаточной мощностью для виртуализации, а разделы не разделяют свободное пространство. Я пытаюсь настроить систему, в которой двойной / тройной / quad / etc загружает дистрибутивы linux, но это делается с одной файловой системой, чтобы не было случая «у меня есть свободное место, но оно не в том разделе!»

Если у кого-то есть предложения, как отредактировать мой вопрос или его название, чтобы быть более понятным, я все уши.

Azendale
источник
1
Там AFAIK ничего не встроено в систему. Вероятно, вам нужно было бы добавить еще один загрузочный параметр и изменить ваши initramfs для chroot в подкаталог перед выполнением init
Ульрих Дангель
@UlrichDangel это то, что я собирался предложить. Сделай ответ!
Нильс
@ Нильс: Хорошо, я только что дал ответ. сначала я не хотел писать его, так как не хотел предоставлять патч / скрипт
Ульрих Дангел

Ответы:

10

Краткий ответ - насколько я знаю, нет готового решения для ваших конкретных требований. Вам нужно будет настроить каждое initramfs каждого дистрибутива для удовлетворения ваших конкретных потребностей.

Длинный ответ - да, это возможно. В настоящее время большинство дистрибутивов Linux используют initramfs, который будет загружен в память загрузчиком, а затем распакован ядром. Там он будет работать, /sbin/initкоторый отвечает за настройку раннего пространства пользователя (запуск udev, загрузка модулей, запуск plymouth, запрос криптофразы, настройка сети для монтирования сети,… вы называете это). Так же вы можете запускать свои собственные скрипты и оценивать пользовательские параметры загрузки.

Пример для Debian

Если вы используете Debian (должно быть то же самое с Ubuntu), вы должны иметь возможность разместить скрипт, /etc/initramfs-tools/scripts/init-bottom/который будет выполняться перед запуском init. Для получения дополнительной информации о скрипте, различные каталоги и макет взгляните на man initramfs-tools . Вам нужно будет настроить rootmntи добавить целевой каталог.

Пример (непроверенный) сценария, который должен быть установлен как /etc/initramfs-tools/scripts/local-bottom/00-myrootили /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

Идея состоит в том, чтобы настроить, rootmnt который используется в initскрипте initramfs для запуска / выполнения реального init. Поскольку корневое устройство уже смонтировано на init-bootomэтапе, вы можете просто настроить / изменить целевой каталог.

Чтобы использовать этот сценарий, просто добавьте новый параметр загрузки, скопируйте сценарий, сделайте его исполняемым, заново сгенерируйте ваши initramfs и добавьте параметр загрузки для вашего дистрибутива Linux, например rootdir=/Ubuntu_Precise.

Ульрих Дангел
источник
Вы также, вероятно, захотите подключить монтирование реального корня в подкаталог корня os, чтобы вы могли видеть другие файлы ОС из того, который вы загрузили.
psusi
@psusi Вы можете сделать это через fstab или просто сделать это сразу mount /dev/rootdevice /mountpointпосле запуска системы
Ульрих Дангель,
Интересно, когда это изменилось? Раньше вы не могли снова смонтировать то же самое блочное устройство; Вы получите EBUSY.
psusi
1
@psusi не уверен, но, вероятно, с введением привязных креплений
Ульрих Дангел
@UlrichDangel Спасибо за (очень) подробный ответ!
Azendale
2

Вот два способа, которые работают в Ubuntu Bionic (и, возможно, в другом месте). у меня недостаточно репутации, чтобы комментировать, но bionic: / usr / share / initramfs-tools / init просматривает / etc / fstab для / usr сразу после вызова mountroot и перед вызовом *-нижних сценариев, поэтому добавление init- Нижний сценарий (как предлагается в другом ответе здесь) "слишком поздно". вместо этого я рекомендую это:

#!/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
gregrwm
источник
Это сработало для меня
paultop6
1

Загрузка разных linux без вмешательства в таблицу разделов интересна для разных целей, альтернативное решение для общей файловой системы - это использовать тома цикла, здесь нужно внести несколько изменений, предполагая, что у вас есть файл / том цикла / debian в файловой системе / dev / sdb1 (Я использую текущий GNU / Debian sid / unstable как для основной, так и для петлевой ОС).

/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
}

Аргументы, определенные в grub как командная строка linux, устанавливаются в env initrd / init, поэтому:

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

Цикл позволяет монтировать том поверх «себя», поток сценариев по умолчанию делает a, mount /dev/sdb1 /rootмы просто необязательно перемонтируем / dev / sdb1 как rw, если это был ro, тогда всегда добавляем 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

Также необходимо предварительно загрузить модуль в initram (тогда не забудьте запустить update-initramfs)

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

Не знаю, насколько использование циклов влияет на производительность или тратит ресурсы, мне интересно, если монтирование ext4 поверх ext4 удваивает вероятность сбоя файловой системы, но думаю, что некоторые настройки могут быть сделаны. Может быть, есть лучший способ использовать цикл, менее хакерский, если есть, пожалуйста, дайте мне знать, потому что я не нашел.

Alex
источник
0

Это не ответ, но я хочу уточнить некоторые моменты относительно ответа и комментариев Ульриха (я не могу комментировать выше).

Решение, которое предлагает Ульрих, «может» работать (пока не проверено), но тогда вы получите неустранимую файловую систему . В качестве обходного пути (IMHO некрасиво) вы можете смонтировать fs как rw перед chroot ( как предлагается здесь ), но будьте осторожны с неработающими скриптами инициализации. Я предполагаю, что у этого обходного пути есть больше побочных эффектов (как сломанный fs, пытающийся перемонтировать ro и терпящий неудачу).

Я использую ядро ​​3.2 с ext4, а монтирование уже смонтированного dev внутри chroot все еще дает EBUSY, как прокомментировал psusi.

Alex
источник