Linux ATA 오류 : 장치 이름으로 번역 하시겠습니까?


36

Linux 상자에 ATA 오류가 발생하면 디스크를 "ata % d.00"으로 식별하는 메시지가 표시됩니다. 장치 이름 (예 :)으로 어떻게 변환 /dev/sdb합니까? 나는 이것이 사소한 것처럼 느껴지지만 그것을 알아낼 수는 없습니다.


1
유닉스 SE에 대한 비슷한 질문에 대한 나의 답변을 참조하십시오 : unix.stackexchange.com/a/13988/1131
maxschlepzig

답변:


28

Peter는 나에게 "ata0.00"과 같은 바보 같은 것들을 출력하는 대신 USB 스틱을 감지 할 수있는 고급 스크립트 (let)를 작성하도록 영감을주었습니다. Peter의 스크립트와 달리 동일한 컨트롤러 resp에 둘 이상의 장치가있는 경우 하위 번호 (4.01에서와 같이)도 얻습니다. 채널. 결과는에서 얻을 수있는 그대로입니다 syslog. 테스트했습니다. 항상 많은 개선이 있지만 (예 : 너무 서투른 정규 표현식) 데비안 상자에서 잘 작동합니다. 그러나 그것을 잡아라! 내 정규 표현식에서 찾을 수있는 너무 많은 이스케이프 문자는 호환성상의 이유입니다! GNU sed를 모든 사람과 함께 할 수는 없기 때문에 의도적으로 확장 정규 표현식을 사용하지 않았습니다.

업데이트
(1) 더 이상 ls출력을 구문 분석하지 않습니다 . (oops!) 모두 알고 있으므로 ls를 구문 분석하지 마십시오.
(2) 이제 읽기 전용 환경에서도 작동합니다.
이 잡담에서 제안에서 영감을 (3) 여기 내가 다시 나오지 제표 방법은 덜 복잡로 처리했다.

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

스크립트에 문제가있는 장치가 표시되지 않을 수 있음을 상기시켜줍니다. softreset 실패 (첫 번째 FIS 실패) (사소한 문제) 나열된 dvice로 ata6 오류가 발생했지만 존재하지 않았습니다. PC에 4 개의 디스크가 있고 3 개만 표시되면 그 이유 일 수 있습니다.
Kendrick

1
@ Kendrick 글쎄, 나는이 경우 스크립트를 비난하지 않습니다. 커널 드라이버의 작동 방식을 알고 있다면 다음과 같이 분명해질 것입니다. 커널 서브 시스템 드라이버는 "문제"가 충분히 심각 해지면 포기하는 것으로 알려져 있습니다. 이것은 UDMA 가능 드라이브의 경우 여러 드라이브 재설정을 유도하고 결국에는 PIO 모드에서 드라이브 작업을 시도 할 수 있음을 읽습니다. 그러나 이것이 너무 불안정한 것으로 판명 되면 (다양한 타이밍 오류 등), 운전자는 드라이브로 "가라"고 말합니다. 기존 PATA 드라이브의 경우 드라이브를 다시 표시하려면 콜드 재부팅 이 필수입니다.
syntaxerror

대본을 비난하려는 의도는 아닙니다. 왜 누락 될 수 있는지에 대한 알림 :) 바보 같은 flakey seagate 컨트롤러 보드는 무슨 일이 일어나고 있는지 알아내는 데 어려움을 겪었습니다.
켄드릭

@Kendrick 당신은 저에게 남자를 말하고 있습니다. :) 글쎄, Seagate는 결코 삼성을 사지 말아야 했습니다. 후자의 드라이브 (Samsung이 여전히 대량 저장 사업을 할 때)와 우수한 지원 팀을 좋아했습니다. 이제 Seagate는이 모든 것을 대체했습니다 ... 그리고 ... 어-오.
syntaxerror

11

/proc/scsi/scsi같이 보일 것이다 :

