![以编程方式识别文件系统的块设备](https://linux22.com/image/135128/%E4%BB%A5%E7%BC%96%E7%A8%8B%E6%96%B9%E5%BC%8F%E8%AF%86%E5%88%AB%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%9D%97%E8%AE%BE%E5%A4%87.png)
以下代码在 RedHat 7 上使用df verison 8.2
和进行了测试lsblk version 2.23.2
。这很重要,因为 lsblk 实用程序比 RedHat 6 版本 (2.17.2) 具有更多的输出选项
确定包含文件的文件系统相当容易:
df -h /path/to/file | tail -n 1 | awk '{print $1}'
然而,确定哪个块设备包含该文件系统是非常困难的。当然,您可以使用 手动确定块设备lsblk -f
,但我想知道如何以自动方式执行此操作。
我已经做了一些相当深入的挖掘,但我还没有找到任何方法来做到这一点。这很奇怪,因为似乎有一个常见的用例(扫描驱动器上的目录,并返回您扫描的物理磁盘的序列号!)
我创建了一个递归 bash 函数,它执行一些丑陋的文本解析,它有效,但看起来很黑客。尽管 lsblk 文档似乎确实建议如果您使用该--output
开关,那么您将在版本更新中拥有可靠的脚本
function findBlockDevice {
fileSystem="${1}"
count="${2}"
potentialBlockDeviceOutput=$(lsblk --paths --output name,type | grep "${fileSystem}" -B${count} | head -n 1)
blockDevice=$(echo ${potentialBlockDeviceOutput} | awk '{print $1}')
blockType=$(echo ${potentialBlockDeviceOutput} | awk '{print $2}')
if [[ "${blockType}" != "disk" ]]; then
count=$(( count + 1 ))
findBlockDevice "${fileSystem}" "${count}"
else
echo "${blockDevice}"
fi
}
用法:
# Assume directory is on /dev/sda1
scanDirectory='/media/suspiciousDrive'
fileSystem=$(df -h ${scanDirectory} | tail -n 1 | awk '{print $1}')
blockDevice=$(findBlockDevice ${fileSystem} 0)
echo "${fileSystem}" # /dev/sda1
echo "${blockDevice}" # /dev/sda
# Now we can get the disk information to use in a report
lsblk --nodeps --paths --pairs --output NAME,SERIAL,MOUNTPOINT,VENDOR,\
FSTYPE,UUID,MODEL,SIZE,TYPE,WWN,STATE ${fileSystem}
编辑: df 的输出是不够的,因为给定文件系统与磁盘时,从 lsblk 实用程序返回的结果是不同的。当给定整个块设备时,以下命令返回许多不同的信息,而不是仅给定文件系统
# Run this on your machine and notice the significant difference
lsblk --nodeps --paths --pairs --output NAME,SERIAL,VENDOR,MODEL /dev/sda
lsblk --nodeps --paths --pairs --output NAME,SERIAL,VENDOR,MODEL /dev/sda1
最终我想要一个简单的解决方案来解决“扫描此硬盘驱动器并自动返回物理设备的驱动器信息,无论您在驱动器上扫描哪个目录”的问题
我有一个解决方案,它非常复杂,并且想知道是否有更简单的方法。
另一个编辑:我很惊讶这么多人认为这是重复的,或者对为什么 df 的输出不够充分感到困惑。 df 返回文件系统,而不是块设备。查询文件系统上的信息不会返回有关块设备的任何元数据,例如其序列号或型号。为什么我要以编程方式了解硬盘的序列号或硬盘型号?我希望这不会成为任何人提出的严肃的后续问题。
答案1
查看您提供的代码,您似乎希望能够将文件系统上的文件映射回其所在的物理磁盘。似乎没有考虑 RAID、LVM 或加密文件系统。
以下代码将打印包含指定文件的磁盘设备。对于 RAID 和 LVM,该文件可能会出现在多个设备上;在这种情况下,将打印所有相关的磁盘设备名称,每行一个。
read -p 'Filename: ' file
devpart=$(mount | awk -v mount=$(stat --format '%m' "$file") '$3 == mount {print $1}')
lsblk --list | awk -v part="${devpart/#*\/}" '$6 == "disk" {disk = $1} $6 != "disk" && $1 == part {print disk}'