パーティションのサブディレクトリからLinuxシステムを起動しますか?


11

複数のLinuxがすべて同じファイルシステムにインストールされるようにコンピューターをセットアップしたいと思います。たとえば、filesytemは3つのフォルダを持っているでしょう/Ubuntu_Precise/Ubuntu_Oneiric/Ubuntu_Natty

(私はあなたがBTRFSとサブボリュームでこれを行うことができることを知っていますが、速度のためにEXT4を使用したいと思います)。

BTRFSを使用して、さまざまなディストリビューションの複数のインストールをセットアップしたことがあり、Grubが「非標準」パスからvmlinuzおよびinitrdイメージを起動することで問題なく動作することを知っています。しかし、私がBTRFSのことをしているときに、rootflags=subvol=@<subvolume_name>そのサブボリュームを/としてファイルシステムにマウントするようにカーネルに指示するメッセージがありました。/としてパーティションのサブフォルダーをバインドマウントしてからブートするカーネルを渡すことができるという引数はありますか?

他の部分については、かなり近いと思います。でバインドマウントを指定する方法を知っています/etc/fstab。また、BTRFSサブボリュームに複数のLinuxインストールを使用してシステムをセットアップしたときから、VMにディストリビューションをインストールしてから、rsyncを使用してそれを移行するので、何をする必要があるかについてあまり心配していません適切な構成を取得し、私はちょうど適切な構成が何であるかを見つけようとしています。それがわかったら、サブフォルダへの移行とファイル編集を簡単に行うことができます。

仮想化とパーティションについてはすでに知っていますが、それは私が探しているものではありません。ターゲットコンピュータに仮想化を実行するための十分なパワーがなく、パーティションが空き領域を共有していません。私はデュアル/トリプル/クワッド/ etcがLinuxディストリビューションを起動するシステムをセットアップしようとしていますが、これは1つのファイルシステムで実行されるため、「空き領域がありますが、間違ったパーティションにあります!」

誰かが私の質問またはそのタイトルをより明確に編集する方法の提案を持っている場合、私はすべて耳にしています。


1
システムには何も組み込まれていません。おそらくあなたがしなければならないことは、別のブートパラメータを追加し、initを実行する前にinitramfsをサブディレクトリにchrootするように変更することです
Ulrich Dangel

@UlrichDangelそれは私が提案しようとしていたものです。それを答えにしてください!
Nils

@Nilsわかりました、答えを提供しました。パッチ/スクリプトを提供したくなかったので、最初は書きたくありませんでした
Ulrich Dangel

回答:


10

短い答え-私の知る限り、あなたの特定の要件に対応できるすぐに使えるソリューションはありません。特定のニーズをサポートするには、各ディストリビューションの各initramfsを調整する必要があります。

長い答え-はい、それは可能です。現在、ほとんどのLinuxディストリビューションは、ブートローダーによってメモリにロードされ、カーネルによって解凍されるinitramfsを使用しています。それはそこに実行されます/sbin/init(...あなたはそれに名前を付ける、udevの、ロード・モジュールを実行し、プリマスを開始し、暗号化パスフレーズを求め、ネットワークマウント用のネットワークを設定)早期ユーザ空間の設定を担当しています。独自のスクリプトを実行して、カスタムブートパラメーターを評価することができます。

Debianの例

Debianを使用している場合(Ubuntuと同じである必要があります)、/etc/initramfs-tools/scripts/init-bottom/initが開始される前に実行されるスクリプトを配置できるはずです。スクリプトの詳細については、さまざまなディレクトリとレイアウトでman initramfs-toolsを参照してくださいrootmntターゲットディレクトリを調整して追加する必要があります。

/etc/initramfs-tools/scripts/local-bottom/00-myrootまたはとしてインストールする必要があるサンプル(テストされていない)スクリプト/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

アイデアは、実際のinitを開始/実行するためにrootmnt initramfs initスクリプトで使用されるものを調整することです。ルートデバイスはすでにinit-bootomステージにマウントされているため、ターゲットディレクトリを調整/変更することができます。

このスクリプトを使用するには、新しいブートパラメータを追加し、スクリプトをコピーして実行可能にし、initramfsを再生成して、Linuxディストリビューション用のブートパラメータを追加しますrootdir=/Ubuntu_Precise


また、実際のルートをosルートのサブディレクトリにバインドマウントして、起動したOSファイルから他のOSファイルを確認できるようにすることもできます。
psusi 2012年

@psusiこれは、fstabを介して、またはmount /dev/rootdevice /mountpointシステムの実行直後に行うことができます
Ulrich Dangel 2012年

いつ変わったのかな?以前は同じブロックデバイスを再びマウントすることができませんでした。あなたはEBUSYを取得します。
psusi

1
@psusiはわかりませんが、おそらくバインドマウントの導入によるものです
Ulrich Dangel

@UlrichDangel(非常に)詳細な回答をありがとう!
Azendale、2012年

2

ubuntuバイオニック(およびおそらく他の場所)で機能する2つの方法を次に示します。コメントするには十分な担当者がいませんが、bionic:/ usr / share / initramfs-tools / initは、mountrootを呼び出した直後で* -bottomスクリプトを呼び出す前に、/ etc / fstabで/ usrを探します。そのため、init-下のスクリプト(ここの別の回答で提案されています)は「遅すぎます」。代わりに私はこれらをお勧めします:

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

これは私のための御馳走でした
paultop6

1

パーティションテーブルをいじることなく別のLinuxを起動することは、さまざまな目的にとって興味深いことです。共有ファイルシステムの代替ソリューションは、ループボリュームを使用することです。 (私はメインとループの両方のOSに現在のGNU / Debian sid / unstableを使用しています)。

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

Linuxコマンドラインとしてgrubに定義された引数は、initrd / initによってenvに設定されるため、次のようになります。

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

loopは、ボリュームを「それ自体」にマウントすることを許可します。デフォルトのスクリプトフローでは、mount /dev/sdb1 /rootオプションで/ dev / sdb1をrwとして再マウントし、roの場合は常にを追加し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

また、いくつかのモジュールをinitramにプリロードする必要があります(次にupdate-initramfsを実行することを忘れないでください)

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

ループの使用がパフォーマンスにどの程度影響するか、リソースを浪費するかわからない。ext4を介してext4をマウントすると、ファイルシステム障害の可能性が2倍になるのではないかと思いますが、ある程度の調整ができると思います。ループを使用するより良い方法があるかもしれません。ハックが少ないです。もしあれば、私が見つけていないので、知らせてください。


0

これは答えではありませんが、Ulrichの答えとコメントについていくつかの点を明確にしたいと思います(上記にはコメントできません)。

ソリューションUlrichは(まだ試されていない)動作する可能性があると提案していますが、その後、再マウントできないファイルシステムを取得します。回避策として(IMHO醜い)、chrootする前にfsをrwとしてマウントできます(ここで提案されています)が、壊れたinitスクリプトに注意してください。この回避策には副作用があります(壊れたfsがroを再マウントしようとして失敗するなど)。

私はext4でカーネル3.2を使用しており、すでにマウントされているdevをchroot内にマウントすると、psusiのコメントどおりにEBUSYが返されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.