web-dev-qa-db-ja.com

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

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

(BTRFSとサブボリュームでこれを実行できることは知っていますが、速度を上げるためにEXT4を使用したいと思います).

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

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

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

誰かが私の質問やそのタイトルをより明確にするために編集する方法について提案があれば、私はすべての耳です。

11
Azendale

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

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

Debianの例

Debianを使用している場合(Ubuntuと同じである必要があります)、initが開始される前に実行されるスクリプトを/etc/initramfs-tools/scripts/init-bottom/に配置できるはずです。スクリプトの詳細については、さまざまなディレクトリとレイアウトで 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

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

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

10
Ulrich Dangel

これがubuntubionic(そしておそらく他の場所)で機能する2つの方法です。コメントするには十分な担当者がいませんが、bionic:/ usr/share/initramfs-tools/initは、mountrootを呼び出した直後で* -bottomスクリプトを呼び出す前に、/ usrの/ etc/fstabを探します。そのため、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, might need tweaking to work elsewhere
#1st choice:  Tweak initramfs-tools/scripts/local
#   pro:  $sub becomes root directly, nothing gets any chance to see the partition root
#   con:  requires the subdirectory's initramfs/initrd to be tweaked and rebuilt
#2nd choice:  specify this scriptfile as init= on the kernel commandline
#   pro:  no need to rebuild initramfs
#   con:  requires bin/bash in the partition root executable by $sub/vmlinux (ie $sub same or newer than partition root)
#   con:  if the partition root etc/fstab mounts /usr, the $sub initramfs will mount the partition root /usr
#   con:  additional initramfs scripts might also look in the partition root rather than $sub

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

#for the 2nd choice, in addition to subroot= on the kernel commandline also specify:
#   init=/path/to/script        #pathname from partition root to this scriptfile (chmod 744)

#for the 1st choice, 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 watch)
#             fi
#          mountroot_status="$?"
#          [ $mountroot_status = 0 ]||sleep 90                                          #if error pause to see it
#          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 initrd/initramfs installed thereafter

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 (eg 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
3
gregrwm

パーティションテーブルをいじらずに別のLinuxを起動することは、さまざまな目的にとって興味深いことです。共有ファイルシステムの代替ソリューションは、ループボリュームを使用することです。ここでは、/ debianループファイル/ボリュームが/ dev/sdb1ファイルシステムにあると仮定していくつかの変更が必要です。 (メインOSとループ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 

ループにより、ボリュームを「それ自体」にマウントできます。デフォルトのスクリプトフローは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倍になるのではないかと思いますが、ある程度の調整ができると思います。ループを使用するより良い方法があるかもしれませんが、ハックが少ないです。もしあれば、私が見つけていないので、知らせてください。

1
Alex

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

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

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

0
Alex