如何使用 Python 获取硬盘序列号

Posted

技术标签:

【中文标题】如何使用 Python 获取硬盘序列号【英文标题】:How to get hard disk serial number using Python 【发布时间】:2011-05-10 18:15:29 【问题描述】:

如何在Linux 上使用Python 获取hard disk 驱动器的serial number

我想使用 Python 模块来执行此操作,而不是运行外部程序,例如 hdparm。也许使用fcntl 模块?

【问题讨论】:

【参考方案1】:

Linux

正如您所建议的,fcntl 是在 Linux 上执行此操作的方法。您要翻译的 C 代码如下所示:

static struct hd_driveid hd;
int fd;

if ((fd = open("/dev/hda", O_RDONLY | O_NONBLOCK)) < 0) 
    printf("ERROR opening /dev/hda\n");
    exit(1);


if (!ioctl(fd, HDIO_GET_IDENTITY, &hd)) 
    printf("%.20s\n", hd.serial_no);
 else if (errno == -ENOMSG) 
    printf("No serial number available\n");
 else 
    perror("ERROR: HDIO_GET_IDENTITY");
    exit(1);

在 Ubuntu 9.10 上翻译成 Python,有点像这样:

import sys, os, fcntl, struct

if os.geteuid() >  0:
    print("ERROR: Must be root to use")
    sys.exit(1)

with open(sys.argv[1], "rb") as fd:
    # tediously derived from the monster struct defined in <hdreg.h>
    # see comment at end of file to verify
    hd_driveid_format_str = "@ 10H 20s 3H 8s 40s 2B H 2B H 4B 6H 2B I 36H I Q 152H"
    # Also from <hdreg.h>
    HDIO_GET_IDENTITY = 0x030d
    # How big a buffer do we need?
    sizeof_hd_driveid = struct.calcsize(hd_driveid_format_str)

    # ensure our format string is the correct size
    # 512 is extracted using sizeof(struct hd_id) in the c code
    assert sizeof_hd_driveid == 512 

    # Call native function
    buf = fcntl.ioctl(fd, HDIO_GET_IDENTITY, " " * sizeof_hd_driveid)
    fields = struct.unpack(hd_driveid_format_str, buf)
    serial_no = fields[10].strip()
    model = fields[15].strip()
    print("Hard Disk Model: %s" % model)
    print("  Serial Number: %s" % serial_no)


