简体   繁体   English

给出路径的挂载点

[英]Give the mount point of a path

The following, very non-robust shell code will give the mount point of $path :以下非常不健壮的 shell 代码将给出$path的挂载点:

(for i in $(df|cut -c 63-99); do case $path in $i*) echo $i;; esac; done) | tail -n 1

Is there a better way to do this in shell?有没有更好的方法在 shell 中做到这一点?

Postscript后记

This script is really awful, but has the redeeming quality that it Works On My Systems.这个脚本真的很糟糕,但它具有在我的系统上工作的可取之处。 Note that several mount points may be prefixes of $path .请注意,几个挂载点可能是$path前缀。

Examples On a Linux system:示例在 Linux 系统上:

cas@txtproof:~$ path=/sys/block/hda1
cas@txtproof:~$ for i in $(df -a|cut -c 57-99); do case $path in $i*) echo $i;; esac; done| tail -1
/sys

On a Mac OSX system在 Mac OSX 系统上

cas local$ path=/dev/fd/0
cas local$ for i in $(df -a|cut -c 63-99); do case $path in $i*) echo $i;; esac; done| tail -1
/dev

Note the need to vary cut's parameters, because of the way df's output differs;注意需要改变 cut 的参数,因为 df 的输出方式不同; using awk solves this, but even awk is non-portable, given the range of result formatting various implementations of df return.使用 awk 解决了这个问题,但即使 awk 也是不可移植的,因为结果格式的范围是 df return 的各种实现。

Answer It looks like munging tabular output is the only way within the shell, but回答看起来 munging tabular output 是 shell 中的唯一方法,但是

df -P "$path"  | tail -1 | awk '{ print $NF}'

based on ghostdog74's answer, is a big improvement on what I had.基于 ghostdog74 的回答,是对我所拥有的一个很大的改进。 Note two new issues: firstly, df $path insists that $path names an existing file, the script I had above doesn't care;注意两个新问题:首先, df $path坚持$path命名现有文件,我上面的脚本并不关心; secondly, there are no worries about dereferencing symlinks.其次,不必担心取消引用符号链接。 This doesn't work if you have mount points with spaces in them, which occurs if one has removable media with spaces in their volume names.如果您的挂载点中有空格,这将不起作用,如果一个可移动媒体的卷名中有空格,就会发生这种情况。

It's not difficult to write Python code to do the job properly.编写 Python 代码来正确完成这项工作并不困难。

df将路径作为参数,所以像这样的东西应该相当健壮;

df "$path" | tail -1 | awk '{ print $6 }'

In theory stat will tell you the device the file is on, and there should be some way of mapping the device to a mount point.理论上stat会告诉您文件所在的设备,并且应该有某种方式将设备映射到安装点。

For example, on linux, this should work:例如,在 linux 上,这应该有效:

stat -c '%m' $path

Always been a fan of using formatting options of a program, as it can be more robust than manipulating output (eg if the mount point has spaces).一直喜欢使用程序的格式化选项,因为它比操作输出更健壮(例如,如果挂载点有空格)。 GNU df allows the following: GNU df允许以下内容:

df --output=target "$path" | tail -1

Unfortunately there is no option I can see to prevent the printing of a header, so the tail is still required.不幸的是,我无法看到阻止打印标题的选项,因此仍然需要尾部。

i don't know what your desired output is, therefore this is a guess我不知道你想要的输出是什么,因此这是一个猜测

#!/bin/bash

path=/home
df | awk -v path="$path" 'NR>1 && $NF~path{
 print $NF
}'

Using cut with -c is not really reliable, since the output of df will be different , say a 5% can change to 10% and you will miss some characters.使用带有 -c 的 cut 并不是很可靠,因为 df 的输出会有所不同,比如 5% 可以更改为 10% 并且您会错过一些字符。 Since the mount point is always at the back, you can use fields and field delimiters.由于挂载点总是在后面,您可以使用字段和字段分隔符。 In the above, $NF is the last column which is the mount point.在上面, $NF 是最后一列,它是挂载点。

I would take the source code to df and find out what it does besides calling stat as Douglas Leeder suggests.我会将源代码带到 df 并找出它除了像 Douglas Leeder 建议的那样调用stat之外还做了什么。

Line-by-line parsing of the df output will cause problems as those lines often look like df输出的逐行解析会导致问题,因为这些行通常看起来像

/dev/mapper/VOLGROUP00-logical--volume
                      1234567  1000000  200000  90% /path/to/mountpoint

With the added complexity of parsing those kinds of lines as well, probably calling stat and finding the mountpoint is less complex.由于解析这些类型的行也增加了复杂性,可能调用stat并找到挂载点就不那么复杂了。

