Linux ATA-Fehler: In einen Gerätenamen übersetzen?

36

Wenn eine Linux-Box einen ATA-Fehler erhält, wird dieser mit einer Meldung protokolliert, die den Datenträger als "ata% d.00" identifiziert. Wie übersetze ich das in einen Gerätenamen (zB /dev/sdb)? Ich denke, das sollte trivial sein, aber ich kann es nicht herausfinden.

nelhage
quelle
1
Siehe auch meine Antwort auf eine ähnliche Frage zu Unix-SE: unix.stackexchange.com/a/13988/1131
maxschlepzig

Antworten:

28

Peter hat mich dazu inspiriert, ein erweitertes Skript (let) zu schreiben, das sogar USB-Sticks erkennen kann (anstatt alberne Dinge wie "ata0.00" auszugeben). Im Gegensatz zu Peters Skript erhalten Sie die Sub-Nummer (wie in 4.01) auch, wenn Sie mehr als ein Gerät am selben Controller bzw. an mehreren Geräten haben. Kanal. Die Ausgabe erfolgt genau so, wie Sie sie erhalten syslog. Geprüft. Funktioniert sehr gut auf meiner Debian-Box, obwohl es immer viele Verbesserungen gibt (zB zu plumpe reguläre Ausdrücke). Aber haltet es! Die scheinbar zu hohe Anzahl von maskierten Zeichen in meinen regulären Ausdrücken dient nur der Kompatibilität! Sie können GNU nicht sedbei jedem annehmen , weshalb ich absichtlich auf erweiterte reguläre Ausdrücke verzichtet habe.

UPDATES
(1) Die lsAusgabe wird nicht mehr analysiert . (Hoppla!) Wie Sie alle wissen: Analysieren Sie nicht ls.
(2) Funktioniert jetzt auch in schreibgeschützten Umgebungen.
(3) Inspiriert von einem Vorschlag aus diesem Chat habe ich es wieder geschafft, die sed-Aussagen viel unkomplizierter zu gestalten.

#!/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"
Syntax-Fehler
quelle
Nur eine Erinnerung, dass das Skript möglicherweise keine Geräte anzeigt, bei denen Probleme auftreten. Ich hatte ata6-Fehler mit fehlgeschlagenem Softreset (1st FIS failed) (Minor Issues) und es waren keine Geräte vorhanden. Wenn Sie wissen, dass Sie 4 Festplatten im PC haben und nur 3 angezeigt werden, ist dies möglicherweise der Grund.
Kendrick
1
@Kendrick Naja, ich würde das Skript in diesem Fall nicht beschuldigen. Wenn Sie wissen, wie die Kernel-Treiber funktionieren, wird Ihnen dies mehr als klar sein :) Kernel-Subsystem-Treiber geben bekanntermaßen auf , sobald die "Probleme" schwerwiegend genug sind. Dies bedeutet, dass ein UDMA-fähiges Laufwerk möglicherweise mehrere Laufwerksrücksetzungen veranlasst und (möglicherweise) einen Laufwerksvorgang im PIO-Modus versucht. Erweist sich dies jedoch ebenfalls als zu instabil (verschiedene Timing-Fehler usw.), sagt der Fahrer "Geh weg" zum Laufwerk. Bei alten PATA-Laufwerken bedeutet dies, dass ein Kaltstart erforderlich ist, damit das Laufwerk wieder angezeigt wird.
Syntaxfehler
Nicht meine Absicht, dem Drehbuch die Schuld zu geben. nur eine erinnerung, warum es fehlen könnte :) dummes seagate controller board machte es zu einer mühe herauszufinden, was los war.
Kendrick
@Kendrick Du sagst es mir, Mann. :) Nun, in meinem Buch hätte Seagate Samsung niemals aufkaufen sollen . Liebte die letzteren Laufwerke (als Samsung noch im Massenspeichergeschäft tätig war) sowie das ausgezeichnete Support-Team. Jetzt hat Seagate das alles übernommen ... und ... äh ... oh.
Syntaxfehler
11

