Lỗi ATA của Linux: Dịch sang tên thiết bị?


36

Khi hộp Linux gặp lỗi ATA, nó sẽ ghi lại thông báo xác định đĩa là "ata% d.00". Làm cách nào để dịch nó sang tên thiết bị (ví dụ /dev/sdb)? Tôi cảm thấy như thế này là tầm thường, nhưng tôi không thể tìm ra nó.


1
Xem thêm câu trả lời của tôi cho một câu hỏi tương tự trên Unix-SE: unix.stackexchange.com/a/13988/1131
maxschlepzig

Câu trả lời:


28

Peter đã truyền cảm hứng cho tôi để viết một kịch bản nâng cao (cho phép), thậm chí có thể phát hiện ra các thanh USB (thay vì xuất ra những thứ ngớ ngẩn như "ata0.00"). Ngược lại với tập lệnh của Peter, bạn cũng sẽ nhận được số phụ (như trong 4.01) nếu bạn có nhiều hơn một thiết bị ở cùng một bộ điều khiển. kênh. Đầu ra sẽ chính xác như bạn nhận được syslog. Thử nghiệm. Hoạt động rất tốt trên hộp Debian của tôi, mặc dù luôn có rất nhiều cải tiến (ví dụ: các biểu thức quá vụng về). Nhưng GIỮ NÓ! Số lượng nhân vật thoát được dường như quá cao mà bạn có thể tìm thấy trong biểu thức chính tả của tôi chỉ vì lý do tương thích! Bạn không thể giả sử GNU sedvới mọi người, đó là lý do tại sao tôi đã làm mà không có mục đích mở rộng.

CẬP NHẬT
(1) Sẽ không còn phân tích lsđầu ra. (Rất tiếc!) Vì tất cả các bạn đều biết: Đừng phân tích ls.
(2) Bây giờ cũng hoạt động trên môi trường chỉ đọc.
(3) Lấy cảm hứng từ một gợi ý từ cuộc trò chuyện này ở đây, tôi đã quản lý để một lần nữa nhận được các tuyên bố sed ít phức tạp hơn.

#!/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"

Chỉ cần nhắc nhở rằng tập lệnh có thể không hiển thị các thiết bị đang gặp sự cố. Tôi đã gặp lỗi ata6 với softreset (FIS thứ 1 không thành công) (Các vấn đề nhỏ) đã liệt kê các dvice và nó không có mặt. Nếu bạn biết bạn có 4 đĩa trong pc và chỉ có 3 đĩa xuất hiện thì đó có thể là lý do.
Kendrick

1
@Kendrick Vâng, tôi sẽ không đổ lỗi cho kịch bản trong trường hợp này. Vì nếu bạn biết trình điều khiển kernel hoạt động như thế nào, thì điều này sẽ rõ ràng hơn với bạn :) Trình điều khiển hệ thống con Kernel được biết là từ bỏ một khi "vấn đề" đủ nghiêm trọng. Điều này cho thấy, đối với một ổ đĩa có khả năng UDMA, nó có thể gây ra nhiều thiết lập lại ổ đĩa và (cuối cùng) thử vận ​​hành ổ đĩa ở chế độ PIO. Tuy nhiên, nếu điều này chứng tỏ quá không ổn định (các lỗi thời gian khác nhau, v.v.), trình điều khiển sẽ nói "biến mất" với ổ đĩa. Đối với các ổ đĩa PATA cũ, điều này có nghĩa là khởi động lại lạnh sẽ là bắt buộc để ổ đĩa hiển thị lại.
cú pháp

Không phải ý định của tôi có nghĩa là đổ lỗi cho kịch bản. chỉ là một lời nhắc nhở về lý do tại sao nó có thể bị mất :) bảng điều khiển cảng biển ngu ngốc làm cho nó đau đớn để tìm hiểu những gì đang xảy ra.
Kendrick

@Kendrick Bạn đang nói với tôi người đàn ông. :) Vâng, trong cuốn sách của tôi, Seagate không bao giờ nên mua Samsung. Yêu các ổ đĩa sau (khi Samsung vẫn còn kinh doanh lưu trữ lớn), cộng với đội ngũ hỗ trợ tuyệt vời của họ. Bây giờ Seagate đã tiếp quản tất cả ... và ... uh-oh.
cú pháp

11

