Démarrage du système Linux à partir d'un sous-répertoire sur une partition?

11

Je voudrais essayer de configurer un ordinateur pour qu'il ait plusieurs installations Linux toutes dans le même système de fichiers. Par exemple, le système de fichier aurait 3 dossiers: /Ubuntu_Precise, /Ubuntu_Oneiricet /Ubuntu_Natty.

(Je sais que vous pouvez le faire avec BTRFS et sous-volumes, mais je voudrais utiliser EXT4 pour la vitesse).

J'ai une fois configuré plusieurs installations de différentes distributions à l'aide de BTRFS, et à partir du moment où cela fonctionne, je sais que Grub réussit très bien à démarrer l'image vmlinuz et initrd à partir de chemins `` non standard ''. Mais quand je faisais le truc BTRFS, il y avait le rootflags=subvol=@<subvolume_name>qui disait au noyau de monter ce sous-volume en tant que / dans le système de fichiers. Y a-t-il un argument selon lequel vous pourriez passer le noyau qui le ferait lier monter un sous-dossier dans une partition en tant que / puis démarrer?

Je pense que pour les autres parties, je suis assez proche. Je sais comment spécifier une monture de liaison dans /etc/fstab. De plus, à partir du moment où j'ai configuré mon système avec plusieurs installations Linux dans des sous-volumes BTRFS, j'ai l'habitude d'installer une distribution dans une machine virtuelle et de la migrer ensuite à l'aide de rsync, donc je ne suis pas trop inquiet de ce que je devrais faire pour obtenir la bonne configuration, j'essaie juste de savoir quelle serait la bonne configuration. Une fois que je le sais, je devrais être capable de faire la migration dans les sous-dossiers et l'édition de fichiers assez facilement.

Je connais déjà la virtualisation et les partitions, mais ce n'est pas ce que je recherche. L'ordinateur cible n'a pas assez de puissance pour effectuer la virtualisation et les partitions ne partagent pas d'espace libre. Je cherche à mettre en place un système qui double / triple / quad / etc démarre les distributions Linux, mais cela le fait avec un seul système de fichiers, afin qu'il n'y ait pas de cas "J'ai de l'espace libre, mais il est dans la mauvaise partition!"

Si quelqu'un a des suggestions pour éditer ma question ou son titre pour être plus clair, je suis à l'écoute.

Azendale
la source
1
Il n'y a rien d'AFAIK dans le système. Ce que vous auriez probablement à faire est d'ajouter un autre paramètre de démarrage et de modifier vos initramfs pour les chrooter dans le sous-répertoire avant d'exécuter init
Ulrich Dangel
@UlrichDangel, c'est ce que j'allais proposer. Faites-en une réponse!
Nils
@Nils ok je viens de fournir une réponse, tbh. je ne voulais pas en écrire un au début car je ne voulais pas fournir le patch / script
Ulrich Dangel

Réponses:

10

Réponse courte - il n'y a pour autant que je sache aucune solution de travail prête à l'emploi pour vos besoins spécifiques. Vous devrez ajuster chaque initramfs de chaque distribution pour répondre à vos besoins spécifiques.

Réponse longue - oui c'est possible. De nos jours, la plupart des distributions Linux utilisent un initramfs qui sera chargé en mémoire par le chargeur de démarrage puis décompressé par le noyau. Là, il s'exécutera, /sbin/initqui est responsable de la configuration de l'espace utilisateur initial (exécution d'udev, chargement des modules, démarrage de plymouth, demande de phrase secrète de cryptage, configuration du réseau pour les montages réseau,… vous l'appelez). Comme vous pouvez exécuter vos propres scripts et évaluer les paramètres de démarrage personnalisés.

Exemple pour Debian

Si vous utilisez Debian (devrait être le même avec Ubuntu), vous devriez pouvoir placer un script dans /etc/initramfs-tools/scripts/init-bottom/lequel il sera exécuté avant le démarrage d'init. Pour plus d'informations sur le script, les différents répertoires et la mise en page jettent un œil à man initramfs-tools . Vous devrez ajuster rootmntet ajouter le répertoire cible.

