#!/bin/bash
###### ZPool & SMART status report with FreeNAS/TrueNAS config backup
### Original script by joeschmuck, modified by Bidelu0hm, then by melp (me)
### At a minimum, enter email address in user-definable parameter section. Feel free to edit other user parameters as needed.
### If you find any errors, feel free to contact me on the FreeNAS forums (username melp) or email me at jason at jro dot io.
### Version: v1.3 TrueNAS Scale (Jeff Alperin 12-6-21)
### Version v1.4c & v1.4d FreeNAS/TrueNAS (joeschmuck 22 June 2022)
### Changelog:
# v1.4d:
# - Fixed Scrub In Progress nuisance error when a scrub is in progress.
# - Added offsetting Reallocated Sectors for four drives. This should be for testing only. Any drives
# -- with a significant number of bad sectors should be replaced, not used to store important data.
# - Added Drive Warranty Expiration warning messages and ability to disable the Email Subject line warning.
# - Added HDD and SSD individual temperature settings.
# -- NOT TESTED ON OTHER THAN U.S. FORMATTED DATE YYYY-MM-DD.
# - Changed order of pulling Temperature data from HDD/SSD.
#
# v1.4c:
# - Rewrite to create functions and enable easier editing.
# - Added Custom Reports.
# - Added disabling the RAW 'smartctl -a' data appened to the end of the email.
# - Added sorting drives alphabetically vice the default the OS reports them.
# - Added RED warning in Device for any single failure in the summary (deviceRedFlag switch controlled).
# - Added some additional SSD definitions.
# - Fixed sorting last two SMART Tests, now reports them in proper order.
# - Fixed detecting "SMART Support is: Enabled", for white spaces.
# - Changed IGNORE DRIVES to a String Format to clean up and simplify programming.
# - Added MultiZone_Errors support for up to eight drives.
# - Added sectorWarn variable to complement the sectorCrit variable.
# - Added ignoreSeekError variable to ignore some of those wild Seek Error Rate values.
# - Added ignoreUDMA CRC Errors due to the "Known Problem"
# - Fixed md5/sha256 error on TrueNAS Scale (only used during config backups).
# - Added selectable config backup periodicity by day vice every run.
# - Added Exporting statistical data for trend analysis.
# -- Can be setup to email statistics weekly, monthly, or not at all.
# -- The -s switch will run Data Collection Only, no email generated. Note: Do Not run two instances at once, the temp files do not survive.
# - Fixed the Capacity to remove the brackets "[]", thanks Jeff Alperin.
# - Fixed Scrub Age failure due to 1 day or longer repair time, now shows anything >24 hours.
#
# - Known Problem: One user reported UDMA_CRC_ERRORS is not subtracting correctly, have not been able to personnaly replicate it.
# -- This error seems to occur around line #1027
#
# v1.4b:
# - Added SMART test reamining percentage if Last Test has a SMART Test is in progress.
# - Fix for empty SMART fields, typically for unsupported SSD's.
# - Added IGNORE SMART Drive so you can ignore specific drives that may cause you wierd readings.
# --- Updated so blank SSD table header is removed when you ignore all the drives (just crazy talk).
# v1.4a:
# - Fixed report errors for if a SCRUB is in progress, now shows estimated completion time.
# - Fixed report error for a Canceled SCRUB.
# - Fixed FreeBSD/Linux use for SCRUB report (minor oversight).
# v1.4:
# - Run on CRON JOB using /path/multi_report_v1.4.sh
# - Fixed for automatic running between FreeBSD and Linux Debian (aka SCALE) as of this date.
# - All SMART Devices will report.
# - Added conditional Subject Line (Good/Critical/Warning).
# - Added Automatic SSD Support.
# --- Some updates may need to be made to fit some of SSD's. Code in the area of about line 530 will
# --- need to be adjusted to add new attributes for the desired SSD's fields.
# - UDMA_CRC_ERROR Override because once a drive encounters this type of error, it cannot be cleared
# --- so you can offset it now vice having an alarm condition for old UDMA_CRC_Errors.
# - Added listing NON-SMART Supported Drives. Use only if useful to you, some drives will
# --- still output some relevant data, many will not.
# 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
######### INSTRUCTIONS ON USE OF THIS SCRIPT
#
# This script will perform two main functions: 1: Generate a report send to email on your drive status,
# and 2: Create a copy of your Config File and attach to the same email.
#
# In order to configure the script properly read over the User Definable Section before making any changes.
# Then make changes as indicted by the section instructions.
#
# To run the program from the command line, use ./program_name.sh
# Also you need to make it executable using "chmod +x program_name.sh"
#
# Enjoy
###### User-definable Parameters
# Enter your email address to send the report to. The from address does not need to be changed.
###### Email Address
email="YourEmail@Address.com"
from="TrueNAS@local.com"
###### REPORT HEADER TITLE ######
HDDreportTitle="Spinning Rust Summary Report" # This is the title of the HDD report, change as you desire.
SSDreportTitle="SSD Summary Report" # This is the title of the SSD report, change as you desire.
### CUSTOM REPORT CONFIGURATION ###
# By default all items are selected. Change the item to "true" to have it displayed, "false" to not have it displayed.
# NOTE: Alarm setpoints are not affected by these settings.
# For Hard Drive Section
HDD_Device_ID="true"
HDD_Serial_Number="true"
HDD_Model_Number="true"
HDD_Capacity="true"
HDD_Rotational_Rate="true"
HDD_SMART_Status="true"
HDD_Drive_Temp="true"
HDD_Power_On_Hours="true"
HDD_Start_Stop_Count="true"
HDD_Load_Cycle="true"
HDD_Spin_Retry="true"
HDD_Reallocated_Sectors="true"
HDD_Reallocated_Events="true"
HDD_Pending_Sectors="true"
HDD_Offline_Uncorrectable="true"
HDD_UDMA_CRC_Errors="true"
HDD_Seek_Error_Rate="true"
HDD_MultiZone_Errors="true"
HDD_Last_Test_Age="true"
HDD_Last_Test_Type="true"
# For Solid State Drive Section
SSD_Device_ID="true"
SSD_Serial_Number="true"
SSD_Model_Number="true"
SSD_Capacity="true"
SSD_SMART_Status="true"
SSD_Drive_Temp="true"
SSD_Power_On_Hours="true"
SSD_Wear_Level="true"
SSD_Reallocated_Sectors="true"
SSD_Reallocated_Events="true"
SSD_Pending_Sectors="true"
SSD_Offline_Uncorrectable="true"
SSD_UDMA_CRC_Errors="true"
SSD_Last_Test_Age="true"
SSD_Last_Test_Type="true"
###### Drive Ignore List
# Use this section to list any drives to ignore and remove from the report. This is useful for ignoring USB Flash Drives.
# We are using a comma delimited file to identify the drive serial numbers. You MUST use the exact and full serial number
# smartctl reports, if there is no identical match then it doesn't work properly.
#
# Format: IGNOREDRIVES="DRIVE_SERIAL_NUMBER,DRIVE_SERIAL_NUMBER"
#
# Example: IGNOREDRIVES="1GVD84B,1JUMLBD,WD-WXQ1E36C19XC"
IGNOREDRIVES="2X1J90CA48799"
###### Drive UDMA_CRC_Error_Count Flags
# List each drive by serial number and include the current UDMA_CRC_Error_Count value.
# If the count exceeds the count in the table below then a warning message will be generated.
# On the Status Report the UDMA CRC Errors block will be YELLOW with a value of "0" for an overridden value, for your indication.
#
# Format: UCRC1SN = Drive Serial Number reported by SMART, UCRC1CNT = Current UDMA Error Count you want to subtract from this drive.
# You may add up to 8 drives with the current code. More drives could be added with a simple modification of the program.
# Do not list your drives with a value of "0" or each one will be Yellow. Yikes!
#
# Example (drive has 2 UDMA CRC Errors): UCRC1SN="S2X1J90CA48799"
# UCRC1CNT=2
# Drives "2011E2940534" and "2011E2940536" are hard coded at lines 1057 through 1060.
UCRC1SN="WD-WMC4N2578099"
UCRC1CNT=1
UCRC2SN="S2X1J90CA48799"
UCRC2CNT=2
UCRC3SN="P02618119268"
UCRC3CNT=1
UCRC4SN="DRIVE_SERIAL_NUMBER"
UCRC4CNT=0
UCRC5SN="DRIVE_SERIAL_NUMBER"
UCRC5CNT=0
UCRC6SN="DRIVE_SERIAL_NUMBER"
UCRC6CNT=0
UCRC7SN="DRIVE_SERIAL_NUMBER"
UCRC7CNT=0
UCRC8SN="DRIVE_SERIAL_NUMBER"
UCRC8CNT=0
###### Multi_Zone_Errors
# This identifies drives with Multi_Zone_Errors which may be irritating people.
# Using same format as UDMA_CRC_Errors (see above).
MULTIZONE1SN="WD-WCC4N0KZDD1L"
MULTIZONE1CNT=4
MULTIZONE2SN="WD-WCC4N2VNZ6HH"
MULTIZONE2CNT=51
MULTIZONE3SN="S2X1J90CA48799"
MULTIZONE3CNT=31
MULTIZONE4SN="DRIVE_SERIAL_NUMBER"
MULTIZONE4CNT=0
MULTIZONE5SN="DRIVE_SERIAL_NUMBER"
MULTIZONE5CNT=0
MULTIZONE6SN="DRIVE_SERIAL_NUMBER"
MULTIZONE6CNT=0
MULTIZONE7SN="DRIVE_SERIAL_NUMBER"
MULTIZONE7CNT=0
MULTIZONE8SN="DRIVE_SERIAL_NUMBER"
MULTIZONE8CNT=0
####### Reallocated Sectors Exceptions
# This section should only be used for testing, normally you should be replacing drives that have a higher than normal reallocated sector count.
BADSECTORS1SN="W3N0B3RP"
BADSECTORS1CNT=16
BADSECTORS2SN="DRIVE_SERIAL_NUMBER"
BADSECTORS2CNT=0
BADSECTORS3SN="DRIVE_SERIAL_NUMBER"
BADSECTORS3CNT=0
BADSECTORS4SN="DRIVE_SERIAL_NUMBER"
BADSECTORS4CNT=0
####### Warranty Expiration Date
# This section is used to add warranty expirations for designated drives and to create an alert when they expire.
# Format of date is YYYY-MM-DD
# To disable this feature, remove the drive on the list below.
WARRANTYDRIVESN1="K1JUMLBD"
WARRANTYDRIVESN1DATE="2020-09-30"
WARRANTYDRIVESN2="K1JRSWLD"
WARRANTYDRIVESN2DATE="2020-09-30"
WARRANTYDRIVESN3="K1JUMW4D"
WARRANTYDRIVESN3DATE="2020-09-30"
WARRANTYDRIVESN4="K1GVD84B"
WARRANTYDRIVESN4DATE="2020-10-12"
###### zpool status summary table settings
usedWarn=90 # Pool used percentage for CRITICAL color to be used.
scrubAgeWarn=37 # Maximum age (in days) of last pool scrub before CRITICAL color will be used (30 + 7 days for day of week). Default=37.
###### Report Status Summary Table Settings
# These settings will adjust how the scripts acts.
#
includeSSD="true" # Set to "true" will engage SSD Automatic Detection and Reporting, false = Disable SSD Automatic Detection and Reporting.
reportnonSMART="true" # Will force even non-SMART devices to be reported, "false" = normal operation to ignore non-SMART devices.
HDDtempWarn=45 # HDD Drive temp (in C) at which WARNING color/message will be used.
HDDtempCrit=50 # HDD Drive temp (in C) at which CRITICAL color/message will be used.
SSDtempWarn=50 # SSD Drive temp (in C) at which WARNING color/message will be used.
SSDtempCrit=65 # SSD Drive temp (in C) at which CRITICAL color/message will be used.
sectorsWarn=2 # Number of sectors per drive with errors before WARNING color/message will be used, this value should be less than sectorsCrit.
sectorsCrit=10 # Number of sectors per drive with errors before CRITICAL color/message will be used.
testAgeWarn=2 # Maximum age (in days) of last SMART test before CRITICAL color/message will be used.
powerTimeFormat="h" # Format for power-on hours string, valid options are "ymdh", "ymd", "ym", "y", or "h" (year month day hour).
deviceRedFlag="true" # Set "true" to have the Device Column indicate RED for ANY alarm condition. Default is true.
ignoreMultiZone="false" # Set to "true" to ignore all MultiZone Errors. Default is false.
ignoreSeekError="true" # Set to "true" to ignore all Seek Error Rate/Health errors. Default is true.
ignoreUDMA="false" # Set to "true" to ignore all UltraDMA CRC Errors for the summary alarm (Email Header) only, errors will appear in the graphical chart.
expDataEnable="true" # Set to "true" will save all drive data into a CSV file defined by "statistical_data_file" below.
expDataEmail="true" # Set to "true" to have an attachment of the file emailed to you. Default is true.
expDataPurge=730 # Set to the number of day you wish to keep in the data. Data older will be purged. Default is 730 days (2 years). 0=Disable.
expDataEmailSend="Mon" # Set to the day of the week the statistical report is emailed. (All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)
disableRAWdata="false" # Set to "true" to remove the 'smartctl -a' data and non-smart data appended to the normal report. Default is false.
disableWarranty="true" # Set to "true to disable email Subject line alerts for any expired warranty alert. The email body will still report the alert.
###### Export Data File
# This is the loction for your export file to reside.
statistical_data_file="/tmp/statisticalsmartdata.csv"
###### FreeNAS config backup settings
configBackup="true" # Set to "true" to save config backup (which renders next two options operational); "false" to keep disable config backups.
configSendDay="Mon" # Set to the day of the week the statistical report is emailed. (All, Mon, Tue, Wed, Thu, Fri, Sat, Sun, Month)
saveBackup="false" # Set to "false" to delete FreeNAS config backup after mail is sent; "true" to keep it in dir below.
backupLocation="/tmp/" # Directory in which to store the backup FreeNAS config files.
###### Global table of colors
# The colors selected you can change but you will need to look up the proper HEX code for a color.
#
okColor="#c9ffcc" # Hex code for color to use in SMART Status column if drives pass (default is light green, #c9ffcc).
warnColor="#f765d0" # Hex code for WARN color (default is purple, #f765d0).
critColor="#ff0000" # Hex code for CRITICAL color (default is red, #ff0000).
altColor="#f4f4f4" # Table background alternates row colors between white and this color (default is light gray, #f4f4f4).
whtColor="#ffffff" # Hex for White background.
ovrdColor="#ffff66" # Hex code for Override Yellow.
blueColor="#87ceeb" # Hex code for Sky Blue, used for the SCRUB In Progress background.
###### STOP EDITING THE SCRIPT HERE ######
# If you really feel like editing below this line, you are customizing the code beyond a novice user.
###### Auto-generated Parameters
programver="Multi-Report v1.4d (22 June 2022)"
softver=$(uname -s)
host=$(hostname -s)
logfile="/tmp/smart_report_body.tmp"
logfile_header="/tmp/smart_report_header.tmp"
logfile_warning="/tmp/smart_report_warning_flag.tmp"
logfile_critical="/tmp/smart_report_critical_flag.tmp"
logfile_warranty="/tmp/smart_report_warranty_flag.tmp"
boundary="gc0p4Jq0M2Yt08jU534c0p"
##########################
##########################
### ###
### DEFINE FUNCTIONS ###
### ###
##########################
##########################
#################### PURGE EXPORT DATA CSV FILE #######################
purge_exportdata () {
### This routine will purge the "statistical_data_file" of data older then "expDataPurge".
#
echo "Running Purging Routine"
# Delete temp file if it exists
if test -e "/tmp/temp_purge_file.csv"; then
rm "/tmp/temp_purge_file.csv"
# Create the header
printf "Date,Time,Device ID,Drive Type,Serial Number,SMART Status,Temp,Power On Hours,Wear Level,Start Stop Count,Load Cycle,Spin Retry,Reallocated Sectors,\
ReAllocated Sector Events,Pending Sectors,Offline Uncorrectable,UDMA CRC Errors,Seek Error Rate,Multi Zone Errors,\n" > "/tmp/temp_purge_file.csv"
fi
{
input="$statistical_data_file"
if [ $softver != "Linux" ]; then
expireDate=$(date -v -"$expDataPurge"d +%Y/%m/%d)
else
expireDate=$(date -d "$expDataPurge days ago" +%Y/%m/%d)
fi
awk -v expireDate="$expireDate" '
BEGIN {
FS=OFS=","
FPAT = "([^,]+)|(\"[^\"]+\")"
count=0
}
data=$1
{
FS=OFS=" "
if (count !=0) if ($1 >= expireDate) {
printf ("%s\n", data) >> "/tmp/temp_purge_file.csv"
}
++count
}
END {
}
' $input >/dev/null
}
cp -R "/tmp/temp_purge_file.csv" "$statistical_data_file"
}
################## EMAIL EXPORT DATA CVS FILE #########################
email_datafile () {
if [ "$expDataEmail" == "true" ]; then
Now=$(date +"%a")
doit="false"
case $expDataEmailSend in
All)
doit="true"
;;
Mon|Tue|Wed|Thu|Fri|Sat|Sun)
if [[ "$expDataEmailSend" == "$Now" ]]; then
doit="true"
fi
;;
Month)
if [[ $(date +"%d") == "01" ]]; then
doit="true"
fi
;;
*)
;;
esac
if [[ "$doit" == "true" ]]; then
(
# Write MIME section header for file attachment (encoded with base64)
echo "--${boundary}"
echo "Content-Type: text/csv"
echo "Content-Transfer-Encoding: base64"
echo "Content-Disposition: attachment; filename=Statistical_Data.csv"
base64 "$statistical_data_file"
echo "--${boundary}--"
) >> "$logfile"
fi
fi
}
#################### GET SMART HARD DRIVES ############################
get_smartHDD_listings () {
### GET non-SSD listing - MUST support SMART
# smartdrives= All Drives that are SMART
# smartdrivesSSD = SSD all SMART
# nonsmartdrives = Any drive not supporting SMART
# Get Hard Drive listing - MUST support SMART
# variable smartdrives
if [ $softver != "Linux" ]; then
smartdrives=$(for drive in $(sysctl -n kern.disks); do
if [ "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && ! [ "$(smartctl -i /dev/"${drive}" | grep "Solid State Device")" ]; then
targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
s="0"
IFS=',' read -ra ADDR <<< "$IGNOREDRIVES"
for i in "${ADDR[@]}"; do
if [[ $i == $targument ]]; then
s="1"
continue
fi
done
if [[ $s == "0" ]]; then
printf "%s " "${drive}"
fi
fi
done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
else
smartdrives=$(for drive in $(fdisk -l | grep "Disk /dev/sd" | cut -c 11-13 | tr '\n' ' '); do
if [ "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && ! [ "$(smartctl -i /dev/"${drive}" | grep "Solid State Device")" ]; then
targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
s="0"
IFS=',' read -ra ADDR <<< "$IGNOREDRIVES"
for i in "${ADDR[@]}"; do
if [[ $i == $targument ]]; then
s="1"
continue
fi
done
if [[ $s == "0" ]]; then
printf "%s " "${drive}"
fi
fi
done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
fi
}
########################## GET SMART SOLID DISK DRIVES ################################
get_smartSSD_listings () {
# Get SSD listing - MUST suport SMART
# variable smartdrivesSSD
if [ $softver != "Linux" ]; then
smartdrivesSSD=$(for drive in $(sysctl -n kern.disks); do
if [ "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && [ "$(smartctl -i /dev/"${drive}" | grep "Solid State Device")" ]; then
targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
s="0"
IFS=',' read -ra ADDR <<< "$IGNOREDRIVES"
for i in "${ADDR[@]}"; do
if [[ $i == $targument ]]; then
s="1"
continue
fi
done
if [[ $s == "0" ]]; then
printf "%s " "${drive}"
fi
fi
done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
else
smartdrivesSSD=$(for drive in $(fdisk -l | grep "Disk /dev/sd" | cut -c 11-13 | tr '\n' ' '); do
if [ "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ] && [ "$(smartctl -i /dev/"${drive}" | grep "Solid State Device")" ]; then
targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
s="0"
IFS=',' read -ra ADDR <<< "$IGNOREDRIVES"
for i in "${ADDR[@]}"; do
if [[ $i == $targument ]]; then
s="1"
continue
fi
done
if [[ $s == "0" ]]; then
printf "%s " "${drive}"
fi
fi
done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
fi
}
########################## GET OTHER SMART DEVICES ##################################
get_smartOther_listings () {
### Get the non-SSD listing - MUST support SMART
# variable nonsmartdrives
if [ $softver != "Linux" ]; then
nonsmartdrives=$(for drive in $(sysctl -n kern.disks); do
if [ ! "$(smartctl -i /dev/"${drive}" | grep "SMART support is:.\s*Enabled")" ]; then
targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
s="0"
IFS=',' read -ra ADDR <<< "$IGNOREDRIVES"
for i in "${ADDR[@]}"; do
if [[ $i == $targument ]]; then
s="1"
continue
fi
done
if [[ $s == "0" ]]; then
printf "%s " "${drive}"
fi
fi
done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
else
nonsmartdrives=$(for drive in $(fdisk -l | grep "Disk /dev/sd" | cut -c 11-13 | tr '\n' ' '); do
if [ ! "$(smartctl -i /dev/"${drive}" | grep "SMART support is: Enabled")" ]; then
targument="$(smartctl -i /dev/"${drive}" | grep "Serial Number:" | awk '{print $3}')";
### Process Ignore List ###
s="0"
IFS=',' read -ra ADDR <<< "$IGNOREDRIVES"
for i in "${ADDR[@]}"; do
if [[ $i == $targument ]]; then
s="1"
continue
fi
done
if [[ $s == "0" ]]; then
printf "%s " "${drive}"
fi
fi
done | awk '{for (i=NF; i!=0 ; i--) print $i }' | tr ' ' '\n' | sort | tr '\n' ' ')
fi
}
########################### FORMAT EMAILS STEP 1 ##########################
email_preformat () {
###### Email pre-formatting
### Set some of the email headers before conditional headers
(
echo "MIME-Version: 1.0"
echo "Content-Type: multipart/mixed; boundary=${boundary}"
) > "$logfile"
}
########################### CONFIGURATION BACKUP ##############################
config_backup () {
###### Config backup (if enabled)
tarfile="/tmp/config_backup.tar.gz"
filename="$(date "+FreeNAS_Config_%Y-%m-%d")"
filename2="Stat_Data"
#1
if [ "$configBackup" == "true" ]; then
############################################################################################################
Now=$(date +"%a")
doit="false"
case $configSendDay in
All)
doit="true"
;;
Mon|Tue|Wed|Thu|Fri|Sat|Sun)
if [[ "$configSendDay" == "$Now" ]]; then
doit="true"
fi
;;
Month)
if [[ $(date +"%d") == "01" ]]; then
doit="true"
fi
;;
*)
;;
esac
if [[ "$doit" == "true" ]]; then
# Set up file names, etc for later
tarfile="/tmp/config_backup.tar.gz"
filename="$(date "+FreeNAS_Config_%Y-%m-%d")"
filename2="Stat_Data"
### Test config integrity
if ! [ "$(sqlite3 /data/freenas-v1.db "pragma integrity_check;")" == "ok" ]; then
# Config integrity check failed, set MIME content type to html and print warning
(
echo "--${boundary}"
echo "Content-Type: text/html"
echo "Automatic backup of FreeNAS configuration has failed! The configuration file is corrupted!"
echo "You should correct this problem as soon as possible!"
echo "
"
) >> "$logfile"
else
# Config integrity check passed; copy config db, generate checksums, make .tar.gz archive
cp /data/freenas-v1.db "/tmp/${filename}.db"
if [ $softver != "Linux" ]; then
md5 "/tmp/${filename}.db" > /tmp/config_backup.md5
sha256 "/tmp/${filename}.db" > /tmp/config_backup.sha256
else
md5sum "/tmp/${filename}.db" > /tmp/config_backup.md5
sha256sum "/tmp/${filename}.db" > /tmp/config_backup.sha256
fi
(
cd "/tmp/" || exit;
tar -czf "${tarfile}" "./${filename}.db" ./config_backup.md5 ./config_backup.sha256;
)
(
# Write MIME section header for file attachment (encoded with base64)
echo "--${boundary}"
echo "Content-Type: application/tar+gzip"
echo "Content-Transfer-Encoding: base64"
echo "Content-Disposition: attachment; filename=${filename}.tar.gz"
base64 "$tarfile"
# Write MIME section header for html content to come below
echo "--${boundary}"
echo "Content-Type: text/html"
) >> "$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
cp "${tarfile}" "${backupLocation}/${filename}.tar.gz"
fi
rm "/tmp/${filename}.db"
rm /tmp/config_backup.md5
rm /tmp/config_backup.sha256
rm "${tarfile}"
fi
else
(
echo "--${boundary}"
echo "Content-Type: text/html"
) >> "$logfile"
fi
else
# configBackup = false so this is what to do
# Config backup enabled; set up for html-type content
(
echo "--${boundary}"
echo "Content-Type: text/html"
) >> "$logfile"
fi
}
################################## GENERATE ZPOOL REPORT ##################################
zpool_report () {
###### Report Summary Section (html tables)
### zpool status summary table
(
# Write HTML table headers to log file; HTML in an email requires 100% in-line styling (no CSS or