确定目录所在的设备

Str*_*Bad 69 directory mount block-device

如果我做

# cd /
# ln -s /home test
# cd test
# mount --bind $PWD /mnt
Run Code Online (Sandbox Code Playgroud)

输入/proc/mounts

/dev/sda2 /mnt ext4 rw,noatime,data=ordered 0 0
Run Code Online (Sandbox Code Playgroud)

这是安装到的设备/home并且不容易从中推断出$PWD/test. /proc/mounts考虑到绑定挂载可能是一个目录/文件,该目录/文件可能被符号链接、其他绑定挂载等“遮蔽”,我如何确定哪个设备(即 /dev/sda2)通常会出现?

slm*_*slm 69

如果我理解你的问题,你想知道哪个设备用于给定的安装。为此,您可以使用以下df命令:

$ df -h 
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/fedora_greeneggs-root   50G   21G   27G  44% /
devtmpfs                           3.8G     0  3.8G   0% /dev
tmpfs                              3.8G   14M  3.8G   1% /dev/shm
tmpfs                              3.8G  984K  3.8G   1% /run
tmpfs                              3.8G     0  3.8G   0% /sys/fs/cgroup
tmpfs                              3.8G  3.4M  3.8G   1% /tmp
/dev/sda1                          477M   99M  349M  23% /boot
/dev/mapper/fedora_greeneggs-home  402G  184G  198G  49% /home
Run Code Online (Sandbox Code Playgroud)

要查找在哪个设备上找到特定文件/目录,请将文件作为参数提供给df. 使用您的示例:

$ df -h /mnt
Filesystem                         Size  Used Avail Use% Mounted on
/dev/sda1                          477M   99M  349M  23% /
Run Code Online (Sandbox Code Playgroud)

您也可以使用以下mount命令:

$ mount | grep '^/dev'
/dev/mapper/fedora_greeneggs-root on / type ext4 (rw,relatime,seclabel,data=ordered)
/dev/sda1 on /boot type ext4 (rw,relatime,seclabel,data=ordered)
/dev/mapper/fedora_greeneggs-home on /home type ext4 (rw,relatime,seclabel,data=ordered)
Run Code Online (Sandbox Code Playgroud)

为每个设备安装的目录是上面输出中的第三个参数。所以对于设备/dev/sda1将是/boot. 其他设备正在使用 LVM(逻辑卷管理),需要进一步查询以了解 LVM 正在使用哪个实际设备。

  • @StrongBad 如果您在被符号链接遮挡时必须确定挂载点/设备,您应该将其放在您的问题中。获得正确答案会容易得多。 (2认同)

rud*_*ier 54

在Linux上,我们findmntutil-linux正是为此做出

findmnt -n -o SOURCE --target /path/to/FILE
Run Code Online (Sandbox Code Playgroud)

其他解决方案的优点是,如果路径被符号链接或重复绑定安装遮挡,它仍然有效。


eth*_*ish 14

我所知道的最准确的方法是使用 lstat() 系统调用的输出。具体来说,st_dev 字段。有一个命令行实用程序 stat(1) 可用于查看此信息。例如,我的笔记本电脑上“stat /etc/issue”的输出:

File: ‘/etc/issue’
  Size: 65          Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 1610916043  Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Run Code Online (Sandbox Code Playgroud)

注意第三行,第一个字段,“设备”。这里列出了 801h。该值可以分为两个字节,8 和 1。第一个字节称为主编号,第二个字节是次要编号。因此,下一步是弄清楚设备主要 8、次要 1 是什么。

我发现咨询 /proc/partitions 是最快的。就我而言,/proc/partitions 包含以下内容:

major minor  #blocks  name

   8       16  234431064 sdb
   8       17   33554432 sdb1
   8       18  200875608 sdb2
   8        0  500107608 sda
   8        1  500106584 sda1
Run Code Online (Sandbox Code Playgroud)

从输出中可以清楚地看出,major 8,minor 1 是 sda1。我们可以用 ls -l /dev/sda1 确认这一点

brw-rw---- 1 root disk 8, 1 May  8 05:33 /dev/sda1
Run Code Online (Sandbox Code Playgroud)

注意日期戳前的 8, 1。

理解/记住像 /dev/sda1 这样的设备文件的名称只是一个标签很重要。主要和次要编号是设备文件的重要值。如果您感到好奇,请查看用于创建设备文件的 mknod(1) 实用程序。我可以使用以下语法创建一个名为 aardvark 的新 /dev 条目,其中主要为 8,次要为 18:

mknod /dev/aardvark b 8 18
Run Code Online (Sandbox Code Playgroud)

然后,我可以轻松安装它:

mount /dev/aardvark /mnt
Run Code Online (Sandbox Code Playgroud)

并且,如果我们查看 mount 命令的输出或 /proc/mounts 的内容,我们会看到:

/dev/aardvark on /mnt type xfs (rw,relatime,attr2,inode64,noquota)
Run Code Online (Sandbox Code Playgroud)

df -h 显示:

/dev/aardvark   192G  154G   38G  81% /mnt
Run Code Online (Sandbox Code Playgroud)

...无论如何,所有这一切的目的是为了说明识别块设备的重要细节是主要和次要号码 - 而不是设备文件标签 - 并且使用 lstat() 系统调用是最好的方法查询这些值。

