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

36

Quand une machine Linux obtient une erreur ATA, elle le syslog avec un message identifiant le disque comme "ata% d.00". Comment traduire cela en un nom de périphérique (par exemple /dev/sdb)? Je pense que cela devrait être trivial, mais je ne peux pas le comprendre.

Nélhage
la source
1
Voir aussi ma réponse à une question similaire sous Unix-SE: unix.stackexchange.com/a/13988/1131
maxschlepzig,

Réponses:

28

Peter m'a inspiré pour écrire un script avancé (let), qui peut même détecter les clés USB (au lieu de produire 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 plusieurs périphériques sur le même contrôleur, resp. canal. La sortie sera exactement telle que vous la recevrez syslog. Testé. Je travaille très bien sur ma machine Debian, même s’il ya toujours beaucoup d’améliorations (par exemple, des expressions rationnelles trop maladroites). Mais tiens-le! Le nombre apparemment trop élevé de caractères d'échappement que vous pouvez trouver dans mes expressions régulières est juste pour des raisons de compatibilité! Vous ne pouvez pas assumer GNU sedavec tout le monde, raison pour laquelle j’ai fait exprès sans regexps étendus.

UPDATES
(1) N'analysera plus la lssortie. (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 les déclarations sed de manière moins compliquée.

#!/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"
erreur de syntaxe
la source
Juste un rappel que le script peut ne pas montrer les périphériques qui ont des problèmes. J'ai eu ata6 erreur avec softreset échoué (1er FIS a échoué) (problèmes mineurs) répertorié dvices et il n'était pas présent. Si vous savez que vous avez 4 disques dans le PC et seulement 3 apparaissent, c'est peut-être pour ça.
Kendrick
1
@Kendrick Eh bien, je ne voudrais pas blâmer le script dans ce cas. Car si vous savez comment fonctionnent les pilotes du noyau, vous comprendrez mieux que jamais :) Les pilotes de sous-systèmes du noyau sont connus pour abandonner dès que les «problèmes» sont suffisamment graves. Cela indique que, pour un lecteur compatible UDMA, cela peut induire la réinitialisation de plusieurs lecteurs et éventuellement tenter une opération de lecteur en mode PIO. Toutefois, si cela s'avère également trop instable (diverses erreurs de chronométrage, etc.), le conducteur dira "Va-t'en" pour le lecteur. Pour les anciens lecteurs PATA, cela signifie qu’un redémarrage à froid sera obligatoire pour que le lecteur se présente à nouveau.
erreur de syntaxe
Ce n'est pas mon intention de blâmer le script. juste un rappel de la raison pour laquelle il manque peut-être :) stupide carte contrôleur Seagate floconneuse rendait la douleur de comprendre ce qui se passait
Kendrick
@ Kendrick Vous me dites mec :) Eh bien, dans mon livre, Seagate n'aurait jamais dû racheter Samsung. J'ai adoré ces derniers disques (lorsque Samsung était encore dans le secteur du stockage de masse), ainsi que leur excellente équipe de support. Maintenant, Seagate a pris en charge tout cela ... et ... euh-oh.
erreur de syntaxe
11

Regardez /proc/scsi/scsiqui ressemble à 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 montre les informations de chargement du pilote ata et rendra les choses un peu plus claires. Recherchez la ligne commençant par "libata".

Phil Hollenback
la source
8
Vous devrez peut-être aussi utiliser 'lsscsi' - ce qui donne une sortie légèrement plus conviviale - par exemple [0: 0: 0: 0] cd / dvd TSSTcorp CDDVDW SH-S202H SB00 / dev / sr0 [2: 0: 0: 0 ] disque ATA ST3500630AS 3.AA / dev / sda [3: 0: 0: 0] disque ATA WDC WD5000AAKS-0 01.0 / dev / sdb (Sur ce serveur, exécutant un noyau 3.2.x, il n'y a pas de / proc / scsi *) (Désolé, je n'arrive pas à comprendre comment obtenir un formatage dans ce qui précède, pour le rendre lisible.)
David Goodwin
1
Cela devrait être une réponse plutôt qu'un commentaire. Utile, rapide et facile à lire sur une machine et à taper sur une autre avec des problèmes.
Elder Geek
10

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
Peter
la source
Votre script est un peu moins effrayant que la réponse, principalement parce que je peux tout voir.
isaaclw
1
Un peu de simplification (fonctionne pour moi sur Centos)ls -l /sys/block/sd* | sed -e 's@.*-> \.\..*/ata@/ata@' -e 's@/host@ @' -e 's@/target.*/@ @'
Shirker
9

