Khởi động hệ thống Linux từ thư mục con trên phân vùng?


11

Tôi muốn thử thiết lập một máy tính để nó có nhiều cài đặt Linux tất cả trong cùng một hệ thống tập tin. Ví dụ, hệ thống file sẽ có 3 thư mục: /Ubuntu_Precise, /Ubuntu_Oneiric, và /Ubuntu_Natty.

(Tôi biết bạn có thể làm điều này với BTRFS và subvolume, nhưng tôi muốn sử dụng EXT4 cho tốc độ).

Tôi đã từng thiết lập nhiều bản cài đặt của các bản phân phối khác nhau bằng BTRFS và từ khi nó hoạt động, tôi biết Grub chỉ hoạt động tốt với việc khởi động vmlinuz và hình ảnh initrd từ các đường dẫn 'không chuẩn'. Nhưng khi tôi đang thực hiện điều BTRFS, có một nhân đã rootflags=subvol=@<subvolume_name>nói với kernel gắn kết subvolume đó như / trong hệ thống tập tin. Có bất kỳ đối số nào mà bạn có thể vượt qua kernel sẽ khiến nó liên kết gắn kết một thư mục con trong một phân vùng là / và sau đó khởi động không?

Tôi nghĩ cho các phần khác, tôi khá gần gũi. Tôi biết làm thế nào để cụ thể gắn kết gắn kết trong /etc/fstab. Ngoài ra, từ khi tôi thiết lập hệ thống của mình với nhiều bản cài đặt linux trong các bản con BTRFS, tôi đã quen với việc cài đặt một bản phân phối trong máy ảo và sau đó di chuyển nó bằng rsync, vì vậy tôi không quá lo lắng về những gì tôi cần làm có được cấu hình phù hợp, tôi chỉ đang cố gắng tìm hiểu cấu hình phù hợp. Khi tôi biết điều đó, tôi sẽ có thể thực hiện di chuyển vào các thư mục con và chỉnh sửa tệp đủ dễ dàng.

Tôi đã biết về ảo hóa và phân vùng, nhưng đó không phải là thứ tôi đang tìm kiếm. Máy tính mục tiêu không có đủ năng lượng để thực hiện ảo hóa và các phân vùng không chia sẻ không gian trống. Tôi đang tìm cách thiết lập một hệ thống khởi động các bản phân phối linux / triple / quad / etc, nhưng nó hoạt động với một hệ thống tập tin, do đó không có trường hợp nào "Tôi có không gian trống, nhưng nó nằm trong phân vùng sai! '

Nếu bất cứ ai có đề xuất làm thế nào để chỉnh sửa câu hỏi của tôi hoặc tiêu đề của nó để rõ ràng hơn, tôi đều nghe thấy.


1
Có AFAIK không có gì xây dựng vào hệ thống. Những gì bạn có thể phải làm là thêm một tham số khởi động khác và sửa đổi initramfs của bạn để chroot vào thư mục con trước khi thực hiện init
Ulrich Dangel

@UlrichDangel đó là những gì tôi sẽ đề xuất. Làm cho nó một câu trả lời!
Nils

@Nils ok tôi chỉ cung cấp một câu trả lời, tbh. ban đầu tôi không muốn viết một bản vì tôi không muốn cung cấp bản vá / kịch bản
Ulrich Dangel

Câu trả lời:


10

Câu trả lời ngắn gọn - theo như tôi biết không có giải pháp làm việc nào phù hợp với yêu cầu cụ thể của bạn. Bạn sẽ phải điều chỉnh từng initramfs của mỗi bản phân phối để hỗ trợ các nhu cầu cụ thể của bạn.

Câu trả lời dài - có nó là có thể. Ngày nay, hầu hết các bản phân phối Linux sử dụng một initramfs sẽ được bộ nạp khởi động tải vào bộ nhớ và sau đó được giải nén bởi kernel. Ở đó, nó sẽ chạy /sbin/init, chịu trách nhiệm thiết lập không gian người dùng sớm (chạy udev, tải các mô-đun, bắt đầu plymouth, yêu cầu mật khẩu mật mã, thiết lập mạng để gắn kết mạng, bạn đặt tên cho nó). Như bạn có thể chạy các tập lệnh của riêng bạn và đánh giá các parmaters khởi động tùy chỉnh.

Ví dụ cho Debian

Nếu bạn đang sử dụng Debian (nên giống với Ubuntu), bạn sẽ có thể đặt một tập lệnh /etc/initramfs-tools/scripts/init-bottom/sẽ được thực thi trước khi init được khởi động. Để biết thêm thông tin về tập lệnh, các thư mục khác nhau và bố cục hãy xem man initramfs-tools . Bạn sẽ phải điều chỉnh rootmntvà thêm thư mục đích.

