Boot sistem Linux dari subdirektori pada partisi?

11

Saya ingin mencoba membuat komputer sehingga memiliki banyak instalasi Linux semua dalam sistem file yang sama. Misalnya, filesytem akan memiliki 3 folder: /Ubuntu_Precise, /Ubuntu_Oneiric, dan /Ubuntu_Natty.

(Saya tahu Anda bisa melakukan ini dengan BTRFS dan subvolume, tapi saya ingin menggunakan EXT4 untuk kecepatan).

Saya pernah mengatur beberapa instalasi dari distro yang berbeda menggunakan BTRFS, dan dari mulai bekerja, saya tahu Grub tidak apa-apa dengan mem-boot vmlinuz dan gambar initrd dari jalur 'tidak standar'. Tetapi ketika saya melakukan hal BTRFS, ada rootflags=subvol=@<subvolume_name>yang memerintahkan kernel untuk me-mount subvolume itu sebagai / di sistem file. Apakah ada argumen bahwa Anda dapat melewati kernel yang akan membuatnya mengikat mount subfolder di partisi sebagai / dan kemudian boot?

Saya pikir untuk bagian lain, saya cukup dekat. Saya tahu bagaimana cara spesifik untuk mengikat mount /etc/fstab. Juga, sejak saya mengatur sistem saya dengan beberapa instal linux di subvolume BTRFS, saya terbiasa menginstal distro di VM dan kemudian memigrasikannya menggunakan rsync, jadi saya tidak terlalu khawatir tentang apa yang perlu saya lakukan untuk dapatkan konfigurasi yang tepat, saya hanya mencoba mencari tahu konfigurasi yang tepat. Setelah saya tahu itu, saya harus dapat melakukan migrasi ke subfolder dan mengedit file dengan cukup mudah.

Saya sudah tahu tentang virtualisasi dan partisi, tapi bukan itu yang saya cari. Komputer target tidak memiliki kekuatan yang cukup untuk melakukan virtualisasi, dan partisi tidak berbagi ruang kosong. Saya mencari untuk membuat sistem yang dual / triple / quad / etc mem-boot distro linux, tetapi itu melakukannya dengan satu filesystem, sehingga tidak ada kasus "Saya punya ruang kosong, tapi ada di partisi yang salah!"

Jika ada yang punya saran bagaimana mengedit pertanyaan saya atau judulnya menjadi lebih jelas, saya mendengar semuanya.

Azendale
sumber
1
Tidak ada yang AFAIK membangun ke dalam sistem. Apa yang mungkin harus Anda lakukan adalah menambahkan bootparameter lain dan memodifikasi initramfs Anda ke chroot ke subdirektori sebelum mengeksekusi init
Ulrich Dangel
@UlrichDangel itulah yang akan saya usulkan. Buat jawaban!
Nils
@Nils ok saya baru saja memberikan jawaban, tbh. saya tidak ingin menulis satu pada awalnya karena saya tidak ingin memberikan tambalan / skrip
Ulrich Dangel

Jawaban:

10

Jawaban singkat - sejauh yang saya tahu tidak ada solusi yang sesuai untuk kebutuhan spesifik Anda. Anda harus menyesuaikan setiap initramf dari setiap distribusi untuk mendukung kebutuhan spesifik Anda.

Jawaban panjang - ya itu mungkin. Saat ini sebagian besar distribusi Linux menggunakan initramfs yang akan dimuat ke dalam memori oleh bootloader dan kemudian dibongkar oleh kernel. Di sana ia akan menjalankan /sbin/inityang bertanggung jawab untuk mengatur ruang pengguna awal (menjalankan udev, memuat modul, mulai plymouth, meminta frasa sandi crypto, mengatur jaringan untuk pemasangan jaringan, ... sebut saja). Karena Anda dapat menjalankan skrip Anda sendiri dan mengevaluasi parmater boot khusus.

Contoh untuk Debian

Jika Anda menggunakan Debian (harus sama dengan Ubuntu), Anda harus dapat menempatkan skrip /etc/initramfs-tools/scripts/init-bottom/yang akan dijalankan sebelum init dimulai. Untuk informasi lebih lanjut tentang skrip, direktori dan tata letak yang berbeda melihat-lihat man-initramfs-tools . Anda harus menyesuaikan rootmntdan menambahkan direktori target.