C'est en fait assez délicat. Bien qu'il soit prudent de supposer que "l'ID scsi" est "l'ID SATA moins un", je préfère être vraiment sûr et inspecter le unique_idque je suppose (sur la base de ce post ) 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 qui ata4est:

  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. alors c’est sur scsi_host/host3, nous pouvons le traduire 3:x:x:x, que nous pouvons grep pour en dmesgsavoir 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 périphérique, nous pouvons (éventuellement) trouver le numéro de série qui permettra d'extraire ce périphérique (ou de vérifier le câblage ou autre) avant que notre système RAID ne soit totalement défaillant:

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

Et tu as fini!

anarcat
la source
7

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 parlent de "ata4", d'autres de "scsi" ou de sdc, mais personne n'attribue "ata4... Sdc" la commande affichée trouve le / sys / bus / path, où ata4 et sdc sont spécifiés.

schweik
la source
5

J'ai eu le même problème et j'ai pu identifier les lecteurs en vérifiant dmesg. Vous pouvez y voir l'identifiant du contrôleur (terme correct ??) et le modèle du disque. Ensuite, utilisez ls -l / dev / disk / by-id pour faire correspondre le numéro de modèle à / dev / sda (ou autre). Alternativement, j'aime Utilitaire de disque pour cette information. Remarque: cela ne fonctionne que si vos disques ont des numéros de modèle différents, sinon vous ne pourrez 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
Ecellingsworth
la source
2

Le moyen le plus simple est de consulter le journal du noyau depuis le démarrage, car les noms des périphériques de lecteur sont mélangés à partir de différentes sources (par exemple, des clés USB) ou attribués en fonction du type de périphérique (c-à-d. Cdrom peut plutôt être scdX, et tout est doté de sgX. ) En pratique, à moins que vous n'ayez mélangé différents types de bus (par exemple, SATA + USB), le périphérique le plus bas numéroté est sda, à moins qu'il s'agisse d'un périphérique cdrom.

En fonction de votre système, vous pouvez le deviner en vous baladant dans sysfs. Sur mon système, ls -l /sys/dev/blockrévèle que 8:0(majeur: mineur à partir de / dev) pointe sur /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda Like, ls -l /sys/class/ata_portque les ata1points sur /sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1lesquels se trouve sur le même sous-périphérique PCI.

Depuis que j'utilise SATA, et qu'un seul lecteur est sur chaque port, je peux en déduire que ata1.00 = sda. Tous mes disques ont une valeur de 0,00. Je suppose que si j'utilisais un multiplicateur de ports, ils seraient dotés de 0,01, 0,02, 0,03, etc. Regardant les journaux des autres utilisateurs et, en fonction de leurs journaux si vous avez ataX.01, le .01 doit être mappé sur "l'ID" dans le dossier hôte: channel: ID: LUN de la /sys/dev/block/liste. Si vous avez plusieurs dossiers ataX/et hostY/dans le même dossier de périphérique PCI, je suppose que le dossier ataX portant le numéro le plus bas correspond au dossier hostY portant le numéro le plus bas.

DerfK
la source
2

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 se host${x}réfère à ce premier numéro dans le [0:0:0:0]. Donc, pour moi, ata1fait référence à host0ce qui peut aussi être représenté sous forme SCSI comme 0:*:

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

Le script ci-dessous vous donnera un bon résumé comme ceci:

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 le nom du périphérique sdX , sa taille , son modèle , s / n et les numéros pci et ata . Le sdc ci-dessus correspond à un lecteur de carte SD USB sans aucune 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)

Ndemou
la source
Comment cela vous permet-il de vous montrer ce qu'est, par exemple, ATA 4.01?
Edward_178118
Dans l'exemple de sortie, vous voyez sda: ... ata1 ... et sdb: ... ata3 ... Et effectivement, sda était à ata1 et sdb à ata2. Depuis que je l'ai écrit et testé sur 4 hôtes différents, j'ai découvert HW où le script ci-dessus ne contient pas de référence à ata. Je dois signaler que dmesg | grep "ata [0-9]" ne m'a jamais manqué.
Ndemou
0

Vous trouverez un script pour trouver cette information, et plus encore, à l' adresse https://www.av8n.com/computer/disk-hw-host-bus-id.

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

John Denker
la source