web-dev-qa-db-fra.com

Erreurs Linux ATA: traduire en un nom de périphérique?

Lorsqu'une boîte Linux obtient une erreur ATA, elle l'enregistre avec un message identifiant le disque comme "ata% d.00". Comment traduire cela en nom d'appareil (par exemple /dev/sdb)? Je pense que cela devrait être trivial, mais je ne peux pas le comprendre.

36
nelhage

Peter m'a inspiré pour écrire un script avancé (let), qui peut même détecter des clés USB (au lieu de produire des choses idiotes 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 appareil sur le même contrôleur resp. canal. La sortie sera exactement telle que vous l'avez obtenue dans syslog. Testé. Fonctionne très bien sur ma boîte Debian, bien qu'il y ait toujours beaucoup d'améliorations (par exemple des regexps trop maladroits). Mais tenez-le! Le nombre apparemment trop élevé de caractères échappés que vous pouvez trouver dans mes expressions régulières est juste pour des raisons de compatibilité! Vous ne pouvez pas supposer GNU sed avec tout le monde, c'est pourquoi je l'ai fait sans regexps étendu exprès.

[~ # ~] met à jour [~ # ~]
(1) N'analysera plus la sortie ls. (oups!) Puisque vous savez tous: Ne pas analyser ls.
(2) Fonctionne désormais également sur les environnements en lecture seule.
(3) Inspiré par une suggestion de ce bavardage ici J'ai réussi à obtenir à nouveau les instructions 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"
28
syntaxerror

Regarder /proc/scsi/scsi, qui ressemblera à 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.

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

11
Phil Hollenback

Je préfère les scriptlets au lieu de longues explications. Cela fonctionne sur ma boîte Ubuntu. Ajoutez des commentaires à votre goût:

# 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
10
Peter

C'est en fait assez délicat. Bien qu'il soit sûr de supposer que "l'ID scsi" est "l'ID SATA moins un", je préfère être vraiment sûr et inspecter le unique_id que je suppose (basé sur cet article ) est l'identifiant SATA.

Mon erreur était:

[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

Donc, ma procédure pour savoir ce que ata4 est:

  1. trouver l'ID 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'ID 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. c'est donc sur scsi_Host/host3, que nous pouvons traduire en 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 (en option) trouver le numéro de série pour sortir cet appareil de là (ou vérifier le câblage ou autre) avant que notre matrice RAID échoue totalement:

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

Et tu as fini!

9
anarcat

Essaye ça:

# 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 portent sur "ata4", d'autres sur "scsi" ou sdc, mais personne n'assigne "ata4 ... sdc" la commande indiquée trouve le/sys/bus/path, où ata4 et sdc sont spécifiés.

7
schweik

J'ai eu le même problème et j'ai pu identifier les disques en vérifiant dmesg. Vous pouvez y voir l'identifiant du contrôleur (terme correct ??) et le modèle du disque. Utilisez ensuite ls -l/dev/disk/by-id pour faire correspondre le numéro de modèle à/dev/sda (ou autre). Alternativement, j'aime l'Utilitaire de disque pour ces informations. Remarque: cela ne fonctionne que si vos disques ont des numéros de modèle différents, sinon vous ne pouvez pas faire la distinction entre les deux.

>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
5
ecellingsworth

Dans /sys/class/ata_port/ata${n}/device/, vous pouvez voir un Host${x} dossier. Par exemple, sur ma machine:

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

Le ${x} dans Host${x} fait référence à ce premier nombre dans le [0:0:0:0]. Donc pour moi ata1 fait référence à Host0 qui peut également être représenté sous forme SCSI comme 0:*:

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

Le moyen le plus simple consiste à consulter le journal du noyau depuis le démarrage, car les noms des périphériques de lecteur sont mélangés à partir de diverses sources (par exemple, des lecteurs USB), ou sont attribués en fonction du type de périphérique (par exemple, cdrom peut être scdX à la place, et tout a un sgX). En pratique, à moins que vous n'ayez mélangé différents types de bus (par exemple SATA + USB), le périphérique ata le moins numéroté sera sda, sauf s'il s'agit d'un périphérique cdrom.

Selon votre système, il peut être deviné en se promenant dans sysfs. Sur mon système ls -l /sys/dev/block révèle que 8:0 (majeur: mineur depuis/dev) pointe vers /sys/devices/pci0000:00/0000:00:1f.2/Host0/target0:0:0/0:0:0:0/block/sda Également, ls -l /sys/class/ata_port révèle que ata1 pointe vers /sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1 qui se trouve sur le même sous-périphérique PCI.

Puisque j'utilise SATA, et qu'un seul lecteur est sur chaque port, je peux en déduire que ata1.00 = sda. Tous mes disques sont .00, je soupçonne que si j'utilisais un multiplicateur de ports, mes disques recevraient .01, .02, .03 etc. En regardant les journaux des autres, les contrôleurs PATA utilisent .00 et .01 pour le maître et l'esclave , et en fonction de leurs journaux si vous avez ataX.01, le .01 doit être mappé à l '"ID" dans le dossier Host: channel: ID: LUN du /sys/dev/block/ référencement. Si vous avez plusieurs ataX/ et hostY/ dossiers dans le même dossier de périphérique PCI, puis je suspect que le dossier ataX numéroté le plus bas correspond au dossier hostY numéroté le plus bas.

2
DerfK

Le script ci-dessous vous donnera un joli résumé comme celui-ci:

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

Donc, sur une ligne par lecteur, vous avez sdX nom du périphérique, taille, modèle, s/n et le - pci et ata nombres. Le sdc ci-dessus correspond à un lecteur de carte SD USB sans carte insérée. D'où le ---- à la place de l'information réelle.

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

(testé uniquement sur Ubuntu 12.04/14.04 et CentOS 6)

0
ndemou

Un script pour trouver ces informations, et plus, peut être trouvé sur https://www.av8n.com/computer/disk-hw-Host-bus-id

Il est similaire au script fourni par M. Syntaxerror, mais plus sophistiqué. - Il fonctionne pour les lecteurs USB ainsi que les lecteurs ATA. - Il fournit la marque et le modèle du lecteur et le numéro de série, - et bien sûr le point de fixation. - Il est plus simple, lisible et maintenable.

0
John Denker