## For documentation purposes, this is the struct copied from <hdreg.h>
# struct hd_driveid 
#   unsigned short  config;     /* lots of obsolete bit flags */
#   unsigned short  cyls;       /* Obsolete, "physical" cyls */
#   unsigned short  reserved2;  /* reserved (word 2) */
#   unsigned short  heads;      /* Obsolete, "physical" heads */
#   unsigned short  track_bytes;    /* unformatted bytes per track */
#   unsigned short  sector_bytes;   /* unformatted bytes per sector */
#   unsigned short  sectors;    /* Obsolete, "physical" sectors per track */
#   unsigned short  vendor0;    /* vendor unique */
#   unsigned short  vendor1;    /* vendor unique */
#   unsigned short  vendor2;    /* Retired vendor unique */
#   unsigned char   serial_no[20];  /* 0 = not_specified */
#   unsigned short  buf_type;   /* Retired */
#   unsigned short  buf_size;   /* Retired, 512 byte increments
#                    * 0 = not_specified
#                    */
#   unsigned short  ecc_bytes;  /* for r/w long cmds; 0 = not_specified */
#   unsigned char   fw_rev[8];  /* 0 = not_specified */
#   unsigned char   model[40];  /* 0 = not_specified */
#   unsigned char   max_multsect;   /* 0=not_implemented */
#   unsigned char   vendor3;    /* vendor unique */
#   unsigned short  dword_io;   /* 0=not_implemented; 1=implemented */
#   unsigned char   vendor4;    /* vendor unique */
#   unsigned char   capability; /* (upper byte of word 49)
#                    *  3:  IORDYsup
#                    *  2:  IORDYsw
#                    *  1:  LBA
#                    *  0:  DMA
#                    */
#   unsigned short  reserved50; /* reserved (word 50) */
#   unsigned char   vendor5;    /* Obsolete, vendor unique */
#   unsigned char   tPIO;       /* Obsolete, 0=slow, 1=medium, 2=fast */
#   unsigned char   vendor6;    /* Obsolete, vendor unique */
#   unsigned char   tDMA;       /* Obsolete, 0=slow, 1=medium, 2=fast */
#   unsigned short  field_valid;    /* (word 53)
#                    *  2:  ultra_ok    word  88
#                    *  1:  eide_ok     words 64-70
#                    *  0:  cur_ok      words 54-58
#                    */
#   unsigned short  cur_cyls;   /* Obsolete, logical cylinders */
#   unsigned short  cur_heads;  /* Obsolete, l heads */
#   unsigned short  cur_sectors;    /* Obsolete, l sectors per track */
#   unsigned short  cur_capacity0;  /* Obsolete, l total sectors on drive */
#   unsigned short  cur_capacity1;  /* Obsolete, (2 words, misaligned int)     */
#   unsigned char   multsect;   /* current multiple sector count */
#   unsigned char   multsect_valid; /* when (bit0==1) multsect is ok */
#   unsigned int    lba_capacity;   /* Obsolete, total number of sectors */
#   unsigned short  dma_1word;  /* Obsolete, single-word dma info */
#   unsigned short  dma_mword;  /* multiple-word dma info */
#   unsigned short  eide_pio_modes; /* bits 0:mode3 1:mode4 */
#   unsigned short  eide_dma_min;   /* min mword dma cycle time (ns) */
#   unsigned short  eide_dma_time;  /* recommended mword dma cycle time (ns) */
#   unsigned short  eide_pio;       /* min cycle time (ns), no IORDY  */
#   unsigned short  eide_pio_iordy; /* min cycle time (ns), with IORDY */
#   unsigned short  words69_70[2];  /* reserved words 69-70
#                    * future command overlap and queuing
#                    */
#   unsigned short  words71_74[4];  /* reserved words 71-74
#                    * for IDENTIFY PACKET DEVICE command
#                    */
#   unsigned short  queue_depth;    /* (word 75)
#                    * 15:5 reserved
#                    *  4:0 Maximum queue depth -1
#                    */
#   unsigned short  words76_79[4];  /* reserved words 76-79 */
#   unsigned short  major_rev_num;  /* (word 80) */
#   unsigned short  minor_rev_num;  /* (word 81) */
#   unsigned short  command_set_1;  /* (word 82) supported
#                    * 15:  Obsolete
#                    * 14:  NOP command
#                    * 13:  READ_BUFFER
#                    * 12:  WRITE_BUFFER
#                    * 11:  Obsolete
#                    * 10:  Host Protected Area
#                    *  9:  DEVICE Reset
#                    *  8:  SERVICE Interrupt
#                    *  7:  Release Interrupt
#                    *  6:  look-ahead
#                    *  5:  write cache
#                    *  4:  PACKET Command
#                    *  3:  Power Management Feature Set
#                    *  2:  Removable Feature Set
#                    *  1:  Security Feature Set
#                    *  0:  SMART Feature Set
#                    */
#   unsigned short  command_set_2;  /* (word 83)
#                    * 15:  Shall be ZERO
#                    * 14:  Shall be ONE
#                    * 13:  FLUSH CACHE EXT
#                    * 12:  FLUSH CACHE
#                    * 11:  Device Configuration Overlay
#                    * 10:  48-bit Address Feature Set
#                    *  9:  Automatic Acoustic Management
#                    *  8:  SET MAX security
#                    *  7:  reserved 1407DT PARTIES
#                    *  6:  SetF sub-command Power-Up
#                    *  5:  Power-Up in Standby Feature Set
#                    *  4:  Removable Media Notification
#                    *  3:  APM Feature Set
#                    *  2:  CFA Feature Set
#                    *  1:  READ/WRITE DMA QUEUED
#                    *  0:  Download MicroCode
#                    */
#   unsigned short  cfsse;      /* (word 84)
#                    * cmd set-feature supported extensions
#                    * 15:  Shall be ZERO
#                    * 14:  Shall be ONE
#                    * 13:6 reserved
#                    *  5:  General Purpose Logging
#                    *  4:  Streaming Feature Set
#                    *  3:  Media Card Pass Through
#                    *  2:  Media Serial Number Valid
#                    *  1:  SMART selt-test supported
#                    *  0:  SMART error logging
#                    */
#   unsigned short  cfs_enable_1;   /* (word 85)
#                    * command set-feature enabled
#                    * 15:  Obsolete
#                    * 14:  NOP command
#                    * 13:  READ_BUFFER
#                    * 12:  WRITE_BUFFER
#                    * 11:  Obsolete
#                    * 10:  Host Protected Area
#                    *  9:  DEVICE Reset
#                    *  8:  SERVICE Interrupt
#                    *  7:  Release Interrupt
#                    *  6:  look-ahead
#                    *  5:  write cache
#                    *  4:  PACKET Command
#                    *  3:  Power Management Feature Set
#                    *  2:  Removable Feature Set
#                    *  1:  Security Feature Set
#                    *  0:  SMART Feature Set
#                    */
#   unsigned short  cfs_enable_2;   /* (word 86)
#                    * command set-feature enabled
#                    * 15:  Shall be ZERO
#                    * 14:  Shall be ONE
#                    * 13:  FLUSH CACHE EXT
#                    * 12:  FLUSH CACHE
#                    * 11:  Device Configuration Overlay
#                    * 10:  48-bit Address Feature Set
#                    *  9:  Automatic Acoustic Management
#                    *  8:  SET MAX security
#                    *  7:  reserved 1407DT PARTIES
#                    *  6:  SetF sub-command Power-Up
#                    *  5:  Power-Up in Standby Feature Set
#                    *  4:  Removable Media Notification
#                    *  3:  APM Feature Set
#                    *  2:  CFA Feature Set
#                    *  1:  READ/WRITE DMA QUEUED
#                    *  0:  Download MicroCode
#                    */
#   unsigned short  csf_default;    /* (word 87)
#                    * command set-feature default
#                    * 15:  Shall be ZERO
#                    * 14:  Shall be ONE
#                    * 13:6 reserved
#                    *  5:  General Purpose Logging enabled
#                    *  4:  Valid CONFIGURE STREAM executed
#                    *  3:  Media Card Pass Through enabled
#                    *  2:  Media Serial Number Valid
#                    *  1:  SMART selt-test supported
#                    *  0:  SMART error logging
#                    */
#   unsigned short  dma_ultra;  /* (word 88) */
#   unsigned short  trseuc;     /* time required for security erase */
#   unsigned short  trsEuc;     /* time required for enhanced erase */
#   unsigned short  CurAPMvalues;   /* current APM values */
#   unsigned short  mprc;       /* master password revision code */
#   unsigned short  hw_config;  /* hardware config (word 93)
#                    * 15:  Shall be ZERO
#                    * 14:  Shall be ONE
#                    * 13:
#                    * 12:
#                    * 11:
#                    * 10:
#                    *  9:
#                    *  8:
#                    *  7:
#                    *  6:
#                    *  5:
#                    *  4:
#                    *  3:
#                    *  2:
#                    *  1:
#                    *  0:  Shall be ONE
#                    */
#   unsigned short  acoustic;   /* (word 94)
#                    * 15:8 Vendor's recommended value
#                    *  7:0 current value
#                    */
#   unsigned short  msrqs;      /* min stream request size */
#   unsigned short  sxfert;     /* stream transfer time */
#   unsigned short  sal;        /* stream access latency */
#   unsigned int    spg;        /* stream performance granularity */
#   unsigned long long lba_capacity_2;/* 48-bit total number of sectors */
#   unsigned short  words104_125[22];/* reserved words 104-125 */
#   unsigned short  last_lun;   /* (word 126) */
#   unsigned short  word127;    /* (word 127) Feature Set
#                    * Removable Media Notification
#                    * 15:2 reserved
#                    *  1:0 00 = not supported
#                    *  01 = supported
#                    *  10 = reserved
#                    *  11 = reserved
#                    */
#   unsigned short  dlf;        /* (word 128)
#                    * device lock function
#                    * 15:9 reserved
#                    *  8   security level 1:max 0:high
#                    *  7:6 reserved
#                    *  5   enhanced erase
#                    *  4   expire
#                    *  3   frozen
#                    *  2   locked
#                    *  1   en/disabled
#                    *  0   capability
#                    */
#   unsigned short  csfo;       /*  (word 129)
#                    * current set features options
#                    * 15:4 reserved
#                    *  3:  auto reassign
#                    *  2:  reverting
#                    *  1:  read-look-ahead
#                    *  0:  write cache
#                    */
#   unsigned short  words130_155[26];/* reserved vendor words 130-155 */
#   unsigned short  word156;    /* reserved vendor word 156 */
#   unsigned short  words157_159[3];/* reserved vendor words 157-159 */
#   unsigned short  cfa_power;  /* (word 160) CFA Power Mode
#                    * 15 word 160 supported
#                    * 14 reserved
#                    * 13
#                    * 12
#                    * 11:0
#                    */
#   unsigned short  words161_175[15];/* Reserved for CFA */
#   unsigned short  words176_205[30];/* Current Media Serial Number */
#   unsigned short  words206_254[49];/* reserved words 206-254 */
#   unsigned short  integrity_word; /* (word 255)
#                    * 15:8 Checksum
#                    *  7:0 Signature
#                    */
# ;

