Avvio del sistema Linux da una sottodirectory su una partizione?


11

Vorrei provare a configurare un computer in modo che abbia più installazioni Linux tutte nello stesso filesystem. Ad esempio, il filesystem avrebbe 3 cartelle: /Ubuntu_Precise, /Ubuntu_Oneiric, e /Ubuntu_Natty.

(So ​​che puoi farlo con BTRFS e sottovolumi, ma vorrei usare EXT4 per la velocità).

Una volta ho impostato più installazioni di diverse distribuzioni utilizzando BTRFS e, dal farlo funzionare, so che Grub funziona bene avviando l'immagine vmlinuz e initrd da percorsi 'non standard'. Ma quando stavo facendo la cosa BTRFS, c'era quello rootflags=subvol=@<subvolume_name>che diceva al kernel di montare quel sottovolume come / nel filesystem. C'è qualche argomento sul fatto che potresti passare il kernel che lo farebbe legare montare una sottocartella in una partizione come / e quindi avviare?

Penso per le altre parti, sono abbastanza vicino. So come specificare un mount bind /etc/fstab. Inoltre, da quando ho impostato il mio sistema con più installazioni di Linux in sottovolumi BTRFS, sono abituato a installare una distribuzione in una VM e quindi a migrarla usando rsync, quindi non sono troppo preoccupato di cosa avrei bisogno di fare per ottenere la giusta configurazione, sto solo cercando di scoprire quale sarebbe la giusta configurazione. Una volta che lo so, dovrei essere in grado di eseguire la migrazione nelle sottocartelle e la modifica dei file abbastanza facilmente.

Conosco già la virtualizzazione e le partizioni, ma non è quello che sto cercando. Il computer di destinazione non ha energia sufficiente per eseguire la virtualizzazione e le partizioni non condividono spazio libero. Sto cercando di impostare un sistema che dual / triple / quad / etc avvii le distribuzioni di Linux, ma che lo faccia con un filesystem, in modo che non ci sia il caso di "Ho spazio libero, ma è nella partizione sbagliata!"

Se qualcuno ha suggerimenti su come modificare la mia domanda o il suo titolo per essere più chiari, sono tutto a posto.


1
Non esiste AFAIK nel sistema. Quello che probabilmente dovresti fare è aggiungere un altro parametro di avvio e modificare i tuoi initramfs per chroot nella sottodirectory prima di eseguire init
Ulrich Dangel

@UlrichDangel è quello che stavo per proporre. Dagli una risposta!
Nils,

@Nils ok ho appena fornito una risposta, grazie. all'inizio non volevo scriverne uno perché non volevo fornire la patch / script
Ulrich Dangel,

Risposte:


10

Risposta breve: per quanto ne so non esiste una soluzione operativa pronta all'uso per le vostre esigenze specifiche. Dovrai adattare ogni initramfs di ogni distribuzione per supportare le tue esigenze specifiche.

Risposta lunga: sì, è possibile. Oggi la maggior parte delle distribuzioni Linux usa un initramfs che verrà caricato in memoria dal bootloader e quindi decompresso dal kernel. Lì verrà eseguito il /sbin/initresponsabile della configurazione dello spazio utente iniziale (esecuzione di udev, caricamento dei moduli, avvio di plymouth, richiesta della passphrase crittografica, impostazione della rete per i montaggi di rete, ... lo chiami). Come è possibile eseguire i propri script e valutare parametri di avvio personalizzati.

Esempio per Debian

Se stai usando Debian (dovrebbe essere lo stesso con Ubuntu) dovresti essere in grado di inserire uno script in /etc/initramfs-tools/scripts/init-bottom/cui verrà eseguito prima dell'avvio di init. Per ulteriori informazioni sulla sceneggiatura, le diverse directory e il layout danno un'occhiata a man initramfs-tools . Dovrai modificare rootmnte aggiungere la directory di destinazione.

Script di esempio (non testato) che deve essere installato come /etc/initramfs-tools/scripts/local-bottom/00-myrooto /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

L'idea è di regolare rootmnt quale viene utilizzato nello initscript initramfs per avviare / eseguire il vero init. Dato che il dispositivo root è già montato sullo init-bootomstage, puoi semplicemente regolare / modificare la directory di destinazione.

Per utilizzare questo script è sufficiente aggiungere un nuovo parametro di avvio, copiare lo script, renderlo eseguibile, rigenerare initramfs e aggiungere un parametro di avvio per la distribuzione Linux, ad es rootdir=/Ubuntu_Precise.


Probabilmente vorrai anche associare mount della radice reale a un sottodir della radice del sistema operativo in modo da poter vedere gli altri file del sistema operativo da quello che avvii.
psusi,

@psusi Puoi farlo tramite fstab o semplicemente mount /dev/rootdevice /mountpointdopo che il sistema è in esecuzione
Ulrich Dangel,

Mi chiedo quando è cambiato? In passato non era possibile montare nuovamente lo stesso dispositivo a blocchi; otterresti un EBUSY.
psusi,

1
@psusi non è sicuro, ma probabilmente con l'introduzione dei supporti di collegamento
Ulrich Dangel,

@UlrichDangel Grazie per la (molto) risposta dettagliata!
Azendale,

2

Qui ci sono due modi che funzionano in Ubuntu Bionic (e forse altrove). non ho abbastanza rappresentante per commentare, ma bionic: / usr / share / initramfs-tools / init cerca in / etc / fstab per / usr subito dopo aver chiamato mountroot e prima di chiamare gli script * -bottom, quindi aggiungendo un init- lo script in basso (come suggerito in un'altra risposta qui) è "troppo tardi". invece raccomando questi:

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

Questo ha funzionato a
meraviglia

1

L'avvio di Linux diversi senza interferire con la tabella delle partizioni è interessante per scopi diversi, una soluzione alternativa a un filesystem condiviso è l'uso di volumi di loop, qui le poche modifiche necessarie supponendo che tu abbia un file / volume di loop / debian nel filesystem / dev / sdb1 (Sto usando GNU / Debian sid / unstable attuali sia per i sistemi operativi principali che per quelli ad anello).

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

Gli argomenti definiti in grub come riga di comando di Linux sono impostati su env da initrd / init, quindi:

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

loop consente di montare il volume su "stesso", il flusso di script predefinito fa un mount /dev/sdb1 /rootfacoltativamente rimontiamo / dev / sdb1 come rw se era ro quindi aggiungi sempre 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

È inoltre necessario pre-caricare alcuni moduli nell'initram (quindi non dimenticare di eseguire update-initramfs)

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

Non so quanto usare le prestazioni di influenza del loop o sprecare risorse, mi chiedo se il montaggio di ext4 su ext4 raddoppi le probabilità di un errore del filesystem, ma immagino che si potrebbe fare qualche messa a punto. Forse c'è un modo migliore per usare loop, meno hack, se per favore fammi sapere perché non l'ho trovato.


0

Questa non è una risposta, ma voglio chiarire alcuni punti sulla risposta e sui commenti di Ulrich (non posso commentare sopra).

La soluzione proposta da Ulrich "può" funzionare (non ancora testata) ma otterrai un filesystem non rimovibile . Come soluzione alternativa (brutto imho) puoi montare la fs come rw prima di chrooting ( come suggerito qui ) ma fai attenzione agli script init non funzionanti. Immagino che questa soluzione alternativa abbia più effetti collaterali (come fs rotti che provano a rimontare ro e falliscono).

Sto usando il kernel 3.2 con ext4 e sto montando uno sviluppatore già montato all'interno del chroot per dare ancora EBUSY come ha commentato psusi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.