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.
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"
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".
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
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:
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)
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
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
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!
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.
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
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
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.
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)
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.