Errores de Linux ATA: ¿se traducen al nombre de un dispositivo?

36

Cuando un cuadro de Linux recibe un error ATA, lo registra con un mensaje que identifica el disco como "ata% d.00". ¿Cómo traduzco eso al nombre de un dispositivo (por ejemplo /dev/sdb)? Siento que esto debería ser trivial, pero no puedo entenderlo.

nelhage
fuente
1
Consulte también mi respuesta a una pregunta similar sobre Unix-SE: unix.stackexchange.com/a/13988/1131
maxschlepzig

Respuestas:

28

Peter me inspiró a escribir un script avanzado (let), que incluso puede detectar memorias USB (en lugar de generar cosas tontas como "ata0.00"). Al contrario del guión de Peter, también obtendrá el subnúmero (como en 4.01) si tiene más de un dispositivo en el mismo controlador resp. canal. La salida será exactamente como la recibes syslog. Probado Funciona muy bien en mi cuadro de Debian, aunque siempre hay muchas mejoras (por ejemplo, expresiones regulares demasiado torpes). Pero aguanta! ¡El número aparentemente elevado de caracteres escapados que puedes encontrar en mis expresiones regulares es solo por razones de compatibilidad! No puedes asumir GNU sedcon todos, por eso lo hice sin expresiones regulares extendidas a propósito.

ACTUALIZACIONES
(1) Ya no analizará la lssalida. (¡Uy!) Como todos ustedes saben: No analice ls.
(2) Ahora también funciona en entornos de solo lectura.
(3) Inspirado por una sugerencia de este chit-chat aquí , he logrado que las declaraciones sed sean mucho menos complicadas.

#!/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"
error de sintaxis
fuente
Solo un recordatorio de que el script puede no mostrar dispositivos que tengan problemas. Tuve un error de ata6 con softreset falló (1er FIS falló) (Problemas menores) enumeró los dispositivos y no estaba presente. Si sabe que tiene 4 discos en la PC y solo aparecen 3, ese puede ser el motivo.
Kendrick
1
@Kendrick Bueno, no culparía al script en este caso. Si sabe cómo funcionan los controladores del kernel, esto será más que claro para usted :) Se sabe que los controladores del subsistema del kernel se rinden una vez que los "problemas" son lo suficientemente graves. Esto dice que, para un disco con capacidad UDMA, puede inducir múltiples reinicios de disco y (eventualmente) intentar una operación de disco en modo PIO. Sin embargo, si esto también resulta demasiado inestable (varios errores de sincronización, etc.), el conductor dirá "vete" a la unidad. Para las unidades PATA antiguas, esto significa que un reinicio en frío será obligatorio para que la unidad vuelva a aparecer.
syntaxerror
No es mi intención culpar al guión. solo un recordatorio de por qué puede faltar :) la estúpida placa controladora de Seagate flakey hizo que fuera difícil entender lo que estaba sucediendo.
Kendrick
@Kendrick Me estás diciendo hombre. :) Bueno, en mi libro, Seagate nunca debería haber comprado Samsung. Me encantaron las últimas unidades (cuando Samsung todavía estaba en el negocio de almacenamiento masivo), además de su excelente equipo de soporte. Ahora Seagate se ha hecho cargo de todo esto ... y ... uh-oh.
syntaxerror
11

Mira /proc/scsi/scsi, que se verá más o menos así:

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

También mire /var/log/dmesg, que muestra la información de carga del controlador ata y hará las cosas un poco más claras. Busque la línea que comienza "libata".

Phil Hollenback
fuente
8
Es posible que también necesite usar 'lsscsi', que proporciona una salida un poco más amigable para los humanos, por ejemplo, [0: 0: 0: 0] cd / dvd TSSTcorp CDDVDW SH-S202H SB00 / dev / sr0 [2: 0: 0: 0 ] disco ATA ST3500630AS 3.AA / dev / sda [3: 0: 0: 0] disco ATA WDC WD5000AAKS-0 01.0 / dev / sdb (En este servidor, ejecutando un núcleo 3.2.x, no hay / proc / scsi *) (Lo siento, parece que no puedo entender cómo obtener ningún formato en lo anterior, para que sea legible)
David Goodwin
1
Esto debería ser una respuesta en lugar de un comentario. Útil, rápido y fácil de leer desde una máquina y escribir en otra con problemas.
Élder Geek,
10

Prefiero guiones en lugar de explicaciones largas. Esto funciona en mi caja de Ubuntu. Agrega comentarios a tu gusto:

# 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
fuente
Su guión es un poco menos aterrador que la respuesta, principalmente porque puedo ver todo.
isaaclw 01 de
1
Un poco de simplificación (funciona para mí en Centos)ls -l /sys/block/sd* | sed -e 's@.*-> \.\..*/ata@/ata@' -e 's@/host@ @' -e 's@/target.*/@ @'
Shirker
9