Nhìn vào /proc/scsi/scsi, nó sẽ trông giống như thế này:

$ 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 là sda và ata1.00, scsi1 id 0 là sdb và ata2.00, v.v.

Cũng nhìn vào /var/log/dmesg, cho thấy thông tin tải trình điều khiển ata và sẽ làm cho mọi thứ rõ ràng hơn một chút. Tìm dòng bắt đầu "libata".


8
Bạn cũng có thể cần sử dụng 'lsscsi' - mang lại đầu ra thân thiện với con người hơn một chút - ví dụ: [0: 0: 0] cd / dvd TSSTcorp CDDVDW SH-S202H SB00 / dev / sr0 [2: 0: 0: 0 ] đĩa ATA ST3500630AS 3.AA / dev / sda [3: 0: 0: 0] đĩa ATA WDC WD5000AAKS-0 01.0 / dev / sdb (Trên máy chủ này, chạy kernel 3.2.x, không có / Proc / scsi *) (Xin lỗi, tôi dường như không thể tìm ra cách lấy bất kỳ định dạng nào ở trên để làm cho nó dễ đọc hơn)
David Goodwin

1
Đây nên là một câu trả lời hơn là một bình luận. Hữu ích, nhanh chóng và dễ dàng để đọc từ một máy và gõ trên một máy khác có vấn đề.
Anh Cả Geek

10

Tôi thích scriptlets thay vì giải thích lenghty. Điều này hoạt động trên hộp Ubuntu của tôi. Thêm ý kiến ​​theo ý thích của bạn:

# 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

Kịch bản của bạn hơi đáng sợ hơn câu trả lời, chủ yếu là vì tôi có thể thấy toàn bộ.
isaaclw

1
Một chút đơn giản hóa (hoạt động với tôi trên Centos)ls -l /sys/block/sd* | sed -e 's@.*-> \.\..*/ata@/ata@' -e 's@/host@ @' -e 's@/target.*/@ @'
Shirker

9

Điều này thực sự khá khó khăn. Mặc dù an toàn khi cho rằng "ID scsi" là "ID ID trừ đi một", tôi thích thực sự an toàn và kiểm tra cái unique_idmà tôi giả sử (dựa trên bài đăng này ) là định danh SATA.

Lỗi của tôi là:

[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

Vì vậy, thủ tục của tôi để tìm hiểu những gì ata4là:

  1. tìm id PCI của bộ điều khiển SATA

    # lspci | grep -i sata
    00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
    
  2. tìm ID duy nhất phù hợp:

    # 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
    
  3. vì vậy nó là scsi_host/host3cái mà chúng ta có thể dịch sang 3:x:x:x, cái mà chúng ta có thể grep dmesgđể tìm hiểu thêm:

    # 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
    
  4. Đây là thiết bị của chúng tôi, chúng tôi có thể (tùy chọn) tìm số sê-ri để đưa thiết bị đó ra khỏi đó (hoặc kiểm tra hệ thống cáp hoặc bất cứ thứ gì) trước khi mảng RAID của chúng tôi hoàn toàn thất bại:

    # hdparm -i /dev/sdd | grep Serial
     Model=ST3250310NS, FwRev=SN06, SerialNo=9SF19GYA
    

Và bạn đã hoàn thành!


7

Thử đi:

# find -L /sys/bus/pci/devices/*/ata*/host*/target* -maxdepth 3 -name "sd*" 2>/dev/null | egrep block |egrep --colour '(ata[0-9]*)|(sd.*)'

Tôi chưa bao giờ hiểu dmesg - một số hàng nói về "ata4" một số hàng khác về "scsi" hoặc sdc, nhưng không ai gán "ata4 .. sdc" lệnh hiển thị tìm thấy / sys / bus / path, trong đó cả ata4 và sdc Được xác định.


5

Tôi có cùng một vấn đề và có thể xác định các ổ đĩa bằng cách kiểm tra dmesg. Ở đó bạn có thể thấy định danh bộ điều khiển (thuật ngữ chính xác ??) và mô hình của đĩa. Sau đó sử dụng ls -l / dev / đĩa / by-id để khớp số mô hình với / dev / sda (hoặc bất cứ điều gì). Ngoài ra, tôi thích Disk Utility cho thông tin này. Lưu ý: điều này chỉ hoạt động nếu các đĩa của bạn có số mô hình khác nhau, nếu không bạn không thể phân biệt giữa hai.

>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

2

Cách dễ nhất là xem lại nhật ký kernel từ boot, vì tên thiết bị ổ đĩa được trộn từ nhiều nguồn khác nhau (ví dụ: ổ USB) hoặc được chỉ định dựa trên loại thiết bị (ví dụ: cdrom có ​​thể là scdX và mọi thứ đều có sgX ). Trong thực tế, trừ khi bạn đã trộn lẫn các loại xe buýt khác nhau (ví dụ: SATA + USB), thiết bị ata được đánh số thấp nhất sẽ là sda trừ khi đó là thiết bị cdrom.

Tùy thuộc vào hệ thống của bạn, nó có thể được đoán bằng cách đi lang thang xung quanh sysfs. Trên hệ thống của tôi ls -l /sys/dev/blockcho thấy rằng 8:0(chính: phụ từ / dev entry) trỏ đến /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda Tương tự, ls -l /sys/class/ata_portcho thấy ata1các điểm /sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1trên cùng một thiết bị phụ PCI.

Vì tôi sử dụng SATA và chỉ có một ổ đĩa trên mỗi cổng nên tôi có thể suy ra rằng ata1.00 = sda. Tất cả các ổ đĩa của tôi là 0,00, tôi nghi ngờ rằng nếu tôi sử dụng hệ số nhân cổng, các ổ đĩa của tôi sẽ được cung cấp .01, .02, .03, v.v. Nhìn vào nhật ký của người khác, bộ điều khiển PATA sử dụng 0,00 và 0,01 cho chủ và nô lệ và dựa trên nhật ký của họ nếu bạn có ataX.01, .01 sẽ được ánh xạ tới "ID" trong máy chủ: channel: ID: LUN từ /sys/dev/block/danh sách. Nếu bạn có nhiều ataX/hostY/thư mục trong cùng một thư mục thiết bị PCI, thì tôi nghi ngờ rằng thư mục ataX được đánh số thấp nhất khớp với thư mục hostY được đánh số thấp nhất.


2

Trong /sys/class/ata_port/ata${n}/device/, bạn có thể thấy một host${x}thư mục. Ví dụ, trên máy của tôi:

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

Các ${x}trong host${x}đề cập đến số đầu tiên trong [0:0:0:0]. Vì vậy, đối với tôi ata1đề cập đến host0cũng có thể được biểu diễn dưới dạng SCSI như 0:*:

gibby ~ # lsscsi 0:\*
[0:0:0:0]    disk    ATA      WDC WD1002FAEX-0 1D05  /dev/sda

0

Kịch bản dưới đây sẽ cung cấp cho bạn một bản tóm tắt hay như thế này:

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

Vì vậy, trong một dòng cho mỗi ổ đĩa bạn có sdX tên thiết bị, kích thước , mô hình , s / npciata số. Các sdc ở trên lõi đến đầu đọc thẻ USB SD không có thẻ được lắp vào. Do đó ---- thay cho thông tin thực sự.

#!/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

(chỉ được thử nghiệm trên Ubuntu 12.04 / 14.04 và CentOS 6)


Làm thế nào mà nó tương đương để cho bạn thấy, ví dụ, ATA 4.01 là gì?
Edward_178118

Trong ví dụ đầu ra, bạn thấy sda: ... ata1 ... và sdb: ... ata3 .... Và thực sự sda đã ở ata1 và sdb tại ata2. Vì tôi đã viết nó và kiểm tra nó trên 4 máy chủ khác nhau, tôi đã tìm ra CTNH trong đó đoạn script trên không chứa tham chiếu đến ata. Tôi nên chỉ ra rằng dmesg | grep "ata [0-9]" chưa bao giờ làm tôi thất bại.
ndemou

0

Có thể tìm thấy tập lệnh để tìm thông tin này và hơn thế nữa tại https://www.av8n.com/computer/disk-hw-host-bus-id

Nó tương tự như kịch bản được cung cấp bởi ông Syntaxerror, nhưng fancier. - Nó hoạt động cho các ổ USB cũng như ổ ATA. - Nó cung cấp ổ đĩa tạo và mô hình và số sê-ri, - và tất nhiên là điểm đính kèm. - Nó đơn giản hơn, dễ đọc và dễ bảo trì hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.