Ошибки Linux ATA: перевод на имя устройства?

36

Когда блок Linux получает ошибку ATA, он заносит его в журнал сообщением, идентифицирующим диск как «ata% d.00». Как мне перевести это на имя устройства (например /dev/sdb)? Я чувствую, что это должно быть тривиально, но я не могу понять это.

nelhage
источник
1
См. Также мой ответ на аналогичный вопрос по Unix-SE: unix.stackexchange.com/a/13988/1131
maxschlepzig

Ответы:

28

Питер вдохновил меня написать расширенный сценарий (пусть), который может даже обнаруживать флешки USB (вместо вывода глупых вещей вроде «ata0.00»). В отличие от сценария Питера, вы также получите дополнительный номер (как в 4.01), если у вас более одного устройства на одном контроллере, соответственно. канал. Вывод будет точно таким, каким вы его получили syslog. Проверено. Очень хорошо работает на моей коробке Debian, хотя всегда есть много улучшений (например, слишком неуклюжие регулярные выражения). Но держи его! Казалось бы, слишком большое число экранированных символов, которые вы можете найти в моих регулярных выражениях, просто из соображений совместимости! Вы не можете использовать GNU sedсо всеми, поэтому я специально сделал это без расширенных регулярных выражений.

ОБНОВЛЕНИЯ
(1) больше не будет анализировать lsвывод. (упс!) Так как вы все знаете: не разбирайте ls.
(2) Теперь также работает в средах только для чтения.
(3) Навеяно предложением от этой болтовни здесь мне удалось снова получить этот анализ заявление пути менее сложным.

#!/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"
синтаксическая ошибка
источник
Просто напоминание о том, что скрипт может не отображать устройства, на которых возникают проблемы. Я имел ошибку ata6 с программным сбросом не удалось (1-й сбой FIS) (незначительные проблемы) перечисленных устройств, и он не присутствовал. если вы знаете, что у вас есть 4 диска на компьютере и только 3 появляются, может быть, поэтому.
Кендрик
1
@ Кендрик Ну, я бы не стал винить сценарий в этом случае. Если вы знаете, как работают драйверы ядра, это будет вам более чем понятно :) Известно, что драйверы подсистемы ядра перестают работать, когда «проблемы» становятся достаточно серьезными. Это означает, что для диска с поддержкой UDMA это может вызвать многократные перезагрузки диска и (в конечном итоге) попытаться выполнить операцию диска в режиме PIO. Однако, если это окажется слишком нестабильным (различные ошибки синхронизации и т. Д.), Драйвер скажет «уйти» на диск. Для старых дисков PATA это означает, что холодная перезагрузка будет обязательной, чтобы диск снова появился.
syntaxerror
Я не намерен обвинять в этом сценарий. просто напоминание о том, почему это может отсутствовать :) глупая ненадежная плата контроллера Seagate причиняла боль, чтобы понять, что происходит.
Кендрик
@ Кендрик Ты говоришь мне, парень. :) Ну, в моей книге Seagate никогда не должен был выкупать Samsung. Очень понравились последние диски (когда Samsung еще занимался массовыми хранилищами), а также отличная команда поддержки. Теперь Seagate взял на себя все это ... и ... э-э-э.
syntaxerror
11

Посмотрите /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

ID 0 scsi0 - это sda и ata1.00, id 0 scsi1 - это sdb и ata2.00 и т. д.

Также посмотрите /var/log/dmesg, что показывает информацию о загрузке драйвера ata и немного прояснит ситуацию. Ищите строку, начинающуюся с «libata».

Фил Холленбек
источник
8
Вам также может понадобиться использовать 'lsscsi' - который дает немного более дружественный для человека вывод - например, [0: 0: 0: 0] CD / DVD TSSTcorp CDDVDW SH-S202H SB00 / dev / sr0 [2: 0: 0: 0 ] disk ATA ST3500630AS 3.AA / dev / sda [3: 0: 0: 0] disk ATA WDC WD5000AAKS-0 01.0 / dev / sdb (На этом сервере, работающем с ядром 3.2.x, нет / proc / scsi *) (Извините, я не могу понять, как получить какое-либо форматирование для того, чтобы сделать его читабельным)
Дэвид Гудвин
1
Это должен быть ответ, а не комментарий. Полезно, быстро и легко читать с одной машины и печатать на другой с проблемами.
Старейшина Гик
10

Я предпочитаю сценарии вместо длинных объяснений. Это работает на моей коробке 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
Питер
источник
Ваш сценарий немного менее страшен, чем ответ, в основном потому, что я вижу все это.
Исаакль
1
Небольшое упрощение (у меня работает на Centos)ls -l /sys/block/sd* | sed -e 's@.*-> \.\..*/ata@/ata@' -e 's@/host@ @' -e 's@/target.*/@ @'
Shirker
9

Это на самом деле довольно сложно. Хотя можно с уверенностью предположить, что «идентификатор scsi» является «идентификатором SATA минус один», я предпочитаю быть действительно безопасным и проверять, как 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это:

  1. найти идентификатор PCI контроллера SATA

    # lspci | grep -i sata
    00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
    
  2. найти соответствующий уникальный идентификатор:

    # 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. так что это 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
    
  4. вот наше устройство, мы можем (необязательно) найти серийный номер, чтобы вывести это устройство (или проверить кабельные соединения или что-то еще), прежде чем наш RAID-массив полностью выйдет из строя:

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

И вы сделали!

anarcat
источник
7

Попробуй это:

# 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», показанная команда находит / sys / bus / path, где и ata4, и sdc указаны.

Швейк
источник
5

У меня была та же проблема, и я смог определить диски, проверив 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
ecellingsworth
источник
2

Самый простой способ - просмотреть журнал ядра при загрузке, поскольку имена устройств дисков смешаны из разных источников (например, USB-накопителей) или назначаются в зависимости от типа устройства (т. Е. Вместо этого 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, я подозреваю, что если бы я использовал множитель порта, мои диски получили бы 0,01, 0,02, 0,03 и т. Д. При просмотре журналов других пользователей контроллеры PATA используют 0,00 и 0,01 для главного и подчиненного устройств. и на основе их журналов, если у вас есть ataX.01, .01 должен быть сопоставлен с «ID» в папке host: channel: ID: LUN из /sys/dev/block/списка. Если у вас есть несколько папок ataX/и hostY/папок в одной папке устройства PCI, то я подозреваю, что папка ataX с наименьшим номером соответствует папке hostY с наименьшим номером.

DerfK
источник
2

В /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

${x}В host${x}относится к этому первому номеру в [0:0:0:0]. Так что для меня ata1относится к host0которому также может быть представлен в форме SCSI как 0:*:

gibby ~ # lsscsi 0:\*
[0:0:0:0]    disk    ATA      WDC WD1002FAEX-0 1D05  /dev/sda
Бинки
источник
0

Сценарий ниже даст вам хорошее резюме, как это:

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 отвечает на устройство чтения карт памяти SD 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)

ndemou
источник
Как это может показать вам, например, что такое ATA 4.01?
Edward_178118
В выходных данных примера вы видите sda: ... ata1 ... и sdb: ... ata3 .... И действительно, sda был в ata1 и sdb в ata2. Поскольку я написал его и протестировал на 4 разных хостах, я обнаружил HW, где приведенный выше скрипт не содержит ссылку на ata. Я должен отметить, что dmesg | grep "ata [0-9]" никогда не подводил меня.
ndemou
0

Сценарий для поиска этой информации и многое другое можно найти по адресу https://www.av8n.com/computer/disk-hw-host-bus-id.

Это похоже на сценарий, предоставленный Mr. Syntaxerror, но причудливее. - Работает как с USB-накопителями, так и с ATA-накопителями. - В нем указывается марка привода, модель и серийный номер, - и, конечно, точка крепления. - Это более простой, читаемый и поддерживаемый.

Джон Денкер
источник