当 Linux 机器出现 ATA 错误时,它会在系统日志中记录一条消息,将磁盘标识为“ata%d.00”。我该如何将其转换为设备名称(例如/dev/sdb
)?我觉得这应该很简单,但我搞不清楚。
答案1
Peter 启发我编写了一个高级脚本 (let),它甚至可以检测 USB 记忆棒(而不是输出“ata0.00”之类的愚蠢内容)。与 Peter 的脚本相反,如果您在同一个控制器或通道上有多个设备,您还将获得子编号(如 4.01 中所示)。输出将与您在 中获得的完全相同syslog
。经过测试。在我的 Debian 机器上运行良好,尽管总是有很多改进(例如太笨拙的正则表达式)。但请稍等!您可能会在我的正则表达式中发现似乎过多的转义字符,这只是为了兼容性原因!您不能假设sed
每个人都使用 GNU,这就是我故意不使用扩展正则表达式的原因。
更新
(1)将不再解析ls
输出。(哎呀!)因为你们都知道:不要解析 ls。
(2)现在也适用于只读环境。
(3)受到这个闲聊中的建议的启发这里我已设法再次使 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 [e. g. 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"
答案2
看一下/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”开头的行。
答案3
我更喜欢小脚本,而不是冗长的解释。这在我的 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
答案4
这实际上相当棘手。虽然可以安全地假设“scsi ID”是“SATA ID减一”,但我更喜欢真正安全并检查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
:
找到 SATA 控制器的 PCI ID
# lspci | grep -i sata 00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
找到匹配的唯一 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
查找更多信息:# 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
这是我们的设备,我们可以(可选)在 RAID 阵列彻底失效之前找到序列号以将该设备从那里取出(或检查电缆或其他):
# hdparm -i /dev/sdd | grep Serial Model=ST3250310NS, FwRev=SN06, SerialNo=9SF19GYA
您已经完成了!