If you want to use only df and awk to find the filesystem device/remote share or a mount point and they include spaces you can cheat by defining the field separator of awk to be a regular expression that matches the format of the numeric sizes used to display total size, used space, available space and capacity percentage.如果您只想使用 df 和 awk 来查找文件系统设备/远程共享或挂载点,并且它们包含空格,您可以通过将 awk 的字段分隔符定义为与用于匹配的数字大小格式的正则表达式来作弊显示总大小、已用空间、可用空间和容量百分比。 By defining those columns as the field separator you are then left with $1 representing the filesystem device/remote share and $NF representing the mount path.通过将这些列定义为字段分隔符,您将剩下$1代表文件系统设备/远程共享和$NF代表安装路径。

Take this for example:以这个为例:

[root@testsystem ~] df -P
Filesystem                       1024-blocks        Used Available Capacity Mounted on
192.168.0.200:/NFS WITH SPACES   11695881728 11186577920 509303808      96% /mnt/MOUNT WITH SPACES

If you attempt to parse this with the quick and dirty awk '{print $1}' or awk '{print $NF}' you'll only get a portion of the filesystem/remote share path and mount path and that's no good.如果您尝试使用快速而肮脏的awk '{print $1}'awk '{print $NF}'解析它,您将只会获得文件系统/远程共享路径和挂载路径的一部分,这是不好的。 Now make awk use the four numeric data columns as the field separator.现在让 awk 使用四个数字数据列作为字段分隔符。

[root@testsystem ~] df -P "/mnt/MOUNT WITH SPACES/path/to/file/filename.txt" | \
awk 'BEGIN {FS="[ ]*[0-9]+%?[ ]+"}; NR==2 {print $1}'
192.168.0.200:/NFS WITH SPACES

[root@testsystem ~] df -P "/mnt/MOUNT WITH SPACES/path/to/file/filename.txt" | \
awk 'BEGIN {FS="[ ]*[0-9]+%?[ ]+"}; NR==2 {print $NF}'
/mnt/MOUNT WITH SPACES

Enjoy :-)享受 :-)

Edit: These commands are based on RHEL/CentOS/Fedora but should work on just about any distribution.编辑:这些命令基于 RHEL/CentOS/Fedora,但应该适用于任何发行版。

Just had the same problem.刚刚有同样的问题。 If some mount point (or the mounted device) is sufficent as in my case You can do:如果某些挂载点(或已挂载的设备)在我的情况下就足够了,您可以执行以下操作:

DEVNO=$(stat -c '%d' /srv/sftp/testconsumer)
MP=$(findmnt -n -f -o TARGET /dev/block/$((DEVNO/2**8)):$((DEVNO&2**8-1)))

(or split the hex DEVNO %D with /dev/block/$((0x${DEVNO:0:${#DEVNO}-2})):$((0x${DEVNO:2:2})) ) (或将十六进制 DEVNO %D拆分为/dev/block/$((0x${DEVNO:0:${#DEVNO}-2})):$((0x${DEVNO:2:2}))

Alternatively the following loop come in to my mind, out of ideas why I cannot find proper basic command..或者,以下循环出现在我的脑海中,出于为什么我找不到合适的基本命令的想法..

TARGETPATH="/srv/sftp/testconsumer"
TARGETPATHTMP=$(readlink -m "$TARGETPATH")
[[ ! -d "$TARGETPATHTMP" ]] && TARGETPATHTMP=$(dirname "$TARGETPATH")
TARGETMOUNT=$(findmnt -d backward -f -n -o TARGET --target "$TARGETPATHTMP")
while [[ -z "$TARGETMOUNT" ]]
do
  TARGETPATHTMP=$(dirname "$TARGETPATHTMP")
  echo "$TARGETPATHTMP"
  TARGETMOUNT=$(findmnt -d backward -f -n -o TARGET --target "$TARGETPATHTMP")
done

This should work always but is much more then I expect for such simple task?这应该总是有效,但比我对这种简单任务的期望要多得多?

(Edited to use readlink -f to allow for non existing files, -m or -e for readlink could be used instead if more components might not exists or all components must exists.) (编辑为使用readlink -f以允许不存在的文件,如果可能不存在更多组件或所有组件必须存在,则可以使用 -m 或 -e 代替 readlink。)

我用这个:

df -h $path | cut -f 1 -d " " | tail -1

Linux has this, which will avoid problem with spaces: Linux 有这个,这将避免空格问题:

lsblk -no MOUNTPOINT ${device}

Not sure about BSD land.不确定BSD土地。

mount | grep "^$path" | awk '{print $3}'
f () { echo $6; }; f $(df -P "$path" | tail -n 1)

I missed this when I looked over prior questions: Python: Get Mount Point on Windows or Linux , which says that os.path.ismount(path) tells if path is a mount point.当我查看之前的问题时,我错过了这一点: Python: Get Mount Point on Windows or Linux ,它说os.path.ismount(path)告诉 path 是否是一个挂载点。

My preference is for a shell solution, but this looks pretty simple.我更喜欢 shell 解决方案,但这看起来很简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM