Inicializa o sistema Linux a partir de um subdiretório em uma partição?

9

Eu gostaria de tentar configurar um computador para que ele tenha várias instalações do Linux no mesmo sistema de arquivos. Por exemplo, o filesytem teria três pastas: /Ubuntu_Precise , /Ubuntu_Oneiric e /Ubuntu_Natty .

(Eu sei que você pode fazer isso com BTRFS e subvolumes, mas eu gostaria de usar EXT4 para velocidade).

Uma vez eu configurei várias instalações de diferentes distros usando o BTRFS e, a partir desse processo, eu sei que o Grub faz muito bem com a inicialização da imagem vmlinuz e initrd de caminhos 'não-padrão'. Mas quando eu estava fazendo o BTRFS, havia o rootflags=subvol=@<subvolume_name> que dizia ao kernel para montar aquele subvolume como / no sistema de arquivos. Existe algum argumento de que você poderia passar o kernel que faria com que ele montasse uma subpasta em uma partição como / e então inicializasse?

Eu acho que para as outras partes, eu estou bem perto. Eu sei como específico montar uma ligação em /etc/fstab . Além disso, desde quando eu configurei meu sistema com várias instalações do Linux em subvolumes do BTRFS, estou acostumado a instalar uma distro em uma VM e depois migrá-la usando o rsync, então não estou muito preocupado com o que eu precisaria fazer para obter a configuração correta, estou apenas tentando descobrir qual seria a configuração correta. Uma vez que eu saiba disso, eu devo ser capaz de fazer a migração para as subpastas e editar arquivos facilmente.

Eu já sei sobre virtualização e partições, mas não é isso que estou procurando. O computador de destino não tem energia suficiente para fazer virtualização e as partições não compartilham espaço livre. Eu estou olhando para configurar um sistema que dual / triple / quad / etc carrega distros linux, mas isso faz com um sistema de arquivos, de modo que não há caso de "eu tenho espaço livre, mas está na partição errada!"

Se alguém tiver sugestões sobre como editar minha pergunta ou seu título para ficar mais claro, sou todo ouvidos.

    
por Azendale 27.05.2012 / 03:04

4 respostas

10

Resposta curta - até onde eu sei, não há solução de trabalho pronta para suas necessidades específicas. Você terá que ajustar cada initramfs de cada distribuição para suportar suas necessidades específicas.

Resposta longa - sim, é possível. Atualmente, a maioria das distribuições Linux usa um initramfs que será carregado na memória pelo bootloader e depois descompactado pelo kernel. Lá, ele executará /sbin/init , que é responsável por configurar o espaço de usuário inicial (executando o udev, carregando módulos, iniciando o plymouth, pedindo criptografia, configurando a rede para montagens de rede,… você escolhe). Como você pode executar seus próprios scripts e avaliar os parâmetros de inicialização personalizados.

Exemplo para o Debian

Se você estiver usando Debian (deve ser o mesmo com o Ubuntu) você deve ser capaz de colocar um script em /etc/initramfs-tools/scripts/init-bottom/ que será executado antes do init ser iniciado. Para mais informações sobre o script, os diferentes diretórios e o layout dão uma olhada em man initramfs-tools . Você terá que ajustar rootmnt e adicionar o diretório de destino.

Script de amostra (não testado) que deve ser instalado como /etc/initramfs-tools/scripts/local-bottom/00-myroot ou /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

A idéia é ajustar rootmnt , que é usado no script initramfs init para iniciar / executar o init real. Como o dispositivo raiz já está montado no estágio init-bootom , você pode apenas ajustar / alterar o diretório de destino.

Para usar este script, basta adicionar um novo parâmetro de inicialização, copiar o script, torná-lo executável, regenerar seu initramfs e adicionar um parâmetro de inicialização para sua distribuição Linux, por exemplo, rootdir=/Ubuntu_Precise .

    
por 28.05.2012 / 04:08
2

Aqui estão duas maneiras que funcionam no Ubuntu biônico (e possivelmente em outros lugares). Eu não tenho o suficiente para comentar, mas, bionic: / usr / share / initramfs-tools / init procura / etc / fstab por / usr logo após chamar mountroot e antes de chamar os scripts * -bottom, então adicionar um init script inferior (como sugerido em outra resposta aqui) é "muito tarde". em vez disso eu recomendo estes:

#!/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
    
por 02.05.2018 / 21:08
1

Inicializar um linux diferente sem mexer na tabela de partições é interessante para diferentes propósitos, uma solução alternativa para um sistema de arquivos compartilhado é usar volumes de loop, aqui as poucas mudanças necessárias supondo que você tenha um / volume de loop debian no / dev / sdb1 filesystem (Estou usando o atual GNU / Debian sid / unstable para os principais e 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
}

Argumentos definidos no grub como linha de comando do linux são configurados para env por initrd / init, então:

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

o laço permite montar o volume sobre "ele mesmo", o fluxo de script padrão faz um mount /dev/sdb1 /root nós apenas remontamos o / dev / sdb1 como rw se foi ro então sempre anexe um 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

Também é necessário pré-carregar algum módulo no initram (então não esqueça de executar update-initramfs)

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

Não sei quanto usando performances de influência de loop ou desperdício de recursos, eu estou querendo saber se montar ext4 sobre ext4 dobrar as probabilidades de uma falha no sistema de arquivos, mas acho que algum ajuste poderia ser feito. Talvez haja uma maneira melhor de usar loop, menos hacker, se houver, por favor me avise porque não encontrei.

    
por 27.03.2013 / 14:09
0

Esta não é uma resposta, mas quero esclarecer alguns pontos sobre a resposta e os comentários de Ulrich (não posso comentar acima).

A solução proposta por Ulrich "pode" funcionar (ainda não testada), mas você receberá um sistema de arquivos não-remontável . Como uma solução alternativa (IMHO feia) você pode montar o fs como rw antes de chrooting ( como sugerido aqui ), mas tenha cuidado com scripts de inicialização quebrados. Eu acho que esta solução alternativa tem mais efeitos colaterais (como fs quebrado tentando remontar ro e falhando).

Estou usando o kernel 3.2 com o ext4 e a montagem de um devedor já montado dentro do chroot ainda dá ao EBUSY um comentário do psusi.

    
por 19.03.2013 / 14:01