Błędy Linux ATA: Tłumaczenie na nazwę urządzenia?

36

Gdy Linux otrzymuje błąd ATA, sysloguje go komunikatem identyfikującym dysk jako „ata% d.00”. Jak mam to przetłumaczyć na nazwę urządzenia (np. /dev/sdb)? Wydaje mi się, że powinno to być trywialne, ale nie mogę tego rozgryźć.

nelhage
źródło
1
Zobacz także moją odpowiedź na podobne pytanie dotyczące Unix-SE: unix.stackexchange.com/a/13988/1131
maxschlepzig

Odpowiedzi:

28

Peter zainspirował mnie do napisania zaawansowanego skryptu (let), który może nawet wykryć pamięć USB (zamiast wypisywać głupie rzeczy, takie jak „ata0.00”). W przeciwieństwie do skryptu Piotra, otrzymasz również pod-numer (jak w 4.01), jeśli masz więcej niż jedno urządzenie na tym samym kontrolerze lub. kanał. Dane wyjściowe będą dokładnie takie, jak je otrzymujesz syslog. Przetestowany. Działa bardzo dobrze na moim pudełku Debiana, chociaż zawsze jest wiele ulepszeń (np. Zbyt niezdarne wyrażenia regularne). Ale TRZYMAJ! Pozornie zbyt duża liczba znaków ucieczki, które możesz znaleźć w moich wyrażeniach regularnych, to tylko ze względu na kompatybilność! Nie możesz założyć GNU sedze wszystkimi, dlatego celowo zrobiłem to bez rozszerzonych wyrażeń regularnych.

AKTUALIZACJE
(1) Nie będą już analizować lsdanych wyjściowych. (ups!) Ponieważ wszyscy wiecie: nie analizujcie ls.
(2) Teraz działa również w środowiskach tylko do odczytu.
(3) Zainspirowany sugestią z tego chit-czatu tutaj udało mi się jeszcze bardziej uprościć zdania 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"
błąd składni
źródło
Przypominamy, że skrypt może nie pokazywać urządzeń, na których występują problemy. Miałem błąd ata6 z błędem miękkiego resetu (1. błąd FIS) (drobne problemy) wymienione urządzenia i nie było go. jeśli wiesz, że masz 4 dyski w komputerze i tylko 3 pojawiają się, może to być powód.
Kendrick
1
@Kendrick Cóż, nie obwiniłbym skryptu w tym przypadku. Bo jeśli wiesz, jak działają sterowniki jądra, będzie to dla Ciebie bardziej niż jasne :) Wiadomo, że sterowniki podsystemu jądra poddają się, gdy „problemy” są wystarczająco poważne. Odczytuje to, że w przypadku dysku obsługującego UDMA może on powodować wielokrotne resetowanie dysku i (ewentualnie) podjęcie próby napędu w trybie PIO. Jeśli jednak okaże się to zbyt niestabilne (różne błędy synchronizacji itp.), Sterownik powie „odejdź” na dysk. W przypadku starych dysków PATA oznacza to, że zimny restart będzie obowiązkowy, aby dysk ponownie się pojawił.
składniaerror
Nie moim zamiarem jest obwinianie scenariusza. tylko przypomnienie, dlaczego może go brakować :) głupia, płatkowa płyta kontrolera Seagate sprawiła, że ​​trudno było zrozumieć, co się dzieje.
Kendrick
@Kendrick Mówisz mi, człowieku. :) Cóż, w mojej książce Seagate nigdy nie powinna była kupować Samsunga. Uwielbiałem te ostatnie dyski (kiedy Samsung był jeszcze w branży pamięci masowych), a także ich doskonały zespół wsparcia. Teraz Seagate przejął to wszystko ... i ... uh-oh.
składniaerror
11

Spójrz /proc/scsi/scsi, który będzie wyglądał mniej więcej tak:

$ 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 to sda i ata1.00, scsi1 id 0 to sdb i ata2.00 itp.

Zobacz także /var/log/dmesg, która pokazuje informacje o ładowaniu sterownika ata i sprawi, że będzie trochę jaśniej. Poszukaj linii zaczynającej się od „libata”.

Phil Hollenback
źródło
8
Może być również konieczne użycie „lsscsi” - co daje nieco bardziej przyjazny dla człowieka wynik - np. [0: 0: 0: 0] cd / dvd TSSTcorp CDDVDW SH-S202H SB00 / dev / sr0 [2: 0: 0: 0 ] dysk ATA ST3500630AS 3.AA / dev / sda [3: 0: 0: 0] dysk ATA WDC WD5000AAKS-0 01.0 / dev / sdb (Na tym serwerze z jądrem 3.2.x nie ma / proc / scsi *) (Przepraszam, nie potrafię wymyślić, jak wprowadzić powyższe formatowanie, aby było czytelne)
David Goodwin
1
To powinna być odpowiedź, a nie komentarz. Przydatny, szybki i łatwy do odczytania z jednego komputera i pisania na innym z problemami.
Elder Geek
10

Wolę skrypty zamiast długich wyjaśnień. Działa to na moim systemie Ubuntu. Dodaj komentarze do swoich upodobań:

# 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
Piotr
źródło
Twój skrypt jest nieco mniej przerażający niż odpowiedź, głównie dlatego, że wszystko widzę.
isaaclw
1
Trochę upraszczające (działa dla mnie na ls -l /sys/block/sd* | sed -e 's@.*-> \.\..*/ata@/ata@' -e 's@/host@ @' -e 's@/target.*/@ @'
Centos
9

To jest właściwie dość trudne. Chociaż można bezpiecznie założyć, że „identyfikator scsi” to „identyfikator SATA minus jeden”, wolę być naprawdę bezpieczny i sprawdzam, unique_idco, jak zakładam (na podstawie tego postu ), jest identyfikatorem SATA.

Mój błąd to:

[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

Więc moja procedura, aby dowiedzieć się, co ata4to jest:

  1. znajdź identyfikator PCI kontrolera SATA

    # lspci | grep -i sata
    00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
    
  2. znajdź pasujący unikalny identyfikator:

    # 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. więc jest włączony scsi_host/host3, na który możemy przetłumaczyć 3:x:x:x, na który możemy dmesgsię dowiedzieć, aby dowiedzieć się więcej:

    # 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. oto nasze urządzenie, możemy (opcjonalnie) znaleźć numer seryjny, aby zabrać to urządzenie stamtąd (lub sprawdzić okablowanie lub cokolwiek innego), zanim nasza macierz RAID całkowicie zawiedzie:

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

I jesteś skończony!

anarcat
źródło
7

Spróbuj tego:

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

Nigdy nie rozumiałem dmesg - niektóre wiersze dotyczą „ata4”, inne zaś dotyczą „scsi” lub sdc, ale nikt nie przypisuje „ata4 ... sdc” pokazane polecenie znajduje ścieżkę / sys / bus / path, gdzie zarówno ata4, jak i sdc są określone.

schweik
źródło
5

Miałem ten sam problem i byłem w stanie zidentyfikować dyski, sprawdzając dmesg. Tam możesz zobaczyć identyfikator kontrolera (poprawny termin?) I model dysku. Następnie użyj ls -l / dev / disk / by-id, aby dopasować numer modelu do / dev / sda (lub cokolwiek innego). Alternatywnie podoba mi się Narzędzie dyskowe dla tych informacji. Uwaga: działa to tylko wtedy, gdy dyski mają różne numery modeli, w przeciwnym razie nie można ich rozróżnić.

>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
źródło
2

Najprostszym sposobem jest przejrzenie dziennika jądra od startu, ponieważ nazwy urządzeń napędowych są mieszane z różnych źródeł (np. Napędów USB) lub są przypisywane na podstawie typu urządzenia (np. Cdrom może być scdX zamiast tego i wszystko ma sgX ). W praktyce, chyba że masz do czynienia z różnymi rodzajami magistrali (np. SATA + USB), urządzeniem ATA o najniższym numerze będzie SDA, chyba że jest to urządzenie CDROM.

W zależności od systemu można go rozróżnić wędrując po dysfunkcjach. W moim systemie ls -l /sys/dev/blockujawnia, że 8:0(major: minor from / dev entry) wskazuje na /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda Podobnie, ls -l /sys/class/ata_portujawnia te ata1punkty, na /sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1których znajduje się to samo urządzenie podrzędne PCI.

Ponieważ używam SATA i na każdym porcie jest tylko jeden dysk, mogę wywnioskować, że ata1.00 = sda. Wszystkie moje dyski mają 0,00, podejrzewam, że gdybym użył multiplikatora portów, moje dyski otrzymałyby 0,01, 0,02, 0,03 itd. Patrząc na logi innych ludzi Kontrolery PATA używają 0,00 i 0,01 dla master i slave , i na podstawie ich dzienników, jeśli masz ataX.01, .01 powinien być mapowany na „ID” w hoście: kanał: ID: folder LUN z /sys/dev/block/listy. Jeśli masz wiele folderów ataX/i hostY/folderów w tym samym folderze urządzenia PCI, podejrzewam, że folder ataX o najniższym numerze odpowiada folderowi hostY o najniższym numerze.

DerfK
źródło
2

W /sys/class/ata_port/ata${n}/device/możesz zobaczyć host${x}folder. Np. Na moim komputerze:

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

Symbol ${x}in host${x}odnosi się do tej pierwszej liczby w [0:0:0:0]. Więc dla mnie ata1odnosi się do, host0który może być również reprezentowany w formie SCSI jako 0:*:

gibby ~ # lsscsi 0:\*
[0:0:0:0]    disk    ATA      WDC WD1002FAEX-0 1D05  /dev/sda
Binki
źródło
0

Poniższy skrypt da Ci takie fajne podsumowanie:

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

Tak więc w jednym wierszu na dysk masz nazwę urządzenia SDX , rozmiar , model , s / n oraz numery pci i ata . Sdc powyżej odpowiada czytnikowi kart USB SD bez włożonej karty. Stąd ---- zamiast prawdziwej informacji.

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

(testowany tylko na Ubuntu 12.04 / 14.04 i CentOS 6)

ndemou
źródło
Jak to równoznaczne z pokazaniem, czym jest na przykład ATA 4.01?
Edward_178118
W przykładowym wyjściu widać sda: ... ata1 ... i sdb: ... ata3 .... I rzeczywiście sda ​​był w ata1, a sdb w ata2. Odkąd napisałem go i przetestowałem na 4 różnych hostach, dowiedziałem się HW, gdzie powyższy skrypt nie zawiera odniesienia do ata. Powinienem zaznaczyć, że dmesg | grep "ata [0-9]" nigdy mnie nie zawiodło.
ndemou
0

Skrypt umożliwiający znalezienie tych informacji i nie tylko można znaleźć na stronie https://www.av8n.com/computer/disk-hw-host-bus-id

Jest podobny do skryptu dostarczonego przez pana Syntaxerrora, ale jest bardziej fantazyjny. - Działa zarówno z dyskami USB, jak i ATA. - Podaje markę i model napędu oraz numer seryjny, - i oczywiście punkt mocowania. - Jest prostszy, czytelniejszy i łatwiejszy w utrzymaniu.

John Denker
źródło