Contoh skrip (belum diuji) yang harus diinstal sebagai /etc/initramfs-tools/scripts/local-bottom/00-myrootatau /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

Idenya adalah untuk menyesuaikan rootmnt yang digunakan dalam initskrip initramfs untuk memulai / mengeksekusi init nyata. Karena perangkat root sudah terpasang di init-bootompanggung Anda hanya dapat menyesuaikan / mengubah direktori target.

Untuk menggunakan skrip ini, cukup tambahkan parameter boot baru, salin skrip, buat skrip tersebut dapat dieksekusi, buat ulang initramfs Anda dan tambahkan parameter boot untuk distribusi Linux Anda, mis rootdir=/Ubuntu_Precise.

Ulrich Dangel
sumber
Anda juga mungkin ingin mengikat mount root yang sebenarnya ke subdir dari os root sehingga Anda dapat melihat file OS lain dari yang Anda boot.
psusi
@psusi Anda dapat melakukan ini melalui fstab atau langsung dilakukan mount /dev/rootdevice /mountpointsetelah sistem berjalan
Ulrich Dangel
Saya bertanya-tanya kapan itu berubah? Anda dulu tidak dapat memasang perangkat blok yang sama lagi; Anda akan mendapatkan EBUSY.
psusi
1
@psusi tidak yakin tetapi mungkin dengan pengenalan bind mounts
Ulrich Dangel
@UlrichDangel Terima kasih atas jawaban terinci (sangat)!
Azendale
2

Berikut adalah dua cara yang berfungsi di ubuntu bionic (dan mungkin di tempat lain). Saya belum cukup rep untuk berkomentar, tetapi, bionik: / usr / share / initramfs-tools / init terlihat di / etc / fstab untuk / usr segera setelah memanggil mountroot dan sebelum memanggil skrip * -bottom, jadi tambahkan init- skrip bawah (seperti yang disarankan dalam jawaban lain di sini) "terlambat". sebagai gantinya saya merekomendasikan ini:

#!/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
sumber
Ini berhasil buat saya
paultop6
1

Boot linux yang berbeda tanpa mengacaukan tabel partisi menarik untuk tujuan yang berbeda, solusi alternatif untuk sistem file bersama adalah dengan menggunakan volume loop, di sini beberapa perubahan yang diperlukan seandainya Anda memiliki file / volume loop debian / volume ke sistem file / dev / sdb1 (Saya menggunakan GNU / Debian sid / saat ini tidak stabil untuk os utama dan loop).

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

Argumen yang didefinisikan ke grub sebagai baris perintah linux diatur ke env oleh initrd / init, jadi:

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

loop memungkinkan untuk me-mount volume lebih dari "itu sendiri", aliran skrip default melakukan mount /dev/sdb1 /rootkita hanya opsional remount / dev / sdb1 sebagai rw jika itu ro maka selalu tambahkan 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

Perlu juga untuk memuat beberapa modul ke dalam initram (maka jangan lupa untuk menjalankan pembaruan-initramfs)

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

Tidak tahu berapa banyak menggunakan kinerja pengaruh loop atau sumber daya limbah, saya bertanya-tanya apakah me-mount ext4 lebih dari ext4 menggandakan probabilitas kegagalan sistem file, tetapi kira beberapa penyesuaian dapat dilakukan. Mungkin ada cara yang lebih baik untuk menggunakan loop, lebih sedikit peretasan, jika ada tolong beri tahu saya karena saya belum menemukan.

Alex
sumber
0

Ini bukan jawaban tetapi saya ingin mengklarifikasi beberapa hal tentang jawaban dan komentar Ulrich (saya tidak bisa berkomentar di atas).

Solusi yang diusulkan Ulrich "mungkin" berfungsi (belum diuji) tetapi kemudian Anda akan mendapatkan sistem file yang tidak dapat di-remount . Sebagai solusinya (IMHO jelek) Anda dapat me-mount fs sebagai rw sebelum chroot ( seperti yang disarankan di sini ) tetapi hati-hati tentang skrip init yang rusak. Saya kira solusi ini memiliki lebih banyak efek samping (seperti rusak fs mencoba remount ro dan gagal).

Saya menggunakan kernel 3.2 dengan ext4 dan pemasangan dev yang sudah terpasang di dalam chroot masih memberikan EBUSY sebagai komentar psusi.

Alex
sumber