抱歉,我认为将原始 C 结构作为注释包含在内很有用。另外,我对fcntlstruct 模块都很陌生,所以我可能正在做一些单一的事情。无论如何,从命令行运行(使用 root privelidges)它看起来像这样(我已经编辑了我的确切序列以保护隐私):

fmark@fmark-laptop:~/Desktop/hdserial$ sudo python hd.py "/dev/sda"
Hard Disk Model: FUJITSU MHV2080BH PL
  Serial Number: NW--------

这是怎么回事?

为了能够理解这里发生了什么,你需要查看原始C程序中的#include &lt;linux/hdreg.h&gt;。这包括导入HDIO_GET_IDENTITY 常量和struct hd_driveid。我已经将结构体作为注释复制到了上面的python源代码中,这里不再赘述。要了解 HDIO_GET_IDENTITY 发生了什么,请用 grep 查找它的源代码(在 Ubuntu 上,它位于 /usr/include/linux/hdreg.h。你应该会找到类似这样的内容:

 #define HDIO_GET_IDENTITY       0x030d  /* get IDE identification info */

因此,您会发现HDIO_GET_IDENTITY 只是一个常量,它告诉 fcntl 您有兴趣获取 HD 信息。您会注意到,相同的值(0x030d 是十六进制表示法的整数)被分配给 Python 代码中的变量。

