以程式方式辨識文件系統的塊設備
以下程式碼在 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 函式,它可以進行一些醜陋的文本解析,這很有效,只是看起來很 hackish。儘管 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 返回文件系統,而不是塊設備。查詢文件系統上的資訊不會返回有關塊設備的任何元數據,例如其序列號或型號。為什麼我會以程式方式想知道硬碟的序列號或硬碟型號?我希望這不會是任何人的嚴重後續問題。
查看您提供的程式碼,您似乎希望能夠將文件系統上的文件映射回它所在的物理磁碟。似乎沒有考慮 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}'