ระบบ Boot Linux จากไดเรกทอรีย่อยในพาร์ทิชันหรือไม่?


11

ฉันต้องการลองติดตั้งคอมพิวเตอร์เพื่อให้สามารถติดตั้ง Linux ได้หลายตัวในระบบไฟล์เดียวกัน ยกตัวอย่างเช่น filesytem จะมี 3 โฟลเดอร์/Ubuntu_Precise, และ/Ubuntu_Oneiric/Ubuntu_Natty

(ฉันรู้ว่าคุณสามารถทำได้ด้วย BTRFS และ subvolumes แต่ฉันต้องการใช้ความเร็ว EXT4)

ฉันเคยตั้งค่าการติดตั้ง distros ที่แตกต่างกันหลายครั้งโดยใช้ BTRFS และจากการทำงานนั้นฉันรู้ว่า Grub ทำได้ดีด้วยการบูท vmlinuz และอิมเมจเริ่มต้นจากเส้นทาง 'ที่ไม่เป็นมาตรฐาน' แต่เมื่อฉันทำสิ่ง BTRFS มีสิ่งrootflags=subvol=@<subvolume_name>ที่บอกเคอร์เนลที่จะติดตั้ง subvolume นั้นเป็น / ในระบบไฟล์ มีข้อโต้แย้งใด ๆ ที่คุณสามารถส่งผ่านเคอร์เนลที่จะทำให้มันผูกติดโฟลเดอร์ย่อยในพาร์ทิชันเป็น / แล้วบูต?

ฉันคิดว่าในส่วนอื่น ๆ ฉันค่อนข้างใกล้ชิด /etc/fstabฉันรู้วิธีการเฉพาะการผูกติดใน นอกจากนี้จากเมื่อฉันตั้งค่าระบบของฉันด้วยการติดตั้ง linux หลายรายการใน BTRFS subvolumes ฉันใช้ในการติดตั้ง distro ใน VM แล้วย้ายมันโดยใช้ rsync ดังนั้นฉันจึงไม่กังวลเกี่ยวกับสิ่งที่ฉันต้องทำ รับการกำหนดค่าที่ถูกต้องฉันแค่พยายามค้นหาว่าการกำหนดค่าที่เหมาะสมจะเป็นอย่างไร เมื่อฉันรู้ว่าฉันควรจะสามารถย้ายข้อมูลไปยังโฟลเดอร์ย่อยและแก้ไขไฟล์ได้อย่างง่ายดาย

ฉันรู้แล้วเกี่ยวกับการจำลองเสมือนและพาร์ติชัน แต่นั่นไม่ใช่สิ่งที่ฉันกำลังมองหา คอมพิวเตอร์เป้าหมายไม่มีพลังงานเพียงพอในการทำ virtualization และพาร์ติชันไม่แบ่งพื้นที่ว่าง ฉันกำลังมองหาการตั้งค่าระบบที่บูทคู่ / สาม / สี่ / etc ลินุกซ์ distros แต่มันทำกับระบบไฟล์เดียวดังนั้นจึงไม่มีกรณีของ "ฉันมีพื้นที่ว่าง แต่มันอยู่ในพาร์ทิชันผิด! '

หากใครมีคำแนะนำวิธีแก้ไขคำถามหรือชื่อของฉันให้ชัดเจนฉันก็ยินดี


1
AFAIK ไม่มีสิ่งใดที่สร้างไว้ในระบบ สิ่งที่คุณอาจต้องทำคือการเพิ่มพารามิเตอร์อื่นและปรับค่าเริ่มต้นของคุณให้เป็น chroot ในไดเรกทอรีย่อยก่อนที่จะดำเนินการ init
Ulrich Dangel

@ UlrichDangel นั่นคือสิ่งที่ฉันจะเสนอ ทำให้เป็นคำตอบ!
นิลส์

@ ไม่เป็นไรฉันแค่ให้คำตอบ tbh ฉันไม่ได้ต้องการที่จะเขียนอย่างใดอย่างหนึ่งที่เป็นครั้งแรกที่ฉันไม่ได้ต้องการที่จะให้แพทช์ / script
Ulrich Dangel

คำตอบ:


10

คำตอบสั้น ๆ - มีเท่าที่ฉันรู้ว่าไม่มีทางออกการทำงานสำหรับความต้องการเฉพาะของคุณ คุณจะต้องปรับค่าเริ่มต้นแต่ละค่าของการแจกแจงเพื่อรองรับความต้องการเฉพาะของคุณ

คำตอบยาว - ใช่มันเป็นไปได้ ทุกวันนี้ลีนุกซ์ลีนุกซ์ส่วนมากใช้ initramfs ซึ่งจะโหลดลงในหน่วยความจำโดย bootloader จากนั้นคลายโดยเคอร์เนล ที่นั่นมันจะทำงาน/sbin/initซึ่งรับผิดชอบการตั้งค่า userspace เริ่มต้น (ใช้ udev, การโหลดโมดูล, เริ่ม plymouth, ขอรหัสผ่าน crypto, ตั้งค่าเครือข่ายสำหรับการติดตั้งเครือข่าย, ... คุณชื่อมัน) ในขณะที่คุณสามารถเรียกใช้สคริปต์ของคุณเองและประเมิน parmaters บูตที่กำหนดเอง

ตัวอย่าง Debian

