Uruchomić system Linux z podkatalogu na partycji?

11

Chciałbym spróbować skonfigurować komputer tak, aby miał wiele instalacji Linuksa w tym samym systemie plików. Na przykład, systemem plików będzie mieć 3 foldery: /Ubuntu_Precise, /Ubuntu_Oneiric, i /Ubuntu_Natty.

(Wiem, że możesz to zrobić za pomocą BTRFS i podwoluminów, ale chciałbym użyć EXT4 dla szybkości).

Kiedyś konfigurowałem wiele instalacji różnych dystrybucji za pomocą BTRFS, a po uruchomieniu tego wiem, że Grub dobrze sobie radzi z uruchamianiem vmlinuz i obrazu initrd ze „niestandardowych” ścieżek. Ale kiedy robiłem BTRFS, było takie, rootflags=subvol=@<subvolume_name>które mówiło kernelowi, aby zamontowało to podobjętość jako / w systemie plików. Czy jest jakiś argument, że można przekazać jądro, które zmusi go do wiązania, zamontowania podfolderu na partycji jako / a następnie rozruchu?

Myślę o pozostałych częściach, jestem dość blisko. Wiem, jak sprecyzować mocowanie bind /etc/fstab. Ponadto, od kiedy skonfigurowałem mój system z wieloma instalacjami linuksowymi w podwoluminach BTRFS, jestem przyzwyczajony do instalowania dystrybucji na maszynie wirtualnej, a następnie migrowania jej za pomocą rsync, więc nie martwię się zbytnio o to, co musiałbym zrobić, aby uzyskać odpowiednią konfigurację, próbuję tylko dowiedzieć się, jaka byłaby właściwa konfiguracja. Gdy się dowiem, powinienem móc dość łatwo przeprowadzić migrację do podfolderów i edytować pliki.

Wiem już o wirtualizacji i partycjach, ale nie tego szukam. Komputer docelowy nie ma wystarczającej mocy do wirtualizacji, a partycje nie współużytkują wolnego miejsca. Chcę skonfigurować system, w którym dual / triple / quad / etc uruchamia dystrybucje linuksowe, ale robi to z jednym systemem plików, więc nie ma przypadku „Mam wolne miejsce, ale jest na niewłaściwej partycji!”

Jeśli ktoś ma sugestie, jak edytować moje pytanie lub jego tytuł, aby było jaśniej, jestem cały w uszach.

Azendale
źródło
1
W systemie nie ma nic AFAIK. To, co prawdopodobnie będziesz musiał zrobić, to dodać kolejny parametr rozruchowy i zmodyfikować initramfs, aby chrootował się do podkatalogu przed uruchomieniem init
Ulrich Dangel
@UlrichDangel to właśnie zamierzałem zaproponować. Zrób to!
Nils
@Nils ok, właśnie dostałem odpowiedź, tbh. nie chciałem na początku pisać, ponieważ nie chciałem dostarczać łatki / skryptu
Ulrich Dangel

Odpowiedzi:

10

Krótka odpowiedź - o ile mi wiadomo, nie ma gotowego do pracy rozwiązania dla konkretnych wymagań. Będziesz musiał dostosować każdy initramfs każdej dystrybucji, aby zaspokoić swoje specyficzne potrzeby.

Długa odpowiedź - tak, jest to możliwe. Obecnie większość dystrybucji Linuksa używa initramfs, które zostaną załadowane do pamięci przez bootloader, a następnie rozpakowane przez jądro. Tam będzie działał, /sbin/initktóry jest odpowiedzialny za skonfigurowanie wczesnej przestrzeni użytkownika (uruchamianie udev, ładowanie modułów, uruchamianie Plymouth, proszenie o hasło kryptograficzne, konfigurowanie sieci do montowania w sieci,… tak to nazywacie). Ponieważ możesz uruchamiać własne skrypty i oceniać niestandardowe programy rozruchowe.

Przykład dla Debiana

Jeśli używasz Debiana (powinien być taki sam z Ubuntu), powinieneś być w stanie umieścić skrypt, w /etc/initramfs-tools/scripts/init-bottom/którym zostanie wykonany przed uruchomieniem init. Aby uzyskać więcej informacji o skrypcie, różne katalogi i układ znajdują się w man initramfs-tools . Będziesz musiał dostosować rootmnti dodać katalog docelowy.