Kịch bản mẫu (chưa được kiểm tra) nên được cài đặt là /etc/initramfs-tools/scripts/local-bottom/00-myroothoặc /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

Ý tưởng là điều chỉnh rootmnt cái được sử dụng trong inittập lệnh initramfs để bắt đầu / thực thi init thực sự. Vì thiết bị gốc đã được gắn trong init-bootomgiai đoạn, bạn chỉ có thể điều chỉnh / thay đổi thư mục đích.

Để sử dụng tập lệnh này, chỉ cần thêm một tham số khởi động mới, sao chép tập lệnh, làm cho nó có thể thực thi được, tạo lại initramfs của bạn và thêm một tham số khởi động cho bản phân phối Linux của bạn, vd rootdir=/Ubuntu_Precise.


Bạn cũng có thể muốn liên kết gắn root thực sự vào một thư mục con của gốc os để bạn có thể xem các tệp HĐH khác từ tệp bạn khởi động.
psusi

@psusi Bạn có thể thực hiện việc này qua fstab hoặc chỉ cần thực hiện trực tiếp mount /dev/rootdevice /mountpointsau khi hệ thống đang chạy
Ulrich Dangel

Tôi tự hỏi khi điều đó thay đổi? Bạn đã từng không thể gắn kết cùng một thiết bị khối; bạn sẽ nhận được một EBUSY.
psusi

1
@psusi không chắc chắn nhưng có lẽ với sự ra đời của mount mount
Ulrich Dangel

@UlrichDangel Cảm ơn câu trả lời (rất) chi tiết!
Azendale

2

Đây là hai cách hoạt động trong Ubuntu bionic (và có thể ở nơi khác). Tôi không đủ đại diện để bình luận, nhưng, bionic: / usr / share / initramfs-tools / init trông trong / etc / fstab cho / usr ngay sau khi gọi mountroot và trước khi gọi các tập lệnh * -bottom, vì vậy hãy thêm init- kịch bản dưới cùng (như được đề xuất trong một câu trả lời khác ở đây) là "quá muộn". thay vào đó tôi đề nghị những điều này:

#!/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

Điều này làm việc một điều trị cho tôi
paultop6

1

Khởi động linux khác nhau mà không làm phiền bảng phân vùng là điều thú vị cho các mục đích khác nhau, một giải pháp thay thế cho hệ thống tệp được chia sẻ là sử dụng khối lượng vòng lặp, ở đây có một số thay đổi cần thiết, giả sử bạn có tệp / vòng lặp debian vào hệ thống tệp / dev / sdb1 (Tôi đang sử dụng sid / GNU / Debian hiện tại không ổn định cho cả hệ điều hành chính và vòng lặp).

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

Các đối số được xác định thành grub là dòng lệnh linux được đặt thành env bởi initrd / init, vì vậy:

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

vòng lặp cho phép gắn kết âm lượng trên "chính nó", luồng tập lệnh mặc định thực hiện một mount /dev/sdb1 /rootcách tùy chọn chúng tôi chỉ nhắc lại / dev / sdb1 là rw nếu nó là ro thì luôn luôn nối 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

Cũng cần tải trước một số mô-đun vào initram (sau đó đừng quên chạy update-initramfs)

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

Không biết bao nhiêu việc sử dụng hiệu suất vòng lặp hoặc lãng phí tài nguyên, tôi tự hỏi liệu việc gắn ext4 trên ext4 có làm tăng gấp đôi xác suất của lỗi hệ thống tập tin hay không, nhưng đoán một số điều chỉnh có thể được thực hiện. Có lẽ có một cách tốt hơn để sử dụng vòng lặp, ít hack hơn, nếu có xin vui lòng cho tôi biết vì tôi chưa tìm thấy.


0

Đây không phải là một câu trả lời nhưng tôi muốn làm rõ một số điểm về câu trả lời và nhận xét của Ulrich (tôi không thể bình luận ở trên).

Giải pháp Ulrich đề xuất "có thể" hoạt động (chưa được kiểm tra) nhưng sau đó bạn sẽ nhận được một hệ thống tập tin không thể đếm được . Như một cách giải quyết (IMHO xấu xí), bạn có thể gắn kết fs dưới dạng rw trước khi chroot ( như được đề xuất ở đây ) nhưng hãy cẩn thận về các tập lệnh init bị hỏng. Tôi đoán cách giải quyết này có nhiều tác dụng phụ hơn (như fs bị hỏng khi cố gắng vượt qua ro và thất bại).

Tôi đang sử dụng kernel 3.2 với ext4 và gắn một dev đã được gắn vào bên trong chroot vẫn cho EBUSY như psusi nhận xét.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.