### Start Timer and Log Start Time Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Initializes the script's execution timer and logs the program start time to a temporary file, with formatting adjusted for Linux and other systems. ```bash SECONDS=0 # Lets start the timer if [[ $softver != "Linux" ]]; then start_time_display=$(date '+%H:%M:%S'); else start_time_display=$(date +"%H:%M:%S.%2N"); fi (echo "This log file is used to track the execution time for each routine and identify any location to optimize if possible."; echo " " echo $start_time_display": Program Start"; echo " ") >> /tmp/drive_selftest/drive_test_timer_temp.txt ``` -------------------------------- ### Download and Install Scripts Source: https://context7.com/joeschmuck/multi-report/llms.txt Download the latest versions of the scripts from GitHub and set up their executable permissions. The -config switch on first run generates the configuration file. ```bash # Download scripts from GitHub curl -LJOs https://raw.githubusercontent.com/JoeSchmuck/Multi-Report/refs/heads/main/multi_report.txt curl -LJOs https://raw.githubusercontent.com/JoeSchmuck/Multi-Report/refs/heads/main/drive_selftest.txt # Rename and make executable cp multi_report.txt /mnt/tank/scripts/multi_report.sh cp drive_selftest.txt /mnt/tank/scripts/drive_selftest.sh chmod 755 /mnt/tank/scripts/multi_report.sh chmod 755 /mnt/tank/scripts/drive_selftest.sh # Run the interactive configuration wizard to generate multi_report_config.txt bash /mnt/tank/scripts/multi_report.sh -config # Verify setup with a dry-run that only generates a report (no SMART tests, no update check) bash /mnt/tank/scripts/multi_report.sh -report_only ``` -------------------------------- ### Initiate SMART Test (Modern Systems) Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Attempts to start a SMART test (short or long) using smartctl for NVMe drives on systems with smartmontools 7.4 or greater. Handles different interface types. ```bash if [[ $1 == "Short" ]]; then if [[ $Debug == "true" ]]; then echo "run_smart_test 2: Short Test drive: "$drive | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi if [[ $No_Test != "true" ]]; then smart_test_ok="$(smartctl -t short /dev/$drive)" fi else if [[ $Debug == "true" ]]; then echo "run_smart_test 3: Long Test drive: "$drive | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi if [[ $No_Test != "true" ]]; then smart_test_ok="$(smartctl -t long /dev/$drive)" fi fi ``` ```bash if [[ $No_Test != "true" ]]; then smartresult=$? else smartresult=0 smart_test_ok="-no_test switch detected" fi ``` ```bash if [[ $Debug == "true" ]]; then echo "run_smart_test 4: Test Results "$smartresult | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi ``` ```bash if [[ $smartresult -eq 0 ]]; then # Exit code of 0 is good, command accepted. if [[ $Debug == "true" ]]; then echo "run_smart_test 5: Punting to update_csv "$1 | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi # Verify we started the test. if echo $smart_test_ok | grep -i -e "testing" -e "begun" > /dev/null 2<&1; then update_csv_file $1 # Update the CSV file with todays date and the next due date. in_test=1 if [[ $Silent != "enable" ]]; then echo "Drive "$drive" indicates it STARTED Testing Normally" | tee -a /tmp/drive_selftest/drive_test_temp.txt fi fi if [[ $Silent != "enable" ]]; then echo "SMART command for drive:"$drive" was received okay, return exit code:"$smartresult | tee -a /tmp/drive_selftest/drive_test_temp.txt fi break 1 # Return to the FOR loop elif [[ $smartresult -eq 4 ]]; then # Exit code of 4 could mean the command was accepted but the drive was busy or the command was not accepted. # Check to see if test is running before assuming exit code 4 is a bust. if echo $smart_test_ok | grep -i -e "remaining" -e "completed" > /dev/null 2<&1; then if [[ $Debug == "true" ]]; then echo "run_smart_test 6: Looking good for drive "$drive | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi in_test=1 if [[ $Silent != "enable" ]]; then echo "Drive "$drive" indicates it WAS ALREADY IN TEST" | tee -a /tmp/drive_selftest/drive_test_temp.txt fi break 1 # Jump out of the FOR loop fi else echo "SMART command for drive:"$drive" was not good, returned exit code:"$smartresult | tee -a /tmp/drive_selftest/drive_test_temp.txt echo "Lets try a different interface type..." | tee -a /tmp/drive_selftest/drive_test_temp.txt fi ``` ```bash else # It looks like we need an interface modifier if [[ $Debug == "true" ]]; then echo "run_smart_test 7: Interface modifier '$dr' for drive "$drive" running a $1 test." | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi driveConnectionType=$dr if [[ $1 == "Short" ]]; then if [[ $No_Test != "true" ]]; then ``` -------------------------------- ### Disk Layout JSON Configuration Format Source: https://context7.com/joeschmuck/multi-report/llms.txt Example structure of the disklayout_config.json file used to assign physical bay locations and drive details. ```json # The JSON file format (disklayout_config.json): # { # "bays": [ # { "slot": "1", "address": "0:0:0:0", "serial": "ZR13JRL0", # "pool": "tank", "drive_color": "green", "drive_temp": "38" }, # { "slot": "2", "address": "0:0:1:0", "serial": "K1JRSWLD", # "pool": "tank", "drive_color": "orange", "drive_temp": "47" } # ] # } ``` -------------------------------- ### Log Script Execution Details Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Logs the start time, script version, and other relevant execution details to temporary files. This helps in tracking script progress and debugging. ```bash echo "Joe's SMART Drive Self-test Script - Run: "$today_day" "$Full_Month_Name" "$(date +%r)" | tee -a /tmp/drive_selftest/drive_test_temp.txt /tmp/drive_selftest/drive_test_timer_temp.txt echo "Script Version: "$Version" "$Version_Date", "$programver | tee -a /tmp/drive_selftest/drive_test_temp.txt /tmp/drive_selftest/drive_test_timer_temp.txt ``` -------------------------------- ### SMR Drive Detection Logic Source: https://context7.com/joeschmuck/multi-report/llms.txt Example of querying the TrueNAS API for disk information and matching against known SMR drive model strings. ```bash # The detection function works by querying the TrueNAS API for all disks: # midclt call disk.query | jq -S '.[] | {devname, model, serial}' # Then matching against arrays like: # WD02=("WDC WD" "20" "30" "40" "60" "EFAX") # WD Red 2–6TB SMR # ST01=("ST" "4000" "DM004") # Seagate Barracuda 4TB SMR ``` -------------------------------- ### Configure New Drive Factor for Throughput Source: https://context7.com/joeschmuck/multi-report/llms.txt Determine whether new drives should start with actual or zeroed read/write throughput values in the statistical data file. ```bash # To control whether new drives start with actual or zeroed read/write throughput: add_new_drive_factor="actual" # "actual" or "zero" ``` -------------------------------- ### TrueNAS Cron Job Setup for Multi-Report and Drive-Selftest Source: https://context7.com/joeschmuck/multi-report/llms.txt Examples of cron job configurations for running `multi_report.sh` daily and `drive_selftest.sh` independently. Includes an option for alert-only emails. ```bash # Recommended cron schedule examples (set in TrueNAS UI: System > Advanced > Cron Jobs) # Multi-Report: run daily at 1:00 AM # Command: bash /mnt/tank/scripts/multi_report.sh # Schedule: 0 1 * * * # Drive-Selftest standalone (if NOT called automatically by Multi-Report): # Command: bash /mnt/tank/scripts/drive_selftest.sh # Schedule: 0 0 * * * # Multi-Report with alert-only emails: # Command: bash /mnt/tank/scripts/multi_report.sh -m # Schedule: 0 1 * * * ``` -------------------------------- ### Check for test started confirmation in smartctl output Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Parses smartctl output for keywords indicating the test has begun. Breaks from retry loop on success and updates CSV file with test date. ```bash if echo $smart_test_ok | grep -i -e "testing" -e "begun" > /dev/null 2<&1; then in_test=1 update_csv_file $1 # Update the CSV file with todays date and the next due date. if [[ $Silent != "enable" ]]; then echo "Drive "$drive" indicates it STARTED Testing using:'-d ${driveConnectionType}'" | tee -a /tmp/drive_selftest/drive_test_temp.txt fi break 1 # Jump out of the FOR loop fi ``` -------------------------------- ### Get Drive Serial Number Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Extracts the serial number of a drive using smartctl, handling potential variations in output format. ```bash csv_drive_serial=$(smartctl -d "${driveConnectionType}" -i /dev/${drive} | grep -i "Serial Number" | cut -d ':' -f2 | tr -d ' ') ``` ```bash csv_serial=$(smartctl -d "${driveConnectionType}" -i /dev/${checking_drives} | grep -i "Serial Number" | cut -d ':' -f2 | tr -d ' ') ``` -------------------------------- ### Initialize Drive Test Variables Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Sets the drives to be tested for short or long self-tests based on input arguments. If 'all' is specified, it defaults to all smart drives. ```shell if [[ $1 == "Short" ]]; then selftest_drives_short=$drives_to_test; fi if [[ $selftest_drives_short == "all" ]]; then selftest_drives_short=$smartdrives if [[ $Silent != "enable" ]]; then echo "ALL DRIVES - SHORT" | tee -a /tmp/drive_selftest/drive_test_temp.txt fi fi if [[ $1 == "Long" ]]; then selftest_drives_long=$drives_to_test; fi if [[ $selftest_drives_long == "all" ]]; then selftest_drives_long=$smartdrives if [[ $Silent != "enable" ]]; then echo "ALL DRIVES - LONG" | tee -a /tmp/drive_selftest/drive_test_temp.txt fi fi ``` -------------------------------- ### Initialize Drive Test Variables Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Sets up initial variables for tracking drive indices, counts, and test-specific flags. ```bash # Setup local variables index=0 # INDEX IS THE REPORTED BACK DRIVES increment=0 # INCREMENT IS THE ACCESS TO THE FULL ARRAY, INCLUDING VIRTUAL AND CD DRIVES skip_drives_count=0 if [[ $Debug == "true" ]]; then echo "Debug - Function 'get_API_Drives'" | tee -a /tmp/drive_selftest/drive_test_temp.txt; echo " " | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi if [[ $Test_ONLY_NVMe_Drives == "enable" ]]; then echo "Testing ONLY NVMe Drives" | tee -a /tmp/drive_selftest/drive_test_temp.txt fi ``` -------------------------------- ### Load Configuration File if Specified Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Loads configuration values from an external file if it exists or if the '-use_external_file' argument is provided. Otherwise, it defaults to script-defined values. ```bash if test -e "$Config_File_Name" || [[ $1 == "-use_external_file" ]]; then if [[ $Use_multi_report_config_values == "enable" ]]; then if test -e "$Config_File_Name"; then . "$Config_File_Name" echo 'Using "'$Config_File_Name'" values...' | tee -a /tmp/drive_selftest/drive_test_temp.txt /tmp/drive_selftest/drive_test_timer_temp.txt else echo 'Using "script" values...' | tee -a /tmp/drive_selftest/drive_test_temp.txt /tmp/drive_selftest/drive_test_timer_temp.txt fi fi fi ``` -------------------------------- ### Verify test has begun and log status Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Checks smartctl output for 'has begun' keyword to confirm test initiation. Sets test_running flag and logs drive test status with optional timer output. ```bash if echo $smart_test_ok | grep -i "has begun" > /dev/null 2<&1; then if [[ $Silent != "enable" ]]; then echo " Drive: $drive in $1 Test" | tee -a /tmp/drive_selftest/drive_test_temp.txt fi if [[ $timer_flag -eq 1 ]]; then echo " Drive: $drive in $1 Test"; fi | tee -a /tmp/drive_selftest/drive_test_temp.txt test_running=1 # Looks like the testing is in progress. No_Tests="false" else if [[ $timer_flag -eq 1 ]]; then echo " An error occurred for Drive: $drive in $1 Test."; fi | tee -a /tmp/drive_selftest/drive_test_temp.txt if echo $smart_test_ok | grep -i -e "remaining" -e "completed" > /dev/null 2<&1; then ( echo -n " Drive $drive is still running a test: " echo $smart_test_ok | grep -o -e '(..% remaining)' -e '(..% completed)') | tee -a /tmp/drive_selftest/drive_test_temp.txt else ``` -------------------------------- ### Initialize and Debug Drive Test Variables Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Sets up initial variables for drive testing and logs their values if debug mode is enabled. This helps in understanding the state of variables before the main testing logic begins. ```bash First_DOM=1 # Set First_DOM to the first day of the month. Temp_drives_tested=0 # Initial value, meaning no drives to test. DOW_temp=$DOW # Start with current DOW valid_today=0 test_it=0 # If set to other than 0, testing is needed. drives_already_tested=0 # Total number of drives previously scheduled tested. The next number is the drive to be tested if test_it != 0. if [[ $Debug == "true" ]]; then echo "Debug - Drive Names="$Drives_name | tee -a /tmp/drive_selftest/drive_test_temp.txt echo "Debug - Drive Count="$Drive_Count | tee -a /tmp/drive_selftest/drive_test_temp.txt echo "Debug - Drives Already Tested="$drives_already_tested | tee -a /tmp/drive_selftest/drive_test_temp.txt echo "Debug - Drives To Test="$drives_to_test | tee -a /tmp/drive_selftest/drive_test_temp.txt fi ``` -------------------------------- ### Run Smartctl Self-Test Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Executes a long or short self-test using smartctl. This is used on systems that do not meet the criteria for direct nvme commands. Ensure smartmontools is installed. ```bash smartctl -d "${driveConnectionType}" -t long /dev/$drive ``` ```bash smartctl -d "${driveConnectionType}" -t short /dev/$drive ``` -------------------------------- ### Drive-Selftest: Help Source: https://context7.com/joeschmuck/multi-report/llms.txt Display the full help text for the Drive-Selftest script. ```bash # Print full help text bash /mnt/tank/scripts/drive_selftest.sh -help ``` -------------------------------- ### Initialize Test Variables Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Sets up and initializes variables used for drive testing, including date-related flags and counters. ```bash First_DOM=1 # Set First_DOM to the first day of the month. Temp_drives_tested=0 # Initial value, meaning no drives to test. DOW_temp=$DOW # Start with current DOW valid_today=0 test_it=0 # If set to other than 0, testing is needed. drives_already_tested=0 # Total number of drives previously scheduled tested. The next number is the drive to be tested if test_it != 0. ``` -------------------------------- ### Calculate Elapsed Time (Linux) Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Calculates the elapsed time in seconds and centiseconds for Linux systems. It requires the start time as an argument. Modifies the global 'SECONDS', 'end_tenths', and 'end_time_display' variables. ```bash end_time_display=$(date +"%H:%M:%S.%2N") time_diff=$(($(date -d "$end_time_display" '+%s%2N') - $(date -d "$1" '+%s%2N'))) rev_time=$(echo $time_diff | rev) end_tenths=$(echo ${rev_time:0:2} | rev) end_time=$(echo ${rev_time:2} | rev) SECONDS=$end_time ``` -------------------------------- ### Log Drive Test Timing Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Appends start and end times, along with elapsed time, to a temporary log file for drive testing. Handles time formatting for both FreeBSD and Linux. ```bash (echo " "$start_time_display": START nvm_selftest") >> /tmp/drive_selftest/drive_test_timer_temp.txt ``` ```bash (echo " "$end_time_display": EXIT nvm_selftest" echo -n " Elapsed Time: $((SECONDS / 60)) minutes and $((SECONDS % 60))" if [[ $end_tenths != "" ]]; then echo ".$end_tenths seconds elapsed." else echo " seconds elapsed." fi echo " ") >> /tmp/drive_selftest/drive_test_timer_temp.txt ``` -------------------------------- ### Execute SMART Drive Tests Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Initiates SMART drive testing if the system is not in demo mode and is ready. It checks for expired tests and removes duplicates before proceeding. ```shell if [[ $Demo != "true" ]] && [[ $Ready_to_Test == "true" ]]; then # Ready_to_Test means the Short and Long drive schedules are complete and actual testing may start. # We need to not start the smart testing until after we process both Short and Long drive lists to test. if [[ $Short_Drives_Tested_Days_of_the_Week == *"$DOW"* ]] || [[ $Long_Drives_Tested_Days_of_the_Week == *"$DOW"* ]]; then # If Long tests are not authorized for this day, do not run remove_duplicate_tests. check_expired_drive_tests remove_duplicate_tests fi else # We have not processed the Long tests yet. Ready_to_Test="true" # This is good for the second pass now. fi ``` -------------------------------- ### Get API Drive Listings Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt A function to retrieve a list of all drives recognized by TrueNAS, including their model, serial number, and interface type. This function replaces previous drive listing methods. ```bash get_API_Drives () { if [[ $Debug_Steps == "true" ]]; then echo "get_API_Drives" | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi # Replaces all the drive listing procedures. # Input = Nothing # Output = List of each drive TrueNAS recognizes along with (within an array; Drive Name, Model, Serial Number, Interface Type) and the full Drive Query output. # # Global Variables: Debug, Drive_Disk_Query, smartdrives, drives_name[@], drives_serial[@], drives_subsystem[@], drives_model[@] # Local Variables: index, increment } ``` -------------------------------- ### Run NVMe Self-Test (FreeBSD) Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Initiates a self-test for NVMe drives using `nvmecontrol` on FreeBSD. Supports both short and long tests. Checks if the drive supports self-tests before execution. ```bash nvmecontrol selftest -c $smart_selftest "$drive" ``` -------------------------------- ### Update Drive Selftest Script Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Copies the new multi_report.sh file and sets execute permissions. Also copies the User Guide. This function is part of an update process that checks for GitHub availability. ```bash cp /tmp/Multi-Report/drive_selftest.txt $SCRIPT_DIR"/drive_selftest.sh" chmod 755 $SCRIPT_DIR"/drive_selftest.sh" > /dev/null 2<&1 # Copy the User Guide cp "/tmp/Multi-Report/Multi_Report_User_Guide.pdf" $SCRIPT_DIR"/." echo " " echo "Your script has been updated and a copy of the User Guide is current." UpdateDriveAvailable="false" # Remove this after the update has completed. ``` -------------------------------- ### Drive List Construction in Test Mode 2 Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Constructs a comma-separated list of drives to test when in 'Test_Mode 2' (All Testing). It iterates through the sorted drives and adds them to the list, handling line breaks for readability if the loop counter reaches the drive list length. ```bash while [ $Demo_loop -lt $Drive_Count ]; do Drive_List_Temp=$(echo $smartdrives_sorted | cut -d ' ' -f ${Demo_Track} | xargs) if [[ $Drive_List != *"${Drive_List_Temp}"* ]]; then if [[ $Demo_loop -eq 0 ]]; then Drive_List=$Drive_List_Temp else if [[ $loop_counter -eq $Drive_List_Length ]]; then Drive_List=$Drive_List",\n "$Drive_List_Temp loop_counter=0 else (( loop_counter ++ )) Drive_List=$Drive_List", "$Drive_List_Temp fi fi fi if [[ $Demo_Track -eq $Drive_Count ]]; then break; fi (( Demo_Track ++ )) (( Demo_loop ++ )) done ``` -------------------------------- ### Get Drive Power On Hours (POH) using JSON output Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Retrieves the Power On Hours (POH) for a drive by parsing the JSON output from smartctl. Exits with status 5 if POH data is unavailable. ```bash if [[ "$(smartctl -d "${driveConnectionType}" -a --json /dev/${checking_drives} | jq -Mre '.power_on_time.hours | values')" ]]; then POH="$(smartctl -d "${driveConnectionType}" -a --json /dev/${checking_drives} | jq -Mre '.power_on_time.hours | values')" else echo "No Power On Hours for Drive: ${checking_drives}" exit 5 fi ``` -------------------------------- ### Update Drive Selftest Script Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt This function handles the process of downloading and replacing the local drive selftest script with the latest version from GitHub. It removes old files, downloads new script and user guide files, and informs the user about the version changes. ```bash update_Drive_script () { if [[ $Debug_Steps == "true" ]]; then echo "update_Drive_script" | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi echo "Update Script Routine" echo "Removing Old Local Script if it exists" if test -e "/tmp/Multi-Report"; then rm -R "/tmp/Multi-Report"; fi echo "Downloading new script files" if [[ "$(curl -is https://github.com | head -n 1)" ]]; then # Go git the file ( mkdir /tmp/Multi-Report cd /tmp/Multi-Report curl -LJOs https://raw.githubusercontent.com/JoeSchmuck/Multi-Report/refs/heads/main/drive_selftest.txt curl -LJOs https://raw.githubusercontent.com/JoeSchmuck/Multi-Report/refs/heads/main/Multi_Report_User_Guide.pdf ) GitDriveVersion=$(cat "/tmp/Multi-Report/drive_selftest.txt" | grep "##### Version" | cut -d 'n' -f2 | tr -d ' ' | head -1) LocalDriveFilename=$(cat $SCRIPT_DIR"/drive_selftest.sh" | grep "##### Version" | cut -d 'n' -f2 | tr -d ' ' | head -1) echo " " echo " - Drive_Selftest current version is: "$LocalDriveFilename echo " - The Github version is: "$GitDriveVersion echo " " if [[ $Automatic_Selftest_Update != "enable" ]]; then echo "Enter 'y' to commit or any other key to abort." read Keyboard_yn else echo "Automatic Update is Enabled..." ``` -------------------------------- ### SMR Detection and Drive Ignore List Configuration Source: https://context7.com/joeschmuck/multi-report/llms.txt Enable SMR detection and configure settings for new drive detection counts. Specify drives to ignore by serial number. ```bash ##### SMR DETECTION ##### SMR_Enable="enable" SMR_Update="enable" SMR_Ignore_Alarm="disable" SMR_New_Drive_Det_Count=14 # Check SMR for first 14 runs after drive is seen ##### DISK LAYOUT (SCALE only) ##### Disklayout="enable" High_Contrast="false" ##### DRIVE IGNORE LIST ##### # Ignore_Drives_List="SERIALNUM1,SERIALNUM2" Ignore_Drives_List="" ``` -------------------------------- ### Configure Statistical Data File Source: https://context7.com/joeschmuck/multi-report/llms.txt Set up the path, enable/disable data recording and emailing, and configure purging and email day for the statistical data CSV file. ```bash # Configure in multi_report_config.txt: statistical_data_file="/mnt/tank/scripts/statisticalsmartdata.csv" SDF_DataRecordEnable="enable" SDF_DataEmail="enable" SDF_DataPurgeDays=730 # Purge records older than 730 days (2 years) SDF_DataEmailDay="Mon" # Email the CSV every Monday ``` -------------------------------- ### Initialize Drive Test Variables Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Initializes variables used for tracking drive tests, including counters, lists, and temporary storage. ```bash DOW_temp=$DOW # Use a temporary variable to add/subtract with. drives_to_list="" # Listing a grouping of drive ids. total_drives_tested_per_day=0 # Might be able to use a fixed number vice a variable. sum_drives_test=0 # Total of drives tested? day_of_month=1 # Set the first of the month. loop_counter=0 # Just a counter. array_location=1 # Presetting the variable drives_tested_demo="" echo " " ``` -------------------------------- ### Configure Demo Mode Test Parameters Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt When the '-demo' flag is set, this block iterates through command-line arguments to set flags for different test types and durations. It also enforces constraints on test period and SMART testing order. ```bash if [[ $Demo == "true" ]]; then counter_loop=0 while [ $counter_loop -lt 20 ]; do # Check for any order of the CLI switches ONLY if -demo is present. if [[ $1 == "short" ]]; then short_cli=1; fi if [[ $1 == "long" ]]; then long_cli=1; fi if [[ $1 == "week" ]]; then week_cli=1; fi if [[ $1 == "month" ]]; then month_cli=1; fi if [[ $1 == "DriveID" ]]; then DriveID_cli=1; fi if [[ $1 == "Serial" ]]; then Serial_cli=1; fi if [[ $1 == "1" ]]; then x1_cli=1; fi if [[ $1 == "2" ]]; then x2_cli=1; fi if [[ $1 == "3" ]]; then x3_cli=1; fi shift 1 # rotate $1 value (( counter_loop ++ )) done # Not two of the opposite values if [[ $week_cli -eq 1 ]] && [[ $short_cli -eq 1 ]]; then Long_Drives_Test_Period="Week"; fi if [[ $week_cli -eq 1 ]] && [[ $long_cli -eq 1 ]]; then Long_Drives_Test_Period="Week"; fi if [[ $month_cli -eq 1 ]] && [[ $short_cli -eq 1 ]]; then Short_Drives_Test_Period="Month"; fi if [[ $month_cli -eq 1 ]] && [[ $long_cli -eq 1 ]]; then Long_Drives_Test_Period="Month"; fi if [[ $DriveID_cli -eq 1 ]] && [[ $short_cli -eq 1 ]]; then Short_SMART_Testing_Order="DriveID"; fi if [[ $DriveID_cli -eq 1 ]] && [[ $long_cli -eq 1 ]]; then Long_SMART_Testing_Order="DriveID"; fi if [[ $Serial_cli -eq 1 ]] && [[ $short_cli -eq 1 ]]; then Short_SMART_Testing_Order="Serial"; fi if [[ $Serial_cli -eq 1 ]] && [[ $long_cli -eq 1 ]]; then Long_SMART_Testing_Order="Serial"; fi if [[ $short_cli -eq 1 ]]; then Short_Test_Mode=1; Long_Test_Mode=3; fi if [[ $long_cli -eq 1 ]]; then Short_Test_Mode=3; Long_Test_Mode=1; fi if [[ $x1_cli -eq 1 ]] && [[ $short_cli -eq 1 ]]; then Short_Test_Mode=1; Long_Test_Mode=3; (( x_cli ++ )); fi if [[ $x2_cli -eq 1 ]] && [[ $short_cli -eq 1 ]]; then Short_Test_Mode=2; Long_Test_Mode=3; (( x_cli ++ )); fi if [[ $x3_cli -eq 1 ]] && [[ $short_cli -eq 1 ]]; then Short_Test_Mode=3; Long_Test_Mode=3; (( x_cli ++ )); fi if [[ $x1_cli -eq 1 ]] && [[ $long_cli -eq 1 ]]; then Long_Test_Mode=1; Short_Test_Mode=3; (( x_cli ++ )); fi if [[ $x2_cli -eq 1 ]] && [[ $long_cli -eq 1 ]]; then Long_Test_Mode=2; Short_Test_Mode=3; (( x_cli ++ )); fi if [[ $x3_cli -eq 1 ]] && [[ $long_cli -eq 1 ]]; then Long_Test_Mode=3; Short_Test_Mode=3; (( x_cli ++ )); fi ``` -------------------------------- ### Test Mode 1 and Troubleshooting Help Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt This script provides a short test in Test Mode 1, displaying the dates of future tests. It prompts the user to press 'Y' to access troubleshooting help or any other key to exit. ```bash echo "a short test in Test Mode 1, providing you the dates they would be tested." echo " " echo "To read the Troubleshooting Help pages, Press 'Y'" echo "Press any other key to exit" read -s -n 1 key_input if [[ $key_input == "y" ]] || [[ $key_input == "Y" ]]; then troubleshooting_help; fi exit 0 ``` -------------------------------- ### Configure Logging Directory Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Creates the log directory if it doesn't exist. If creation fails, it defaults to the script's directory. Logging is confirmed if not in silent mode. ```bash if [[ $Enable_Logging == "enable" ]]; then if ! test -e "$LOG_DIR"; then echo "'"$LOG_DIR"' does not exist, attempting to create it..." | tee -a /tmp/drive_selftest/drive_test_temp.txt /tmp/drive_selftest/drive_test_timer_temp.txt mkdir $LOG_DIR if test -e "$LOG_DIR"; then echo "Success" | tee -a /tmp/drive_selftest/drive_test_temp.txt /tmp/drive_selftest/drive_test_timer_temp.txt else echo "Failed to create '"$LOG_DIR"', using script default directory of "$SCRIPT_DIR | tee -a /tmp/drive_selftest/drive_test_temp.txt /tmp/drive_selftest/drive_test_timer_temp.txt LOG_DIR=$SCRIPT_DIR fi fi if [[ $Silent != "enable" ]]; then echo " " echo "Logging Enabled" | tee -a /tmp/drive_selftest/drive_test_temp.txt /tmp/drive_selftest/drive_test_timer_temp.txt fi fi ``` -------------------------------- ### Enable High-Contrast Mode for Accessibility Source: https://context7.com/joeschmuck/multi-report/llms.txt Activate high-contrast mode for the Disk Layout visualization to improve accessibility. ```bash # High-contrast mode for accessibility: High_Contrast="true" ``` -------------------------------- ### Display Help Text - Bash Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt This function displays detailed help information for the drive_selftest script, including configuration options and command-line switches. It is called when the script needs to present usage instructions to the user. ```bash help_text () { if [[ $Debug_Steps == "true" ]]; then echo "help_text" | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi clear echo "SMART Drive Self-test Script: "$Version" "$Version_Date echo "Standalone or Companion to Multi-Report 3.1 and later." echo " " echo "For Standalone Operation (not using multi_report_config.txt file)," echo "edit lines (around line 110) '######### USER SETTINGS #########' as desired." echo " " echo "There are six significant groups of variables: Automatic Update, Short tests, Long tests," echo "SCRUB/RESILVER, Ignore Drives, and Reports." echo " " echo "Open this file up in a simple text editor to view the configuration notes, starts on line 110'ish." echo "NOTE: If you edit this file and it states the file cannot be run, ensure your text editor" echo "did not end each line with 'CRLF'. All lines should end with 'LF'." echo " " echo "Automatic Updates will allow the drive_selftest.sh file to be updated should it be out of date." echo " " echo "This script can use the multi_report_config.txt file when combined with Multi-Report." echo "You must configure these settings in Multi-Report, otherwise the values at the beginning" echo "of this script will be used." echo " " echo "Short and Long tests are configured as follows:" echo " " echo " Test_Mode: 1 = Use Short(or Long) Drives_to_Test_Per_Day value" echo " 2 = All Drives Tested (Ignores other options except when active)" echo " 3 = No Drives Tested" echo " " echo " Time_Delay_Between_Drives: Tests will have a XX second delay between the" echo " drives starting testing." echo " " echo " Short_Drives_Test_Delay: Time period in seconds to wait for SHORT tests to complete." echo " Default is 130 seconds for use with Multi-Report, if not then set to 1 second." echo " " echo "BELOW OPTIONS ARE USED ONLY WITH Test Mode 1" echo "--------------------------------------------" echo " " echo ' SMART_Testing_Order: Select "DriveID" or "Serial" sorting order.' echo " " echo " Drives_to_Test_Per_Day: How many drives to run each day minimum." echo " The script will auto-correct if you choose too small of a value." echo " " echo ' Drives_Test_Period: Options are "Week" (Mon-Sun) or "Month" (days 1 - 28)' echo " " echo " Drives_Tested_Days_of_the_Week: Days of the week allowed to run:" echo ' 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat, 7=Sun Default = "1,2,3,4,5,6,7"' echo " " echo "Press Any Key to Continue" read -s -n 1 key_input echo "--------------------------------------------------------------------------" echo " " echo "Missed Drive Catchup Feature" echo "----------------------------" echo " " echo " This feature was added to enable catching up on any S.M.A.R.T. Long tests for" echo " drives that were missed because the script was not being run every day." echo " The default setting is to make up one extra drive per day." echo " You may change this setting to 0 (zero) to disable this feature," echo "or increase the value as desired." echo " " echo " " echo "NORMAL OPERATION DOES NOT REQUIRE ANY COMMAND LINE SWITCHES" echo "-----------------------------------------------------------" echo " " echo "Command Line Switches:" echo "NOTE! The demo mode uses the 'Drives_Tested_Days_of_the_Week' value to" echo "calculate how many drives are to be run on which days of the week." echo "If the demo results are not the desired effect, adjust the values." echo " " echo " '-update' --- Will download the current published version of this script." echo " " echo " '-timer' --- Generates a file which tracks how many seconds are utilized" echo " for each routine within the script. Used for development." echo " " echo " '-demo' '[short|long]' '[1|2|3]' '[week|month]' '[driveid|serial]'" echo " Lists full drive testing schedule." echo " Use short or long options to focus on one list." echo " Override Settings will not use the script set values." echo " Test Mode using '1','2', or '3'." echo " Testing Period 'week' or 'month'." echo " " echo " '-clearlog' --- Delete all the drive_selftest log files." echo " " echo " '-debug' --- Runs the script in Debug Mode" echo " " echo "Example: drive_selftest -demo short 1 week serial" echo " Means: Simulate Short SMART Test, Test Mode 1 to spread across a Week" echo " and using the days of the week set in the script setup." echo " " echo "Example: drive_selftest -demo short" echo " Means: Simulate a Short SMART Test using the current configured settings" echo " " echo "This will provide a listing of how your drives would be tested for" ``` -------------------------------- ### Troubleshooting Help Function Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt This function provides guidance for users encountering errors or unexpected behavior during drive testing. It explains common problem messages, non-problematic messages, and provides contact information for support. ```bash troubleshooting_help () { if [[ $Debug_Steps == "true" ]]; then echo "troubleshooting_help" | tee -a /tmp/drive_selftest/drive_test_temp.txt; fi clear echo "TROUBLESHOOTING HELP Script Version: "$Version" "$Version_Date echo "You are running on "$programver echo " " echo "This section will attempt to help you define and solve any error messages" echo "in which you may encounter." echo " " echo "First: What is a problem message?" echo " 1. If you see an error message about exit code that is other than zero (0)." echo " 2. If you notice drives are being tested in an improper sequence." echo " 3. Any script failure messages." echo " " echo "Second: What is not a problem message?" echo " 1. Any message by the ROBOT. These are informational letting you know" echo " that you entered an unsustainable variable and ROBOT made an" echo " adjustment to ensure all drives are testing in the configured time frame." echo " 2. 'Skipping drive' means the drive was already in test." echo " 3. Days being skipped in '-demo' mode. First check your Authorized Days" echo " to run the test, odds are you are missing the week days not included." echo " " echo " " echo "Press Any Key to Continue" read -s -n 1 key_input echo "--------------------------------------------------------------------------" echo " " echo "If you are virtualizing a drive, this script removes virtual drives." echo "You will need to pass through the controller or run bare metal." echo "Even real drives passed through as RDM (ESXi) will be seen as Virtual." echo " " echo "If you feel the script is taking too long, then use the '-timer' switch" echo "to generate a file with timing information, located in the log directory" echo "with all the other logs. Joe needs that if you think there is a problem." echo " " echo "For any other failures, contact Joe at joeschmuck2023@hotmail.com with" echo "the following details: A copy of the log data file(s). If you feel a few" echo "earlier log data files would help, send those as well, and any other" echo "information you feel is relevant. While there is a such thing as too much" echo "data, I'd rather have more than less." echo " " echo "--- Be patient as I will answer as soon as I see the email, I am not glued" echo "to my computer and have a life. I may ask you to perform a few commands" echo "to help troubleshoot the issue." echo " " echo "Five Waka Waka Jokes: https://www.youtube.com/watch?v=rDpUAqQPnzM" echo "If you are bored" } ``` -------------------------------- ### Drive Summary and Timer Logging Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Logs a summary of drive counts, including ignored and virtual drives, and records the exit time and elapsed time for the 'get_API_Drives' function to a temporary timer file. ```bash skip_drives_ignore="Ignored: "${skip_drives_ignore:1} skip_drives_virtual="Virtual: "${skip_drives_virtual:1} (echo " Good Drive Count: "$drives_count if [[ $skip_drives_ignore != "" || $skip_drives_virtual != "" ]]; then echo " Drives Removed: "$skip_drives_count" : "$skip_drives_virtual", "$skip_drives_ignore; fi if [[ $softver != "Linux" ]]; then end_time_display=$(date '+%H:%M:%S') else elapsed_time $start_time_display fi echo " "$end_time_display": EXIT get_API_Drives" echo -n " Elapsed Time: $((SECONDS / 60)) minutes and $((SECONDS % 60))" if [[ $end_tenths != "" ]]; then echo ".$end_tenths seconds elapsed." else echo " seconds elapsed." fi echo " ") >> /tmp/drive_selftest/drive_test_timer_temp.txt ``` -------------------------------- ### Demo Mode Activation in Drive Selftest Source: https://github.com/joeschmuck/multi-report/blob/main/drive_selftest.txt Activates demo mode if the first argument is '-demo'. In demo mode, it prints a simulated testing schedule and appends it to a temporary log file. ```bash if [[ $1 == "-demo" ]]; then Demo="true" echo "Demo Mode: Below is the simulated testing schedule based on current settings." echo " " (echo "Demo Mode: Below is the simulated testing schedule based on current settings." echo " ") >> /tmp/drive_selftest/drive_test_temp.txt fi ```