¿Cómo asignar identificadores ataX.0 en mensajes de error kern.log a dispositivos reales / dev / sdY?


11

Considere seguir el kern.logfragmento:

 ata4.00: failed command: WRITE FPDMA QUEUED
 ata4.00: cmd 61/00:78:40:1e:6c/04:00:f0:00:00/40 tag 15 ncq 524288 out
        res 41/04:00:00:00:00/04:00:00:00:00/00 Emask 0x1 (device error)
 ata4.00: status: { DRDY ERR }
 ata4.00: error: { ABRT }
 ata4: hard resetting link
 ata4: nv: skipping hardreset on occupied port
 ata4: SATA link up 3.0 Gbps (SStatus 123 SControl 300)
 ata4.00: configured for UDMA/133
 ata4: EH complete

¿Cómo puedo identificar a qué disco duro se refiere realmente el núcleo cuando habla ata4.00?

¿Cómo puedo encontrar el /dev/sdYnombre del dispositivo correspondiente ?

Respuestas:


10

Puede encontrar el dispositivo / dev / sdY correspondiente atravesando el /sysárbol:

$ find /sys/devices | grep '/ata[0-9]\+/.*/block/s[^/]\+$' \
    | sed 's@^.\+/\(ata[0-9]\+\)/.\+/block/\(.\+\)$@\1 => /dev/\2@'

Con un /sysrecorrido más eficiente (cf. lsata.sh ):

$ echo /sys/class/ata_port/ata*/../../host*/target*/*/block/s* | tr ' ' '\n' \
    | awk -F/ '{printf("%s => /dev/%s\n", $5, $NF)}'

Ejemplo de salida de un sistema de 2 discos:

ata1 => /dev/sda
ata2 => /dev/sdb

Luego, para identificar de manera confiable el hardware real, debe asignar / dev / sdY al número de serie, por ejemplo:

$ ls /dev/disk/by-id -l | grep 'ata.*sd[a-zA-Z]$'

lssci

La lssciutilidad también se puede utilizar para derivar la asignación:

$ lsscsi | sed 's@^\[\([^:]\+\).\+\(/dev/.\+\)$@\1,\2@' \
    | awk -F, '{ printf("ata%d => %s\n", $1+1, $2) }'

Tenga en cuenta que la enumeración lsscsi relevante comienza desde 0 mientras que la enumeración ata comienza desde 0.

Syslog

Si nada más funciona, uno puede mirar el syslog / journal para derivar el mapeo.

Los /dev/sdYdispositivos se crean en el mismo orden en que se enumeran los identificadores ataX kern.logmientras se ignoran los dispositivos sin disco (ATAPI) y los enlaces no conectados.

Por lo tanto, el siguiente comando muestra la asignación:

$ grep '^May 28 2'  /var/log/kern.log.0  | \
   grep 'ata[0-9]\+.[0-9][0-9]: ATA-' | \
   sed 's/^.*\] ata//' | \
   sort -n | sed 's/:.*//' | \
   awk ' { a="ata" $1; printf("%10s is /dev/sd%c\n", a, 96+NR); }'
ata1.00 is /dev/sda
ata3.00 is /dev/sdb
ata5.00 is /dev/sdc
ata7.00 is /dev/sdd
ata8.00 is /dev/sde
ata10.00 is /dev/sdf

(Tenga en cuenta que ata4 no se muestra porque los mensajes de registro anteriores son de otro sistema).

Estoy usando /var/log/kern.log.0y no /var/log/kern.logporque los mensajes de arranque ya están rotados. Estoy ansioso May 28 2porque este fue el último tiempo de arranque y quiero ignorar los mensajes anteriores.

Para verificar la asignación, puede hacer algunas comprobaciones mirando la salida de:

$ grep '^May 28 2'  /var/log/kern.log.0  | \
grep 'ata[0-9]\+.[0-9][0-9]: ATA-'
May 28 20:43:26 hn kernel: [    1.260488] ata1.00: ATA-7: SAMSUNG SV0802N, max UDMA/100
May 28 20:43:26 hn kernel: [    1.676400] ata5.00: ATA-5: ST380021A, 3.19, max UDMA/10
[..]

Y puede comparar esta salida con la hdparmsalida, por ejemplo:

$ hdparm -i /dev/sda

/dev/sda:

Model=SAMSUNG SV0802N [..]