Esto es realmente bastante complicado. Si bien es seguro suponer que "la identificación scsi" es "la identificación SATA menos uno", prefiero estar realmente seguro e inspeccionar unique_idlo que supongo (según esta publicación ) es el identificador SATA.

Mi error fue:

[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

Entonces, mi procedimiento para averiguar qué ata4es:

  1. encontrar la identificación PCI del controlador SATA

    # lspci | grep -i sata
    00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
    
  2. encuentre la ID única que coincida:

    # 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. así que está activado scsi_host/host3, lo que podemos traducir 3:x:x:x, a lo que podemos acceder para dmesgobtener más información:

    # 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. aquí está nuestro dispositivo, podemos (opcionalmente) encontrar el número de serie para sacar ese dispositivo de allí (o verificar el cableado o lo que sea) antes de que nuestra matriz RAID falle por completo:

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

¡Y tu estas listo!

anarcat
fuente
7

Prueba esto:

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

Nunca entendí el dmesg: algunas filas son sobre "ata4" y otras sobre "scsi" o sdc, pero nadie asigna "ata4 ... están especificados

Schweik
fuente
5

Tuve el mismo problema y pude identificar las unidades comprobando dmesg. Allí puede ver el identificador del controlador (término correcto ??) y el modelo del disco. Luego use ls -l / dev / disk / by-id para hacer coincidir el número de modelo con / dev / sda (o lo que sea). Alternativamente, me gusta Disk Utility para esta información. Nota: esto solo funciona si sus discos tienen números de modelo diferentes, de lo contrario no podrá distinguir entre los dos.

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

La forma más fácil es revisar el registro del núcleo desde el inicio, ya que los nombres de los dispositivos de la unidad se mezclan desde varias fuentes (por ejemplo, unidades USB), o se asignan según el tipo de dispositivo (es decir, cdrom puede ser scdX en su lugar, y todo tiene un sgX ) En la práctica, a menos que haya mezclado diferentes tipos de buses (por ejemplo, SATA + USB), el dispositivo ata de menor número será sda a menos que sea un dispositivo cdrom.

Dependiendo de su sistema, puede adivinarse deambulando por sysfs. En mi sistema ls -l /sys/dev/blockrevela que 8:0(mayor: menor desde la entrada / dev) apunta a /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda Likewise, ls -l /sys/class/ata_portrevela los ata1puntos a los /sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1que está en el mismo subdispositivo PCI.

Como uso SATA, y solo hay una unidad en cada puerto, puedo deducir que ata1.00 = sda. Todas mis unidades son .00, sospecho que si usara un multiplicador de puerto, mis unidades recibirían .01, .02, .03, etc. Mirando los registros de otras personas, los controladores PATA usan .00 y .01 para maestro y esclavo , y según sus registros si tiene ataX.01, el .01 debe asignarse a la "ID" en el host: canal: ID: carpeta LUN de la /sys/dev/block/lista. Si tiene varias carpetas ataX/y hostY/en la misma carpeta del dispositivo PCI, sospecho que la carpeta ataX con el número más bajo coincide con la carpeta hostY con el número más bajo.

DerfK
fuente
2

En /sys/class/ata_port/ata${n}/device/, puedes ver una host${x}carpeta. Por ejemplo, en mi máquina:

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

El ${x}in se host${x}refiere a ese primer número en el [0:0:0:0]. Entonces para mí se ata1refiere a host0que también se puede representar en forma SCSI como 0:*:

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

El siguiente script le dará un buen resumen como este:

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

Entonces, en una línea por unidad, tiene el nombre del dispositivo sdX , el tamaño , el modelo , s / ny los números pci y ata . El SDC anterior corresponde a un lector de tarjetas SD USB sin tarjeta insertada. De ahí el ---- en lugar de información real.

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

(solo probado en ubuntu 12.04 / 14.04 y CentOS 6)

ndemou
fuente
¿Cómo equivale a mostrarle qué es, por ejemplo, ATA 4.01?
Edward_178118
En la salida de ejemplo, verá sda: ... ata1 ... y sdb: ... ata3 .... Y de hecho, sda estaba en ata1 y sdb en ata2. Desde que lo escribí y lo probé en 4 hosts diferentes, descubrí HW donde el script anterior no contiene una referencia a ata. Debo señalar que dmesg | grep "ata [0-9]" nunca me ha fallado.
ndemou
0

Puede encontrar un script para encontrar esta información y más en https://www.av8n.com/computer/disk-hw-host-bus-id

Es similar al guión proporcionado por Mr. Syntaxerror, pero más elegante. - Funciona tanto para unidades USB como para unidades ATA. - Proporciona la marca, modelo y número de serie de la unidad, y, por supuesto, el punto de conexión. - Es más sencillo, legible y fácil de mantener.

John Denker
fuente