Schau dir an /proc/scsi/scsi, was ungefähr so ​​aussieht:

$ 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 ist sda und ata1.00, scsi1 id 0 ist sdb und ata2.00, etc.

Schauen Sie sich auch an /var/log/dmesg, was die Ladeinformationen des ata-Treibers anzeigt und die Dinge ein wenig klarer macht. Suchen Sie nach der Zeile, die mit "libata" beginnt.

Phil Hollenback
quelle
8
Möglicherweise müssen Sie auch 'lsscsi' verwenden, was eine etwas menschlichere Ausgabe ergibt, z. B. [0: 0: 0: 0] CD / DVD TSSTcorp CDDVDW SH-S202H SB00 / dev / sr0 [2: 0: 0: 0 ] Festplatte ATA ST3500630AS 3.AA / dev / sda [3: 0: 0: 0] Festplatte ATA WDC WD5000AAKS-0 01.0 / dev / sdb (Auf diesem Server, auf dem ein 3.2.x-Kernel ausgeführt wird, gibt es kein / proc / scsi *) (Entschuldigung, ich kann nicht herausfinden, wie ich Formatierungen in das Obige bringen kann, um es lesbar zu machen)
David Goodwin
1
Dies sollte eher eine Antwort als ein Kommentar sein. Nützlich, schnell und einfach von einem Computer aus zu lesen und bei Problemen auf einem anderen Computer zu tippen.
Elder Geek
10

Ich bevorzuge Scriptlets anstelle von ausführlichen Erklärungen. Das funktioniert auf meiner Ubuntu-Box. Fügen Sie Kommentare hinzu, die Ihnen gefallen:

# 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
Peter
quelle
Ihr Skript ist ein bisschen weniger beängstigend als die Antwort, vor allem, weil ich das Ganze sehen kann.
Isaaclw
1
Ein wenig vereinfacht (funktioniert für mich auf Centos)ls -l /sys/block/sd* | sed -e 's@.*-> \.\..*/ata@/ata@' -e 's@/host@ @' -e 's@/target.*/@ @'
Shirker
9

Das ist eigentlich ziemlich knifflig. Man kann zwar mit Sicherheit davon ausgehen, dass "die SCSI-ID" "die SATA-ID minus eins" ist, aber ich möchte lieber wirklich sicher sein und die SATA-ID überprüfen, von der unique_idich annehme (basierend auf diesem Beitrag ).

Mein Fehler war:

[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

Also mein Verfahren, um herauszufinden, was ata4ist:

  1. Finden Sie die PCI-ID des SATA-Controllers

    # lspci | grep -i sata
    00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
    
  2. Finden Sie die passende eindeutige 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
    
  3. Also ist es an scsi_host/host3, in das wir übersetzen können, nach 3:x:x:xdem wir dmesgsuchen können, um mehr herauszufinden:

    # 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. Hier ist unser Gerät. Wir können (optional) die Seriennummer finden, um das Gerät herauszunehmen (oder die Verkabelung oder was auch immer zu überprüfen), bevor unser RAID-Array vollständig ausfällt:

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

Und du bist fertig!

Anarkatze
quelle
7

Versuche dies:

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

Ich habe das dmesg nie verstanden - einige Zeilen handeln von "ata4", andere von "scsi" oder "sdc", aber niemand weist "ata4 ... sdc" zu. Der gezeigte Befehl findet das / sys / bus / path, wobei sowohl ata4 als auch sdc angegeben sind.

schweik
quelle
5

Ich hatte das gleiche Problem und konnte Laufwerke durch Überprüfen von dmesg identifizieren. Dort sehen Sie die Controller-ID (korrekter Begriff ??) und das Modell der Festplatte. Verwenden Sie dann ls -l / dev / disk / by-id, um die Modellnummer mit / dev / sda (oder was auch immer) abzugleichen. Alternativ mag ich Disk Utility für diese Informationen. Hinweis: Dies funktioniert nur, wenn Ihre Festplatten unterschiedliche Modellnummern haben, andernfalls können Sie die beiden nicht unterscheiden.

>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
quelle
2

Am einfachsten ist es, das Kernel-Protokoll nach dem Start zu überprüfen, da die Laufwerksgerätenamen aus verschiedenen Quellen (z. B. USB-Laufwerken) eingemischt oder je nach Gerätetyp zugewiesen werden (z. B. CD-ROM kann stattdessen SCDX sein und alles hat SGX) ). In der Praxis ist, sofern Sie nicht verschiedene Arten von Bussen gemischt haben (z. B. SATA + USB), das Gerät mit der niedrigsten Nummer sda, es sei denn, es handelt sich um ein CD-ROM-Gerät.

