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


11

Eu gostaria de tentar configurar um computador para que ele tenha várias instalações Linux, tudo no mesmo sistema de arquivos. Por exemplo, o filesytem teria 3 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).

Certa vez, configurei várias instalações de diferentes distribuições usando BTRFS e, ao fazê-lo funcionar, sei que o Grub se sai bem ao inicializar a imagem vmlinuz e initrd a partir de caminhos 'fora do padrão'. Mas quando eu estava fazendo o BTRFS, havia o rootflags=subvol=@<subvolume_name>que dizia ao kernel para montar esse subvolume como / no sistema de arquivos. Existe algum argumento de que você poderia passar o kernel que o faria ligar a montagem de uma subpasta em uma partição como / e depois inicializar?

Para as outras partes, acho que estou bem perto. Eu sei como especificar uma montagem de ligação /etc/fstab. Além disso, a partir de quando configuro meu sistema com várias instalações linux nos subvolumes BTRFS, estou acostumado a instalar uma distribuição em uma VM e depois migrá-la usando o rsync, por isso não estou muito preocupado com o que precisaria fazer para obter a configuração correta, estou apenas tentando descobrir qual seria a configuração correta. Depois que eu souber disso, devo poder fazer a migração para as subpastas e editar arquivos com bastante facilidade.

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 executar a virtualização e as partições não compartilham espaço livre. Eu estou procurando configurar um sistema que dual / triple / quad / etc inicialize distribuições linux, mas que o faça com um sistema de arquivos, para que não haja nenhum caso de "Eu tenho espaço livre, mas está na partição errada!"

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


1
Não há nada AFAIK embutido no sistema. O que você provavelmente teria que fazer é adicionar outro bootparameter e modificar suas initramfs para chroot para o subdiretório antes de executar o init
Ulrich Dangel

@UlrichDangel é isso que eu ia propor. Faça disso uma resposta!
Nils

@ Nils ok, acabei de fornecer uma resposta, tbh. Eu não queria escrever um no primeiro como eu não quis fornecer o patch / script
Ulrich Dangel

Respostas:


10

Resposta curta - existe, até onde eu sei, nenhuma solução pronta para atender às suas necessidades específicas. Você precisará 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 gerenciador de inicialização e depois descompactado pelo kernel. Lá será executado o /sbin/initresponsável pela configuração do espaço inicial do usuário (executando o udev, carregando módulos, iniciando o plymouth, solicitando uma senha criptografada, configurando a rede para montagens de rede, ... o nome dele). Como você pode executar seus próprios scripts e avaliar os parâmetros de inicialização personalizados.

Exemplo para Debian

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

Exemplo de script (não testado) que deve ser instalado como /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

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

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


Você provavelmente também deseja vincular mount the root real em um subdiretório da raiz do sistema operacional para poder ver os outros arquivos do sistema operacional daquele a partir do qual você inicializou.
Psusi 28/05/12

@psusi Você pode fazer isso através fstab ou apenas fazer diretamente mount /dev/rootdevice /mountpointdepois que o sistema está em execução
Ulrich Dangel

Gostaria de saber quando isso mudou? Você não costumava montar o mesmo dispositivo de bloco novamente; você obteria um EBUSY.
Psusi 28/05

1
@psusi não tenho certeza, mas provavelmente com a introdução de montagens bind
Ulrich Dangel

@UlrichDangel Obrigado pela resposta (muito) detalhada!
Azendale 30/05

2

Aqui estão duas maneiras que funcionam no ubuntu biion (e possivelmente em outro lugar). Eu não tenho representante suficiente para comentar, mas biônico: / usr / share / initramfs-tools / init procura em / etc / fstab / usr logo após chamar o mountroot e antes de chamar os scripts * -bottom, adicionando um init- O script inferior (como sugerido em outra resposta aqui) é "tarde demais". em vez disso, recomendo:

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

Isso funcionou um deleite para mim
paultop6

1

A inicialização de linux diferente sem mexer com a tabela de partição é interessante para propósitos diferentes. 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 arquivo / volume / debian loop no sistema de arquivos / dev / sdb1 (Estou usando o atual GNU / Debian sid / unstable para os sistemas operacionais principal e de loop).

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

Os argumentos definidos no grub como linha de comando linux são definidos como env pelo initrd / init, portanto:

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

loop permite montar o volume sobre "a si próprio", o fluxo de script padrão mount /dev/sdb1 /rooté o caso de apenas remontarmos o / dev / sdb1 como rw se fosse ro, sempre anexar 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

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

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

Não sei quanto o uso do loop influencia no desempenho ou desperdiça recursos, estou me perguntando se a montagem 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 hackish, se houver, por favor me avise porque não encontrei.


0

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

A solução que Ulrich propõe "pode" funcionar (ainda não testada), mas você obterá um sistema de arquivos não remontável . Como solução alternativa (IMHO feio), você pode montar o fs como rw antes de executar o chroot ( como sugerido aqui ), mas tenha cuidado com os scripts init quebrados. Eu acho que essa solução alternativa tem mais efeitos colaterais (como fs quebrados tentando remontar ro e falhar).

Estou usando o kernel 3.2 com ext4 e montando um dev já montado dentro do chroot ainda dá EBUSY como psusi comentou.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.