Linux ATA errors: Translating to a device name?

Peter inspired me to write an advanced script(let), which can even detect USB sticks (instead of outputting silly things like “ata0.00”). In contrary to Peter’s script, you will also get the sub-number (as in 4.01) if you have more than one device at the same controller resp. channel. The output will be exactly as you get it in syslog.
Tested. Working very well on my Debian box, though there is always lots of improvement (e. g. too clumsy regexps). But HOLD IT! The seemingly too high number of escaped characters you may find in my regexps is just for compatibility reasons! You can’t assume GNU sed with everyone, which is why I did without extended regexps on purpose.

UPDATES
(1) Will no longer parse ls output. (oops!) Since you all know: Do not parse ls.
(2) Now also works on read-only environments.
(3) Inspired by a suggestion from this chit-chat here I have managed to again get the sed statements way less complicated.

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

Leave a Comment