当一个Linux机箱出现ATA错误时,系统将其标识为“ata%d.00”。 如何将其转换为设备名称(例如/dev/sdb
)? 我觉得这应该是微不足道的,但我无法弄清楚。
彼得鼓励我写一个高级脚本(let),甚至可以检测USB棒(而不是像“ata0.00”那样输出愚蠢的东西)。 与Peter的脚本相反,如果在同一个控制器上有多个设备,您也将获得子编号(如4.01)。 渠道。 输出将与您在syslog
获得的结果完全一样。 testing。 在我的Debian框上工作得很好,但总是有很多的改进(例如太笨拙的正则expression式)。 但是坚持下去! 在我的正则expression式中看到的似乎太多的转义字符只是出于兼容性原因! 你不能假设每个人都有GNU sed
,这就是为什么我没有使用扩展正则expression式的原因。
更新
(1)将不再parsingls
输出。 (哎呀!)既然你们都知道: 不要分析ls。
(2)现在也适用于只读环境。
(3)受到这个闲聊的build议的启发,我设法再次让sed语句更加复杂。
#!/bin/bash # note: inspired by Peter # # *UPDATE 1* now we're no longer parsing ls output # *UPDATE 2* now we're using an array instead of the <<< operator, which on its # part insists on a writable /tmp directory: # restricted environments with read-only access often won't allow you that # save original IFS OLDIFS="$IFS" for i in /sys/block/sd*; do readlink $i | sed 's^\.\./devices^/sys/devices^ ; s^/host[0-9]\{1,2\}/target^ ^ ; s^/[0-9]\{1,2\}\(:[0-9]\)\{3\}/block/^ ^' \ \ | while IFS=' ' read Path HostFull ID do # OLD line: left in for reasons of readability # IFS=: read HostMain HostMid HostSub <<< "$HostFull" # NEW lines: will now also work without a hitch on r/o environments IFS=: h=($HostFull) HostMain=${h[0]}; HostMid=${h[1]}; HostSub=${h[2]} if echo $Path | grep -q '/usb[0-9]*/'; then echo "(Device $ID is not an ATA device, but a USB device [eg a pen drive])" else echo $ID: ata$(< "$Path/host$HostMain/scsi_host/host$HostMain/unique_id").$HostMid$HostSub fi done done # restore original IFS IFS="$OLDIFS"
看看/proc/scsi/scsi
,它看起来像这样:
$ cat /proc/scsi/scsi Attached devices: Host: scsi0 Channel: 00 Id: 00 Lun: 00 Vendor: ATA Model: ST3250823AS Rev: 3.03 Type: Direct-Access ANSI SCSI revision: 05 Host: scsi1 Channel: 00 Id: 00 Lun: 00 Vendor: ATA Model: ST3750528AS Rev: CC44 Type: Direct-Access ANSI SCSI revision: 05 Host: scsi2 Channel: 00 Id: 00 Lun: 00 Vendor: ATA Model: ST3750330AS Rev: SD1A Type: Direct-Access ANSI SCSI revision: 05 Host: scsi10 Channel: 00 Id: 00 Lun: 00 Vendor: WDC WD20 Model: EARS-00MVWB0 Rev: Type: Direct-Access ANSI SCSI revision: 02
scsi0 id 0是sda和ata1.00,scsi1 id 0是sdb和ata2.00等
另外看看/var/log/dmesg
,它显示了ata驱动加载信息,并且会使事情变得更清楚。 寻找开始“libata”的行。
我更喜欢scriptlets而不是简单的解释。 这在我的Ubuntu盒子上工作。 根据您的喜好添加评论:
# on Ubuntu get ata ID for block devices sd* ls -l /sys/block/sd* \ | sed -e 's^.*-> \.\.^/sys^' \ -e 's^/host^ ^' \ -e 's^/target.*/^ ^' \ | while read Path HostNum ID do echo ${ID}: $(cat $Path/host$HostNum/scsi_host/host$HostNum/unique_id) done
这实际上是相当棘手的。 尽pipe假设“scsi ID”是“SATA ID减1”是安全的,但我更愿意保证安全,并检查我认为的unique_id
(基于此帖 )是SATA标识符。
我的错误是:
[6407990.328987] ata4.00: exception Emask 0x10 SAct 0x1 SErr 0x280100 action 0x6 frozen [6407990.336824] ata4.00: irq_stat 0x08000000, interface fatal error [6407990.343012] ata4: SError: { UnrecovData 10B8B BadCRC } [6407990.348395] ata4.00: failed command: READ FPDMA QUEUED [6407990.353819] ata4.00: cmd 60/20:00:28:c2:39/00:00:0c:00:00/40 tag 0 ncq 16384 in [6407990.353820] res 40/00:00:28:c2:39/00:00:0c:00:00/40 Emask 0x10 (ATA bus error) [6407990.369618] ata4.00: status: { DRDY } [6407990.373504] ata4: hard resetting link [6407995.905574] ata4: SATA link up 3.0 Gbps (SStatus 123 SControl 300) [6407995.976946] ata4.00: configured for UDMA/133 [6407995.976961] ata4: EH complete
所以我的程序找出ata4
是什么:
findSATA控制器的PCI ID
# lspci | grep -i sata 00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
find匹配的唯一ID:
# grep 4 /sys/devices/pci0000:00/0000:00:1f.2/*/*/*/unique_id /sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/unique_id:4
所以它在scsi_host/host3
,我们可以将其转换为3:x:x:x
,我们可以在dmesg
中find更多信息:
# dmesg | grep '3:.:.:.' [ 2.140616] scsi 3:0:0:0: Direct-Access ATA ST3250310NS SN06 PQ: 0 ANSI: 5 [ 2.152477] sd 3:0:0:0: [sdd] 488397168 512-byte logical blocks: (250 GB/232 GiB) [ 2.152551] sd 3:0:0:0: [sdd] Write Protect is off [ 2.152554] sd 3:0:0:0: [sdd] Mode Sense: 00 3a 00 00 [ 2.152576] sd 3:0:0:0: [sdd] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA [ 2.157004] sd 3:0:0:0: [sdd] Attached SCSI disk [ 2.186897] sd 3:0:0:0: Attached scsi generic sg3 type 0
这里是我们的设备,我们可以(可选地)find序列号,让我们的RAIDarrays完全失败之前,该设备(或检查布线或其他)
# hdparm -i /dev/sdd | grep Serial Model=ST3250310NS, FwRev=SN06, SerialNo=9SF19GYA
你完成了!
我有同样的问题,并能够通过检查dmesg来识别驱动器。 在那里你可以看到控制器标识符(正确的术语??)和磁盘的型号。 然后使用ls -l / dev / disk / by-id将模型编号匹配到/ dev / sda(或其他)。 另外,我喜欢这个信息的磁盘工具。 注意:这只适用于你的磁盘有不同的型号,否则你不能区分这两者。
>dmesg |grep ata ... [ 19.178040] ata2.00: ATA-8: WDC WD2500BEVT-00A23T0, 01.01A01, max UDMA/133 [ 19.178043] ata2.00: 488397168 sectors, multi 16: LBA48 NCQ (depth 31/32), AA [ 19.179376] ata2.00: configured for UDMA/133 [ 19.264152] ata3.00: ATA-8: WDC WD3200BEVT-00ZCT0, 11.01A11, max UDMA/133 [ 19.264154] ata3.00: 625142448 sectors, multi 16: LBA48 NCQ (depth 31/32), AA [ 19.266767] ata3.00: configured for UDMA/133 ... >ls -l /dev/disk/by-id lrwxrwxrwx 1 root root 9 Feb 18 12:17 ata-WDC_WD2500BEVT-00A23T0_WD-WXE1A7131446 -> ../../sda lrwxrwxrwx 1 root root 10 Feb 18 11:48 ata-WDC_WD2500BEVT-00A23T0_WD-WXE1A7131446-part1 -> ../../sda1 lrwxrwxrwx 1 root root 9 Feb 18 12:17 ata-WDC_WD3200BEVT-00ZCT0_WD-WXHZ08045183 -> ../../sdb lrwxrwxrwx 1 root root 10 Feb 18 11:48 ata-WDC_WD3200BEVT-00ZCT0_WD-WXHZ08045183-part1 -> ../../sdb1
最简单的方法是从引导中查看内核日志,因为驱动器设备名称是从各种来源(例如USB驱动器)混合而成,或者是根据设备types分配的(即,cdrom可能是scdX,而且所有的都有sgX )。 实际上,除非你有不同种类的总线(例如SATA + USB),否则最低编号的ata设备将会是sda,除非它是一个cdrom设备。
根据你的系统,它可能会围绕sysfs徘徊。 在我的系统上, ls -l /sys/dev/block
显示8:0
(major:minor from / dev entry)指向/sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
同样, ls -l /sys/class/ata_port
显示ata1
指向/sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1
位于同一个PCI子设备上。
由于我使用SATA,并且每个端口上只有一个驱动器,我可以推断出ata1.00 = sda。 我所有的驱动器都是.00,我怀疑如果我使用端口倍增器,我的驱动器将被赋予.01,.02,.03等。查看其他人的日志PATA控制器使用.00和.01作为主从服务器,如果你有ataX.01,根据它们的日志,.01应该映射到/sys/dev/block/
列表中host:channel:ID:LUN文件夹中的“ID”。 如果在同一PCI设备文件夹中有多个ataX/
和hostY/
文件夹,则怀疑最低编号的ataX文件夹与最低编号的hostY文件夹匹配。
尝试这个:
# find -L /sys/bus/pci/devices/*/ata*/host*/target* \ -maxdepth 3 -name "sd*" 2>/dev/null |\ egrep block |egrep --colour '(ata[0-9]*)|(sd.*)' \ ;
我从来没有理解dmesg – 有些行是关于“ata4”的一些关于“scsi”或sdc的,但是没有人指定“ata4 … sdc”,显示的命令find了/ sys / bus /path,其中ata4和sdc被指定。
J.
下面的脚本会给你一个很好的总结,像这样:
sda [ 180.0 GB] INTEL SSDSC2BW180A4, BTDA4052066D1802GN pci0000:00/0000:00:11.0/ata1/host0/target0:0:0/0:0:0:0/block/sda sdb [ 1000.2 GB] WDC WD1000DHTZ-04N21V1, WD-WXM1E83CNTX5 pci0000:00/0000:00:11.0/ata3/host2/target2:0:0/2:0:0:0/block/sdc sdc [ ------ GB] -- pci0000:00/0000:00:12.2/usb1/1-5/1-5:1.0/host6/target6:0:0/6:0:0:0/block/sdf
所以在每个驱动器的一行中,您有sdX设备名称, 大小 , 型号 , s / n以及pci和ata数字。 上面的sdc核心到没有插入卡的USB SD读卡器。 因此,取代了真实的信息。
#!/bin/bash BLKDEVS=`ls -l /sys/block/sd*|sed -e 's/^.* -> //' -e 's/^...devices.//'` echo $BLKDEVS|tr \ \\n |sort| \ while read DISK ; do SD=`echo $DISK|sed -e 's/^.*\///'` INFO=`hdparm -i /dev/$SD 2>/dev/null|grep Model=|sed -e 's/Model=//' -e 's/FwRev=[^ ]*//' -e 's/SerialNo=//'` ! [[ $INFO ]] && INFO='--' SIZE=`fdisk -l /dev/$SD 2>/dev/null|grep '^Disk .* bytes'|sed -e 's/^[^,]*, \([0-9]*\) bytes$/\1/'` if [[ $SIZE ]] ; then SIZE=`echo $SIZE|awk '{printf "[%7.1f GB]" , $1/1000/1000/1000}'|tr \ _` else SIZE='[ ------ GB]' fi echo $SD $SIZE $INFO $DISK done
(只在Ubuntu 12.04 / 14.04和CentOS 6上testing过)
在/sys/class/ata_port/ata${n}/device/
,您可以看到一个host${x}
文件夹。 例如,在我的机器上:
gibby ~ # ls /sys/class/ata_port/ata1/device/ ata_port host0 link1 power uevent gibby ~ # ls /sys/class/ata_port/ata2/device/ ata_port host1 link2 power uevent gibby ~ # lsscsi [0:0:0:0] disk ATA WDC WD1002FAEX-0 1D05 /dev/sda [1:0:0:0] disk ATA WDC WD2001FFSX-6 0A81 /dev/sdb [2:0:0:0] disk ATA WDC WD1002FAEX-0 1D05 /dev/sdc [3:0:0:0] disk ATA WDC WD2001FFSX-6 0A81 /dev/sdd [5:0:0:0] disk ATA SAMSUNG MZ7TD256 2L5Q /dev/sde
host${x}
${x}
中的host${x}
指向[0:0:0:0]
中的第一个数字。 所以对于我来说, ata1
是指host0
,它也可以用SCSIforms表示为0:*
:
gibby ~ # lsscsi 0:\* [0:0:0:0] disk ATA WDC WD1002FAEX-0 1D05 /dev/sda
可以在https://www.av8n.com/computer/disk-hw-host-bus-idfind脚本来查找这些信息等等。
这与Syntaxerror先生提供的脚本类似,但更有趣。 – 它适用于USB驱动器以及ATA驱动器。 它提供了驱动器的型号,型号和序列号,当然还有附加点。 – 这是更直接,可读和可维护的。