原文地址: 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
中各類設備與驅動的細節,很底層也很枯燥,不過看完後應該會頗有收穫。但願你們在使用各類已有工具和框架的基礎上,多去了解背後的實現機制,這樣能夠幫助咱們更好地實現更深層次的需求。