了解绑定挂载
1. 概述
我们在 Linux 挂载设备的过程中使用了mount和umount 命令。但是,还有另一种挂载点类型,称为绑定挂载。在本教程中,我们将了解什么是绑定挂载,并且还会看到一些何时可以使用它的示例。
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*,里面有两个目录,bin和lib64:
$ 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*。此外,我们可以列出其中的文件。