「バインドマウント」とは何ですか?どうやって作るの?何がいいの?
何かにバインドマウントを使用するように言われましたが、それが何であるか、またはどのように使用するのかわかりません。
bind mountは、ディレクトリツリーの代替ビューです。古典的には、マウントすると、ストレージツリーがディレクトリツリーとして表示されます。代わりに、バインドマウントは既存のディレクトリツリーを取得し、それを別のポイントに複製します。バインドマウントのディレクトリとファイルは、元のディレクトリと同じです。 2つのビューは同じデータを表示するため、片側の変更はすぐに反対側に反映されます。
たとえば、Linuxコマンドを発行した後
mount --bind /some/where /else/where
ディレクトリ/some/where
と/else/where
の内容は同じです。
ハードリンクやシンボリックリンクとは異なり、バインドマウントはファイルシステムに格納されているものに影響を与えません。これはライブシステムのプロパティです。
bindfs
ファイルシステムは、ディレクトリツリーのビューを作成する Fuse ファイルシステムです。たとえば、次のコマンド
bindfs /some/where /else/where
/else/where
を、/some/where
の内容が表示されるマウントポイントにします。
Bindfsは独立したファイルシステムであるため、ファイル/some/where/foo
と/else/where/foo
は、アプリケーションでは異なるファイルとして表示されます(bindfsファイルシステムには独自のst_dev
値があります)。一方の変更は「魔法のように」もう一方の側に反映されますが、ファイルが同じであるという事実は、bindfsの動作を知っている場合にのみ明らかになります。
Bindfsはマウントポイントを認識しないため、/some/where
の下にマウントポイントがある場合、/else/where
の下の単なる別のディレクトリとして表示されます。 /some/where
の下のファイルシステムをマウントまたはアンマウントすると、対応するディレクトリの変更として/else/where
の下に表示されます。
Bindfsは一部のファイルメタデータを変更する可能性があります。ファイルの偽のアクセス許可と所有権を表示できます。詳細については manual を、例については以下を参照してください。
Bindfsファイルシステムは非rootユーザーとしてマウントできます。Fuseファイルシステムをマウントするための特権のみが必要です。ディストリビューションによっては、これをFuse
グループに含めるか、すべてのユーザーに許可する必要がある場合があります。 Fuseファイルシステムをマウント解除するには、umount
の代わりにfusermount -u
を使用します。
fusermount -u /else/where
FreeBSDは、ファイルシステムの代替ビューを作成する nullfs
ファイルシステムを提供します。次の2つのコマンドは同等です。
mount -t nullfs /some/where /else/where
mount_nullfs /some/where /else/where
いずれかのコマンドを発行した後、/else/where
は、/some/where
の内容が表示されるマウントポイントになります。
Nullfsは独立したファイルシステムであるため、ファイル/some/where/foo
と/else/where/foo
は、アプリケーションに対して異なるファイルとして表示されます(nullfsファイルシステムには独自のst_dev
値があります)。一方の変更は「魔法のように」反対側に反映されますが、ファイルが同じであるという事実は、nullfsの動作を知っている場合にのみ明らかになります。
ディレクトリツリーのレベルで機能するFuse bindfsとは異なり、FreeBSDのnullfsはカーネル内でより深く機能するため、/else/where
の下のマウントポイントは表示されません。/some/where
と同じマウントポイントの一部であるツリーのみが/else/where
に反映されます。
Nullfsファイルシステムは、他のBSDバリアント(OS X、OpenBSD、NetBSD)で使用できる場合がありますが、デフォルトシステムの一部としてコンパイルされていません。
Linuxでは、バインドマウントはカーネル機能として使用できます。 mount
コマンドを使用して、--bind
コマンドラインオプションまたはbind
マウントオプションを渡すことにより、1つを作成できます。次の2つのコマンドは同等です。
mount --bind /some/where /else/where
mount -o bind /some/where /else/where
ここで、「デバイス」/some/where
は、ディスク上のファイルシステムの場合のようなディスクパーティションではなく、既存のディレクトリです。マウントポイント/else/where
は、通常どおり既存のディレクトリでなければなりません。どちらの方法でもファイルシステムタイプが指定されていないことに注意してください。バインドマウントの作成にはファイルシステムドライバーは含まれず、元のマウントからカーネルデータ構造がコピーされます。
mount --bind
は、非ディレクトリーへの非ディレクトリーのマウントもサポートします。/some/where
は通常のファイルにすることができます(この場合、/else/where
も通常のファイルである必要があります)。
Linuxバインドマウントは、元のマウントとほとんど区別がつきません。コマンドdf -T /else/where
は、df -T /some/where
と同じデバイスおよび同じファイルシステムタイプを示します。ファイル/some/where/foo
と/else/where/foo
は、ハードリンクであるかのように区別できません。 /some/where
をマウント解除することができます。その場合、/else/where
はマウントされたままになります。
古いカーネルでは(いつかは正確にはわかりませんが、3.xまではそう思います)、バインドマウントは元のカーネルとまったく区別できませんでした。最近のカーネルはバインドマウントを追跡し、PID/mountinfoを介して情報を公開します。これにより、 findmnt
がバインドマウントを示すことができます 。
バインドマウントエントリを/etc/fstab
に配置できます。オプションにbind
(またはrbind
など)を、必要な他のオプションと一緒に含めるだけです。 「デバイス」は既存のツリーです。ファイルシステム列にはnone
またはbind
を含めることができます(無視されますが、ファイルシステム名を使用すると混乱を招きます)。例えば:
/some/where /readonly/view none bind,ro
/some/where
の下にマウントポイントがある場合、その内容は/else/where
の下には表示されません。 bind
の代わりにrbind
を使用できます。また、/some/where
の下のマウントポイントを複製できます。たとえば、/some/where/mnt
がマウントポイントの場合
mount --rbind /some/where /else/where
に相当
mount --bind /some/where /else/where
mount --bind /some/where/mnt /else/where/mnt
さらに、Linuxではマウントをshared、slave、privateまたはnbindableとして宣言できます。これは、そのマウント操作が、マウントポイントを複製するバインドマウントに反映されるかどうかに影響します。詳細については、 カーネルのドキュメント を参照してください。
Linuxはマウントを移動する方法も提供します。ここで、--bind
はコピーし、--move
はマウントポイントを移動します。
2つのバインドマウントディレクトリに異なるマウントオプションを設定することができます。ただし、奇妙な点があります。バインドマウントの作成とマウントオプションの設定は、アトミックに実行できないため、2つの連続した操作である必要があります。 (古いカーネルはこれを許可していませんでした。)たとえば、次のコマンドは読み取り専用ビューを作成しますが、/else/where
が読み取り/書き込みである短い時間枠があります。
mount --bind /some/where /else/where
mount -o remount,ro,bind /else/where
システムがFuseをサポートしていない場合、同じ効果を得るための古典的なトリックは、NFSサーバーを実行し、公開するファイルをエクスポートして(localhost
へのアクセスを許可)、同じファイルにマウントすることです。機械。これはメモリとパフォーマンスの点でかなりのオーバーヘッドがあるため、バインドマウントは利用可能な場合に明確な利点があります(これはFuseのおかげでほとんどのUnixバリアントにあります)。
セキュリティ上の理由から、または誤って変更しないようにするための安全のレイヤーとして、ファイルシステムの読み取り専用のビューを作成すると便利です。
Bindfsの場合:
bindfs -r /some/where /mnt/readonly
Linuxでは、簡単な方法:
mount --bind /some/where /mnt/readonly
mount -o remount,ro,bind /mnt/readonly
これにより、/mnt/readonly
が読み書き可能な短い間隔が残ります。これがセキュリティ上の問題である場合は、最初にルートのみがアクセスできるディレクトリにバインドマウントを作成し、読み取り専用にしてから、パブリックマウントポイントに移動します。以下のスニペットでは、/root/private
(マウントポイントの上のディレクトリ)がプライベートであることが重要です。 /root/private/mnt
の元の権限は、マウントポイントの背後に隠されているため、無関係です。
mkdir -p /root/private/mnt
chmod 700 /root/private
mount --bind /some/where /root/private/mnt
mount -o remount,ro,bind /root/private/mnt
mount --move /root/private/mnt /mnt/readonly
ファイルシステムは、ユーザーとグループを数値IDで記録します。場合によっては、同じユーザーに異なるユーザーIDを割り当てる複数のシステムになることがあります。これはネットワークアクセスの問題ではありませんが、ディスク上のあるシステムから別のシステムにデータを運ぶときにユーザーIDを無意味にします。 AliceがユーザーID 1000を持ち、BobがユーザーID 1001を持っているシステムに、マルチユーザーファイルシステム(例:ext4、btrfs、zfs、UFSなど)で作成されたディスクがあり、そのディスクにアクセスできるようにするとします。 AliceのユーザーIDが1001で、BobのユーザーIDが1000のシステム。ディスクを直接マウントすると、AliceのファイルはBobが所有していると表示され(ユーザーIDが1001であるため)、BobのファイルはAliceが所有していると表示されます(ユーザーIDは1000です)。
Bindfsを使用してユーザーIDを再マップできます。まず、ディスクパーティションをプライベートディレクトリにマウントします。ここで、rootだけがアクセスできます。次に、AliceとBobのユーザーIDとグループIDを交換するユーザーIDとグループIDの再マッピングを使用して、パブリックエリアにbindfsビューを作成します。
mkdir -p /root/private/alice_disk /media/alice_disk
chmod 700 /root/private
mount /dev/sdb1 /root/private/alice_disk
bindfs --map=1000/1001:1001/1000:@1000/1001:@1001/1000 /root/private/alice_disk /media/alice_disk
を参照してください起動されていないシステムのユーザーのホームフォルダーにあるファイルにどのようにアクセスできますか? および mount-他のユーザーを自分自身としてバインド 別の例。
chroot jail または container は、システムのディレクトリツリーのサブツリーでプロセスを実行します。これは、アクセスが制限されたプログラムを実行するのに役立ちます。自身のファイルとサーバーが提供するファイルのみにアクセスし、同じコンピューターに保存されている他のデータにはアクセスできないネットワークサーバーを実行します。 chrootの制限は、プログラムが1つのサブツリーに限定されていることです。独立したサブツリーにはアクセスできません。バインドマウントを使用すると、他のサブツリーをそのメインツリーに移植できます。これにより、Linuxでのコンテナーの最も実用的な使用法の基礎となります。
たとえば、マシンが/usr/sbin/somethingd
の下のデータにのみアクセスできるサービス/var/lib/something
を実行するとします。これらのファイルの両方を含む最小のディレクトリツリーがルートです。サービスをどのように制限できますか? 1つの可能性は、サービスが必要とするすべてのファイル(少なくとも/usr/sbin/somethingd
およびいくつかの共有ライブラリ)へのハードリンクを/var/lib/something
の下に作成することです。しかし、これは扱いにくく(ファイルをアップグレードするたびにハードリンクを更新する必要があります)、/var/lib/something
と/usr
が異なるファイルシステムにある場合は機能しません。より良い解決策は、アドホックルートを作成し、マウントを使用してそこにデータを追加することです。
mkdir /run/something
cd /run/something
mkdir -p etc/something lib usr/lib usr/sbin var/lib/something
mount --bind /etc/something etc/something
mount --bind /lib lib
mount --bind /usr/lib usr/lib
mount --bind /usr/sbin usr/sbin
mount --bind /var/lib/something var/lib/something
mount -o remount,ro,bind etc/something
mount -o remount,ro,bind lib
mount -o remount,ro,bind usr/lib
mount -o remount,ro,bind usr/sbin
chroot . /usr/sbin/somethingd &
Linuxの mount名前空間 はchrootを一般化します。バインドマウントは、名前空間を柔軟な方法で設定する方法です。例については、 プロセスに同じファイル名の別のファイルを読み取らせる を参照してください。
Chrootsのもう1つの用途は、ディレクトリに別のディストリビューションをインストールして、そこからプログラムを実行することです。ベースシステム上に存在しない、またはコンテンツが異なるハードコーディングされたパスにファイルが必要な場合でもです。これは、たとえば、混合パッケージをサポートしていない64ビットシステムに32ビットのディストリビューションをインストールしたり、互換性をテストするために古いリリースのディストリビューションや他のディストリビューションをインストールしたり、新しいリリースをインストールしてテストしたりするのに役立ちます。 Debian/Ubuntuの例については、 64ビットのDebian/Ubuntuで32ビットプログラムを実行するにはどうすればよいですか? を参照してください。
/f/unstable
ディレクトリの下にディストリビューションの最新パッケージがインストールされていて、chroot /f/unstable
でそのディレクトリに切り替えてプログラムを実行するとします。このインストールからホームディレクトリを利用できるようにするには、それらをchrootにバインドマウントします。
mount --bind /home /f/unstable/home
プログラム schroot はこれを自動的に行います。
ファイルシステムをディレクトリにマウントすると、ディレクトリの背後にあるものが隠されます。そのディレクトリ内のファイルは、ディレクトリがアンマウントされるまでアクセスできなくなります。 BSD nullfsおよびLinuxバインドマウントはマウントインフラストラクチャよりも低いレベルで動作するため、ファイルシステムのnullfsマウントまたはバインドマウントは、元のサブマウントの背後に隠されていたディレクトリを公開します。
たとえば、/tmp
にtmpfsファイルシステムがマウントされているとします。 tmpfsファイルシステムが作成されたときに/tmp
の下にファイルがあった場合、これらのファイルはそのまま残り、実質的にアクセスできなくなりますが、ディスク領域を占有します。走る
mount --bind / /mnt
(Linux)または
mount -t nullfs / /mnt
(FreeBSD)/mnt
にルートファイルシステムのビューを作成します。ディレクトリ/mnt/tmp
は、ルートファイルシステムからのディレクトリです。
一部のNFSサーバー(NFSv4の前のLinuxカーネルNFSサーバーなど)は、ディレクトリをエクスポートするときに常に実際のディレクトリの場所を通知します。つまり、クライアントがserver:/requested/location
を要求すると、サーバーは/requested/location
の場所でツリーを提供します。クライアントが/request/location
をリクエストできるようにすることが望ましい場合がありますが、実際には/actual/location
でファイルを提供します。 NFSサーバーが別の場所でのサービスをサポートしていない場合は、期待されるリクエストのバインドマウントを作成できます。
/requested/location *.localdomain(rw,async)
/etc/exports
内、および/etc/fstab
内の以下:
/actual/location /requested/location bind bind
シンボリックリンクを作成してファイルを/some/where/is/my/file
を/else/where
の下に表示したい場合がありますが、file
を使用するアプリケーションはシンボリックリンクを展開し、/some/where/is/my/file
を拒否します。バインドマウントはこれを回避できます:bind-mount /some/where/is/my
to /else/where/is/my
そして、 realpath
は、/else/where/is/my/file
が/else/where
の下ではなく/some/where
の下にあると報告します。
バインドマウントを使用する場合は、バックアップやインデックス作成など、ファイルシステムツリーを再帰的に走査するアプリケーションに注意する必要があります(たとえば、 locate データベースを構築するため)。
通常、バインドマウントは、再帰的なディレクトリトラバーサルから除外する必要があります。これにより、各ディレクトリツリーは、元の場所で一度だけトラバースされます。 bindfsとnullfsを使用して、可能であれば、これらのファイルシステムタイプを無視するように走査ツールを構成します。 Linuxバインドマウントはそのように認識できません。新しい場所は元の場所と同じです。 Linuxバインドマウント、またはファイルシステムタイプではなくパスのみを除外できるツールを使用する場合は、バインドマウントのマウントポイントを除外する必要があります。
ファイルシステムの境界(たとえば、find -xdev
、rsync -x
、du -x
、…)で停止するトラバーサルは、bindfsまたはnullfsマウントポイントが検出されると、そのマウントポイントが別のファイルシステムであるため、自動的に停止します。 Linuxバインドマウントを使用すると、状況は少し複雑になります。ファイルシステムの境界は、バインドマウントが別のファイルシステムを移植している場合のみであり、同じファイルシステムの別の部分を移植している場合ではありません。
バインドマウントは、別の場所にあるディレクトリツリーのビューを提供します。それらは同じファイルを公開しますが、おそらくマウントオプションが異なり、(bindfsを使用して)所有権と権限が異なります。ディレクトリツリーのビューが変更されたファイルシステムは、overlay filesystemsまたはstackable filesystemsと呼ばれます。より高度な変換を実行する他の多くのオーバーレイファイルシステムがあります。ここにいくつかの一般的なものがあります。ここで目的のユースケースがカバーされていない場合は、Fuseファイルシステムの リポジトリをチェックしてください .
bindfs -r
と同様に、もう少し軽量です。Union mounts —単一のディレクトリの下に複数のファイルシステム(branchesと呼ばれる)を表示します:tree1
にfoo
が含まれ、tree2
にbar
すると、それらのユニオンビューにはfoo
とbar
の両方が含まれます。新しいファイルは、特定のブランチ、またはより複雑なルールに従って選択されたブランチに書き込まれます。この概念には、次のようないくつかの実装があります。