(usando Kernel 2.6.32-31)


Esto es simplemente impresionante, muchas gracias por esta excelente respuesta ...
stuartc

@stuarte, de nada - por cierto, cks ha escrito sobre todos los diferentes esquemas de nombres de dispositivos SATA en los sistemas Linux actuales . Con respecto a los identificadores ataX, escribe: 'Estos nombres no aparecen en sysfs en lo que puedo ver'
maxschlepzig

1
Hmm Mi problema con la operación de verificación de esto es que generalmente tengo más de 8 discos del mismo modelo, por lo que las comprobaciones del fabricante no son tan valiosas.
drescherjm

1
@drescherjm, he actualizado mi respuesta. El nuevo método debe ser robusto y, por lo tanto, eliminar cualquier necesidad de una verificación de proveedor.
maxschlepzig

Tengo lo que creo que es un script sysfs mejorado; en particular, maneja números ata de dos dígitos (/ ata [0-9] / no coincidirá con ata10) y también encuentra dispositivos sata no nombrados sd * (por ejemplo, sr0): para un in / sys / class / ata_port / ata * ; do printf '% s \ t% s \ n' "$ (nombre base" $ a ")" "$ (buscar" $ a / dispositivo / "-iname 'block' -exec ls {} \;)"; hecho
Jason

2

Aquí está mi versión, modificada desde arriba. Como no sé la fecha exacta en que se inició el sistema (para probar esto fue hace 27 días), y no sé qué kern.log contiene los datos que necesito (algunos pueden estar gzippeden mi sistema), utilizo uptimey datepara calcular una fecha aproximada de inicio del sistema (al día, de todos modos), luego use zgreppara buscar en todos los archivos kern.log disponibles.

También modifiqué ligeramente la segunda grepdeclaración, ya que ahora también mostrará una unidad de CD / DVD ATAPI, así como unidades ATA- *.

Todavía podría usar refinamiento (es decir, si el tiempo de actividad del sistema es mayor a un año), pero debería funcionar bien por ahora.

#!/bin/bash

