48 votes

Erreurs ATA Linux : Translating to a device name ?

Lorsqu'une boîte Linux reçoit une erreur ATA, elle l'enregistre dans le syslog avec un message identifiant le disque comme "ata%d.00". Comment traduire ce message en un nom de périphérique (par ex. /dev/sdb ) ? J'ai l'impression que cela devrait être trivial, mais je n'y arrive pas.

33voto

syntaxerror Points 400

Peter m'a inspiré pour écrire un script(let) avancé, qui peut même détecter les clés USB (au lieu de sortir des choses stupides comme "ata0.00"). Contrairement au script de Peter, vous obtiendrez également le sous-numéro (comme dans 4.01) si vous avez plus d'un périphérique sur le même contrôleur ou canal. La sortie sera exactement comme vous l'obtenez dans syslog . Testé. Fonctionne très bien sur ma Debian, bien qu'il y ait toujours beaucoup d'améliorations à apporter (par exemple des regexps trop maladroites). Mais attention ! Le nombre apparemment trop élevé de caractères échappés que vous pouvez trouver dans mes regexps est juste pour des raisons de compatibilité ! Vous ne pouvez pas supposer que GNU sed avec tout le monde, c'est pourquoi j'ai volontairement renoncé aux regexps étendues.

MISE À JOUR
(1) N'analysera plus ls de la production. (oops !) Comme vous le savez tous : Ne pas analyser ls.
(2) Fonctionne désormais également dans les environnements en lecture seule.
(3) Inspiré par une suggestion de ce bavardage aquí J'ai réussi à rendre les déclarations sed beaucoup moins compliquées.

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

14voto

RyanBrady Points 1903

Regarder /proc/scsi/scsi qui ressemblera à quelque chose comme ceci :

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

Voir aussi /var/log/dmesg qui affiche les informations de chargement du pilote ata et rendra les choses un peu plus claires. Cherchez la ligne commençant par "libata".

13voto

DragonMinerToons Points 333

Je préfère les scripts aux longues explications. Cela fonctionne sur ma machine Ubuntu. Ajoutez des commentaires à votre convenance :

# 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

10voto

schweik Points 253

Essayez ceci :

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

Je n'ai jamais compris le dmesg - certaines lignes concernent "ata4", d'autres "scsi" ou sdc, mais personne n'attribue "ata4 . . . sdc" la commande affichée trouve le chemin /sys/bus/, où ata4 et sdc sont spécifiés.

Seulement si votre système udev le crée, vous pouvez simplement taper :

# ls -l /dev/disk/by-path/ 
lrwxrwxrwx 1 root root 2020-06-17 12:01 pci-0000:00:1d.7-usb-0:3:1.0-scsi-0:0:0:0 -> ../../sdc 
lrwxrwxrwx 1 root root 2020-06-17 12:07 pci-0000:00:1f.2-ata-1 -> ../../sda 
lrwxrwxrwx 1 root root 2020-06-17 12:07 pci-0000:00:1f.2-ata-1-part1 -> ../../sda1 
lrwxrwxrwx 1 root root 2020-06-17 12:07 pci-0000:00:1f.2-ata-2 -> ../../sdb

Le résultat contient tous les dispositifs de bas niveau et les dispositifs de bloc correspondants sur la même ligne.

9voto

Theturtguy Points 378

Il s'agit en fait d'une question assez délicate. Bien qu'il soit prudent de supposer que "l'ID scsi" est "l'ID SATA moins un", je préfère être vraiment prudent et inspecter l'ID unique_id que je suppose (sur la base de ce poste ) est l'identifiant SATA.

Mon erreur était la suivante :

[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

Je me suis donc efforcé de trouver ce que ata4 est :

  1. trouver l'identifiant PCI du contrôleur SATA

    # lspci | grep -i sata
    00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
  2. trouver l'identifiant unique correspondant :

    # 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. donc c'est parti scsi_host/host3 que l'on peut traduire par 3:x:x:x que nous pouvons rechercher dans dmesg pour en savoir plus :

    # 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. voici notre appareil, nous pouvons (éventuellement) trouver le numéro de série pour sortir cet appareil de là (ou vérifier le câblage ou autre) avant que notre réseau RAID ne tombe totalement en panne :

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

Et le tour est joué !

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X