วิธีแมปตัวระบุ ataX.0 ในข้อความแสดงข้อผิดพลาด kern.log กับอุปกรณ์จริง / dev / sdY?


11

พิจารณาkern.logตัวอย่างต่อไปนี้:

 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

ฉันจะระบุได้อย่างไรว่าฮาร์ดไดรฟ์เคอร์เนลจริงหมายถึงเมื่อพูดถึงata4.00?

ฉันจะค้นหา/dev/sdYชื่ออุปกรณ์ที่เกี่ยวข้องได้อย่างไร

คำตอบ:


11

คุณสามารถค้นหาอุปกรณ์ / dev / sdY ที่เกี่ยวข้องผ่านการสำรวจแผนผัง/sys:

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

ด้วยการแวะ/sysผ่านที่มีประสิทธิภาพมากขึ้น(cf. lsata.sh ):

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

ตัวอย่างเอาต์พุตจากระบบดิสก์ 2:

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

จากนั้นสำหรับการระบุฮาร์ดแวร์จริงที่เชื่อถือได้คุณต้องแมป / dev / sdY กับหมายเลขซีเรียลเช่น:

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

lssci

lssciยูทิลิตี้นอกจากนี้ยังสามารถนำมาใช้เพื่อการทำแผนที่:

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

โปรดทราบว่าการนับ lsscsi ที่เกี่ยวข้องเริ่มจาก 0 ในขณะที่การแจงนับ ata เริ่มจาก 0

syslog

หากไม่มีสิ่งใดที่ใช้งานได้เราสามารถดู syslog / journal เพื่อรับการแม็พ

/dev/sdYอุปกรณ์ที่สร้างขึ้นในลำดับเดียวกับที่ตัวระบุ ataX ที่มีการแจกแจงในkern.logขณะที่ละเว้นอุปกรณ์ที่ไม่ใช่ดิสก์ (ATAPI) และการเชื่อมโยงไม่ได้เชื่อมต่อ

ดังนั้นคำสั่งต่อไปนี้แสดงการแมป:

$ 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

(โปรดทราบว่า ata4 ไม่ปรากฏขึ้นเนื่องจากข้อความบันทึกด้านบนมาจากระบบอื่น)

ฉันกำลังใช้งานอยู่/var/log/kern.log.0และไม่ใช่/var/log/kern.logเพราะข้อความการบู๊ตถูกหมุนไปแล้ว ฉันต้องการMay 28 2เพราะนี่เป็นเวลาบูตครั้งสุดท้ายและฉันต้องการที่จะไม่สนใจข้อความก่อนหน้า

เพื่อตรวจสอบการทำแผนที่คุณสามารถทำการตรวจสอบบางอย่างผ่านการดูผลลัพธ์ของ:

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

และคุณสามารถเปรียบเทียบผลลัพธ์นี้กับhdparmผลลัพธ์เช่น:

$ hdparm -i /dev/sda

/dev/sda:

Model=SAMSUNG SV0802N [..]

(ใช้เคอร์เนล 2.6.32-31)


นี้จะน่ากลัวเพียงแค่ขอบคุณมากสำหรับการตอบกลับที่ยอดเยี่ยมนี้ ...
stuartc

@stuarte คุณจะยินดี - BTW, cksได้ทำเขียนขึ้นเกี่ยวกับทุกรูปแบบการตั้งชื่อที่แตกต่างกันของอุปกรณ์ SATA บนระบบลินุกซ์ในปัจจุบัน เกี่ยวกับตัวระบุ ataX ที่เขาเขียน: 'ชื่อเหล่านี้ไม่ปรากฏใน sysfs เลยเท่าที่ฉันเห็น'
maxschlepzig

1
อืมมม ปัญหาของฉันกับการดำเนินการตรวจสอบของฉันนี้ฉันมักจะมี 8+ ดิสก์ของรูปแบบเดียวกันแน่นอนดังนั้นการตรวจสอบผู้ผลิตไม่คุ้มค่า
drescherjm

1
@drescherjm ฉันได้อัปเดตคำตอบของฉันแล้ว วิธีการใหม่ควรมีประสิทธิภาพและทำให้ไม่จำเป็นต้องมีการตรวจสอบผู้ขาย
maxschlepzig

ฉันมีสิ่งที่ฉันคิดว่าเป็นสคริปต์ที่ปรับปรุงแล้ว; โดยเฉพาะอย่างยิ่งมันจัดการหมายเลข ata สองหลัก (/ ata [0-9] / จะไม่ตรงกับ ata10) และยังพบว่าอุปกรณ์ sata ที่ไม่มีชื่อ sd * (เช่น sr0): สำหรับใน / sys / class / ata_port / ata * ; ทำ printf '% s \ t% s \ n' "$ (basename" $ ​​a ")" "$ (หา" $ a / อุปกรณ์ / "-iname 'block' -exec ls {} \;)"; เสร็จแล้ว
Jason

