以编程方式识别文件系统的块设备

以编程方式识别文件系统的块设备

以下代码在 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}'

相关内容