Przykładowy (nieprzetestowany) skrypt, który powinien zostać zainstalowany jako /etc/initramfs-tools/scripts/local-bottom/00-myrootlub /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

Chodzi o to, aby dostosować, rootmnt który jest używany w initskrypcie initramfs do uruchamiania / wykonywania prawdziwego init. Ponieważ urządzenie root jest już zamontowane na init-bootometapie, możesz po prostu dostosować / zmienić katalog docelowy.

Aby użyć tego skryptu, po prostu dodaj nowy parametr rozruchowy, skopiuj skrypt, uczyń go wykonywalnym, zregeneruj initramfs i dodaj parametr rozruchowy do dystrybucji Linuksa, np rootdir=/Ubuntu_Precise.

Ulrich Dangel
źródło
Prawdopodobnie chcesz również powiązać zamontowanie prawdziwego katalogu głównego w podkatalogu root systemu operacyjnego, abyś mógł zobaczyć inne pliki systemu operacyjnego z tego, który uruchamiasz.
psusi
@psusi Możesz to zrobić za pomocą fstab lub bezpośrednio mount /dev/rootdevice /mountpointpo uruchomieniu systemu
Ulrich Dangel
Zastanawiam się, kiedy to się zmieniło? Kiedyś nie mogłeś ponownie zamontować tego samego urządzenia blokowego; dostałbyś EBUSY.
psusi
1
@psusi nie jestem pewien, ale prawdopodobnie wraz z wprowadzeniem opraw wierzchnich
Ulrich Dangel
@UlrichDangel Dzięki za (bardzo) szczegółową odpowiedź!
Azendale
3

Oto dwa sposoby, które działają w Ubuntu Bionic (i ewentualnie gdzie indziej). nie mam wystarczającej liczby komentarzy do skomentowania, ale bionic: / usr / share / initramfs-tools / init szuka / etc / fstab dla / usr zaraz po wywołaniu mountroot i przed wywołaniem skryptów * -bottom, więc dodanie init- dolny skrypt (jak zasugerowano w innej odpowiedzi tutaj) jest „za późno”. zamiast tego polecam te:

#!/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
gregrwm
źródło
To zadziałało dla mnie
paultop6
1

Uruchamianie różnych Linuksa bez bałaganu przy użyciu tablicy partycji jest interesujące do różnych celów, alternatywnym rozwiązaniem dla współdzielonego systemu plików jest użycie woluminów pętli, tutaj kilka potrzebnych zmian, zakładając, że masz plik / wolumin pętli / debian w systemie plików / dev / sdb1 (Używam obecnego GNU / Debiana sid / unstable zarówno dla systemu głównego, jak i pętli).

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

Argumenty zdefiniowane w grub jako linia poleceń Linuxa są ustawione na env przez initrd / init, więc:

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

pętla pozwala zamontować wolumin nad „samym sobą”, domyślny przepływ skryptu wykonujemy po mount /dev/sdb1 /rootprostu opcjonalnie ponownie montujemy / dev / sdb1 jako rw, jeśli był to ro, to zawsze dołączamy 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

Musisz również wstępnie załadować moduł do initram (nie zapomnij uruchomić update-initramfs)

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

Nie wiem, ile przy użyciu wydajności pętli wpływa na marnowanie zasobów, zastanawiam się, czy zamontowanie ext4 na ext4 podwaja prawdopodobieństwo awarii systemu plików, ale zgaduję, że można by to zrobić. Może jest lepszy sposób na użycie pętli, mniej hackerski, jeśli istnieje, proszę dać mi znać, ponieważ nie znalazłem.

Alex
źródło
0

To nie jest odpowiedź, ale chcę wyjaśnić pewną kwestię dotyczącą odpowiedzi i komentarzy Ulricha (nie mogę komentować powyżej).

Rozwiązanie Ulrich proponuje „może” działać (jeszcze nie przetestowane), ale wtedy otrzymasz system plików, którego nie można ponownie wymontować . Jako obejście (brzydkie IMHO) możesz zamontować fs jako rw przed chrootowaniem ( jak sugerowano tutaj ), ale uważaj na zepsute skrypty init. Wydaje mi się, że to obejście ma więcej skutków ubocznych (np. Zepsuty fs próbujący ponownie zamontować ro i zawodzić).

Używam jądra 3.2 z ext4 i montowanie już zamontowanego dev wewnątrz chroota nadal daje EBUSY, jak psusi komentuje.

Alex
źródło