$ 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은 sda 및 ata1.00, scsi1 id 0은 sdb 및 ata2.00 등입니다.

또한 /var/log/dmesgata 드라이버 로딩 정보를 표시하고 일을 좀 더 명확하게 만드는를보십시오. "libata"로 시작하는 줄을 찾으십시오.


8
약간 더 인간 친화적 인 출력을 제공하는 'lsscsi'를 사용해야 할 수도 있습니다. 예 : [0 : 0 : 0 : 0] cd / dvd TSSTcorp CDDVDW SH-S202H SB00 / dev / sr0 [2 : 0 : 0 : 0 ] 디스크 ATA ST3500630AS 3.AA / dev / sda [3 : 0 : 0 : 0] 디스크 ATA WDC WD5000AAKS-0 01.0 / dev / sdb (3.2.x 커널을 실행하는이 서버에는 / proc / scsi가 없습니다. *) (죄송합니다, 위의 형식을
읽어서

1
이것은 의견이 아닌 답변이어야합니다. 한 컴퓨터에서 유용하고 빠르고 쉽게 읽을 수 있으며 문제가있는 다른 컴퓨터에서 입력 할 수 있습니다.
Geek

10

자세한 설명 대신 스크립틀릿을 선호합니다. 이것은 내 우분투 상자에서 작동합니다. 원하는대로 의견을 추가하십시오.

# 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

당신의 스크립트는 대답보다 약간 덜 무섭습니다. 주로 모든 것을 볼 수 있기 때문입니다.
isaaclw

1
약간 단순화 (Centos에서 작동)ls -l /sys/block/sd* | sed -e 's@.*-> \.\..*/ata@/ata@' -e 's@/host@ @' -e 's@/target.*/@ @'
Shirker

9

이것은 실제로 까다 롭습니다. "scsi ID"가 "SATA ID에서 1을 뺀 것" unique_id이라고 가정하는 것이 안전하지만, 실제로는 안전 하고이 게시물을 기반으로 한 SATA 식별자를 검사하는 것이 좋습니다.

내 오류는 :

[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

그래서 내 절차 ata4는 무엇인지 알아내는 것 입니다.

  1. SATA 컨트롤러의 PCI ID를 찾으십시오

    # lspci | grep -i sata
    00:1f.2 SATA controller: Intel Corporation 631xESB/632xESB SATA AHCI Controller (rev 09)
    
  2. 일치하는 고유 ID를 찾으십시오.

    # 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. 따라서에 scsi_host/host3번역 3:x:x:x할 수 있습니다 dmesg. 자세한 정보를 얻으 려면 grep 할 수 있습니다 .

    # 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. 여기에 장치가 있습니다. RAID 어레이가 완전히 고장 나기 전에 해당 장치를 꺼내기위한 일련 번호 (또는 선택 사항)를 찾을 수 있습니다 (선택 사항).

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

그리고 당신은 끝났습니다!


7

이 시도:

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

나는 dmesg를 이해하지 못했습니다. 어떤 행은 "ata4"에 관한 것이고 다른 행은 "scsi"또는 sdc에 관한 것이지만, "ata4.. sdc"를 할당 한 사람은 아무도 없습니다. 지정되어 있습니다.


5

나는 같은 문제가 있었고 dmesg를 확인하여 드라이브를 식별 할 수있었습니다. 여기에서 컨트롤러 식별자 (정확한 용어 ??)와 디스크 모델을 볼 수 있습니다. 그런 다음 ls -l / dev / disk / by-id를 사용하여 모델 번호를 / dev / sda (또는 기타)와 일치 시키십시오. 또는이 정보에 디스크 유틸리티가 마음에 듭니다. 참고 : 디스크의 모델 번호가 다른 경우에만 작동합니다. 그렇지 않으면 두 모델을 구별 할 수 없습니다.

>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

2

가장 쉬운 방법은 드라이브 장치 이름이 다양한 소스 (예 : USB 드라이브)에서 혼합되어 있거나 장치 유형에 따라 할당되기 때문에 부팅에서 커널 로그를 검토하는 것입니다 (예 : cdrom은 대신 scdX 일 수 있으며 모든 것이 sgX를 갖습니다) ). 실제로, 다른 종류의 버스 (예 : SATA + USB)를 혼합하지 않은 경우 가장 낮은 번호의 장치는 cdrom 장치가 아닌 한 sda가됩니다.

시스템에 따라 sysfs를 돌아 다니면서 신성 할 수도 있습니다. 내 시스템에 ls -l /sys/dev/block그 계시 8:0:에 점 (주요 / dev에 항목에서 미성년자) /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda 마찬가지로, ls -l /sys/class/ata_port그 계시 ata1에 포인트를 /sys/devices/pci0000:00/0000:00:1f.2/ata1/ata_port/ata1같은 PCI 하위 장치이다.

SATA를 사용하고 각 포트에 하나의 드라이브 만 있기 때문에 ata1.00 = sda라고 추론 할 수 있습니다. 모든 드라이브는 .00입니다. 포트 멀티 플라이어를 사용하면 드라이브에 .01, .02, .03 등이 제공 될 것으로 생각됩니다. 다른 사람의 로그보기 PATA 컨트롤러는 마스터 및 슬레이브에 .00 및 .01을 사용합니다. ataX.01이있는 경우 로그를 기반으로 .01은 /sys/dev/block/목록 에서 host : channel : ID : LUN 폴더의 "ID"에 매핑되어야합니다 . 여러 경우 ataX/hostY/같은 PCI 장치 폴더에서 폴더를 다음 나는 의심 번호가 가장 낮은 ataX 폴더 번호가 가장 낮은 hostY 폴더를 일치하는지 확인합니다.


2

에서가 /sys/class/ata_port/ata${n}/device/, 당신은 볼 수있는 host${x}폴더를. 예를 들어, 내 컴퓨터에서 :

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

에서는의 첫 번째 숫자 ${x}host${x}나타냅니다 [0:0:0:0]. 나를 위해 그래서 것은 ata1하는 의미 host0도 SCSI의 형태로 표현 될 수있다 0:*:

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

0

아래 스크립트는 다음과 같은 멋진 요약을 제공합니다.

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

따라서 드라이브 당 한 줄에 sdX 장치 이름, 크기 , 모델 , s / npciata 번호가 있습니다. 위의 sdc는 카드가 삽입되지 않은 USB SD 카드 리더에 응답합니다. 따라서 실제 정보 대신 ----.

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

(우분투 12.04 / 14.04 및 CentOS 6에서만 테스트 됨)


예를 들어, ATA 4.01이 무엇인지를 어떻게 알 수 있습니까?
Edward_178118

예제 출력에서 ​​sda : ... ata1 ... 및 sdb : ... ata3 ....을 볼 수 있으며 실제로 sda는 ata1에 있고 sdb는 ata2에있었습니다. 내가 쓰고 4 개의 다른 호스트에서 테스트 한 결과 위의 스크립트에 ata에 대한 참조가없는 HW를 발견했습니다. 나는 dmesg | grep "ata [0-9]"가 결코 실패하지 않았다는 것을 지적해야한다.
ndemou

0

이 정보 등을 찾기위한 스크립트는 https://www.av8n.com/computer/disk-hw-host-bus-id 에서 찾을 수 있습니다.

Mr. Syntaxerror가 제공 한 스크립트와 비슷하지만 더 환상적입니다. -ATA 드라이브뿐만 아니라 USB 드라이브에서도 작동합니다. -드라이브 제조업체, 모델 및 일련 번호 및 물론 연결 지점을 제공합니다. -더 간단하고 읽기 쉽고 유지 관리가 쉽습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.