หากคุณใช้ Debian (ควรเหมือนกันกับ Ubuntu) คุณควรวางสคริปต์/etc/initramfs-tools/scripts/init-bottom/ที่จะถูกเรียกใช้งานก่อนที่ init จะเริ่มต้น สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสคริปต์ไดเรกทอรีที่แตกต่างกันและรูปแบบมีลักษณะที่คน initramfs คุณจะต้องปรับ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 rootdir=/Ubuntu_Preciseของคุณและเพิ่มพารามิเตอร์บูตสำหรับการกระจายลินุกซ์ของคุณเช่น


คุณอาจต้องการผูกเมาท์รูทจริงลงในส่วนย่อยของรูทระบบปฏิบัติการเพื่อให้คุณสามารถดูไฟล์ระบบปฏิบัติการอื่น ๆ จากไฟล์ที่คุณบู๊ต
psusi

@psusi คุณสามารถทำได้ผ่าน fstab หรือเพียงแค่ทำmount /dev/rootdevice /mountpointหลังจากที่ระบบกำลังทำงานอยู่
Ulrich Dangel

ฉันสงสัยว่าเปลี่ยนไปเมื่อใด คุณเคยไม่สามารถเมานต์อุปกรณ์บล็อกเดียวกันได้อีก คุณจะได้รับ EBUSY
psusi

1
@psusi ไม่แน่ใจ แต่อาจมีการเปิดตัว bind mounts
Ulrich Dangel

@ UlrichDangel ขอบคุณสำหรับคำตอบที่ละเอียดมาก
Azendale

3

ต่อไปนี้เป็นสองวิธีที่ใช้งานได้ใน Ubuntu bionic (และที่อื่น ๆ ) ฉันมีตัวแทนไม่เพียงพอที่จะแสดงความคิดเห็น แต่ bionic: / usr / share / initramfs-tools / init ดูใน / etc / fstab สำหรับ / usr ทันทีหลังจากเรียก Mountroot และก่อนที่จะเรียกสคริปต์ * -bottom ดังนั้นการเพิ่ม 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, might need tweaking to work elsewhere
#1st choice:  tweak initramfs-tools/scripts/local
#   pro:  $sub becomes root directly, nothing gets any chance to see the partition root
#   con:  requires the subdirectory's initramfs/initrd to be tweaked and rebuilt
#2nd choice:  specify this scriptfile as init= on the kernel commandline
#   pro:  no need to rebuild initramfs
#   con:  requires bin/bash in the partition root executable by $sub/vmlinux (ie $sub same or newer than partition root)
#   con:  if the partition root etc/fstab mounts /usr, the $sub initramfs will mount the partition root /usr
#   con:  additional initramfs scripts might also look in the partition root rather than $sub

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

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

#for the 1st choice, 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 watch)
#             fi
#          mountroot_status="$?"
#          [ $mountroot_status = 0 ]||sleep 90                                          #if error pause to see it
#          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 initrd/initramfs installed thereafter

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 (eg 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

สิ่งนี้ใช้ได้กับฉัน
paultop6

1

การบูทลินุกซ์ที่แตกต่างกันโดยไม่ต้องยุ่งกับตารางพาร์ติชั่นนั้นน่าสนใจสำหรับวัตถุประสงค์ที่ต่างกัน, ทางเลือกอื่นสำหรับระบบไฟล์ที่ใช้ร่วมกันคือการใช้ลูปวอลุ่ม, นี่คือการเปลี่ยนแปลงเล็กน้อยที่จำเป็นหากคุณมีไฟล์ (ฉันใช้ GNU / Debian sid ปัจจุบัน / ไม่เสถียรสำหรับทั้ง main และ loop os)

/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 

ห่วงอนุญาตให้มีการติดตั้งไดรฟ์มากกว่า "ตัวเอง" การไหลสคริปต์เริ่มต้นทำmount /dev/sdb1 /rootเราก็เลือกที่จะ remount / dev / sdb1 เป็น RW ถ้ามันเป็น RO 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 จะเพิ่มความน่าจะเป็นของความล้มเหลวของระบบไฟล์เป็นสองเท่าหรือไม่ อาจจะมีวิธีที่ดีกว่าในการใช้ลูปการแฮ็กน้อยถ้ามีโปรดแจ้งให้เราทราบเพราะฉันไม่พบ


0

นี่ไม่ใช่คำตอบ แต่ฉันต้องการชี้แจงบางอย่างเกี่ยวกับคำตอบและความคิดเห็นของ Ulrich (ฉันไม่สามารถออกความคิดเห็นด้านบน)

วิธีแก้ปัญหา Ulrich เสนอ "อาจ" ทำงาน (ยังไม่ทดลอง) แต่คุณจะได้รับระบบไฟล์ที่ไม่สามารถเล่าซ้ำได้ ในฐานะที่เป็นวิธีแก้ปัญหา (IMHO น่าเกลียด) คุณสามารถติด fs เป็น rw ก่อนที่จะ chrooting ( ตามที่แนะนำที่นี่ ) แต่ระวังเกี่ยวกับสคริปต์ init ที่แตก ฉันเดาวิธีแก้ปัญหานี้มีผลข้างเคียงมากขึ้น (เช่น fs ที่เสียหายพยายามที่จะนับใหม่และล้มเหลว)

ฉันใช้เคอร์เนล 3.2 กับ ext4 และติดตั้ง dev ที่ติดตั้งแล้วภายใน chroot ยังคงให้ EBUSY ตามที่ psusi แสดงความคิดเห็น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.