Exemple de script (non testé) qui doit être installé en tant que /etc/initramfs-tools/scripts/local-bottom/00-myrootou /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'idée est d'ajuster rootmnt ce qui est utilisé dans le initscript initramfs pour démarrer / exécuter le vrai init. Comme le périphérique racine est déjà monté dans la init-bootomscène, vous pouvez simplement ajuster / modifier le répertoire cible.

Pour utiliser ce script, ajoutez simplement un nouveau paramètre de démarrage, copiez le script, rendez-le exécutable, régénérez vos initramfs et ajoutez un paramètre de démarrage pour votre distribution Linux, par exemple rootdir=/Ubuntu_Precise.

Ulrich Dangel
la source
Vous voudrez aussi probablement lier le montage de la vraie racine dans un sous-répertoire de la racine du système d'exploitation afin que vous puissiez voir les autres fichiers du système d'exploitation à partir de celui que vous démarrez.
psusi
@psusi Vous pouvez le faire via fstab ou simplement le faire directement mount /dev/rootdevice /mountpointaprès le fonctionnement du système
Ulrich Dangel
Je me demande quand ça a changé? Auparavant, vous ne pouviez plus monter le même périphérique de bloc; vous obtiendrez un EBUSY.
psusi
1
@psusi pas sûr mais probablement avec l'introduction de montures de liaison
Ulrich Dangel
@UlrichDangel Merci pour la réponse (très) détaillée!
Azendale
2

Voici deux méthodes qui fonctionnent dans ubuntu bionic (et peut-être ailleurs). Je n'ai pas assez de représentants pour commenter, mais, bionic: / usr / share / initramfs-tools / init cherche dans / etc / fstab pour / usr juste après avoir appelé mountroot et avant d'appeler les scripts * -bottom, donc ajouter un init- le script du bas (comme suggéré dans une autre réponse ici) est "trop ​​tard". au lieu de cela, je recommande ces derniers:

#!/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
la source
Cela m'a fait
plaisir
1

Amorcer différents linux sans jouer avec la table de partition est intéressant à différentes fins, une solution alternative à un système de fichiers partagé est d'utiliser des volumes de boucle, ici les quelques changements nécessaires en supposant que vous avez un fichier / volume de boucle / debian dans le système de fichiers / dev / sdb1 (J'utilise GNU / Debian sid / unstable actuel pour les OS principal et de boucle).

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

Les arguments définis dans grub comme ligne de commande linux sont définis sur env par initrd / init, donc:

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

la boucle permet de monter le volume sur "lui-même", le flux de script par défaut fait un mount /dev/sdb1 /rootnous remontons simplement le / dev / sdb1 comme rw s'il était ro puis ajoutons toujours 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

Besoin également de précharger un module dans l'initram (puis n'oubliez pas d'exécuter update-initramfs)

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

Je ne sais pas combien utiliser les performances d'influence de la boucle ou gaspiller les ressources, je me demande si le montage ext4 sur ext4 double les probabilités de défaillance d'un système de fichiers, mais devinez qu'un ajustement pourrait être fait. Peut-être y a-t-il une meilleure façon d'utiliser la boucle, moins de hack, s'il vous plaît faites le moi savoir car je n'ai pas trouvé.

Alex
la source
0

Ce n'est pas une réponse mais je veux clarifier un point sur la réponse et les commentaires d'Ulrich (je ne peux pas commenter ci-dessus).

La solution proposée par Ulrich "peut" fonctionner (non encore testée) mais vous obtiendrez alors un système de fichiers non remontable . Comme solution de contournement (à mon humble avis), vous pouvez monter le fs en tant que rw avant le chrootage ( comme suggéré ici ) mais faites attention aux scripts d'initialisation cassés. Je suppose que cette solution de contournement a plus d'effets secondaires (comme les fs brisés qui tentent de remonter le ro et échouent).

J'utilise le noyau 3.2 avec ext4 et je monte un dev déjà monté à l'intérieur du chroot, ce qui donne toujours EBUSY comme le commentait psusi.

Alex
la source