我知道对于linux中的一个磁盘,我们可以使用诸如hdparm
或之类的命令smartctl
来获取它的基本信息。但对于这些命令的实现,我认为它们都是通过读取linux中磁盘的相应文件来实现的。例如,要获取设备的大小/dev/sda,我们可以使用或cat /sys/block/sda/size
之类的命令来代替。那么问题是如何通过直接读取磁盘对应的文件来获取磁盘的序列号。hdparm
smartctl
答案1
我只是尝试一下。它确实通过 ioctl 获取序列号。这是 strace 的一些输出:
open("/dev/sda", O_RDONLY|O_NONBLOCK) = 3
fcntl(3, F_SETFD, FD_CLOEXEC) = 0
ioctl(3, SG_IO, {'S', SG_DXFER_FROM_DEV, cmd[6]=[12, 00, 00, 00, 24, 00], mx_sb_len=32, iovec_count=0, dxfer_len=36, timeout=20000, flags=0, data[36]=["\0\0\5\2[\0\0\0ATA WDC WD5000LPVX-0"...], status=00, masked_status=00, sb[0]=[], host_status=0, driver_status=0, resid=0, duration=0, info=0}) = 0
ioctl(3, SG_IO, {'S', SG_DXFER_FROM_DEV, cmd[16]=[85, 08, 0e, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, ec, 00], mx_sb_len=32, iovec_count=0, dxfer_len=512, timeout=20000, flags=0, data[512]=["zB\377?7\310\20\0\0\0\0\0?\0\0\0\0\0\0\0 W -DXW11"...], status=00, masked_status=00, sb[0]=[], host_status=0, driver_status=0, resid=0, duration=0, info=0}) = 0
ioctl(3, SG_IO, {'S', SG_DXFER_FROM_DEV, cmd[16]=[85, 08, 0e, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, ec, 00], mx_sb_len=32, iovec_count=0, dxfer_len=512, timeout=20000, flags=0, data[512]=["zB\377?7\310\20\0\0\0\0\0?\0\0\0\0\0\0\0 W -DXW11"...], status=00, masked_status=00, sb[0]=[], host_status=0, driver_status=0, resid=0, duration=0, info=0}) = 0
答案2
这是可能的,至少在我的系统上是这样。该解决方案依赖于/run/udev/data
转储数据。
下面是一个 bash 脚本示例:
#!/bin/bash
IFS=$'\n' read -d '' -r -a DRIVES <<< "$(ls /dev/sd*[0-9] 2>/dev/null)"
IFS=$'\n' read -d '' -r -a NVME_DRIVES <<< "$(ls /dev/nvme*[0-9]n[0-9] 2>/dev/null)"
DRIVES+=("${NVME_DRIVES[@]}")
for drive in "${DRIVES[@]}"; do
drive=${drive##*/}
IFS=$'\n' read -d '' -r -a _uevent <<< "$(grep -e "MAJOR" -e "MINOR" "/sys/class/block/${drive}/uevent"| sort | awk -F "=" '{print $2}')"
_serial=$(grep "ID_SERIAL=" "/run/udev/data/b${_uevent[0]}:${_uevent[1]}" | awk -F "=" '{print $2}')
echo "[${drive}] serial: ${_serial} short: ${_serial##*_}"
done
该脚本的逻辑如下:
- 获取系统中的驱动器列表
- 读取每个驱动设备的块地址
- 从 udev 元数据中获取数据
步骤是从 strace 中扣除的lsblk --nodeps -no serial /dev/sda
答案3
您可以使用 strace 来了解 smartctl 如何获取磁盘的序列号。 CMD 行如下:strace smartctl -a /dev/sda。也许它只是通过 ioctl 获取序列号。
答案4
在 Linux 上磁盘 sda:
egrep '^E:ID_SERIAL' /run/udev/data/b$(basename $(readlink --canonicalize /sys/block/sda/bdi)) E:ID_SERIAL=Samsung_SSD_850_EVO_500GB_S3R3NF0JA99600T E:ID_SERIAL_SHORT=S3R3NF0JA99600T
日期 && uname --kernel-release 2021 年太平洋夏令时间 11 月 2 日星期二上午 11:50:37 5.13.0-20-通用