updated my variables in master.conf
This commit is contained in:
@@ -2,20 +2,19 @@
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# --------------------------------- Bandwidth Monitor ------------------------------------------
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# Logs daily rsync transfer totals and generates weekly summary reports.
|
||||
# Designed for minimal flash drive impact — one bounded write per day.
|
||||
# Logs rsync transfer history and generates weekly summary reports.
|
||||
# Designed for minimal flash drive impact — one bounded write per rsync run.
|
||||
#
|
||||
# Two modes:
|
||||
# --log-transfer "profile" bytes duration — called by rsync.sh after each sync
|
||||
# appends one line, trims old entries
|
||||
# --report — generates weekly summary from log
|
||||
# (no args) — generates summary report
|
||||
# --log-transfer "profile" duration status — called by rsync.sh after each sync
|
||||
# appends one line, trims old entries
|
||||
# --report (or no args) — generates summary from log
|
||||
#
|
||||
# Log format (one line per transfer):
|
||||
# YYYY-MM-DD|profile|bytes|duration_seconds
|
||||
# Log format — one line per transfer, version-proof, never needs rsync output parsing:
|
||||
# YYYY-MM-DD|HH:MM|profile|duration_seconds|status
|
||||
#
|
||||
# Log file stays bounded to BANDWIDTH_LOG_RETENTION days — old entries trimmed on write.
|
||||
# Minimal writes: one append per rsync run, one trim per append.
|
||||
# Log file stays bounded to BANDWIDTH_LOG_RETENTION days — old entries trimmed on every write.
|
||||
# Minimal flash drive impact: one append + one trim per rsync run.
|
||||
#
|
||||
# All configuration in Master.conf under Bandwidth Monitor section.
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
@@ -27,51 +26,61 @@ source "$SCRIPT_DIR/../common.sh"
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
# Check for log-transfer mode
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# Parse mode from PARSED_ARGS
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
LOG_TRANSFER_MODE=false
|
||||
REPORT_MODE=false
|
||||
TRANSFER_PROFILE=""
|
||||
TRANSFER_BYTES=0
|
||||
TRANSFER_DURATION=0
|
||||
TRANSFER_STATUS="success"
|
||||
|
||||
for arg in "${PARSED_ARGS[@]}"; do
|
||||
case "$arg" in
|
||||
--log-transfer) LOG_TRANSFER_MODE=true ;;
|
||||
--report) REPORT_MODE=true ;;
|
||||
--report) LOG_TRANSFER_MODE=false ;;
|
||||
*)
|
||||
if [[ "$LOG_TRANSFER_MODE" == true && -z "$TRANSFER_PROFILE" ]]; then
|
||||
TRANSFER_PROFILE="$arg"
|
||||
elif [[ "$LOG_TRANSFER_MODE" == true && "$TRANSFER_BYTES" -eq 0 ]]; then
|
||||
TRANSFER_BYTES="$arg"
|
||||
elif [[ "$LOG_TRANSFER_MODE" == true ]]; then
|
||||
TRANSFER_DURATION="$arg"
|
||||
if [[ "$LOG_TRANSFER_MODE" == true ]]; then
|
||||
if [[ -z "$TRANSFER_PROFILE" ]]; then
|
||||
TRANSFER_PROFILE="$arg"
|
||||
elif [[ "$TRANSFER_DURATION" -eq 0 ]]; then
|
||||
TRANSFER_DURATION="$arg"
|
||||
else
|
||||
TRANSFER_STATUS="$arg"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Ensure log file exists
|
||||
# Ensure log directory and file exist
|
||||
mkdir -p "$(dirname "$BANDWIDTH_LOG")"
|
||||
touch "$BANDWIDTH_LOG" 2>/dev/null || {
|
||||
error "Cannot create bandwidth log: $BANDWIDTH_LOG"
|
||||
error "Cannot write to bandwidth log: $BANDWIDTH_LOG"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# LOG TRANSFER MODE
|
||||
# Called by rsync.sh after each successful sync — appends one line and trims old entries
|
||||
# Usage: bandwidth_monitor.sh --log-transfer "profile" bytes duration
|
||||
# Called by rsync.sh after each sync — appends one line and trims old entries.
|
||||
# Usage: bandwidth_monitor.sh --log-transfer "profile" duration_seconds status
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
if [[ "$LOG_TRANSFER_MODE" == true ]]; then
|
||||
[[ -z "$TRANSFER_PROFILE" ]] && error "No profile specified for --log-transfer" && exit 1
|
||||
|
||||
TODAY=$(date '+%Y-%m-%d')
|
||||
echo "${TODAY}|${TRANSFER_PROFILE}|${TRANSFER_BYTES}|${TRANSFER_DURATION}" >> "$BANDWIDTH_LOG"
|
||||
log "Logged transfer: $TRANSFER_PROFILE — $TRANSFER_BYTES bytes in ${TRANSFER_DURATION}s"
|
||||
NOW=$(date '+%H:%M')
|
||||
DURATION_FMT=$(format_duration "$TRANSFER_DURATION")
|
||||
|
||||
# Append entry
|
||||
echo "${TODAY}|${NOW}|${TRANSFER_PROFILE}|${TRANSFER_DURATION}|${TRANSFER_STATUS}" >> "$BANDWIDTH_LOG"
|
||||
log "$ICON_BANDWIDTH Logged: $TRANSFER_PROFILE — ${DURATION_FMT} — $TRANSFER_STATUS"
|
||||
|
||||
# Trim entries older than retention period — keeps file bounded
|
||||
CUTOFF=$(date -d "${BANDWIDTH_LOG_RETENTION} days ago" '+%Y-%m-%d')
|
||||
TEMP_FILE="${BANDWIDTH_LOG}.tmp"
|
||||
awk -F'|' -v cutoff="$CUTOFF" '$1 >= cutoff' "$BANDWIDTH_LOG" > "$TEMP_FILE"
|
||||
mv "$TEMP_FILE" "$BANDWIDTH_LOG"
|
||||
log "Log trimmed — keeping entries from $CUTOFF onwards"
|
||||
awk -F'|' -v cutoff="$CUTOFF" '$1 >= cutoff' "$BANDWIDTH_LOG" > "$TEMP_FILE" && \
|
||||
mv "$TEMP_FILE" "$BANDWIDTH_LOG"
|
||||
log "$ICON_BANDWIDTH Log trimmed — retaining entries from $CUTOFF onwards"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -84,69 +93,76 @@ echo ""
|
||||
|
||||
if [[ ! -s "$BANDWIDTH_LOG" ]]; then
|
||||
warn "No bandwidth data yet — log is empty"
|
||||
warn "Data accumulates as rsync jobs run"
|
||||
warn "Data accumulates as rsync jobs complete"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
START=$(date +%s)
|
||||
|
||||
# Calculate date range in log
|
||||
# Date range
|
||||
OLDEST=$(awk -F'|' 'NR==1{print $1}' "$BANDWIDTH_LOG")
|
||||
NEWEST=$(awk -F'|' 'END{print $1}' "$BANDWIDTH_LOG")
|
||||
ENTRY_COUNT=$(wc -l < "$BANDWIDTH_LOG")
|
||||
SUCCESS_COUNT=$(awk -F'|' '$5=="success"' "$BANDWIDTH_LOG" | wc -l)
|
||||
FAILED_COUNT=$(awk -F'|' '$5=="failed"' "$BANDWIDTH_LOG" | wc -l)
|
||||
|
||||
info "Log covers: $OLDEST → $NEWEST ($ENTRY_COUNT entries)"
|
||||
info "Log covers: $OLDEST → $NEWEST ($ENTRY_COUNT runs)"
|
||||
echo ""
|
||||
|
||||
# Total bytes transferred
|
||||
TOTAL_BYTES=$(awk -F'|' '{sum += $3} END {print sum+0}' "$BANDWIDTH_LOG")
|
||||
TOTAL_GB=$(awk "BEGIN {printf \"%.2f\", $TOTAL_BYTES / 1073741824}")
|
||||
|
||||
# Per-profile breakdown
|
||||
echo "━━━ $ICON_BANDWIDTH Per-Profile Totals ━━━"
|
||||
# ── Per-profile breakdown ────────────────────────────────────────────────────────────────────
|
||||
echo "━━━ $ICON_BANDWIDTH Per-Profile Summary ━━━"
|
||||
awk -F'|' '{
|
||||
bytes[$2] += $3
|
||||
runs[$2]++
|
||||
duration[$2] += $4
|
||||
runs[$3]++
|
||||
duration[$3] += $4
|
||||
if ($5 == "failed") fails[$3]++
|
||||
}
|
||||
END {
|
||||
for (profile in bytes) {
|
||||
gb = bytes[profile] / 1073741824
|
||||
printf " %-20s %6.2f GB (%d runs)\n", profile, gb, runs[profile]
|
||||
for (profile in runs) {
|
||||
avg = (runs[profile] > 0) ? duration[profile] / runs[profile] : 0
|
||||
mins = int(avg / 60)
|
||||
secs = int(avg % 60)
|
||||
fail_count = (profile in fails) ? fails[profile] : 0
|
||||
printf " %-20s %3d runs avg %dm%ds failed: %d\n", \
|
||||
profile, runs[profile], mins, secs, fail_count
|
||||
}
|
||||
}' "$BANDWIDTH_LOG" | sort -k3 -rn
|
||||
}' "$BANDWIDTH_LOG" | sort
|
||||
|
||||
echo ""
|
||||
|
||||
# Daily totals for the last 7 days
|
||||
# ── Last 7 days ──────────────────────────────────────────────────────────────────────────────
|
||||
echo "━━━ $ICON_BANDWIDTH Last 7 Days ━━━"
|
||||
for i in 6 5 4 3 2 1 0; do
|
||||
day=$(date -d "$i days ago" '+%Y-%m-%d')
|
||||
day_bytes=$(awk -F'|' -v d="$day" '$1==d{sum+=$3} END{print sum+0}' "$BANDWIDTH_LOG")
|
||||
day_gb=$(awk "BEGIN {printf \"%.2f\", $day_bytes / 1073741824}")
|
||||
day_name=$(date -d "$i days ago" '+%a')
|
||||
day_runs=$(awk -F'|' -v d="$day" '$1==d' "$BANDWIDTH_LOG" | wc -l)
|
||||
day_success=$(awk -F'|' -v d="$day" '$1==d && $5=="success"' "$BANDWIDTH_LOG" | wc -l)
|
||||
day_failed=$(awk -F'|' -v d="$day" '$1==d && $5=="failed"' "$BANDWIDTH_LOG" | wc -l)
|
||||
day_duration=$(awk -F'|' -v d="$day" '$1==d{sum+=$4} END{print sum+0}' "$BANDWIDTH_LOG")
|
||||
day_duration_fmt=$(format_duration "$day_duration")
|
||||
|
||||
# Flag days that exceeded warning threshold
|
||||
over_warn=$(awk "BEGIN {print ($day_bytes > $BANDWIDTH_WARN_GB * 1073741824) ? 1 : 0}")
|
||||
if [[ "$over_warn" == "1" ]]; then
|
||||
echo " $ICON_WARN $day ${day_gb} GB ← exceeded ${BANDWIDTH_WARN_GB}GB threshold"
|
||||
if [[ "$day_runs" -eq 0 ]]; then
|
||||
echo " $ICON_TIME $day ($day_name) — no syncs"
|
||||
elif [[ "$day_failed" -gt 0 ]]; then
|
||||
echo " $ICON_WARN $day ($day_name) — $day_runs runs / ${day_duration_fmt} total / $ICON_ERROR $day_failed failed"
|
||||
else
|
||||
echo " $ICON_TIME $day ${day_gb} GB"
|
||||
echo " $ICON_DONE $day ($day_name) — $day_runs runs / ${day_duration_fmt} total"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "━━━ $ICON_SUMMARY Totals ━━━"
|
||||
echo " $ICON_BANDWIDTH Total transferred: ${TOTAL_GB} GB"
|
||||
echo " $ICON_TIME Log period: $OLDEST → $NEWEST"
|
||||
echo " $ICON_GEAR Retention: ${BANDWIDTH_LOG_RETENTION} days"
|
||||
|
||||
# ── Totals ───────────────────────────────────────────────────────────────────────────────────
|
||||
TOTAL_DURATION=$(awk -F'|' '{sum+=$4} END{print sum+0}' "$BANDWIDTH_LOG")
|
||||
TOTAL_DURATION_FMT=$(format_duration "$TOTAL_DURATION")
|
||||
|
||||
END=$(date +%s)
|
||||
|
||||
echo ""
|
||||
echo "━━━━━ $ICON_SUMMARY BANDWIDTH SUMMARY ━━━━━"
|
||||
echo "$ICON_BANDWIDTH Total: ${TOTAL_GB} GB"
|
||||
echo "$ICON_TIME Duration: $(format_duration $((END - START)))"
|
||||
echo "$ICON_DONE Status: $ICON_SUCCESS DONE"
|
||||
echo "$ICON_BANDWIDTH Total runs: $ENTRY_COUNT ($SUCCESS_COUNT success / $FAILED_COUNT failed)"
|
||||
echo "$ICON_TIME Total time: $TOTAL_DURATION_FMT"
|
||||
echo "$ICON_TIME Log period: $OLDEST → $NEWEST"
|
||||
echo "$ICON_GEAR Retention: ${BANDWIDTH_LOG_RETENTION} days"
|
||||
echo "$ICON_TIME Generated in: $(format_duration $((END - START)))"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
notify "Bandwidth report on $(hostname) — ${TOTAL_GB}GB transferred (${OLDEST} to ${NEWEST})" "Bandwidth Monitor" "normal"
|
||||
notify "Bandwidth report on $(hostname) — $ENTRY_COUNT rsync runs ($SUCCESS_COUNT success / $FAILED_COUNT failed) over ${BANDWIDTH_LOG_RETENTION} day window" "Bandwidth Monitor" "normal"
|
||||
@@ -0,0 +1,230 @@
|
||||
#!/bin/bash
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# --------------------------------- ZFS Memory Snapshot ----------------------------------------
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# Weekly ZFS pool health and memory diagnostic report.
|
||||
# Combines ZFS pool status, ARC statistics, memory summary, Docker memory usage
|
||||
# and kernel pressure into a single report. Informational only — no action taken.
|
||||
# system_watchdog.sh handles threshold-based intervention.
|
||||
#
|
||||
# Output goes to both console and ZFS_REPORT_LOG for later review.
|
||||
# Notifies if any warning thresholds are exceeded.
|
||||
#
|
||||
# All configuration in Master.conf under ZFS Memory Snapshot section.
|
||||
# Supports --dry-run (preview only, no log write) and --status.
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
source "$SCRIPT_DIR/../Master.conf"
|
||||
source "$SCRIPT_DIR/../common.sh"
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
# Tee output to log file unless dry run
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
mkdir -p "$(dirname "$ZFS_REPORT_LOG")"
|
||||
exec > >(tee -a "$ZFS_REPORT_LOG") 2>&1
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# ━━━ $ICON_GEAR Setup ━━━
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "━━━ $ICON_GEAR Setup ━━━"
|
||||
|
||||
if [[ "$EUID" -ne 0 ]]; then
|
||||
error "Must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
success "Running as root"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# ━━━ $ICON_SUMMARY Status ━━━
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
if [[ "$SHOW_STATUS" == true ]]; then
|
||||
echo ""
|
||||
echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━"
|
||||
echo "$ICON_ZFS Log file: $ZFS_REPORT_LOG"
|
||||
echo "$ICON_ZFS ARC warn: ${ZFS_REPORT_ARC_WARN_PCT}%"
|
||||
echo "$ICON_MEM Free RAM warn: ${ZFS_REPORT_FREE_WARN_GB}GB"
|
||||
echo "$ICON_MEM Avail RAM warn: ${ZFS_REPORT_AVAIL_WARN_GB}GB"
|
||||
echo "$ICON_CONTAINERS Docker top: $ZFS_REPORT_DOCKER_TOP"
|
||||
echo "$ICON_GEAR Dry Run: $DRY_RUN"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — output will not be written to log"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# Tracking
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
WARNINGS=()
|
||||
START=$(date +%s)
|
||||
DATE=$(date +"%Y-%m-%d %H:%M:%S")
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " $ICON_ZFS ZFS WEEKLY HEALTH REPORT — $DATE"
|
||||
echo " $ICON_HOST Host: $(hostname)"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# ━━━ $ICON_ZFS ZFS Pool Health ━━━
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "━━━ $ICON_ZFS ZFS Pool Health ━━━"
|
||||
|
||||
if ! command -v zpool >/dev/null 2>&1; then
|
||||
warn "ZFS not available on this system — skipping pool checks"
|
||||
else
|
||||
info "Pool status:"
|
||||
zpool status 2>/dev/null | grep -E "pool:|state:|status:|errors:|scan:" | while IFS= read -r line; do
|
||||
echo " $line"
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
info "Pool overview:"
|
||||
zpool list 2>/dev/null | while IFS= read -r line; do
|
||||
echo " $line"
|
||||
done
|
||||
|
||||
UNHEALTHY=$(zpool list -H -o health 2>/dev/null | grep -v ONLINE || true)
|
||||
if [[ -n "$UNHEALTHY" ]]; then
|
||||
error "One or more ZFS pools are NOT ONLINE"
|
||||
WARNINGS+=("ZFS pool unhealthy")
|
||||
else
|
||||
success "All ZFS pools are ONLINE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# ━━━ $ICON_ZFS ARC Statistics ━━━
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "━━━ $ICON_ZFS ARC Statistics ━━━"
|
||||
|
||||
if [[ ! -f /proc/spl/kstat/zfs/arcstats ]]; then
|
||||
warn "ZFS arcstats not available — skipping ARC section"
|
||||
else
|
||||
ARC_MAX=$(cat /sys/module/zfs/parameters/zfs_arc_max 2>/dev/null || \
|
||||
awk '/^c_max / {print $3}' /proc/spl/kstat/zfs/arcstats)
|
||||
ARC_SIZE=$(awk '/^size / {print $3}' /proc/spl/kstat/zfs/arcstats)
|
||||
ARC_META_USED=$(awk '/^arc_meta_used / {print $3}' /proc/spl/kstat/zfs/arcstats)
|
||||
|
||||
ARC_MAX_GB=$(awk "BEGIN {printf \"%.1f\", $ARC_MAX / 1073741824}")
|
||||
ARC_CUR_GB=$(awk "BEGIN {printf \"%.1f\", $ARC_SIZE / 1073741824}")
|
||||
ARC_META_GB=$(awk "BEGIN {printf \"%.1f\", $ARC_META_USED / 1073741824}")
|
||||
ARC_PCT=$(awk "BEGIN {printf \"%.1f\", $ARC_SIZE * 100 / $ARC_MAX}")
|
||||
ARC_PCT_INT=$(printf "%.0f" "$ARC_PCT")
|
||||
|
||||
echo " $ICON_ZFS ARC Max: ${ARC_MAX_GB}GB"
|
||||
echo " $ICON_ZFS ARC Current: ${ARC_CUR_GB}GB"
|
||||
echo " $ICON_ZFS ARC Meta Used: ${ARC_META_GB}GB"
|
||||
echo " $ICON_ZFS ARC Utilization: ${ARC_PCT}%"
|
||||
|
||||
if [[ "$ARC_PCT_INT" -ge "$ZFS_REPORT_ARC_WARN_PCT" ]]; then
|
||||
warn "ARC utilization ${ARC_PCT}% — above ${ZFS_REPORT_ARC_WARN_PCT}% threshold"
|
||||
WARNINGS+=("ARC high: ${ARC_PCT}%")
|
||||
else
|
||||
success "ARC utilization ${ARC_PCT}% — within threshold"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
info "Metadata pressure:"
|
||||
META_MRU_GHOST=$(awk '/^mru_ghost_metadata / {print $3}' /proc/spl/kstat/zfs/arcstats 2>/dev/null || echo 0)
|
||||
META_MFU_GHOST=$(awk '/^mfu_ghost_metadata / {print $3}' /proc/spl/kstat/zfs/arcstats 2>/dev/null || echo 0)
|
||||
META_MISSES=$(awk '/^demand_metadata_misses / {print $3}' /proc/spl/kstat/zfs/arcstats 2>/dev/null || echo 0)
|
||||
|
||||
MRU_GB=$(awk "BEGIN {printf \"%.2f\", $META_MRU_GHOST / 1073741824}")
|
||||
MFU_GB=$(awk "BEGIN {printf \"%.2f\", $META_MFU_GHOST / 1073741824}")
|
||||
|
||||
echo " $ICON_ZFS MRU Ghost: ${MRU_GB}GB"
|
||||
echo " $ICON_ZFS MFU Ghost: ${MFU_GB}GB"
|
||||
echo " $ICON_ZFS Metadata Misses: ${META_MISSES}"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# ━━━ $ICON_MEM Memory Status ━━━
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "━━━ $ICON_MEM Memory Status ━━━"
|
||||
|
||||
FREE_HUMAN=$(free -h | awk '/Mem:/ {print $4}')
|
||||
AVAIL_HUMAN=$(free -h | awk '/Mem:/ {print $7}')
|
||||
TOTAL_HUMAN=$(free -h | awk '/Mem:/ {print $2}')
|
||||
FREE_GB=$(free -g | awk '/Mem:/ {print $4}')
|
||||
AVAIL_GB=$(free -g | awk '/Mem:/ {print $7}')
|
||||
|
||||
echo " $ICON_MEM Total RAM: $TOTAL_HUMAN"
|
||||
echo " $ICON_MEM Free RAM: $FREE_HUMAN"
|
||||
echo " $ICON_MEM Available RAM: $AVAIL_HUMAN"
|
||||
|
||||
if [[ "$FREE_GB" -lt "$ZFS_REPORT_FREE_WARN_GB" ]]; then
|
||||
warn "Free RAM ${FREE_HUMAN} — below ${ZFS_REPORT_FREE_WARN_GB}GB threshold"
|
||||
WARNINGS+=("Low free RAM: ${FREE_HUMAN}")
|
||||
else
|
||||
success "Free RAM ${FREE_HUMAN} — within threshold"
|
||||
fi
|
||||
|
||||
if [[ "$AVAIL_GB" -lt "$ZFS_REPORT_AVAIL_WARN_GB" ]]; then
|
||||
warn "Available RAM ${AVAIL_HUMAN} — below ${ZFS_REPORT_AVAIL_WARN_GB}GB threshold"
|
||||
WARNINGS+=("Low available RAM: ${AVAIL_HUMAN}")
|
||||
else
|
||||
success "Available RAM ${AVAIL_HUMAN} — within threshold"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# ━━━ $ICON_CONTAINERS Docker Memory ━━━
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "━━━ $ICON_CONTAINERS Top $ZFS_REPORT_DOCKER_TOP Docker Memory Users ━━━"
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
warn "Docker not available — skipping container memory section"
|
||||
else
|
||||
docker stats --no-stream \
|
||||
--format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}" \
|
||||
2>/dev/null | head -n $(( ZFS_REPORT_DOCKER_TOP + 1 )) | while IFS= read -r line; do
|
||||
echo " $line"
|
||||
done
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# ━━━ $ICON_GEAR Kernel Pressure ━━━
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "━━━ $ICON_GEAR Kernel Pressure ━━━"
|
||||
|
||||
if ! command -v vmstat >/dev/null 2>&1; then
|
||||
warn "vmstat not available — skipping kernel pressure section"
|
||||
else
|
||||
info "vmstat snapshot (3 samples):"
|
||||
vmstat 1 3 2>/dev/null | while IFS= read -r line; do
|
||||
echo " $line"
|
||||
done
|
||||
fi
|
||||
|
||||
END=$(date +%s)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
# ━━━ $ICON_SUMMARY Summary ━━━
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "━━━━━ $ICON_SUMMARY ZFS REPORT SUMMARY ━━━━━"
|
||||
echo "$ICON_TIME Duration: $(format_duration $((END - START)))"
|
||||
echo "$ICON_ZFS Log: $ZFS_REPORT_LOG"
|
||||
echo ""
|
||||
if [[ ${#WARNINGS[@]} -eq 0 ]]; then
|
||||
success "Report complete — no warnings"
|
||||
else
|
||||
echo "$ICON_WARN Warnings: ${#WARNINGS[@]}"
|
||||
for w in "${WARNINGS[@]}"; do
|
||||
echo " $ICON_WARN $w"
|
||||
done
|
||||
notify "ZFS weekly report on $(hostname) — ${#WARNINGS[@]} warning(s): ${WARNINGS[*]}" "ZFS Report" "warning"
|
||||
fi
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
Reference in New Issue
Block a user