Kesalahan Linux ATA: Menerjemahkan ke nama perangkat?

36

Ketika sebuah kotak Linux mendapatkan kesalahan ATA, ia men-slog-nya dengan pesan yang mengidentifikasi disk sebagai "ata% d.00". Bagaimana cara menerjemahkannya ke nama perangkat (misalnya /dev/sdb)? Saya merasa ini sepele, tetapi saya tidak bisa mengetahuinya.

nhage
sumber
1
Lihat juga jawaban saya untuk pertanyaan serupa di Unix-SE: unix.stackexchange.com/a/13988/1131
maxschlepzig

Jawaban:

28

Peter mengilhami saya untuk menulis skrip tingkat lanjut (biarkan), yang bahkan dapat mendeteksi stik USB (alih-alih mengeluarkan hal-hal konyol seperti "ata0.00"). Berbeda dengan skrip Peter, Anda juga akan mendapatkan sub-angka (seperti pada 4.01) jika Anda memiliki lebih dari satu perangkat pada resp controller yang sama. saluran. Outputnya akan persis seperti yang Anda dapatkan syslog. Diuji. Bekerja sangat baik pada kotak Debian saya, meskipun selalu ada banyak peningkatan (misalnya regexps terlalu canggung). Tapi TAHAN! Jumlah karakter luput yang tampaknya terlalu tinggi yang mungkin Anda temukan di regexps saya hanya untuk alasan kompatibilitas! Anda tidak dapat mengasumsikan GNU seddengan semua orang, itulah sebabnya saya sengaja melakukannya tanpa memperpanjang regexps.

PEMBARUAN
(1) Tidak akan lagi menguraikan lsoutput. (ups!) Karena Anda semua tahu: Jangan parsing ls.
(2) Sekarang juga berfungsi pada lingkungan read-only.
(3) Terinspirasi oleh saran dari obrolan-obrolan ini di sini saya telah berhasil membuat pernyataan sed tidak terlalu rumit.

#!/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"
kesalahan sintaks
sumber
Hanya pengingat bahwa skrip mungkin tidak menampilkan perangkat yang mengalami masalah. Saya memiliki kesalahan ata6 dengan softreset gagal (FIS 1 gagal) (Masalah Kecil) terdaftar dan tidak ada. jika Anda tahu Anda memiliki 4 disk di pc dan hanya 3 yang muncul itu sebabnya.
Kendrick
1
@ Kendrick Yah, saya tidak akan menyalahkan skrip dalam kasus ini. Karena jika Anda tahu cara kerja driver kernel, ini akan lebih jelas bagi Anda :) Driver subsistem kernel diketahui menyerah begitu "masalah" cukup parah. Ini berbunyi, bahwa untuk drive berkemampuan UDMA, drive dapat menyebabkan beberapa drive ulang dan (akhirnya) mencoba operasi drive dalam mode PIO. Namun, jika ini terbukti terlalu tidak stabil (berbagai kesalahan waktu dll.), Pengemudi akan mengatakan "pergi" ke drive. Untuk drive PATA lama, ini berarti reboot dingin akan wajib bagi drive untuk muncul lagi.
syntaxerror
Bukan maksud saya untuk menyalahkan naskah. hanya pengingat mengapa itu mungkin hilang :) papan pengontrol seagate bodoh flakey membuatnya sulit untuk mencari tahu apa yang sedang terjadi.
Kendrick
@Kendrick Kau memberitahuku kawan. :) Nah, dalam bukuku, Seagate seharusnya tidak pernah membeli Samsung. Mencintai drive terakhir (ketika Samsung masih dalam bisnis penyimpanan massal), ditambah tim dukungan mereka yang sangat baik. Sekarang Seagate telah mengambil alih semua ini ... dan ... uh-oh.
sintaksis
11

Lihat /proc/scsi/scsi, yang akan terlihat seperti ini:

$ 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 adalah sda dan ata1.00, scsi1 id 0 adalah sdb dan ata2.00, dll.

Lihat juga /var/log/dmesg, yang menunjukkan info memuat driver ata dan akan membuat hal-hal sedikit lebih jelas. Cari baris mulai "libata".

Phil Hollenback
sumber
8
Anda mungkin juga perlu menggunakan 'lsscsi' - yang memberikan hasil yang sedikit lebih ramah terhadap manusia - misalnya [0: 0: 0: 0] cd / dvd TSSTcorp CDDVDW SH-S202H SB00 / dev / sr0 [2: 0: 0: 0: 0 ] disk ATA ST3500630AS 3.AA / dev / sda [3: 0: 0: 0] disk ATA WDC WD5000AAKS-0 01.0 / dev / sdb (Pada server ini, menjalankan kernel 3.2.x, tidak ada / proc / scsi *) (Maaf, sepertinya saya tidak tahu cara memformat apa pun di atas, agar bisa dibaca)
David Goodwin
1
Ini harus menjadi jawaban daripada komentar. Berguna, cepat dan mudah dibaca dari satu mesin dan ketik yang lain dengan masalah.
Penatua Geek
10

Saya lebih suka scriptlets daripada penjelasan panjang. Ini berfungsi pada kotak Ubuntu saya. Tambahkan komentar sesuai keinginan Anda:

# 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
sumber
Script Anda sedikit lebih menakutkan daripada jawabannya, terutama karena saya bisa melihat semuanya.
isaaclw
1
Sedikit menyederhanakan (bekerja untuk saya di Centos)ls -l /sys/block/sd* | sed -e 's@.*-> \.\..*/ata@/ata@' -e 's@/host@ @' -e 's@/target.*/@ @'
Shirker
9