Abhängig von Ihrem System kann dies durch Umherwandern von sysfs erkannt werden. Auf meinem System wird ls -l /sys/dev/blockangezeigt, dass 8:0(major: minor from / dev entry) verweist auf /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda Ebenso werden ls -l /sys/class/ata_portdie ata1Punkte /sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1angezeigt, auf die sich dasselbe PCI-Subgerät befindet.

Da ich SATA verwende und nur ein Laufwerk an jedem Port angeschlossen ist, kann ich ableiten, dass ata1.00 = sda ist. Alle meine Laufwerke sind .00, ich vermute, wenn ich einen Port-Multiplikator verwenden würde, würden meine Laufwerke mit .01, .02, .03 usw. versehen. In den Protokollen anderer verwenden PATA-Controller .00 und .01 für Master und Slave , und basierend auf ihren Protokollen, wenn Sie ataX.01 haben, sollte die .01 der "ID" im Ordner host: channel: ID: LUN aus der /sys/dev/block/Auflistung zugeordnet werden. Wenn Sie mehrere ataX/und hostY/Ordner im selben PCI- Geräteordner haben , vermute ich , dass der ataX-Ordner mit der niedrigsten Nummer mit dem hostY-Ordner mit der niedrigsten Nummer übereinstimmt.

DerfK
quelle
2

In /sys/class/ata_port/ata${n}/device/können Sie einen host${x}Ordner sehen. ZB auf meiner Maschine:

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

Das ${x}in host${x}bezieht sich auf die erste Ziffer im [0:0:0:0]. Also für mich ata1bezieht sich host0was auch in SCSI Form dargestellt werden kann als 0:*:

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

Das folgende Skript gibt Ihnen eine schöne Zusammenfassung wie folgt:

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

So in einer Zeile pro Laufwerk haben Sie sdX Gerätenamen, Größe , Modell , s / n und die pci und ATA - Nummern. Der obige SDC entspricht einem USB-SD-Kartenleser ohne eingesetzte Karte. Daher das ---- anstelle von wirklicher Information.

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

(nur unter Ubuntu 12.04 / 14.04 und CentOS 6 getestet)

ndemou
quelle
Wie bedeutet das, Ihnen zu zeigen, was beispielsweise ATA 4.01 ist?
Edward_178118
In der Beispielausgabe sehen Sie sda: ... ata1 ... und sdb: ... ata3 .... Und tatsächlich war sda bei ata1 und sdb bei ata2. Da ich es auf 4 verschiedenen Hosts geschrieben und getestet habe, habe ich herausgefunden, wo das obige Skript keinen Verweis auf ata enthält. Ich sollte darauf hinweisen, dass dmesg | grep "ata [0-9]" mich nie im Stich gelassen hat.
Ndemou
0

Ein Skript zum Auffinden dieser und weiterer Informationen finden Sie unter https://www.av8n.com/computer/disk-hw-host-bus-id

Es ähnelt dem Skript von Mr. Syntaxerror, ist aber schicker. - Es funktioniert sowohl für USB-Laufwerke als auch für ATA-Laufwerke. - Sie enthält die Marke und das Modell des Laufwerks sowie die Seriennummer - und natürlich den Befestigungspunkt. - Es ist einfacher, lesbarer und wartbarer.

John Denker
quelle