原文地址: https://www.tony-yin.site/201...
早前写过一篇【利用Raid卡工具获取逻辑盘是否为SSD】的文章,大概讲述了如何经过raid
卡工具判断一个逻辑磁盘对应物理磁盘是否为SSD
,当时主要提到了megacli
和sas3ircu
这两种工具,核心是如何经过raid
卡工具定位到逻辑磁盘对应的物理磁盘的位置,当时的方式如今看来在有些场景会存在缺陷。php
当时的方案主要是先经过lspci
获取raid
卡型号,而后找到对应的raid
卡型号,紧接着经过lsscsi
命令获取逻辑磁盘的targetid
,再经过raid
卡工具根据targetid
定位到对应的物理盘。当时的方案在多controller
的场景下存在问题,可能会出现重复target id
的状况,因此这时候只能再借助controller id
来定位惟一的磁盘了。总而言之,想真正定位逻辑磁盘对应的物理磁盘,就必需要获取到磁盘的controller id
,enclosure id
和slot number
,有了这三个参数,即可以获取该磁盘的信息,或者对该物理磁盘进行点灯、响音和作raid
等操做。linux
那么,具体如何定位逻辑磁盘的物理位置呢?且看下文分析ios
经过lspci
命令能够获取到操做系统上全部raid
卡信息,咱们能够看到每一个raid
卡最前面都有一串数字,好比第一行是02:00.0
,第二行是03:00.0
,这里的02
和03
表示的是raid
卡的busid
,即raid
卡控制器在pci
总线上的id
。git
[root@tony ~]# lspci | grep "LSI Logic" 02:00.0 RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS-3 3008 [Fury] (rev 02) 03:00.0 RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS-3 3108 [Invader] (rev 02)
在linux
中,一切皆文件,每一个文件都有本身的惟一标识,对于磁盘而言,pcipath
就是它的惟一标识,pci
总线上面有不少控制器,好比scsi
控制器,而磁盘又存在于scsi
控制器上,因此咱们能够在lsscsi
命令获取到的scsi
设备列表中查看到操做系统上的磁盘信息。github
以sda
为例,咱们能够在/dev/disk/by-path
目录下查看到磁盘的pcipath
shell
[root@tony ~]# ll /dev/disk/by-path/ total 4 lrwxrwxrwx 1 root root 9 May 11 10:30 pci-0000:02:00.0-scsi-0:2:0:0 -> ../../sda lrwxrwxrwx 1 root root 10 May 11 10:30 pci-0000:02:00.0-scsi-0:2:0:0-part1 -> ../../sda1 lrwxrwxrwx 1 root root 10 May 11 10:30 pci-0000:02:00.0-scsi-0:2:0:0-part2 -> ../../sda2 lrwxrwxrwx 1 root root 9 May 11 16:22 pci-0000:02:00.0-scsi-0:2:1:0 -> ../../sdb lrwxrwxrwx 1 root root 9 May 11 16:22 pci-0000:02:00.0-scsi-0:2:10:0 -> ../../sdk
因为在linux
中,udev
是用户态的设备管理,因此咱们也能够经过udev
获取。框架
[root@tony ~]# udevadm info --query=symlink --name=sda disk/by-id/scsi-36509a4c0ac86790022337b9105005435 disk/by-id/wwn-0x6509a4c0ac86790022337b9105005435 disk/by-path/pci-0000:02:00.0-scsi-0:2:0:0
这边咱们能够获得磁盘sda
的pcipath
为pci-0000:02:00.0-scsi-0:2:0:0
,02
就是磁盘的raid
卡的bus id
,后面的00
表示channel id
,再后面的0:2:0:0
就和lsscsi
获取的同样了,其中2
就表示target id
。工具
因此经过bud id
,咱们能够获取到磁盘对应的raid
卡型号,根据对应的raid
卡工具操做磁盘。这边咱们只讨论megaraid
,因此工具也就是megacli
了。spa
上面咱们获取到了磁盘的target id
和对应raid
卡的bus id
,而对于megacli
工具而言,每一个raid
卡都有一个与之对应的controller
。操作系统
[root@tony ~]# /opt/MegaRAID/MegaCli/MegaCli64 -AdpGetPciInfo -aall -NoLog PCI information for Controller 0 -------------------------------- Bus Number : 2 Device Number : 0 Function Number : 0 PCI information for Controller 1 -------------------------------- Bus Number : 3 Device Number : 0 Function Number : 0 Exit Code: 0x00
这边咱们能够看到megacli
获取到了两个controller
,也就对应上面lspci
获取到的两张raid
卡。细心的朋友能够发现这边有一个Bus Number
,分别为2
和3
,而咱们上面获取到了raid
卡的bus id
分别为02
和03
,没错,这边的Bus Number
和bus id
是对应的,只是Bus number
没有自动填补成两位数,因此咱们能够经过bus id
获得sda
所对应的controller
为0
。
注意:
本来系统中版本8.07.07
的megacli
工具获取raid
卡信息的时候会存在问题,每次Bus Number
都会变化,咱们只要升级megacli
便可,我这边是把megacli
升级到了8.07.14
版本。
此时,咱们拥有了controller id
,能够获取该controller
下全部的磁盘组信息。
[root@tony ~]# /opt/MegaRAID_new/MegaCli/MegaCli64 -LdPdInfo -a0 -NoLog Adapter #0 Number of Virtual Disks: 13 Virtual Drive: 0 (Target Id: 0) Name : RAID Level : Primary-1, Secondary-0, RAID Level Qualifier-0 Size : 558.375 GB Sector Size : 512 Is VD emulated : No Mirror Data : 558.375 GB State : Optimal Strip Size : 64 KB Number Of Drives : 2 Span Depth : 1 Default Cache Policy: WriteThrough, ReadAheadNone, Direct, No Write Cache if Bad BBU Current Cache Policy: WriteThrough, ReadAheadNone, Direct, No Write Cache if Bad BBU Default Access Policy: Read/Write Current Access Policy: Read/Write Disk Cache Policy : Disk's Default Encryption Type : None Default Power Savings Policy: Controller Defined Current Power Savings Policy: None Can spin up in 1 minute: Yes LD has drives that support T10 power conditions: Yes LD's IO profile supports MAX power savings with cached writes: No Bad Blocks Exist: No Is VD Cached: No Number of Spans: 1 Span: 0 - Number of PDs: 2 PD: 0 Information Enclosure Device ID: 32 Slot Number: 12 Drive's position: DiskGroup: 0, Span: 0, Arm: 0 Enclosure position: 1 Device Id: 12 WWN: 50000398181A974C Sequence Number: 2 Media Error Count: 0 Other Error Count: 0 Predictive Failure Count: 0 Last Predictive Failure Event Seq Number: 0 PD Type: SAS ... ...
而后咱们能够根据target id
获取对应的磁盘组信息,target id
与上面的Target Id
所对应,这样咱们能够过滤获得惟一的磁盘组信息。这边咱们能够看到sda
对应Target Id
为0
的磁盘组,该raid
类型为raid1
,虚拟磁盘组中有两块物理盘,而后咱们能够获取这两块物理盘的enclosure id
和slot number
,这样再加上前文的controller id
,咱们就能够完彻底全地定位到具体一块磁盘的物理位置。
针对这种需求,本人根据以上逻辑写了一个简单的脚本能够一键获取磁盘的定位。
[root@tony ~]# ./get_disk_location.py sda ['0:32:12', '0:32:13']
这边0:32:12
分别表示磁盘的controller id
,enclosure id
和slot number
。
完整代码地址: https://github.com/tony-yin/M...
以前的作法大部分场景可行,可是在一些场合偶尔会发现问题,总感受仍是不够靠谱,身边的人还有经过sda
,sdb
这种排列顺序来查找和megacli
中显示磁盘的对应关系的,就更不靠谱了。linux
操做系统是能够识别到具体硬件设备的,因此是确定存在方法识别硬件对应的逻辑设备的,本文经过pcipath
获取到设备的惟一标识,而后根据pcipath
中的bus id
和megacli
中的cobtroller
创建链接,最后经过target id
锁定惟一磁盘组中的磁盘信息。
经过这种方式,咱们不须要肉眼判断,也不须要顾虑部分场景方案不适用,这彻底就是操做系统使用的方式,使用这种最基础,最底层的方式实现,真是让人豁然开朗。这跟看源码相似,了解一个功能的背后具体实现,你才知道最正确的姿式,不用去碰,去凑,这种感受真好。
给你们推荐一本书《Linux
设备驱动程序》,这本书详细讲解了linux
中各类设备与驱动的细节,很底层也很枯燥,不过看完后应该会颇有收获。但愿你们在使用各类已有工具和框架的基础上,多去了解背后的实现机制,这样能够帮助咱们更好地实现更深层次的需求。