Ini sebenarnya cukup rumit. Meskipun aman untuk menganggap bahwa "ID scsi" adalah "SATA ID minus satu", saya lebih suka benar-benar aman dan memeriksa unique_idyang saya asumsikan (berdasarkan posting ini ) adalah pengidentifikasi SATA.

Kesalahan saya adalah:

[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

Jadi prosedur saya untuk mencari tahu apa ata4itu:

  1. temukan id PCI dari pengontrol SATA

    # lspci | grep -i sata
    00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
    
  2. temukan ID unik yang cocok:

    # 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. jadi aktif scsi_host/host3 , yang bisa kita terjemahkan 3:x:x:x, yang bisa kita ambil untuk dmesgmengetahui lebih lanjut:

    # 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. inilah perangkat kami, kami dapat (opsional) menemukan nomor seri untuk mengeluarkan perangkat itu dari sana (atau memeriksa kabel atau apa pun) sebelum array RAID kami gagal total:

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

Dan kamu selesai!

anarcat
sumber
7

Coba ini:

# find -L /sys/bus/pci/devices/*/ata*/host*/target* -maxdepth 3 -name "sd*" 2>/dev/null | egrep block |egrep --colour '(ata[0-9]*)|(sd.*)'

Saya tidak pernah mengerti dmesg - beberapa baris adalah tentang "ata4" beberapa lainnya tentang "scsi" atau sdc, tetapi tidak ada yang menugaskan "ata4 ... sdc" perintah yang ditampilkan menemukan / sys / bus / path, di mana baik ata4 dan sdc ditentukan.

schweik
sumber
5

Saya memiliki masalah yang sama dan dapat mengidentifikasi drive dengan memeriksa dmesg. Di sana Anda dapat melihat pengontrol pengontrol (istilah yang benar ??) dan model disk. Kemudian gunakan ls -l / dev / disk / by-id untuk mencocokkan nomor model dengan / dev / sda (atau apa pun). Atau, saya suka Disk Utility untuk informasi ini. Catatan: ini hanya berfungsi jika disk Anda memiliki nomor model yang berbeda, jika tidak, Anda tidak dapat membedakan keduanya.

>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
sumber
2

Cara termudah adalah dengan meninjau log kernel dari boot, karena nama perangkat drive dicampur dari berbagai sumber (misalnya drive USB), atau ditugaskan berdasarkan jenis perangkat (yaitu cdrom mungkin scdX sebagai gantinya, dan semuanya memiliki sgX ). Dalam praktiknya, kecuali jika Anda telah mencampur berbagai jenis bus (misalnya SATA + USB), perangkat ata bernomor terendah akan menjadi sda kecuali jika itu adalah perangkat cdrom.

Tergantung pada sistem Anda, itu mungkin diramalkan dengan berkeliaran di sekitar sysfs. Pada sistem saya ls -l /sys/dev/blockmengungkapkan bahwa 8:0(utama: minor dari / entri dev) menunjuk ke /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda Demikian juga, ls -l /sys/class/ata_portmengungkapkan ata1hal itu/sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1 yang pada sub-perangkat PCI yang sama.

Karena saya menggunakan SATA, dan hanya satu drive di setiap port saya dapat menyimpulkan bahwa ATA1.00 = sda. Semua drive saya adalah 0,00, saya curiga bahwa jika saya menggunakan port multiplier, drive saya akan diberikan .01, .02, .03 dll. Melihat log orang lain Pengontrol PATA menggunakan .00 dan .01 untuk master dan slave , dan berdasarkan log mereka jika Anda memiliki ataX.01, .01 harus dipetakan ke "ID" di host: saluran: ID: folder LUN dari /sys/dev/block/daftar. Jika Anda memiliki banyak ataX/dan hostY/folder dalam folder perangkat PCI yang sama, maka saya menduga bahwa folder ataX bernomor terendah cocok dengan folder hostY bernomor terendah.

DerfK
sumber
2

Di /sys/class/ata_port/ata${n}/device/, Anda dapat melihat host${x}folder. Misalnya, di komputer saya:

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

The ${x}dalam host${x}mengacu pada nomor pertama dalam [0:0:0:0]. Jadi bagi saya ata1merujuk host0yang juga dapat direpresentasikan dalam bentuk SCSI sebagai 0:*:

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

Script di bawah ini akan memberi Anda ringkasan yang bagus seperti ini:

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

Jadi dalam satu baris per drive Anda memiliki nama perangkat sdX , ukuran , model , s / n dan nomor pci dan ata . Sdc di atas sesuai dengan pembaca kartu SD USB tanpa kartu dimasukkan. Karenanya ---- di tempat informasi nyata.

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

(hanya diuji di ubuntu 12.04 / 14.04 dan CentOS 6)

ndemou
sumber
Bagaimana hal itu sama dengan menunjukkan kepada Anda apa, misalnya, ATA 4.01?
Edward_178118
Dalam contoh output Anda melihat sda: ... ata1 ... dan sdb: ... ata3 .... Dan memang sda berada di ata1 dan sdb di ata2. Karena saya menulisnya dan mengujinya pada 4 host yang berbeda, saya menemukan HW di mana skrip di atas tidak berisi referensi ke ata. Saya harus menunjukkan bahwa dmesg | grep "ata [0-9]" tidak pernah mengecewakan saya.
ndemou
0

Sebuah skrip untuk menemukan informasi ini, dan banyak lagi, dapat ditemukan di https://www.av8n.com/computer/disk-hw-host-bus-id

Ini mirip dengan skrip yang disediakan oleh Mr. Syntaxerror, tetapi lebih bagus. - Ini berfungsi untuk drive USB dan drive ATA. - Ini menyediakan drive drive dan model dan nomor seri, - dan tentu saja titik lampiran. - Ini lebih mudah, mudah dibaca, dan dipelihara.

John Denker
sumber