2

นี่คือเวอร์ชั่นของฉันซึ่งแก้ไขจากด้านบน เนื่องจากฉันไม่ทราบวันที่แน่นอนที่ระบบถูกบูท (สำหรับการทดสอบนี้เมื่อ 27 วันก่อน) และฉันไม่รู้ว่า kern.log ใดที่มีข้อมูลที่ฉันต้องการ (บางอันอาจอยู่gzippedในระบบของฉัน) ฉันจึงใช้uptimeและdateเพื่อคำนวณวันที่บูตระบบโดยประมาณ (จนถึงทุกวันนี้) จากนั้นใช้zgrepเพื่อค้นหาไฟล์ kern.log ที่มีอยู่ทั้งหมด

ฉันยังแก้ไขข้อความที่สองเล็กน้อยgrepเนื่องจากตอนนี้จะแสดงไดรฟ์ ATAPI CD / DVD เช่นเดียวกับไดรฟ์ ATA- *

มันยังคงสามารถใช้การปรับแต่งได้ (เช่นถ้าเวลาของระบบมากกว่าหนึ่งปี) แต่ควรจะใช้งานได้ในตอนนี้

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

1

เพิ่งมีปัญหาเดียวกันนี้และพบวิธีแก้ปัญหาที่คนอื่นอาจชอบ

เครื่องมือ lsscsi แสดงรายการอุปกรณ์ SCSI (หรือโฮสต์) และแอตทริบิวต์ของอุปกรณ์

ด้วย lsscsi one จะได้รับชื่อ ata และชื่ออุปกรณ์

ดูเหมือนว่านี้:

$ 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

ใน Ubuntu เราสามารถติดตั้ง lsscsi ได้ง่ายๆ

$ sudo apt-get install lsscsi

2
อืมและataXแผนที่ทำส่วนใดในlsscsiเอาต์พุตได้อย่างไร
maxschlepzig

1
@maxschlepzig หมายเลขแรกใน: quads เหมือนกับ ataX ที่มีความแตกต่างที่สำคัญอย่างหนึ่ง เอาต์พุตของ lsscsi คือ 0-indexed และ ataZ เป็น 1-indexed; ดังนั้น [2: 0: 0: 0] น่าจะเป็น ata3 ซึ่งเป็น / dev / sda ในผลลัพธ์ที่ longsleep โพสต์
Jason

@ Jason, ok, นี่คือหนึ่งซับ:lsscsi | sed 's@^\[\([^:]\+\).\+\(/dev/.\+\)$@\1,\2@' | awk -F, '{ printf("ata%d => %s\n", $1+1, $2) }'
maxschlepzig

@ สันเห็นคำตอบของฉันสำหรับการปรับปรุงทางเลือกที่เข้าถึงโดยตรงโดยไม่ต้อง/sys/devices lsscsi
maxschlepzig

0

คำตอบข้างต้นไม่ได้ผลสำหรับฉันและวิธีการ lsscsi นั้นให้คำตอบที่ผิดเนื่องจากความแตกต่างระหว่างหมายเลขบัส SCSI และหมายเลข ATA ในระบบ 21 ดิสก์ฉันมีรายงาน syslog มากมายเกี่ยวกับปัญหาของ ATA18 (การละเมิด HSM) ดิสก์ตัวใดที่ทำให้เกิดข้อผิดพลาดเหล่านี้ บางตัวเป็นไดรฟ์ usb ซึ่งทำให้เกิดความสับสนมากขึ้น ฉันต้องการบัญชีว่าแต่ละไดรฟ์ SCSI แต่ละตัวเชื่อมต่อกับระบบได้อย่างไรและฉันเขียนสคริปต์ด้านล่างที่ให้รายการแบบตารางสำหรับดิสก์ SCSI ทั้งหมด (/ dev / s [dr]?) โดยไม่คำนึงว่า ATA หรือ USB

จากนั้นด้วยดิสก์ไดรฟ์ทั้งหมดที่คำนึงถึงอย่างสมบูรณ์ฉันรู้สึกประหลาดใจที่เห็นว่าข้อผิดพลาด ATA ของฉันไม่มีส่วนเกี่ยวข้องใด ๆกับดิสก์ไดรฟ์ของฉัน ฉันถามคำถามผิดและฉันคิดว่าคนอื่นอาจตกหลุมพรางเดียวกันได้ง่ายซึ่งเป็นสาเหตุที่ฉันพูดถึงที่นี่ จากนั้นฉันใช้วิธีที่สองที่ระบุฮาร์ดแวร์ที่สร้างข้อความการละเมิด HSM รวมทั้งรายละเอียดในเอกสารประกอบที่ปรากฏในสคริปต์ด้านล่าง

#!/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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.