Comment mapper les identifiants ataX.0 dans les messages d'erreur kern.log aux périphériques réels / dev / sdY?

11

Envisagez l' kern.logextrait suivant:

 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

Comment puis-je identifier le disque dur que le noyau signifie réellement lorsqu'il parle ata4.00?

Comment puis-je trouver le /dev/sdYnom d'appareil correspondant ?

maxschlepzig
la source

Réponses:

10

Vous pouvez trouver le périphérique / dev / sdY correspondant en parcourant l' /sysarborescence:

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

Avec une /systraversée plus efficace (cf. lsata.sh ):

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

Exemple de sortie d'un système à 2 disques:

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

Ensuite, pour identifier de manière fiable le matériel réel, vous devez mapper / dev / sdY au numéro de série, par exemple:

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

lssci

L' lssciutilitaire peut également être utilisé pour dériver le mappage:

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

Notez que l'énumération lsscsi appropriée commence à 0 tandis que l'énumération ata commence à 0.

Syslog

Si rien d'autre ne fonctionne, on peut consulter le journal / journal sys pour dériver le mappage.

Les /dev/sdYpériphériques sont créés dans le même ordre que les identifiants ataX sont énumérés dans le kern.logtout en ignorant les périphériques non-disque (ATAPI) et les liens non connectés.

Ainsi, la commande suivante affiche le mappage:

$ 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

(Notez que ata4 ne s'affiche pas car les messages de journal ci-dessus proviennent d'un autre système.)

J'utilise /var/log/kern.log.0et pas /var/log/kern.logparce que les messages de démarrage sont déjà tournés. Je demande May 28 2car c'était le dernier démarrage et je veux ignorer les messages précédents.

Pour vérifier le mappage, vous pouvez effectuer quelques vérifications en regardant la sortie 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
[..]

Et vous pouvez comparer cette sortie avec une hdparmsortie, par exemple:

$ hdparm -i /dev/sda

/dev/sda:

Model=SAMSUNG SV0802N [..]

(en utilisant le noyau 2.6.32-31)

maxschlepzig
la source
C'est tout simplement génial, merci beaucoup pour cette excellente réponse ...
stuartc
@stuarte, vous êtes les bienvenus - btw, cks a fait un résumé de tous les différents schémas de dénomination des périphériques SATA sur les systèmes Linux actuels . En ce qui concerne les identifiants ataX, il écrit: «Ces noms n'apparaissent pas du tout dans sysfs pour autant que je puisse voir»
maxschlepzig
1
Hmm. Mon problème avec l'opération de vérification de ceci est que j'ai généralement plus de 8 disques du même modèle, les vérifications du fabricant ne sont donc pas si précieuses.
drescherjm
1
@drescherjm, j'ai mis à jour ma réponse. La nouvelle méthode devrait être robuste et éliminer ainsi tout besoin de vérification du fournisseur.
maxschlepzig
J'ai ce que je pense être un script sysfs amélioré; en particulier, il gère les nombres ata à deux chiffres (/ ata [0-9] / ne correspondra pas à ata10) et trouve également des périphériques sata non nommés sd * (par exemple sr0): pour un fichier dans / sys / class / ata_port / ata * ; do printf '% s \ t% s \ n' "$ (nom de base" $ a ")" "$ (find" $ a / device / "-iname 'block' -exec ls {} \;)"; fait
Jason
2

Voici ma version, modifiée d'en haut. Comme je ne connais pas la date exacte à laquelle le système a été démarré (pour le tester, il y a 27 jours), et je ne sais pas quel kern.log contient les données dont j'ai besoin (certaines peuvent être gzippedsur mon système), j'utilise uptimeet datepour calculer une date approximative de démarrage du système (jour après jour), puis utilisez zgreppour rechercher dans tous les fichiers kern.log disponibles.

J'ai également légèrement modifié la deuxième grepdéclaration, car elle affichera désormais également un lecteur de CD / DVD ATAPI ainsi que des lecteurs ATA- *.

Il pourrait toujours utiliser le raffinement (c'est-à-dire si la disponibilité du système est supérieure à un an), mais devrait fonctionner correctement pour l'instant.

#!/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); }'
ectospasme
la source
1

Je viens d'avoir ce même problème et j'ai trouvé une autre solution que l'on pourrait aimer.

L'outil lsscsi répertorie les périphériques SCSI (ou hôtes) et leur attribut.

Avec lsscsi, on obtient le nom ata et le nom du périphérique.

Ressemble à ça:

$ 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

Sur Ubuntu, on peut installer lsscsi simplement avec

$ sudo apt-get install lsscsi
long sommeil
la source
2
hm, et comment la ataXcarte à quelle partie de la lsscsisortie?
maxschlepzig
1
@maxschlepzig Le premier nombre dans les: quads est le même que l'ataX avec une distinction importante; la sortie de lsscsi est indexée 0 et ataZ est indexée 1; donc [2: 0: 0: 0] serait ata3 qui est / dev / sda dans la sortie publiée par longleep
Jason
@Jason, ok, voici un lsscsi | sed 's@^\[\([^:]\+\).\+\(/dev/.\+\)$@\1,\2@' | awk -F, '{ printf("ata%d => %s\n", $1+1, $2) }'
aller simple
@Jason, voir aussi ma réponse mise à jour pour une alternative qui accède directement /sys/devicessans lsscsi.
maxschlepzig
0

Aucune des réponses ci-dessus n'a fonctionné pour moi, et l'approche lsscsi a en fait donné la mauvaise réponse, en raison de divergences entre les numéros de bus SCSI et les numéros ATA. Sur un système à 21 disques, j'avais de nombreux rapports Syslog sur des problèmes avec ATA18 (violations HSM). Quel disque était à l'origine de ces erreurs? Certains étaient des lecteurs USB, ce qui rendait les choses beaucoup plus confuses. J'avais besoin d'une comptabilité de la façon dont chaque lecteur SCSI est connecté au système, et j'ai écrit le script ci-dessous qui fournit des listes tabulaires pour tous les disques SCSI (/ dev / s [dr]?), Qu'ils soient ATA ou USB.

Ensuite, avec tous les disques durs entièrement pris en compte, j'ai été surpris de voir que mes erreurs ATA n'avaient rien à voir avec aucun de mes disques durs. J'avais posé la mauvaise question, et je pense que d'autres pourraient facilement tomber dans le même piège, c'est pourquoi je le mentionne ici. J'ai ensuite utilisé une deuxième approche qui a identifié le matériel qui générait les messages de violation HSM, également détaillé dans la documentation apparaissant dans le script ci-dessous.

#!/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
Steve Newcomb
la source