Bagaimana cara memetakan pengidentifikasi ataX.0 dalam pesan kesalahan kern.log ke perangkat aktual / dev / sdY?

11

Pertimbangkan kern.logcuplikan berikut :

 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

Bagaimana saya bisa mengidentifikasi hard drive mana sebenarnya yang dimaksud kernel ketika dibicarakan ata4.00?

Bagaimana saya bisa menemukan /dev/sdYnama perangkat yang sesuai ?

maxschlepzig
sumber

Jawaban:

10

Anda dapat menemukan perangkat / dev / sdY yang sesuai melalui melintasi /syspohon:

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

Dengan /systraversal yang lebih efisien (lih. Lsata.sh ):

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

Contoh output dari sistem 2 disk:

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

Kemudian, untuk mengidentifikasi perangkat keras aktual yang andal, Anda perlu memetakan / dev / sdY ke nomor seri, misalnya:

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

lssci

The lssciutilitas juga dapat digunakan untuk menurunkan pemetaan:

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

Perhatikan bahwa enumerasi lsscsi yang relevan dimulai dari 0 sedangkan enumerasi ata dimulai dari 0.

Syslog

Jika tidak ada yang berhasil, seseorang dapat melihat syslog / jurnal untuk mendapatkan pemetaan.

Para /dev/sdYperangkat diciptakan dalam urutan yang sama seperti pengidentifikasi ataX yang disebutkan dalam kern.logsementara mengabaikan perangkat non-disk (ATAPI) dan link tidak terhubung.

Dengan demikian, perintah berikut menampilkan pemetaan:

$ 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

(Perhatikan bahwa ata4 tidak ditampilkan karena pesan log di atas berasal dari sistem lain.)

Saya menggunakan /var/log/kern.log.0dan bukan /var/log/kern.logkarena pesan boot sudah diputar. Saya setuju May 28 2karena ini adalah waktu boot terakhir dan saya ingin mengabaikan pesan sebelumnya.

Untuk memverifikasi pemetaan Anda dapat melakukan beberapa pemeriksaan melalui melihat output dari:

$ 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
[..]

Dan Anda dapat membandingkan output ini dengan hdparmoutput, misalnya:

$ hdparm -i /dev/sda

/dev/sda:

Model=SAMSUNG SV0802N [..]

(menggunakan Kernel 2.6.32-31)

maxschlepzig
sumber
Ini luar biasa, terima kasih banyak atas balasan luar biasa ini ...
stuartc
@stuarte, Anda dipersilakan - btw, cks telah melakukan writeup tentang semua skema penamaan yang berbeda dari perangkat SATA pada sistem Linux saat ini . Mengenai pengidentifikasi ATX ia menulis: 'Nama-nama ini tidak muncul sama sekali di sysfs sejauh yang saya bisa lihat'
maxschlepzig
1
Hmm. Masalah saya dengan operasi verifikasi ini adalah saya biasanya memiliki 8+ disk dengan model yang sama sehingga pengecekan pabrik tidak begitu berharga.
drescherjm
1
@drescherjm, saya sudah memperbarui jawaban saya. Metode baru harus kuat dan dengan demikian menghilangkan kebutuhan untuk pemeriksaan vendor.
maxschlepzig
Saya memiliki apa yang saya pikir skrip sysfs ditingkatkan; khususnya menangani nomor dua digit ata (/ ata [0-9] / tidak akan cocok dengan ata10) dan juga menemukan perangkat sata yang tidak bernama sd * (misalnya sr0): untuk in / sys / class / ata_port / ata * ; lakukan printf '% s \ t% s \ n' "$ (nama samaran" $ a ")" "$ (temukan" $ a / device / "-iname 'block' -exec ls {} \;)"; selesai
Jason
2

Ini versi saya, dimodifikasi dari atas. Karena saya tidak tahu tanggal pasti sistem di-boot (untuk pengujian ini 27 hari yang lalu), dan saya tidak tahu kern.log mana yang berisi data yang saya butuhkan (beberapa mungkin ada gzippeddi sistem saya), saya menggunakan uptimedan dateuntuk menghitung perkiraan tanggal boot sistem (hingga hari itu), kemudian gunakan zgrepuntuk mencari semua file kern.log yang tersedia.

Saya juga sedikit mengubah greppernyataan kedua , karena sekarang ini juga akan menampilkan drive CD / DVD ATAPI serta drive ATA- *.

Itu masih bisa menggunakan penyempurnaan (yaitu jika uptime sistem lebih besar dari satu tahun), tetapi harus berfungsi OK untuk saat ini.

#!/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); }'
ectospasm
sumber
1

Baru saja mengalami masalah yang sama dan menemukan solusi lain yang mungkin disukai.

Alat lsscsi mencantumkan perangkat SCSI (atau host) dan atributnya.

Dengan lsscsi, seseorang mendapatkan nama ata dan nama perangkat.

Terlihat seperti ini:

$ 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

Di Ubuntu kita dapat menginstal lsscsi hanya dengan

$ sudo apt-get install lsscsi
tidur panjang
sumber
2
hm, dan bagaimana ataXpeta ke bagian mana dalam lsscsioutput?
maxschlepzig
1
@maxschlepzig Angka pertama dalam: quads sama dengan ATX dengan satu perbedaan penting; output lsscsi diindeks 0 dan ataZ diindeks 1; jadi [2: 0: 0: 0] akan menjadi ata3 yang merupakan / dev / sda dalam output yang sudah lama diposting
Jason
@ Jason, ok, ini satu lsscsi | sed 's@^\[\([^:]\+\).\+\(/dev/.\+\)$@\1,\2@' | awk -F, '{ printf("ata%d => %s\n", $1+1, $2) }'
kalimat
@Jason, lihat juga jawaban saya yang diperbarui untuk alternatif yang secara langsung mengakses /sys/devicestanpa lsscsi.
maxschlepzig
0

Tidak ada jawaban di atas yang bekerja untuk saya, dan pendekatan lsscsi benar-benar menghasilkan jawaban yang salah, karena perbedaan antara nomor bus SCSI dan nomor ATA. Pada sistem 21-disk, saya punya banyak laporan syslog tentang masalah dengan ATA18 (pelanggaran HSM). Disk mana yang menyebabkan kesalahan ini? Beberapa di antaranya adalah drive usb, yang membuat segalanya jauh lebih membingungkan. Saya membutuhkan penghitungan bagaimana setiap drive SCSI terhubung ke sistem, dan saya menulis skrip di bawah ini yang menghasilkan daftar tabular untuk semua disk SCSI (/ dev / s [dr]?) Terlepas dari apakah ATA atau USB.

Kemudian, dengan semua disk drive sepenuhnya diperhitungkan, saya terkejut melihat bahwa kesalahan ATA saya tidak ada hubungannya dengan salah satu drive disk saya. Saya telah mengajukan pertanyaan yang salah, dan saya pikir orang lain mungkin dengan mudah jatuh ke dalam perangkap yang sama, itulah sebabnya saya menyebutkannya di sini. Saya kemudian menggunakan pendekatan kedua yang mengidentifikasi perangkat keras yang menghasilkan pesan pelanggaran HSM, juga dirinci dalam dokumentasi yang muncul dalam skrip di bawah ini.

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