Contents

了解绑定挂载

1. 概述

我们在 Linux 挂载设备的过程中使用了mountumount 命令。但是,还有另一种挂载点类型,称为绑定挂载。在本教程中,我们将了解什么是绑定挂载,并且还会看到一些何时可以使用它的示例。

2. mount介绍

首先,让我们快速回顾一下mount命令。在 Linux 系统中,我们可以使用mount *命令*将设备挂载到目录中。这允许我们访问设备的文件系统。让我们在*/mnt/usb上挂载一个由设备/dev/sdc1*表示的 U 盘,然后列出它的内容:

$ mkdir /mnt/usb
$ mount /dev/sdc1 /mnt/usb
$ ls /mnt/usb
appendix.pdf pictures/

我们可以看到我们刚刚挂载的 U 盘中有一个文件和一个文件夹。现在,我们可以使用*findmnt –-real*列出所有挂载的设备:

$ findmnt --real
TARGET               SOURCE                   FSTYPE      OPTIONS
/                    /dev/sda2                ext4        rw,relatime
├─/home              /dev/sdb1                ext4        rw,relatime
├─/mnt/usb           /dev/sdc1                vfat        rw,relatime,fmask=0022,dmask=0022,codepage=437,errors=remount-ro
└─/boot/efi          /dev/sda1                vfat        rw,relatime,fmask=0022,dmask=0022,codepage=437,errors=remount-ro

如我们所见,系统上安装了四个设备,包括我们的 U 盘。每个设备都有一个目标目录,我们可以从中访问设备的文件系统。最后,我们可以卸载 U 盘:

$ umount /dev/sdc1

3. 绑定

正如我们在上一节中看到的,我们通常将设备挂载到目录中。但是,我们也可以将一个目录挂载到另一个目录上

我们通过使用带有*–bind参数的mount命令来做到这一点。我们可以将绑定挂载视为别名。例如,当我们将目录/tmp/foo绑定到/tmp/bar*时,两者将引用相同的内容。

我们可以从*/tmp/bar访问/tmp/foo*中的文件,反之亦然。

我们可以使用任何目录作为绑定挂载源。如果源目录是设备的挂载点,则整个设备绑定挂载到目标目录。相反,如果源是设备的子目录,则设备将从该子目录开始绑定安装。

当我们使用*–bind参数时,源目录中的挂载点不会重新挂载。因此,如果我们想绑定挂载一个目录和该目录内的所有子挂载,我们必须使用–rbind*参数。

进行绑定挂载后,我们将无法访问目标目录中的原始内容。当我们挂载设备时也会发生同样的情况。让我们创建一个目录*/tmp/foo*,其中包含一些文件:

$ mkdir /tmp/foo
$ touch /tmp/foo/bind_mount_example
$ touch /tmp/foo/blogdemo

现在,让我们创建一个*/tmp/bar目录并将我们的/tmp/foo*目录挂载到它:

$ mkdir /tmp/bar
$ mount --bind /tmp/foo /tmp/bar

现在,让我们看看两个文件夹上的内容:

$ ls -l /tmp/foo
total 0
-rw-r--r-- 1 blogdemo users 0 Oct 30 19:26 blogdemo
-rw-r--r-- 1 blogdemo users 0 Oct 30 19:26 bind_mount_example
$ ls -l /tmp/bar
total 0
-rw-r--r-- 1 blogdemo users 0 Oct 30 19:26 blogdemo
-rw-r--r-- 1 blogdemo users 0 Oct 30 19:26 bind_mount_example

我们可以看到两个文件夹具有相同的内容。让我们在/tmp/bar中创建一个新文件,我们将看到内容也可以从/tmp/foo*访问:*

$ echo "new file" > /tmp/bar/new_file
$ cat /tmp/foo/new_file 
new file

我们可以使用findmnt –real列出所有挂载点,包括绑定挂载:

$ findmnt --real
TARGET               SOURCE                   FSTYPE      OPTIONS
/                    /dev/sda2                ext4        rw,relatime
├─/home              /dev/sdb1                ext4        rw,relatime
├─/boot/efi          /dev/sda1                vfat        rw,relatime,fmask=0022,dmask=0022,codepage=437,errors=remount-ro
└─/tmp/bar           /dev/sda2[/tmp/foo]      ext4        rw,relatime

