nvme 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #!/bin/sh
  2. # {{{ Variables
  3. DEVICE=
  4. ATTRIBUTE=
  5. SCAN=0
  6. ZBX_DISCOVERY_OUTPUT=0
  7. # }}}
  8. # {{{ usage()
  9. usage() {
  10. cat <<EOH
  11. USAGE: $(basename "$0") -d DEVICE -a ATTRIBUTE
  12. Get SMART attribute value for a NVMe device
  13. Options:
  14. -d NVMe device path
  15. -a Attribute name (e.g: temperature, program_fail_count, etc.)
  16. -S Scan devices and display list
  17. -s Scan devices and display (Zabbix discovery output)
  18. EOH
  19. }
  20. # }}}
  21. # {{{ list_nvme_devices()
  22. list_nvme_devices() {
  23. ZBX="${1}"
  24. if [ "${ZBX}" = 1 ]; then
  25. printf '{"data":['
  26. fi
  27. if which nvme >/dev/null 2>&1 && which jq >/dev/null 2>&1 ; then
  28. (
  29. nvme list --output json | \
  30. jq --raw-output \
  31. '.Devices | .[] | .DevicePath + " " + .SerialNumber + " " + (.PhysicalSize|tostring) + " NVMe"' | \
  32. while read device serial physsize hwinfo ; do
  33. if which numfmt >/dev/null 2>&1 ; then
  34. capacity=$(numfmt --to=si --suffix=B --round=nearest --format="%2f" 1920383410176|sed -r 's/([a-z]+)/ \1/i')
  35. else
  36. capacity="$(( ${physsize} / 1000 / 1000 / 1000 )) GB"
  37. fi
  38. if [ "${ZBX}" = 1 ]; then
  39. printf '{'
  40. printf '"{#DEVICE}":"%s",' "${device}"
  41. printf '"{#SERIAL}":"%s",' "${serial}"
  42. printf '"{#CAPACITY}":"%s",' "${capacity}"
  43. printf '"{#HWROT}":"%s"' "${hwinfo}"
  44. printf '},'
  45. else
  46. echo "${device}|${serial}|${capacity}|${hwinfo}"
  47. fi
  48. done
  49. ) | sed 's/},$/}/'
  50. fi
  51. if [ "${ZBX}" = 1 ]; then
  52. printf ']}'
  53. fi
  54. }
  55. # }}}
  56. # {{{ main()
  57. while getopts "d:a:Ss" OPT ; do
  58. case "$OPT" in
  59. \?|h)
  60. usage
  61. exit 0
  62. ;;
  63. d)
  64. DEVICE="$OPTARG"
  65. ;;
  66. a)
  67. ATTRIBUTE="$OPTARG"
  68. ;;
  69. S)
  70. SCAN=1
  71. ;;
  72. s)
  73. SCAN=1
  74. ZBX_DISCOVERY_OUTPUT=1
  75. ;;
  76. esac
  77. done
  78. if [ "${SCAN}" = 1 ]; then
  79. list_nvme_devices "${ZBX_DISCOVERY_OUTPUT}"
  80. exit 0
  81. fi
  82. if [ -z "${DEVICE}" ] ; then
  83. printf "[ERR] device is not defined\n"
  84. usage
  85. exit 1
  86. fi
  87. if [ -z "${ATTRIBUTE}" ] ; then
  88. printf "[ERR] attribute name is not defined\n"
  89. usage
  90. exit 1
  91. fi
  92. if [ "${ATTRIBUTE}" = "error_count" ]; then
  93. data=$(nvme error-log "${DEVICE}" --output json | jq '.[][-1] | .error_count')
  94. else
  95. data=$(nvme smart-log --output json "${DEVICE}" | jq --raw-output ".${ATTRIBUTE}")
  96. if [ "${ATTRIBUTE}" = "temperature" ]; then
  97. data=$(( ${data} - 273 )) # convert into Celcius 'temperature' value (Kelvin in JSON output)
  98. fi
  99. fi
  100. if [ $? != 0 ] || [ "${data}" = "null" ]; then
  101. printf -- "-1\n"
  102. else
  103. printf "${data}\n" | \
  104. tr -s ' ' | \
  105. sed 's/^[[:space:]]*\(.*\)[[:space:]]*$/\1/' | \
  106. cut -d ' ' -f 10
  107. fi
  108. exit 0
  109. # }}}
  110. # vim: foldmethod=marker foldlevel=0 foldenable