audit echo vs log across all scripts — outcomes always visible, verbose for per-item loops
This commit is contained in:
+385
@@ -0,0 +1,385 @@
|
||||
#!/bin/bash
|
||||
# ==============================================================================================
|
||||
# ============================= Health Digest ==================================================
|
||||
# ==============================================================================================
|
||||
#
|
||||
# PURPOSE
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Full ecosystem health aggregation from existing state files. Scheduled daily
|
||||
# (8am). DIGEST_PROFILE controls when notifications actually send — the cron
|
||||
# schedule never changes, only the profile in master.conf.
|
||||
#
|
||||
# Reads state files from across the system (watchdog strikes, fallback state,
|
||||
# skip list, bandwidth history, transcode stats, cert status) and compiles them
|
||||
# into a single digest. Reads only — writes nothing, changes nothing.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# OPERATIONAL MODEL
|
||||
# ==============================================================================================
|
||||
#
|
||||
# Three profiles — switch by changing DIGEST_PROFILE in master.conf:
|
||||
#
|
||||
# always — sends every run regardless of findings
|
||||
# Use: daily digest of everything, even when healthy
|
||||
#
|
||||
# smart — sends only when something worth reporting was found
|
||||
# Stays silent on clean days. DIGEST_SMART_ON_* toggles control
|
||||
# what triggers a send — all independently configurable.
|
||||
#
|
||||
# weekly — sends once per week on DIGEST_DAY (default Sunday), silent all other days
|
||||
# Use: one weekly summary without daily noise
|
||||
#
|
||||
# Data sources (reads only):
|
||||
# FALLBACK_STATE_FILE — current fallback state
|
||||
# DOCKER_WATCHDOG_FAILED_FILE — container skip list (manual intervention needed)
|
||||
# WATCHDOG_STATE_FILE — active container watchdog strikes
|
||||
# SYS_WATCHDOG_STATE_FILE — active system watchdog strikes
|
||||
# BANDWIDTH_LOG — yesterday's transfer totals
|
||||
# TRANSCODE_DAILY_LOG — weekly transcode statistics
|
||||
# CERT_MONITOR_DOMAINS — live SSL cert check via openssl
|
||||
# RAMDISK_PATH / TRANSCODE_LINK — current transcode location and usage
|
||||
#
|
||||
# ==============================================================================================
|
||||
# OPERATIONAL SAFEGUARDS
|
||||
# ==============================================================================================
|
||||
#
|
||||
# Single Instance Lock
|
||||
# acquire_lock prevents duplicate reports — report generation takes time.
|
||||
#
|
||||
# Per-Host Variables
|
||||
# detect_hosts() aliases CERT_MONITOR_DOMAINS, RAMDISK_WARN_GB, RAMDISK_SIZE,
|
||||
# RAMDISK_LOW_GB, and all other host-specific vars used in the report.
|
||||
#
|
||||
# Per-Section Guards
|
||||
# Each data source section checks whether its state file exists before reading.
|
||||
# A missing state file is skipped cleanly — it does not abort the report.
|
||||
#
|
||||
# Silent Smart Profile
|
||||
# smart profile produces no output and no notification when nothing worth
|
||||
# reporting is found.
|
||||
#
|
||||
# Notifications Validated
|
||||
# platform_require_cmd confirms notify and openssl are present before use.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================================
|
||||
#
|
||||
# master.conf
|
||||
#
|
||||
# DIGEST_PROFILE
|
||||
# Notification frequency: always | smart | weekly. (default: weekly)
|
||||
#
|
||||
# DIGEST_DAY
|
||||
# Day name for weekly profile — must match `date +%A` output. (default: Sunday)
|
||||
#
|
||||
# DIGEST_SMART_ON_WATCHDOG
|
||||
# Send smart profile notification if any active watchdog strikes. (default: true)
|
||||
#
|
||||
# DIGEST_SMART_ON_FALLBACK
|
||||
# Send smart profile notification if fallback state is not NORMAL. (default: true)
|
||||
#
|
||||
# DIGEST_SMART_ON_CERT_WARN
|
||||
# Send smart profile notification if any cert is within CERT_WARN_DAYS. (default: true)
|
||||
#
|
||||
# DIGEST_SMART_ON_BANDWIDTH
|
||||
# Send smart profile notification if any transfer exceeded BANDWIDTH_WARN_GB. (default: true)
|
||||
#
|
||||
# CERT_WARN_DAYS / CERT_CRIT_DAYS / CERT_TIMEOUT
|
||||
# Cert check thresholds — shared with cert_monitor.sh.
|
||||
#
|
||||
# BANDWIDTH_WARN_GB
|
||||
# High-transfer threshold — shared with bandwidth_monitor.sh.
|
||||
#
|
||||
# TRANSCODE_DAILY_LOG
|
||||
# Path to the transcode statistics log.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# RUNTIME MODES
|
||||
# ==============================================================================================
|
||||
#
|
||||
# weekly_health_digest.sh
|
||||
# Run digest. DIGEST_PROFILE determines whether a notification is sent.
|
||||
#
|
||||
# weekly_health_digest.sh --dry-run
|
||||
# Generate and display digest output. No notification sent regardless of profile.
|
||||
#
|
||||
# weekly_health_digest.sh --status
|
||||
# Show profile, day, and smart trigger configuration. Then exit.
|
||||
#
|
||||
# weekly_health_digest.sh --log
|
||||
# Verbose per-section output during digest generation.
|
||||
#
|
||||
# ==============================================================================================
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
source "$SCRIPT_DIR/../load_config.sh"
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
# ==============================================================================================
|
||||
# ━━━ Setup ━━━
|
||||
# ==============================================================================================
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
error "Must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
platform_require_cmd \
|
||||
"/usr/local/emhttp/plugins/dynamix/scripts/notify" \
|
||||
"" "" \
|
||||
"unRAID notify script" || warn "unRAID notify script not found — native notifications disabled"
|
||||
|
||||
platform_require_cmd \
|
||||
"$(command -v openssl 2>/dev/null || echo /usr/bin/openssl)" \
|
||||
"version" "OpenSSL" \
|
||||
"openssl" || warn "openssl not found — SSL cert checks will be skipped"
|
||||
|
||||
acquire_lock
|
||||
|
||||
# detect_hosts() sets MY_ID and aliases all host-specific vars used in this report
|
||||
detect_hosts
|
||||
|
||||
log "$ICON_GEAR Config: profile=${DIGEST_PROFILE} day=${DIGEST_DAY}"
|
||||
log "$ICON_GEAR Smart triggers: watchdog=${DIGEST_SMART_ON_WATCHDOG} fallback=${DIGEST_SMART_ON_FALLBACK} cert=${DIGEST_SMART_ON_CERT_WARN} bandwidth=${DIGEST_SMART_ON_BANDWIDTH}"
|
||||
|
||||
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — report generated but no notification sent"
|
||||
|
||||
# ==============================================================================================
|
||||
# ━━━ Status ━━━
|
||||
# ==============================================================================================
|
||||
if [[ "$SHOW_STATUS" == true ]]; then
|
||||
echo ""
|
||||
echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━"
|
||||
echo "$ICON_HOST Identity: $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
echo "$ICON_DIGEST Profile: $DIGEST_PROFILE"
|
||||
echo "$ICON_DIGEST Digest day: $DIGEST_DAY"
|
||||
echo "$ICON_DIGEST Smart triggers: watchdog=$DIGEST_SMART_ON_WATCHDOG fallback=$DIGEST_SMART_ON_FALLBACK cert=$DIGEST_SMART_ON_CERT_WARN bandwidth=$DIGEST_SMART_ON_BANDWIDTH"
|
||||
echo "$ICON_CERT Cert domains: ${CERT_MONITOR_DOMAINS[*]:-none}"
|
||||
echo "$ICON_BANDWIDTH Bandwidth warn: ${BANDWIDTH_WARN_GB}GB"
|
||||
echo "$ICON_GEAR Dry Run: $DRY_RUN"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ==============================================================================================
|
||||
# ── Profile gate — should we send today? ──────────────────────────────────────────────────────
|
||||
# ==============================================================================================
|
||||
SHOULD_SEND=false
|
||||
|
||||
case "$DIGEST_PROFILE" in
|
||||
always)
|
||||
SHOULD_SEND=true
|
||||
log "Profile: always — will send"
|
||||
;;
|
||||
weekly)
|
||||
TODAY_NAME=$(date '+%A')
|
||||
if [[ "$TODAY_NAME" == "$DIGEST_DAY" ]]; then
|
||||
SHOULD_SEND=true
|
||||
log "Profile: weekly — today is $DIGEST_DAY — will send"
|
||||
else
|
||||
echo "Profile: weekly — today is $TODAY_NAME, digest day is $DIGEST_DAY — no-op"
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
smart)
|
||||
log "Profile: smart — evaluating findings before deciding"
|
||||
SHOULD_SEND=false
|
||||
;;
|
||||
*)
|
||||
warn "Unknown DIGEST_PROFILE: $DIGEST_PROFILE — defaulting to weekly"
|
||||
TODAY_NAME=$(date '+%A')
|
||||
[[ "$TODAY_NAME" == "$DIGEST_DAY" ]] && SHOULD_SEND=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# ==============================================================================================
|
||||
# ── Data Gathering ────────────────────────────────────────────────────────────────────────────
|
||||
# ==============================================================================================
|
||||
FINDINGS=() # notable but not critical
|
||||
ISSUES=() # need attention
|
||||
DIGEST_LINES=() # full report lines
|
||||
|
||||
# ── fallback State ────────────────────────────────────────────────────────────────────────────
|
||||
log "Reading: fallback=$FALLBACK_STATE_FILE skip=$DOCKER_WATCHDOG_FAILED_FILE watchdog=$WATCHDOG_STATE_FILE sys=$SYS_WATCHDOG_STATE_FILE"
|
||||
if [[ -f "$FALLBACK_STATE_FILE" ]]; then
|
||||
FALLBACK_STATE=$(grep "^state=" "$FALLBACK_STATE_FILE" 2>/dev/null | cut -d= -f2)
|
||||
if [[ -n "$FALLBACK_STATE" ]]; then
|
||||
DIGEST_LINES+=("$ICON_FALLBACK Fallback: $FALLBACK_STATE")
|
||||
if [[ "$FALLBACK_STATE" != "NORMAL" ]]; then
|
||||
ISSUES+=("Fallback state: $FALLBACK_STATE")
|
||||
[[ "$DIGEST_SMART_ON_FALLBACK" == true ]] && SHOULD_SEND=true
|
||||
fi
|
||||
fi
|
||||
else
|
||||
DIGEST_LINES+=("$ICON_FALLBACK Fallback: state file not found")
|
||||
fi
|
||||
|
||||
# ── Container Skip List ───────────────────────────────────────────────────────────────────────
|
||||
if [[ -f "$DOCKER_WATCHDOG_FAILED_FILE" ]] && [[ -s "$DOCKER_WATCHDOG_FAILED_FILE" ]]; then
|
||||
SKIP_COUNT=$(wc -l < "$DOCKER_WATCHDOG_FAILED_FILE")
|
||||
SKIP_LIST=$(cat "$DOCKER_WATCHDOG_FAILED_FILE" | tr '\n' ' ')
|
||||
DIGEST_LINES+=("$ICON_NOT_RUNNING Skip list: $SKIP_COUNT containers — $SKIP_LIST")
|
||||
ISSUES+=("Containers on skip list (manual intervention needed): $SKIP_LIST")
|
||||
SHOULD_SEND=true
|
||||
else
|
||||
DIGEST_LINES+=("$ICON_RUNNING Skip list: empty ✅")
|
||||
fi
|
||||
|
||||
# ── Container Watchdog Strikes ────────────────────────────────────────────────────────────────
|
||||
if [[ -f "$WATCHDOG_STATE_FILE" ]]; then
|
||||
ACTIVE_STRIKES=$(grep -v ":0$" "$WATCHDOG_STATE_FILE" 2>/dev/null | grep -c ".")
|
||||
if [[ "$ACTIVE_STRIKES" -gt 0 ]]; then
|
||||
STRIKE_LIST=$(grep -v ":0$" "$WATCHDOG_STATE_FILE" 2>/dev/null | tr '\n' ' ')
|
||||
DIGEST_LINES+=("$ICON_WATCHDOG Container strikes: $ACTIVE_STRIKES active — $STRIKE_LIST")
|
||||
FINDINGS+=("Container watchdog: $ACTIVE_STRIKES active strikes")
|
||||
[[ "$DIGEST_SMART_ON_WATCHDOG" == true ]] && SHOULD_SEND=true
|
||||
else
|
||||
DIGEST_LINES+=("$ICON_WATCHDOG Container watchdog: no active strikes ✅")
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── System Watchdog Strikes ───────────────────────────────────────────────────────────────────
|
||||
if [[ -f "$SYS_WATCHDOG_STATE_FILE" ]]; then
|
||||
SYS_STRIKES=$(grep "^[^=]*:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -cv -E "(:0$|:false$)")
|
||||
if [[ "$SYS_STRIKES" -gt 0 ]]; then
|
||||
SYS_STRIKE_LIST=$(grep "^[^=]*:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -v -E "(:0$|:false$)" | tr '\n' ' ')
|
||||
DIGEST_LINES+=("$ICON_REBOOT_SMART System strikes: $SYS_STRIKES active — $SYS_STRIKE_LIST")
|
||||
FINDINGS+=("System watchdog: $SYS_STRIKES active strikes")
|
||||
[[ "$DIGEST_SMART_ON_WATCHDOG" == true ]] && SHOULD_SEND=true
|
||||
else
|
||||
DIGEST_LINES+=("$ICON_REBOOT_SMART System watchdog: no active strikes ✅")
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Transcode Ramdisk ─────────────────────────────────────────────────────────────────────────
|
||||
if mountpoint -q "$RAMDISK_PATH" 2>/dev/null; then
|
||||
RAMDISK_USED_KB=$(df "$RAMDISK_PATH" --output=used 2>/dev/null | tail -1 | tr -d ' ')
|
||||
RAMDISK_USED_GB=$(awk "BEGIN {printf \"%.2f\", ${RAMDISK_USED_KB:-0} / 1048576}")
|
||||
SYMLINK_TARGET=$(readlink "$TRANSCODE_LINK" 2>/dev/null || echo "unknown")
|
||||
DIGEST_LINES+=("$ICON_RAM Transcodes: ${RAMDISK_USED_GB}GB used → $SYMLINK_TARGET")
|
||||
|
||||
# Weekly transcode stats from TRANSCODE_DAILY_LOG
|
||||
if [[ -f "${TRANSCODE_DAILY_LOG:-}" ]]; then
|
||||
WEEK_CUTOFF=$(date -d "7 days ago" '+%Y-%m-%d')
|
||||
WEEK_PEAK=$(awk -F'|' -v c="$WEEK_CUTOFF" \
|
||||
'$1>=c{if($2>max)max=$2} END{printf "%.2f",max+0}' "$TRANSCODE_DAILY_LOG")
|
||||
WEEK_FLIPS=$(awk -F'|' -v c="$WEEK_CUTOFF" \
|
||||
'$1>=c{sum+=$3} END{print sum+0}' "$TRANSCODE_DAILY_LOG")
|
||||
WEEK_RAM=$(awk -F'|' -v c="$WEEK_CUTOFF" \
|
||||
'$1>=c{sum+=$4} END{print sum+0}' "$TRANSCODE_DAILY_LOG")
|
||||
WEEK_SSD=$(awk -F'|' -v c="$WEEK_CUTOFF" \
|
||||
'$1>=c{sum+=$5} END{print sum+0}' "$TRANSCODE_DAILY_LOG")
|
||||
WEEK_FILES=$(awk -F'|' -v c="$WEEK_CUTOFF" \
|
||||
'$1>=c{sum+=$6} END{print sum+0}' "$TRANSCODE_DAILY_LOG")
|
||||
|
||||
DIGEST_LINES+=("$ICON_RAM Transcode week: peak ${WEEK_PEAK}GB | flips: $WEEK_FLIPS | sessions: ${WEEK_RAM} ramdisk / ${WEEK_SSD} SSD | cleaned: ${WEEK_FILES} files")
|
||||
|
||||
PEAK_INT=$(printf "%.0f" "$WEEK_PEAK")
|
||||
WARN_INT=$(printf "%.0f" "${RAMDISK_WARN_GB:-6.8}")
|
||||
if [[ "$PEAK_INT" -ge "$WARN_INT" ]]; then
|
||||
DIGEST_LINES+=("$ICON_WARN Peak ${WEEK_PEAK}GB near threshold ${RAMDISK_WARN_GB}GB — consider increasing HOST*_RAMDISK_SIZE")
|
||||
FINDINGS+=("Transcode ramdisk near threshold: ${WEEK_PEAK}GB / ${RAMDISK_WARN_GB}GB")
|
||||
fi
|
||||
fi
|
||||
else
|
||||
DIGEST_LINES+=("$ICON_RAM Transcodes: ramdisk not mounted")
|
||||
ISSUES+=("Ramdisk not mounted at $RAMDISK_PATH")
|
||||
SHOULD_SEND=true
|
||||
fi
|
||||
|
||||
# ── Bandwidth ─────────────────────────────────────────────────────────────────────────────────
|
||||
# Updated for new log format: date|time|profile|duration|status|bytes|warn_flag
|
||||
if [[ -f "${BANDWIDTH_LOG:-}" ]] && [[ -s "$BANDWIDTH_LOG" ]]; then
|
||||
YESTERDAY=$(date -d "yesterday" '+%Y-%m-%d')
|
||||
YESTERDAY_BYTES=$(awk -F'|' -v d="$YESTERDAY" '$1==d{sum+=$6} END{print sum+0}' \
|
||||
"$BANDWIDTH_LOG")
|
||||
YESTERDAY_GB=$(awk "BEGIN {printf \"%.2f\", ${YESTERDAY_BYTES:-0} / 1073741824}")
|
||||
YESTERDAY_LARGE=$(awk -F'|' -v d="$YESTERDAY" '$1==d && $7=="LARGE"' \
|
||||
"$BANDWIDTH_LOG" | wc -l)
|
||||
|
||||
if [[ "${YESTERDAY_LARGE:-0}" -gt 0 ]]; then
|
||||
DIGEST_LINES+=("$ICON_BANDWIDTH Yesterday: ${YESTERDAY_GB}GB — $YESTERDAY_LARGE large transfer(s) exceeded ${BANDWIDTH_WARN_GB}GB")
|
||||
FINDINGS+=("High bandwidth day: ${YESTERDAY_GB}GB transferred")
|
||||
[[ "$DIGEST_SMART_ON_BANDWIDTH" == true ]] && SHOULD_SEND=true
|
||||
else
|
||||
DIGEST_LINES+=("$ICON_BANDWIDTH Yesterday: ${YESTERDAY_GB}GB")
|
||||
fi
|
||||
else
|
||||
DIGEST_LINES+=("$ICON_BANDWIDTH Bandwidth: no data yet")
|
||||
fi
|
||||
|
||||
# ── SSL Certificates ──────────────────────────────────────────────────────────────────────────
|
||||
if [[ ${#CERT_MONITOR_DOMAINS[@]} -gt 0 ]] && command -v openssl >/dev/null 2>&1; then
|
||||
CERT_ISSUES=()
|
||||
for domain in "${CERT_MONITOR_DOMAINS[@]}"; do
|
||||
[[ -z "$domain" ]] && continue
|
||||
expiry_str=$(echo | timeout "${CERT_TIMEOUT:-10}" openssl s_client \
|
||||
-connect "${domain}:443" -servername "$domain" \
|
||||
2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
|
||||
if [[ -n "$expiry_str" ]]; then
|
||||
expiry_epoch=$(date -d "$expiry_str" +%s 2>/dev/null)
|
||||
days_remaining=$(( (expiry_epoch - $(date +%s)) / 86400 ))
|
||||
if [[ "$days_remaining" -le "${CERT_CRIT_DAYS:-7}" ]]; then
|
||||
CERT_ISSUES+=("$domain: ${days_remaining}d CRITICAL")
|
||||
SHOULD_SEND=true
|
||||
elif [[ "$days_remaining" -le "${CERT_WARN_DAYS:-30}" ]]; then
|
||||
CERT_ISSUES+=("$domain: ${days_remaining}d warning")
|
||||
[[ "$DIGEST_SMART_ON_CERT_WARN" == true ]] && SHOULD_SEND=true
|
||||
else
|
||||
log "$ICON_CERT $domain: ${days_remaining}d remaining ✅"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [[ ${#CERT_ISSUES[@]} -gt 0 ]]; then
|
||||
DIGEST_LINES+=("$ICON_CERT Certificates: ${CERT_ISSUES[*]}")
|
||||
FINDINGS+=("Cert issues: ${CERT_ISSUES[*]}")
|
||||
else
|
||||
DIGEST_LINES+=("$ICON_CERT Certificates: all healthy ✅")
|
||||
fi
|
||||
fi
|
||||
|
||||
# ==============================================================================================
|
||||
# ── Smart profile — exit silently if nothing to report ────────────────────────────────────────
|
||||
# ==============================================================================================
|
||||
if [[ "$DIGEST_PROFILE" == "smart" && "$SHOULD_SEND" == false ]]; then
|
||||
echo "Profile: smart — no findings worth reporting — silent exit"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ==============================================================================================
|
||||
# ━━━ Build and Send Digest ━━━
|
||||
# ==============================================================================================
|
||||
echo ""
|
||||
echo "━━━ $ICON_DIGEST Health Digest — $(date '+%Y-%m-%d %H:%M:%S') ━━━"
|
||||
echo "$ICON_HOST $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
echo ""
|
||||
|
||||
for line in "${DIGEST_LINES[@]}"; do
|
||||
echo " $line"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "━━━━━ $ICON_SUMMARY DIGEST SUMMARY ━━━━━"
|
||||
echo "$ICON_HOST Identity: $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
echo "$ICON_DIGEST Profile: $DIGEST_PROFILE"
|
||||
echo "$ICON_ERROR Issues: ${#ISSUES[@]}"
|
||||
echo "$ICON_WARN Findings: ${#FINDINGS[@]}"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
# Build notification message
|
||||
NOTIFY_MSG="Health Digest — $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
[[ ${#ISSUES[@]} -gt 0 ]] && NOTIFY_MSG+=" | Issues: ${ISSUES[*]}"
|
||||
[[ ${#FINDINGS[@]} -gt 0 ]] && NOTIFY_MSG+=" | Findings: ${FINDINGS[*]}"
|
||||
[[ ${#ISSUES[@]} -eq 0 && ${#FINDINGS[@]} -eq 0 ]] && NOTIFY_MSG+=" | All systems healthy"
|
||||
|
||||
NOTIFY_SEV="normal"
|
||||
[[ ${#ISSUES[@]} -gt 0 ]] && NOTIFY_SEV="warning"
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
warn "DRY RUN — digest generated but not sent"
|
||||
elif [[ "$SHOULD_SEND" == true ]]; then
|
||||
notify "$NOTIFY_MSG" "Health Digest" "$NOTIFY_SEV"
|
||||
echo "Digest sent"
|
||||
fi
|
||||
Reference in New Issue
Block a user