最后,让我们卸载*/tmp/bar*:

$ umount /tmp/bar

4. 用例

在本节中,我们将看到两个使用绑定挂载的示例。一个为我们提供了一种访问被挂载点隐藏的文件的方法。另一个在使用chroot环境时很有用,它允许我们访问它之外的文件。

4.1. 访问被挂载点隐藏的文件

当我们在目录上挂载设备时,该目录的先前内容会被挂载点隐藏。因此,我们无法通过传统方式访问原始内容。但是,我们从上一节中了解到,当我们使用*–bind参数时,mount不会绑定来自源目录的子挂载。因此,我们可以使用此功能来访问隐藏文件。假设我们有/mnt/usb*目录并且我们还没有安装任何 USB 记忆棒。让我们在上面写一些文件:

$ echo blogdemo > /mnt/usb/hidden_file_example
$ ls /mnt/usb
hidden_file_example

然后,让我们挂载 U 盘,我们会看到hidden_file_example文件不再列出:

$ mount /dev/sdc1 /mnt/usb
$ ls /mnt/usb
appendix.pdf pictures/

所以现在,我们可以使用绑定挂载来访问hidden_file_example文件。我们将首先创建*/tmp/oldmnt目录,然后将/mnt*绑定挂载到我们的新目录中:

$ mkdir /tmp/oldmnt
$ mount --bind /mnt /tmp/oldmnt

然后,我们可以在*/tmp/oldmnt/usb中看到原来的/mnt/usb*内容:

$ ls /tmp/oldmnt/usb
hidden_file_example
$ cat /tmp/oldmnt/usb/hidden_file_example 
blogdemo

我们可以注意到,在进行绑定挂载时,我们使用*/mnt作为源目录。这是因为–bind参数只忽略子挂载。如果我们使用/mnt/usb*,我们会将 USB 记忆棒绑定安装在*/tmp/oldmnt中。最后,让我们卸载两个挂载点/mnt/usb/tmp/oldmnt*:

$ umount /mnt/usb /tmp/oldmnt

4.2. 在chroot环境之外访问文件

何时使用绑定挂载的另一个示例是在chroot环境中挂载目录。chroot 是一个为进程提供有限隔离的程序 。使用chroot,我们可以在执行程序时设置根目录。

例如,我们可以使用chroot在根目录*/home/apache下运行httpd*。这将有效地使*/home/apache作为该进程的根目录/。因此,例如,目录/home/apache/www将变为/www*。这样,httpd进程将无法访问外部的任何文件*/home/apache*。

**现在,在chroot环境中执行的进程如何访问它之外的文件?例如,该进程可能需要访问来自/lib64的库和来自/bin的二进制文件。为了解决这个问题,我们可以使用绑定挂载来使这些目录可以从chroot目录访问。

让我们准备一个目录*/home/chroot以使用chroot命令。首先,让我们创建目录/home/chroot*,里面有两个目录,binlib64

$ mkdir /home/chroot
$ mkdir /home/chroot/bin
$ mkdir /home/chroot/lib64

然后,让我们将 mount /bin绑定到*/home/chroot/bin并将/lib64绑定到/home/chroot/lib64*:

$ mount --bind /bin /home/chroot/bin
$ mount --bind /lib64 /home/chroot/lib64

最后,我们可以使用chroot将根目录更改为*/home/chroot*:

$ chroot /home/chroot

现在,我们有了以*/home/chroot为根目录的 shell。让我们使用ls*列出根目录的内容:

$ ls -l / 
total 16
drwxr-xr-x 2 0 0  4096 Oct 29 21:47 bin
drwxr-xr-x 8 0 0 12288 Oct 29 17:02 lib64
$ ls -l /bin/bash
-rwxr-xr-x 1 0 0 1218032 May  5 16:37 /bin/bash
$ ls -l /lib64/libc-*.so
-rwxr-xr-x 1 0 0 2173576 Aug 17 20:03 /lib64/libc-2.33.so

如我们所见,我们在chroot环境中,只能访问*/bin/lib64*。此外,我们可以列出其中的文件。