uptime=$(uptime | awk -F' '  '{ print $3" "$4 }' | sed s/,//)
date=$(date -d "$uptime ago" | awk '{print $2" "$3 }')
zgrep "$date"  /var/log/kern.log*  | \
grep 'ata[0-9]\+.[0-9][0-9]: ATA'  | \
sed 's/^.*\] ata//' | \
sort -n | sed 's/:.*//' | \
awk ' { a="ata" $1; printf("%10s is /dev/sd%c\n", a, 96+NR); }'

1

Acabo de tener este mismo problema y encontré otra solución que podría gustarle.

La herramienta lsscsi enumera los dispositivos SCSI (o hosts) y sus atributos.

Con lsscsi se obtiene el nombre ata y el nombre del dispositivo.

Se ve como esto:

$ lsscsi --long
[0:0:1:0]    cd/dvd  MATSHITA DVD-ROM UJDA780  1.50  /dev/sr0
  state=running queue_depth=1 scsi_level=6 type=5 device_blocked=0 timeout=30
[2:0:0:0]    disk    ATA      WDC WD3000FYYZ-0 01.0  /dev/sda
  state=running queue_depth=1 scsi_level=6 type=0 device_blocked=0 timeout=30
[3:0:0:0]    disk    ATA      WDC WD1002FBYS-0 03.0  /dev/sdb
  state=running queue_depth=1 scsi_level=6 type=0 device_blocked=0 timeout=30
[4:0:0:0]    disk    ATA      WDC WD1002FBYS-0 03.0  /dev/sdc
  state=running queue_depth=1 scsi_level=6 type=0 device_blocked=0 timeout=30
[5:0:0:0]    disk    ATA      WDC WD1002FBYS-0 03.0  /dev/sdd
  state=running queue_depth=1 scsi_level=6 type=0 device_blocked=0 timeout=30
[6:0:0:0]    disk    ATA      WDC WD3000FYYZ-0 01.0  /dev/sde
  state=running queue_depth=1 scsi_level=6 type=0 device_blocked=0 timeout=30
[7:0:0:0]    disk    ATA      WDC WD1002FBYS-0 03.0  /dev/sdf
  state=running queue_depth=1 scsi_level=6 type=0 device_blocked=0 timeout=30

En Ubuntu uno puede instalar lsscsi simplemente con

$ sudo apt-get install lsscsi

2
hm, y ¿cómo se asigna el ataXmapa a qué parte de la lsscsisalida?
maxschlepzig

1
@maxschlepzig El primer número en: quads es el mismo que el ataX con una distinción importante; la salida de lsscsi está indexada en 0 y ataZ está indexada en 1; así que [2: 0: 0: 0] sería ata3 que es / dev / sda en la salida que publicó longsleep
Jason

@ Jason, ok, aquí hay una lsscsi | sed 's@^\[\([^:]\+\).\+\(/dev/.\+\)$@\1,\2@' | awk -F, '{ printf("ata%d => %s\n", $1+1, $2) }'
frase

@ Jason, vea también mi respuesta actualizada para una alternativa que accede directamente /sys/devicessin lsscsi.
maxschlepzig

0

Ninguna de las respuestas anteriores funcionó para mí, y el enfoque lsscsi en realidad arrojó la respuesta incorrecta, debido a las discrepancias entre los números de bus SCSI y los números ATA. En un sistema de 21 discos, tuve muchos informes de syslog sobre problemas con ATA18 (violaciones de HSM). ¿Qué disco estaba causando estos errores? Algunos eran unidades USB, lo que hacía las cosas considerablemente más confusas. Necesitaba un recuento de cómo todas y cada una de las unidades SCSI están conectadas al sistema, y ​​escribí el siguiente script que produce listados tabulares para todos los discos SCSI (/ dev / s [dr]?) Independientemente de si es ATA o USB.

Luego, con todas las unidades de disco totalmente explicadas, me sorprendió ver que mis errores ATA no tenían nada que ver con ninguna de mis unidades de disco. Había estado haciendo la pregunta equivocada, y creo que otros podrían caer fácilmente en la misma trampa, por eso lo menciono aquí. Luego utilicé un segundo enfoque que identificaba el hardware que generaba los mensajes de violación de HSM, también detallado en la documentación que aparece en el script a continuación.

#!/bin/bash

## This script lists the ata and usb bus numbers, as well as the
## overall "host" numbers, of each scsi disk.  The same information
## appears formatted four ways, redundantly, for ease of lookup by (1)
## device lettername, (2) ata bus, (3) usb bus, or (4) overall "host"
## number.

#######################################################

## Q: What if you're looking for an ATA bus number, e.g. ata18, that
##    isn't listed by this script?

## (1) Well, it's probably not a SCSI disk, at least not one that's
##     operating.

## (2) Somewhere in /sys you can find a mapping from the ATA bus
##     number to some overall host number, such as host17.  For example,
##     if you're looking for ata18, you can use a find command...

##     find /sys -type l -exec bash -c 'link=`readlink "$0"`; if [[ "$link" =~ /ata18/ ]] ; then echo $link ; fi' {} \;

##     ...which, after some delay, might yield output something like this:

##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/ata_port/ata18
##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17/target17:0:0/17:0:0:0/scsi_generic/sg5
##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/link18/dev18.0/ata_device/dev18.0
##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17/scsi_host/host17
##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/link18/ata_link/link18
##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17/target17:0:0/17:0:0:0/bsg/17:0:0:0
##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17/target17:0:0/17:0:0:0/scsi_device/17:0:0:0
##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17/target17:0:0/17:0:0:0/scsi_generic/sg5
##    ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17/target17:0:0/17:0:0:0/bsg/17:0:0:0
##    ../../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17/target17:0:0/17:0:0:0
##    ../../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17
##    ../../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/ata18/host17/target17:0:0

##     Then you might notice the "/host17/" or "scsi_device/17:0:0:0"
##     in the above output lines, and look in the output of...

##     lshw

##     .. for "scsi17" or "17:0" or such, and discover, somewhere in it ...

##     ...
##        *-scsi:5
##           physical id: 8
##           logical name: scsi17
##           capabilities: emulated
##         *-processor UNCLAIMED
##              description: SCSI Processor
##              product: 91xx Config
##              vendor: Marvell
##              physical id: 0.0.0
##              bus info: scsi@17:0.0.0
##              version: 1.01
##              capabilities: removable
##              configuration: ansiversion=5
##     ...

## ...thus learning that ata18 corresponds to an unclaimed device (but
## not actually a disk).  Q.E.D.

## P.S. the lsscsi command yields the following, which might lead
## one to think that the problem was being caused by a CD-ROM drive
## (SCSI18:0) rather than emanating from the Marvell (SCSI17:0):

## [17:0:0:0]   process Marvell  91xx Config      1.01  -        
## [18:0:0:0]   cd/dvd  HL-DT-ST DVDRAM GH22NS90  HN00  /dev/sr0 

## ... but ATA != SCSI, and 17 != 18.  The CD/DVD drive was ATA19, 
## actually.  You can still use lsscsi, but
## bear in mind that what you're seeing in the left column
## is *not* ATA numbers but rather SCSI bus numbers, and the two
## are not to be confused.
#######################################################

blockDevsDir=/sys/dev/block

declare -A scsiDevLetters
declare -A hostNumbers
declare -A ataNumbers
declare -A usbNumbers

scsiDevLetterRE='/s(d[a-z]|r[0-9])$'
hostNumberRE='/host([0-9]+)/'
ataNumberRE='/ata([0-9]+)/'
usbNumberRE='/usb([0-9]+)/'

cd "$blockDevsDir"
for busid in `ls -1` ; do
    linkval=`readlink "$busid" `
    if [[ "$linkval" =~ $scsiDevLetterRE ]] ; then
        scsiDevLetter="${BASH_REMATCH[1]}"
        if [[ "$linkval" =~ $hostNumberRE ]] ; then
            hostNumber="${BASH_REMATCH[1]}"
            if [[ "$linkval" =~ $ataNumberRE ]] ; then
                ataNumber="${BASH_REMATCH[1]}"
                scsiDevLetters[$scsiDevLetter]=`printf 'ata%-2.2s  host%-2.2s' "${ataNumber}" "${hostNumber}"`
                hostNumbers[${hostNumber}]=`printf '/dev/sd%s  ata%-2.2s' "${scsiDevLetter}" "${ataNumber}"`
                ataNumbers[${ataNumber}]=`printf '/dev/sd%s  host%-2.2s' "${scsiDevLetter}" "${hostNumber}"`
            elif [[ "$linkval" =~ $usbNumberRE ]] ; then
                usbNumber="${BASH_REMATCH[1]}"
                scsiDevLetters[$scsiDevLetter]=`printf 'usb%-2.2s  host%-2.2s' "${usbNumber}" "${hostNumber}"`
                hostNumbers[${hostNumber}]=`printf '/dev/sd%s  usb%-2.2s' "${scsiDevLetter}" "${usbNumber}"`

                existingUsbValue="${usbNumbers[${usbNumber}]}"
                addedUsbValue=`printf '/dev/sd%s  host%-2.2s' "${scsiDevLetter}" "${hostNumber}"`
                if [ -n "$existingUsbValue" ] ; then
                    usbNumbers[${usbNumber}]="$existingUsbValue | $addedUsbValue"
                else
                    usbNumbers[${usbNumber}]="$addedUsbValue"
        fi
            else
        echo "Neither ata nor usb: /dev/sd${scsiDevLetter} (host${hostNumber}) !"
            fi
        else
        echo "No host number for /dev/sd${scsiDevLetter}"
        fi
    fi
done    

echo '/dev/sd?'
echo '--------'
for scsiDevLetter in `echo "${!scsiDevLetters[*]}" | tr ' ' '\n' | sort` ; do
    echo "/dev/sd${scsiDevLetter}    ${scsiDevLetters[$scsiDevLetter]}"
done
echo
echo 'ataNN'
echo '-----'
for ataNumber in `echo "${!ataNumbers[*]}" | tr ' ' '\n' | sort -n` ; do
    printf 'ata%-2.2s    %s\n' "$ataNumber" "${ataNumbers[$ataNumber]}"
done
echo
echo 'usbNN'
echo '-----'
for usbNumber in `echo "${!usbNumbers[*]}" | tr ' ' '\n' | sort -n` ; do
    printf 'usb%-2.2s    %s\n' "$usbNumber" "${usbNumbers[$usbNumber]}"
done
echo
echo 'hostNN'
echo '------'
for hostNumber in `echo "${!hostNumbers[*]}" | tr ' ' '\n' | sort -n` ; do
    printf 'host%-2.2s    %s\n' "$hostNumber" "${hostNumbers[$hostNumber]}"
done
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.