作为最后一条评论,我只是重新阅读了您的问题以确保我正在回答它,并且我意识到您在问什么源设备标签会显示在 /proc/mounts 中以进行绑定安装。这将与用于绑定挂载的文件系统挂载点源的原始 mount(2) 调用中使用的源设备标签相同。也许一个例子会有所帮助:

我有 /dev/sdb2 和 /dev/aardvark(同上)。它们都是主要的 8,次要的 18。注意,我将安装相同的文件系统两次。我执行以下操作:

mkdir /mnt1 /mnt2 /foo

mount /dev/aardvark /mnt1
mount /dev/sdb2 /mnt2
Run Code Online (Sandbox Code Playgroud)

请注意,我在 /mnt1 中创建了目录 somedir。但是由于 /mnt1 和 /mnt2 安装了相同的文件系统,somedir 也可以通过 /mnt2 访问。

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

mount -o bind /mnt1/somedir /foo/left
mount -o bind /mnt2/somedir /foo/right
Run Code Online (Sandbox Code Playgroud)

现在,如果我们检查 /proc/mounts,我们会看到:

/dev/aardvark /mnt1 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdb2 /mnt2 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/aardvark /foo/left xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdb2 /foo/right xfs rw,relatime,attr2,inode64,noquota 0 0
Run Code Online (Sandbox Code Playgroud)

/foo/... 绑定挂载上的源设备标签与文件系统 mount(2) 调用中最初提供的值相同。请记住,我的示例中的 /dev/aardvark 和 /dev/sdb2 是同一个设备。

我意识到我刚刚输入了一本小说,前半部分根本没有真正回答你的问题,但删除它似乎太浪费了。也许它会帮助别人。

祝你好运。

PS 请记住,某些文件系统是基于网络的——比如 NFS 或 CIFS——或者是虚拟的——比如 procfs 或 sysfs,并且没有源块设备。我不知道什么会作为 stat 输出中的设备返回,只是为了它的价值。

  • 第一部分肯定有助于我理解最后一部分。 (2认同)

小智 7

给出以下典型的安装点:

\n\n
$ df --output=target\nMounted on\n/\n/dev\n/run\n/sys/fs/cgroup\n/run/lock\n/run/shm\n/run/user\n
Run Code Online (Sandbox Code Playgroud)\n\n

stat --format %m <path>将以可循环捕获的方式仅打印挂载点(尽管您需要检查退出代码以明确检测权限错误;挂载表方法在此获胜):

\n\n
$ stat --format %m /\n/\n$ stat --format %m /tmp\n/\n$ stat --format %m /proc\n/proc\n$ stat --format %m /run\n/run\n$ stat --format %m /run/mount\n/run\n$ stat --format %m /run/user\n/run/user\n$ stat --format %m /run/user/1000/dconf\n/run/user\n$ stat --format %m /run/user/1000/gvfs\n/run/user/1000/gvfs\n
Run Code Online (Sandbox Code Playgroud)\n\n

像往常一样,符号链接需要小心一些:

\n\n
$ ls -lh ~/.gvfs\n/home/cwillu/.gvfs -> /run/user/1000/gvfs\n$ stat --format %m ~/.gvfs\n/run/user/1000/gvfs\n$ stat --format %m ~/.gvfs\n/\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然,记住在编写脚本时使用引号。考虑带有空格等的安装点路径:

\n\n
$ mkdir /tmp/Something\\ Like\\ This\\!\n$ sudo mount none /tmp/Something\\ Like\\ This\\! -t tmpfs\n$ stat --format %m /tmp/Something\\ Like\\ This\\!\n/tmp/Something Like This!\n$ touch /tmp/Something\\ Like\\ This\\!/pretend-I\\\'m-big\n$ ls /tmp/Something\\ Like\\ This\\!\npretend-I\'m-big\n
Run Code Online (Sandbox Code Playgroud)\n\n

你多大

\n\n
$ du $(stat --format %m /tmp/Something\\ Like\\ This\\!/)\ndu: cannot access /tmp/Something: No such file or directory\ndu: cannot access Like: No such file or directory\ndu: cannot access This!: No such file or directory\n\n$ du "$(stat --format %m /tmp/Something\\ Like\\ This\\!/)"\n0   /tmp/Something Like This!\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的发行版的制表符补全功能甚至无法正确完成此操作,因此我们只需使用回车符、换行符和空格来通配此示例安装点:

\n\n
$ stat --format %m /tmp/Something*\n/tmp/Something   \nLike   This!\n\n$ a="$(stat --format %m /tmp/Something*)"\n    # the above assignment is actually the one place you don\'t need quotes, \n    # but `export a=...` or similar _would_ need them, so we\'ll just put them in;\n    # they don\'t change the behaviour in this form of assignment.\n\n$ stat "$a"\n  File: \xe2\x80\x98/tmp/Something   \\r\\n\\rLike   This!\xe2\x80\x99\n  Size: 40          Blocks: 0          IO Block: 4096   directory\nDevice: 7bh/123d    Inode: 1279171     Links: 2\nAccess: (1777/drwxrwxrwt)  Uid: (    0/    root)   Gid: (    0/    root)\nAccess: 2016-09-30 11:43:17.933467344 -0600\nModify: 2016-09-30 11:43:17.933467344 -0600\nChange: 2016-09-30 11:43:17.933467344 -0600\n Birth: -\n
Run Code Online (Sandbox Code Playgroud)\n