窗口

我现在意识到您对 Linux 很感兴趣,但我将把它留在这里以备后用。下面将获取Windows上的硬盘序列号(需要安装wmi package):

import wmi
c = wmi.WMI()
for item in c.Win32_PhysicalMedia():
    print item

【讨论】:

太棒了,这很好用。我们想在启动到救援环境的系统上获取序列号,但“hdparm -i”不起作用,所以我们正在尝试这个 Python 代码。 要获得实际序列号的 windows 必须阅读 item.wmi_property('SerialNumber').value 这种方式不支持SCSI的磁盘类型,会报错:HDIO_GET_IDENTITY failed: Invalid argument【参考方案2】:

拿一把螺丝刀打开盒子;-)

如果您在 Windows 上,这可能会解决问题

import win32api
print win32api.GetVolumeInformation("C:\\")

为此,您需要 Windows 的 Mark Hammond 模块 http://python.net/crew/mhammond/

【讨论】:

这将返回卷序列号,而不是 HDD 序列号。有用,但不同。 我知道 Python 自带电池,但我不知道它有螺丝刀!【参考方案3】:

在 Windows 上,您也可以使用内置的subprocess 获取它!

import subprocess

serials = subprocess.check_output('wmic diskdrive get SerialNumber').decode().split('\n')[1:]
serials = [s.strip() for s in serials if s.strip()]

如果您还想要其他信息,例如索引和制造商:

import subprocess

serials = subprocess.check_output('wmic diskdrive get Index, SerialNumber, Manufacturer').decode().split('\n')[1:]

有关可用属性的列表,请查看this documentation。

【讨论】:

【参考方案4】:

窗口

def get_serial_number_of_physical_disk(drive_letter='C:'):
    import wmi
    
    c = wmi.WMI()
    logical_disk = c.Win32_LogicalDisk(Caption=drive_letter)[0]
    partition = logical_disk.associators()[1]
    physical_disc = partition.associators()[0]
    return physical_disc.SerialNumber

例如:

get_serial_number_of_physical_disk(os.getenv('SystemDrive'))

将为您提供包含逻辑系统驱动器的磁盘序列号。

【讨论】:

谢谢!效果很好,只需要用圆括号写os.getenv('SystemDrive') :) 已修复。感谢您提供信息。

以上是关于如何使用 Python 获取硬盘序列号的主要内容,如果未能解决你的问题,请参考以下文章

VC++如何获取机器码?硬盘序列号、CPU编号、BIOS编号等~

centos怎么获取硬盘序列号

如何在 Lua 上使用 Win API 获取硬盘的序列号

国产电脑linux系统如何查看硬盘序列号

Python获取电脑硬件配置的封装类,可以获取CPU序列号主板序列号BIOS序列号硬盘序列号和网卡MAC地址

Python获取电脑硬件配置的封装类,可以获取CPU序列号主板序列号BIOS序列号硬盘序列号和网卡MAC地址