#!/bin/bash # shellcheck disable=SC1004,SC2236,SC2001 #set -euxo pipefail ###### ZPool, SMART, and UPS Status Report with TrueNAS Config Backup ### Original Script By: joeschmuck ### Modified By: bidelu0hm, melp, fohlsso2, onlinepcwizard, ninpucho, isentropik, dak180 ### Last Edited By: dak180 ### At a minimum, enter email address and set defaultFile to 0 in the config file. ### Feel free to edit other user parameters as needed. ### Current Version: v1.8 ### https://github.com/dak180/FreeNAS-Report ### Changelog: # v1.8.1 # - With smartctl 7.4+ use the new features. # - Add a wear leveling stat to the SAS table for SAS SSDs. # v1.8 # - Accommodate both SSD and HDD temp settings # - Keep SAS drives in their own section # - Improved support for SAS and NVMe # - Remove all awk # - Add support for per drive overrides # v1.7.5 # - Add initial support for SAS drives # v1.7 # - Refactor to reduce dependence on awk # - Use a separate config file # - Add support for conveyance test # v1.6.5 # - HTML boundary fix, proper message ids, support for dma mailer # - Better support for NVMe and SSD # - Support for new smartmon-tools # v1.6 # - Actually fixed the broken borders in the tables. # - Split the SMART table into two tables, one for SSDs and one for HDDs. # - Added several options for SSD reporting. # - Modified the SSD table in order to capture relevant (seemingly) SSD data. # - Changed 'include SSD' default to true. # - Cleaned up minor formatting and error handling issues (tried to have the cell fill with "N/A" instead of non-sensical values). # v1.5 # - Added Frag%, Size, Allocated, Free for ZPool status report summary. # - Added Disk Size, RPM, Model to the Smart Report # - Added if statment so that if "Model Family" is not present script will use "Device Model" for brand in the SMART Satus report details. # - Added Glabel Status Report # - Removed Power-On time labels and added ":" as a separator. # - Added Power-On format to the Power-On time Header. # - Changed Backup default to false. # v1.4 # - in statusOutput changed grep to scrub: instead of scrub # - added elif for resilvered/resilver in progress and scrub in progress with (hopefully) som useful info fields # - changed the email subject to include hostname and date & time # v1.3 # - Added scrub duration column # - Fixed for FreeNAS 11.1 (thanks reven!) # - Fixed fields parsed out of zpool status # - Buffered zpool status to reduce calls to script # v1.2 # - Added switch for power-on time format # - Slimmed down table columns # - Fixed some shellcheck errors & other misc stuff # - Added .tar.gz to backup file attached to email # - (Still coming) Better SSD SMART support # v1.1 # - Config backup now attached to report email # - Added option to turn off config backup # - Added option to save backup configs in a specified directory # - Power-on hours in SMART summary table now listed as YY-MM-DD-HH # - Changed filename of config backup to exclude timestamp (just uses datestamp now) # - Config backup and checksum files now zipped (was just .tar before; now .tar.gz) # - Fixed degrees symbol in SMART table (rendered weird for a lot of people); replaced with a * # - Added switch to enable or disable SSDs in SMART table (SSD reporting still needs work) # - Added most recent Extended & Short SMART tests in drive details section (only listed one before, whichever was more recent) # - Reformatted user-definable parameters section # - Added more general comments to code # v1.0 # - Initial release # Defaults LANG="en_US.UTF-8" # Ensure date works as expected. # Functions function rpConfig () { # Write out a default config file tee > "${configFile}" <<"EOF" # Set this to 0 to enable defaultFile="1" ###### User-definable Parameters ### Email Address email="email@address.com" ### Global table colors okColor="#c9ffcc" # Hex code for color to use in SMART Status column if drives pass (default is light green, #c9ffcc) warnColor="#ffd6d6" # Hex code for WARN color (default is light red, #ffd6d6) critColor="#ff0000" # Hex code for CRITICAL color (default is bright red, #ff0000) altColor="#f4f4f4" # Table background alternates row colors between white and this color (default is light gray, #f4f4f4) ### zpool status summary table settings usedWarn="90" # Pool used percentage for CRITICAL color to be used scrubAgeWarn="30" # Maximum age (in days) of last pool scrub before CRITICAL color will be used ### SMART status summary table settings includeSSD="true" # Change to "true" to include SSDs in SMART status summary table; "false" to disable includeSAS="false" # Change to "true" to include SAS drives in SMART status summary table; "false" to disable lifeRemainWarn="75" # Life remaining in the SSD at which WARNING color will be used lifeRemainCrit="50" # Life remaining in the SSD at which CRITICAL color will be used totalBWWarn="100" # Total bytes written (in TB) to the SSD at which WARNING color will be used totalBWCrit="200" # Total bytes written (in TB) to the SSD at which CRITICAL color will be used tempWarn="35" # Drive temp (in C) at which WARNING color will be used tempCrit="40" # Drive temp (in C) at which CRITICAL color will be used ssdTempWarn="40" # SSD drive temp (in C) at which WARNING color will be used ssdTempCrit="45" # SSD drive temp (in C) at which CRITICAL color will be used sectorsCrit="10" # Number of sectors per drive with errors before CRITICAL color will be used testAgeWarn="5" # Maximum age (in days) of last SMART test before CRITICAL color will be used powerTimeFormat="ymdh" # Format for power-on hours string, valid options are "ymdh", "ymd", "ym", or "y" (year month day hour) ### TrueNAS config backup settings configBackup="false" # Change to "false" to skip config backup (which renders next two options meaningless); "true" to keep config backups enabled emailBackup="false" # Change to "true" to email TrueNAS config backup saveBackup="true" # Change to "false" to delete TrueNAS config backup after mail is sent; "true" to keep it in dir below backupLocation="/root/backup" # Directory in which to save TrueNAS config backups ### UPS status summary settings reportUPS="false" # Change to "false" to skip reporting the status of the UPS ### General script settings logfileLocation="/tmp" # Directory in which to save TrueNAS log file. Can be set to /tmp. logfileName="logfilename" # Log file name saveLogfile="true" # Change to "false" to delete the log file after creation ##### Drive Overrides # In the form: declare -A _ # And then for each override: _[]="" # Replace any non ascii alphanumeric characters with _ in the serial. EOF echo "Please edit the config file for your setup" >&2 exit 0 } function ConfigBackup () { local tarfile local fnconfigdest_version local fnconfigdest_date local filename # Set up file names, etc for later tarfile="/tmp/report/config_backup.tar.gz" fnconfigdest_version="$(< /etc/version sed -e 's:)::' -e 's:(::' -e 's: :-:' | tr -d '\n')" if [ "${systemType}" = "BSD" ]; then fnconfigdest_date="$(date -r "${runDate}" '+%Y%m%d%H%M%S')" else fnconfigdest_date="$(date -d "@${runDate}" '+%Y%m%d%H%M%S')" fi filename="${fnconfigdest_date}_${fnconfigdest_version}" ### if [ ! -d "/tmp/report/" ]; then mkdir -p "/tmp/report/" fi ### Test config integrity if [ "${systemSubType}" = "pfSense" ]; then filename="${filename}_config" cp -a "/conf/config.xml" "/tmp/report/${filename}.xml" ( cd "/tmp/report/" || exit; tar -czf "${tarfile}" "./${filename}.xml" ) { if [ "${emailBackup}" = "true" ]; then # Write MIME section header for file attachment (encoded with base64) tee <<- EOF --${boundary} Content-Type: application/tar+gzip name="${filename}.tar.gz" Content-Disposition: attachment; filename="${filename}.tar.gz" Content-Transfer-Encoding: base64 EOF base64 "${tarfile}" fi # Write MIME section header for html content to come below tee <<- EOF --${boundary} Content-Transfer-Encoding: 8bit Content-Type: text/html; charset="utf-8" EOF } >> "${logfile}" elif [ ! "$(sqlite3 "/data/freenas-v1.db" "pragma integrity_check;")" = "ok" ]; then # Config integrity check failed, set MIME content type to html and print warning { tee <<- EOF --${boundary} Content-Transfer-Encoding: 8bit Content-Type: text/html; charset=utf-8 Automatic backup of TrueNAS configuration has failed! The configuration file is corrupted! You should correct this problem as soon as possible!
EOF } >> "${logfile}" else # Config integrity check passed; copy config db, generate checksums, make .tar.gz archive sqlite3 "/data/freenas-v1.db" ".backup main /tmp/report/${filename}.db" cp -f "/data/pwenc_secret" "/tmp/report/" if [ ! -z "${MD5SUM}" ]; then ${MD5SUM} "/tmp/report/${filename}.db" > /tmp/report/config_backup.md5 else md5sum "/tmp/report/${filename}.db" > /tmp/report/config_backup.md5 fi if [ ! -z "${SHA256SUM}" ]; then ${SHA256SUM} "/tmp/report/${filename}.db" > /tmp/report/config_backup.sha256 else sha256sum "/tmp/report/${filename}.db" > /tmp/report/config_backup.sha256 fi ( cd "/tmp/report/" || exit; tar -czf "${tarfile}" "./${filename}.db" "./config_backup.md5" "./config_backup.sha256" "./pwenc_secret" ) { if [ "${emailBackup}" = "true" ]; then # Write MIME section header for file attachment (encoded with base64) tee <<- EOF --${boundary} Content-Type: application/tar+gzip name="${filename}.tar.gz" Content-Disposition: attachment; filename="${filename}.tar.gz" Content-Transfer-Encoding: base64 EOF base64 "${tarfile}" fi # Write MIME section header for html content to come below tee <<- EOF --${boundary} Content-Transfer-Encoding: 8bit Content-Type: text/html; charset="utf-8" EOF } >> "${logfile}" # If logfile saving is enabled, copy .tar.gz file to specified location before it (and everything else) is removed below if [ "${saveBackup}" = "true" ]; then if [ ! -d "${backupLocation}/" ]; then mkdir -p "${backupLocation}/" fi cp "${tarfile}" "${backupLocation}/${filename}.tar.gz" fi rm "${tarfile}" rm /tmp/report/* fi } function ZpoolSummary () { { local pool local status local frag local size local allocated local free local errors local readErrors local err local writeErrors local cksumErrors local used local scrubRepBytes local scrubErrors local scrubAge local scrubDuration local resilver local statusOutput local bgColor local statusColor local readErrorsColor local writeErrorsColor local cksumErrorsColor local usedColor local scrubRepBytesColor local scrubErrorsColor local scrubAgeColor local multiDay local altRow local zfsVersion } zfsVersion="$(zpool version 2> /dev/null | head -n 1 | sed -e 's:zfs-::')" ### zpool status summary table { # Write HTML table headers to log file; HTML in an email requires 100% in-line styling (no CSS or