Skip to content

Testing — System Health Monitor

Testing a monitoring script requires both verifying normal operation and simulating alert conditions.

Basic Smoke Test

Run the script manually and check its exit code:

cd ~/projects/health-monitor
bash health_check.sh
echo "Exit code: $?"

Expected output:

[2024-01-15 09:30:00] [INFO ] === Health check started on my-server === [2024-01-15 09:30:00] [INFO ] Disk / OK: 45% (threshold: 85%) [2024-01-15 09:30:00] [INFO ] Memory OK: 62% (threshold: 80%) [2024-01-15 09:30:00] [INFO ] CPU load OK: 0.42 (threshold: 4.0) [2024-01-15 09:30:00] [INFO ] === All systems normal === Exit code: 0

Test Alert Triggering

Temporarily lower a threshold to force an alert:

# Override threshold inline — don't edit the config file
THRESHOLD_DISK=1 bash health_check.sh

Expected output:

[2024-01-15 09:30:05] [INFO ] === Health check started on my-server === [2024-01-15 09:30:05] [ALERT] Disk / at 45% — threshold 1% exceeded [2024-01-15 09:30:05] [INFO ] Memory OK: 62% (threshold: 80%) [2024-01-15 09:30:05] [INFO ] CPU load OK: 0.42 (threshold: 4.0) [2024-01-15 09:30:05] [WARN ] === 1 alert(s) triggered ===

Test Each Function Independently

# Source the script without running main
# (requires main to be guarded: [[ "${BASH_SOURCE[0]}" == "$0" ]] && main "$@")
source health_check.sh

# Now test individual functions
get_disk_pct          # should print a number
get_mem_pct           # should print a number
get_cpu_load          # should print a decimal

check_metric "Disk" "45" "85" "%"    # should log INFO and return 0
check_metric "Disk" "95" "85" "%"    # should log ALERT and return 1
echo "Return code: $?"

To support source testing, add this guard at the bottom of your script:

# Replace: main "$@"
# With:
[[ "${BASH_SOURCE[0]}" == "$0" ]] && main "$@"

Test Log Rotation

# Fill the log beyond LOG_MAX_LINES
for i in $(seq 1 1100); do
    echo "[test] line $i" >> ~/projects/health-monitor/logs/health_check.log
done

wc -l ~/projects/health-monitor/logs/health_check.log
# Should show: 1100 ...

# Run the script — rotation should trim it
bash health_check.sh
wc -l ~/projects/health-monitor/logs/health_check.log
# Should show <= 1000 ...

Test the Cron Environment

The most common failure mode is the script working on the command line but failing in cron because $PATH is different. Test this explicitly:

# Simulate cron's minimal environment
env -i HOME="$HOME" PATH="/usr/bin:/bin" bash health_check.sh

If this fails while the normal run succeeds, you have a $PATH dependency. Fix it by using absolute paths for all commands (/usr/bin/awk, /bin/df, etc.) or adding this to the top of your script:

export PATH="/usr/local/bin:/usr/bin:/bin"

Test Error Cases

# What happens if the log directory doesn't exist?
LOGFILE=/nonexistent/path/test.log bash health_check.sh

# What happens if the config file has a syntax error?
echo "THRESHOLD_DISK=bad value" >> health_check.conf
bash health_check.sh
# Restore config afterwards

Checklist

□ Script runs without errors □ Low threshold triggers ALERT log line □ All metrics appear in log □ Log rotation trims file correctly □ Script works with cron's minimal $PATH □ Missing config file uses sensible defaults □ Interrupted with Ctrl+C leaves no temp files □ shellcheck health_check.sh returns 0 warnings

implementation | enhancements