Guest User

k-smart 1.5

a guest
Feb 14th, 2014
327
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 8.26 KB | None | 0 0
  1. #!/bin/bash
  2. #
  3. # DESCRIPTION
  4. #
  5. # k-smart.app is a simple Application Wrapper around this small bash script, the
  6. # smartctl binary and a very small binary called keys used to check whether modifier
  7. # keys are pressed or released.
  8. #
  9. # It's main purpose is to display the smartctl output for each disk 'diskutil' lists.
  10. # When [[shift]] is pressed a short self-test will be executed. When [[option]] is
  11. # pressed then a long test will be performed.
  12. #
  13. # The only purpose of this tool is an easy way to get an actual snapshot of SMART data
  14. # related to your disks since many GUI tools that focus on SMART on OS X fail in some ways.
  15. # Also important is the ability to save/copy smartctl's output so you can provide admins
  16. # or experienced users with the actual SMART data and not that what your SMART GUI thinks.
  17. # If you want to provide this information to others think about using a platform like
  18. # http://pastebin.com since it's essential to get the informations smartctl provides in
  19. # 'raw' format (without lines being wrapped around and the like).
  20. #
  21. # MORE INFO
  22. #
  23. # Since k-smart is based solely on smartmontools you find all the relevant informations
  24. # here: http://sourceforge.net/apps/trac/smartmontools/wiki
  25. #
  26. # The source of the included 'keys' binary can be found here:
  27. # http://brettterpstra.com/2012/08/05/quick-tip-checking-for-modifier-keys-in-shell-scripts/
  28. #
  29. # The Application Wrapper is made using Platypus 4.8: http://sveinbjorn.org/platypus
  30. #
  31. # Have a look at http://sourceforge.net/apps/trac/smartmontools/ticket/25#comment:9 to
  32. # understand what you might need to do to get your external drives working correctly
  33. # with smartctl (applies to most other SMART utilities on OS X as well!)
  34. #
  35. # CHANGES
  36. #
  37. # 1.5: - added "-q noserial" to "smartctl -a" invocation to hide serial numbers from drives
  38. #        in output
  39. #      - get model name from smartctl's 'Device Model' entry when displaying warnings
  40. #
  41. # 1.4: - always use a temporary file to store smartctl's output because we use the
  42. #        results multiple times
  43. #      - grep smartctl's output for "WARNING" and display these warnings using 'System
  44. #        Events'. In case the output contains also the string 'http' provide a 'More Info'
  45. #        button which will try to open each URL in Safari if pressed
  46. #      - disable GetSmartCtl function and solely rely on the smartctl binary provided
  47. #        inside the Application Bundle
  48. #
  49. # 1.3: - fixed quoting bug which prevented execution of the keys binary if the path to
  50. #        k-smart.app contained whitespace ('keys' is necessary to check whether the user
  51. #        pressed modifier keys)
  52. #
  53. # 1.2: - replaced smartctl with an Universal Binary which also runs on 32 bit Macs
  54. #
  55. # 1.1: - Added GetListOfVolumes function which skips CoreStorage devices since they
  56. #        appear as normal disks and passthrough SMART which might confuse users
  57. #      - Added CreateShellAlias function to define an alias in the user's .profile
  58. #        which points to the current location of smartctl. From then on a simple
  59. #        invocation of smartctl in Terminal should be possible regardless of k-smart.app's
  60. #        location
  61. #
  62. # 1.0: - first version. Simply walks through 'diskutil list' output and calls 'smartctl -a'
  63. #        for every device found
  64. #      - included smartctl 6.1 in the Application Bundle
  65. #      - replaced smartctl 6.1 with a freshly compiled 6.2 (64 bit only)
  66. #      - added 'keys' binary to Application Bundle. When [[shift]]Β is pressed k-smart
  67. #        will execute a short self-test for each and every device. If [[option]] is
  68. #        pressed as well, a long self-test will be executed.
  69. #
  70. # TODO
  71. #
  72. # - Documentation! Internationalization! Localization!
  73. # - maybe rely on an older version of Platypus (4.4) to be PPC compatible?
  74. # - maybe set up an automated build system for smartmontools to always include the most
  75. #   recent smartctl version as Universal Binary?
  76. # - maybe add some Automator Actions utilizing the GetSmartCtl function to get the path
  77. #   to smartctl to simply automate SMART checks and result verification in a highly
  78. #   flexible fashion?
  79. # - maybe include smartd correctly (including a routine that installs smartd including
  80. #   a LaunchDaemon using administrator privileges on servers)
  81. # - maybe include an user agent in ~/Library/LaunchAgents to periodically check drive
  82. #   health via smartctl on 'client' systems?
  83. # - maybe include the most recent version of the SATSMART kext, check the version on
  84. #   each launch, display an informative message in case a mismatch occured and call
  85. #   installer to let the user install/update the SATSMART driver?
  86.  
  87. Main() {
  88.     export PATH=/bin:/usr/bin:/opt/local/bin:/usr/local/bin
  89.     MyTmpFile="$(mktemp /tmp/${0##*/}.XXXXXX || (echo -e "Not able to create temporary file below /tmp/. Exiting." | logger ; exit 1))"
  90.     trap "rm -f \"${MyTmpFile}\"; exit 0" 0 1 2 3 15
  91.    
  92.     # PathToSmartCtl="$(GetSmartCtl)"
  93.     PathToSmartCtl="${0%/*}"/smartctl
  94.     PathToKeys="${0%/*}"/keys
  95.  
  96.     CreateShellAlias
  97.  
  98.     sleep 1
  99.     IsShiftPressed=$("${PathToKeys}" shift)
  100.     IsOptionPressed=$("${PathToKeys}" option)
  101.  
  102.     case ${IsShiftPressed} in
  103.         1)
  104.             # shift is pressed, we are in test mode!
  105.             # if option is pressed as well we're
  106.             # performing a long test otherwise short
  107.             if [ "X${IsOptionPressed}" = "X1" ]; then
  108.                 TestMode=long
  109.             else
  110.                 TestMode=short         
  111.             fi
  112.             GetListOfVolumes | while read ; do
  113.                 # check whether device is SMART capable
  114.                 "${PathToSmartCtl}" -a ${REPLY} >/dev/null 2>&1
  115.                 if [ $? -eq 0 ]; then
  116.                     echo -e "${AbstandSchraddel}Previous test results for ${REPLY}:\n"
  117.                     "${PathToSmartCtl}" -l selftest ${REPLY}
  118.                     echo -e "\nNow performing a ${TestMode} test on ${REPLY} in the background. You can close this window and try again in several minutes. Please see below the smartctl output.\n"
  119.                     "${PathToSmartCtl}" -t ${TestMode} ${REPLY}
  120.                     AbstandSchraddel="\n\n\n"
  121.                 fi
  122.             done
  123.             ;;
  124.         *)
  125.             # we simply display SMART status for all devices
  126.             GetListOfVolumes | while read ; do
  127.                 echo -e "${AbstandSchraddel}Examining ${REPLY}\n"
  128.                 "${PathToSmartCtl}" -q noserial -a ${REPLY} | tee "${MyTmpFile}"
  129.                 # check for warning messages in smartctl output
  130.                 ButtonPressed=""
  131.                 grep -q "WARNING" "${MyTmpFile}" && ButtonPressed="$(DisplayWarning "${REPLY}" "${MyTmpFile}")"
  132.                 if [ "X${ButtonPressed}" = "XMore Info" ]; then
  133.                     grep "^http" "${MyTmpFile}" | while read ; do
  134.                         open -b com.apple.Safari "${REPLY}"
  135.                     done
  136.                 fi
  137.                 AbstandSchraddel="\n\n\n"
  138.             done
  139.             ;;
  140.     esac
  141. } # Main
  142.  
  143. CreateShellAlias() {
  144.     if [ -f "${HOME}/.profile" ]; then
  145.         grep -v "^alias smartctl" <"${HOME}/.profile" >"${MyTmpFile}"
  146.         echo -e "alias smartctl=\"${PathToSmartCtl}\"" >>"${MyTmpFile}"
  147.         cat "${MyTmpFile}" >"${HOME}/.profile"
  148.     else
  149.         echo -e "alias smartctl=\"${PathToSmartCtl}\"" >>"${HOME}/.profile"
  150.     fi
  151. } # CreateShellAlias
  152.  
  153. GetListOfVolumes() {
  154.     /usr/sbin/diskutil list | grep "^/dev/" | while read ; do
  155.         /usr/sbin/diskutil corestorage info ${REPLY} >/dev/null 2>&1 || echo ${REPLY}
  156.     done
  157. } # GetListOfVolumes
  158.  
  159. GetSmartCtl() {
  160.     mdfind "kMDItemCFBundleIdentifier == 'de.kaiser-edv.k-smart'" | grep "\.app$" | while read ; do
  161.         SmartCtlVersion=$("${REPLY}"/Contents/Resources/smartctl | awk -F" " '/^smartctl / {print $2}')
  162.         echo -e "${SmartCtlVersion}\t${REPLY}/Contents/Resources/smartctl"
  163.     done | sort -r | head -n1 | cut -f2
  164. } # GetSmartCtl
  165.  
  166. DisplayWarning() {
  167.     # $1 is the device in question
  168.     # $2 is the path to the redirected "smartctl -a" output
  169.  
  170.     DeviceShortName="$(echo "$1" | sed 's|^/dev/||')"
  171.     # DeviceName="$(/usr/sbin/diskutil info $1 | awk -F":" '/Media Name:/ {print $2}' | sed -e 's/^ *//g' -e 's/\ Media$//' -e 's/TOSHIBA\ TOSHIBA/TOSHIBA/')"
  172.     DeviceName="$(awk -F":" '/^Device Model/ {print $2}' <"$2" | sed 's/^ *//g')"
  173.     DisplayString=$(grep "WARNING" "$2" | sed -e 's/\"/\\\"/g' -e 's/^==\>\ //')
  174.     grep "^http" "$2" >/dev/null 2>&1
  175.     if [ $? -eq 0 ]; then
  176.         Buttons='{"More Info", "OK"}'
  177.     else
  178.         Buttons='{"OK"}'
  179.     fi
  180.     osascript <<-EOF
  181.         tell application "System Events"
  182.             activate
  183.             set ButtonPressed to (button returned of (display dialog "${DeviceName} (${DeviceShortName})" & return & "${DisplayString}" buttons ${Buttons} default button 1 with icon caution giving up after 30))
  184.         end tell
  185.     EOF
  186. } # DisplayWarning
  187.  
  188. Main "$@"
Advertisement
Add Comment
Please, Sign In to add comment