Plugin: common.php library, watchdog expansion, monitor + scheduler improvements

PHP architecture:
- Extract common.php from monitor.php — shared system functions (vv_system_info,
  vv_memory_breakdown, vv_remote_hosts_stats, disk/GPU/UPS/network/docker/parity, etc.)
  now live in one place; monitor.php and watchdog.php both require common.php
- Add unraid_api.php as explicit include (was implicit via config.php chain)
- confform.php: add missing require_once config.php (implicit dep made explicit)
- Delete orphaned pages/docs.php and pages/config.php (absorbed into scheduler)

Watchdog page:
- Add Storage watchdog card (growth + log strikes, baseline age, suppress ceilings)
- Add Network watchdog card (NPM strikes, DDNS domain/container, NPM URL)
- One host per row layout — all 5 watchdog cards equally spaced via inner grid
- Watchdog now uses Unraid API for local system stats; remote nodes with API key
  but no SSH get system info from vv_remote_hosts_stats() with api_only flag
- SSH bundle: /proc/meminfo passed as raw section instead of awk-parsed header
  fields — fixes RAM showing 0 on remote hosts where awk quoting was unreliable
- vv_wd_local_system() rewritten as thin wrapper over vv_system_info() + vv_memory_breakdown()

Monitor page:
- Watchdog card: add stability strikes, storage watchdog strikes, network NPM status,
  live system stats (rootfs/log/tmp %, RAM free, load, CPU temp, zombies, NIC, sshd)
- Row height: switch from max-height on cards to minmax(0, calc(...)) on grid track —
  all cards in a row now fill to the tallest card's height correctly (fixes Pools card
  being shorter than neighbours)

Scheduler page:
- Add Tools section above Custom Scripts — lists Tools/*.sh with run/dry-run/cron/log
- vv_tools_scripts() function in scheduler.php include

Tools:
- Add docker_prune_images.sh — removes dangling Docker images; --dry-run and --status modes
This commit is contained in:
Gmer4Lfe
2026-05-29 23:33:52 -04:00
parent 8f05f0d27c
commit 86048b32d3
13 changed files with 2072 additions and 898 deletions
+95
View File
@@ -0,0 +1,95 @@
#!/bin/bash
# ==============================================================================================
# ============================= Docker Prune Images ============================================
# ==============================================================================================
#
# PURPOSE
# ─────────────────────────────────────────────────────────────────────────────
# Removes dangling Docker images — images no longer tagged or referenced by any
# container. These accumulate after container updates pull a new image version,
# leaving the old image behind with no tag.
#
# Safe to run at any time. Only removes images with no tag and no container
# reference — running containers are never affected.
#
# ==============================================================================================
# RUNTIME MODES
# ==============================================================================================
#
# docker_prune_images.sh
# Show dangling images and remove them.
#
# docker_prune_images.sh --dry-run
# Show what would be removed without removing anything.
#
# docker_prune_images.sh --status
# Show current dangling images and disk usage. No changes.
#
# ==============================================================================================
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
acquire_lock
# ==============================================================================================
# ━━━ Status ━━━
# ==============================================================================================
if [[ "$SHOW_STATUS" == true ]]; then
echo ""
echo "━━━━━ $ICON_SUMMARY DOCKER PRUNE IMAGES STATUS ━━━━━"
DANGLING=$(docker images -f "dangling=true" --format "{{.ID}}\t{{.Size}}\t{{.CreatedSince}}" 2>/dev/null)
if [[ -z "$DANGLING" ]]; then
echo "$ICON_DONE No dangling images."
else
COUNT=$(echo "$DANGLING" | wc -l)
echo "$ICON_CONTAINERS $COUNT dangling image(s):"
echo "$DANGLING" | while IFS=$'\t' read -r id size age; do
echo " $id $size created $age"
done
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━"
exit 0
fi
# ==============================================================================================
# ━━━ Run ━━━
# ==============================================================================================
echo "━━━ $ICON_CONTAINERS Docker Prune Images — $(date '+%Y-%m-%d %H:%M:%S') ━━━"
DANGLING_IDS=$(docker images -f "dangling=true" -q 2>/dev/null)
if [[ -z "$DANGLING_IDS" ]]; then
success "No dangling images — nothing to do"
exit 0
fi
COUNT=$(echo "$DANGLING_IDS" | wc -l)
log "Found $COUNT dangling image(s)"
if [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would remove $COUNT dangling image(s):"
docker images -f "dangling=true" --format " {{.ID}} {{.Size}} created {{.CreatedSince}}" 2>/dev/null
exit 0
fi
OUTPUT=$(docker image prune -f 2>&1)
echo "$OUTPUT"
RECLAIMED=$(echo "$OUTPUT" | grep -E "^Total reclaimed" || echo "")
if [[ -n "$RECLAIMED" ]]; then
success "Done — $RECLAIMED"
else
success "Done — $COUNT image(s) removed"
fi