Files
arr-suite-template-bootstrap/templates/disk-usage-monitor.sh.j2
openhands 24f2cd64e9 Initial template repository
🎬 ARR Suite Template Bootstrap - Complete Media Automation Stack

Features:
- 16 production services (Prowlarr, Sonarr, Radarr, Plex, etc.)
- One-command Ansible deployment
- VPN-protected downloads via Gluetun
- Tailscale secure access
- Production-ready security (UFW, Fail2Ban)
- Automated backups and monitoring
- Comprehensive documentation

Ready for customization and deployment to any VPS.

Co-authored-by: openhands <openhands@all-hands.dev>
2025-11-28 04:26:12 +00:00

210 lines
6.9 KiB
Django/Jinja

#!/bin/bash
# Disk usage monitoring script for Arrs Media Stack
# Generated by Ansible
LOG_DIR="{{ docker_root }}/logs/system"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
DISK_LOG="$LOG_DIR/disk-usage-$(date '+%Y%m%d').log"
# Ensure log directory exists
mkdir -p "$LOG_DIR"
# Function to log with timestamp
log_disk() {
echo "[$TIMESTAMP] $1" >> "$DISK_LOG"
}
# Disk usage thresholds
WARNING_THRESHOLD=80
CRITICAL_THRESHOLD=90
log_disk "=== DISK USAGE MONITORING ==="
# Monitor main directories
DIRECTORIES=(
"{{ docker_root }}"
"{{ media_root }}"
"/var/lib/docker"
"/tmp"
"/var/log"
)
for dir in "${DIRECTORIES[@]}"; do
if [[ -d "$dir" ]]; then
USAGE=$(df "$dir" | tail -1)
FILESYSTEM=$(echo "$USAGE" | awk '{print $1}')
TOTAL=$(echo "$USAGE" | awk '{print $2}')
USED=$(echo "$USAGE" | awk '{print $3}')
AVAILABLE=$(echo "$USAGE" | awk '{print $4}')
PERCENT=$(echo "$USAGE" | awk '{print $5}' | cut -d'%' -f1)
# Convert to human readable
TOTAL_GB=$((TOTAL / 1024 / 1024))
USED_GB=$((USED / 1024 / 1024))
AVAILABLE_GB=$((AVAILABLE / 1024 / 1024))
log_disk "DISK_USAGE $dir - Filesystem: $FILESYSTEM, Total: ${TOTAL_GB}GB, Used: ${USED_GB}GB (${PERCENT}%), Available: ${AVAILABLE_GB}GB"
# Check thresholds
if [[ $PERCENT -ge $CRITICAL_THRESHOLD ]]; then
log_disk "CRITICAL_ALERT $dir disk usage is ${PERCENT}% (>=${CRITICAL_THRESHOLD}%)"
elif [[ $PERCENT -ge $WARNING_THRESHOLD ]]; then
log_disk "WARNING_ALERT $dir disk usage is ${PERCENT}% (>=${WARNING_THRESHOLD}%)"
fi
else
log_disk "DIRECTORY_NOT_FOUND $dir does not exist"
fi
done
# Monitor specific subdirectories in Docker root
log_disk "=== DOCKER SUBDIRECTORY USAGE ==="
DOCKER_SUBDIRS=(
"{{ docker_root }}/sonarr"
"{{ docker_root }}/radarr"
"{{ docker_root }}/lidarr"
"{{ docker_root }}/bazarr"
"{{ docker_root }}/prowlarr"
"{{ docker_root }}/compose"
"{{ docker_root }}/logs"
)
for subdir in "${DOCKER_SUBDIRS[@]}"; do
if [[ -d "$subdir" ]]; then
SIZE=$(du -sh "$subdir" 2>/dev/null | cut -f1)
log_disk "SUBDIR_SIZE $subdir: $SIZE"
fi
done
# Monitor media subdirectories
log_disk "=== MEDIA DIRECTORY USAGE ==="
MEDIA_SUBDIRS=(
"{{ media_root }}/movies"
"{{ media_root }}/tv"
"{{ media_root }}/music"
"{{ media_root }}/downloads"
)
for subdir in "${MEDIA_SUBDIRS[@]}"; do
if [[ -d "$subdir" ]]; then
SIZE=$(du -sh "$subdir" 2>/dev/null | cut -f1)
FILE_COUNT=$(find "$subdir" -type f 2>/dev/null | wc -l)
log_disk "MEDIA_SIZE $subdir: $SIZE ($FILE_COUNT files)"
else
log_disk "MEDIA_DIR_NOT_FOUND $subdir does not exist"
fi
done
# Docker system disk usage
if command -v docker >/dev/null 2>&1; then
log_disk "=== DOCKER SYSTEM USAGE ==="
# Docker system df
DOCKER_DF=$(docker system df --format "{{ '{{.Type}}' }}\t{{ '{{.TotalCount}}' }}\t{{ '{{.Active}}' }}\t{{ '{{.Size}}' }}\t{{ '{{.Reclaimable}}' }}" 2>/dev/null)
if [[ -n "$DOCKER_DF" ]]; then
echo "$DOCKER_DF" | while IFS=$'\t' read -r type total active size reclaimable; do
log_disk "DOCKER_USAGE $type - Total: $total, Active: $active, Size: $size, Reclaimable: $reclaimable"
done
fi
# Container sizes
cd {{ docker_compose_dir }}
SERVICES=("sonarr" "radarr" "lidarr" "bazarr" "prowlarr" "watchtower")
for service in "${SERVICES[@]}"; do
CONTAINER_ID=$(docker-compose ps -q "$service" 2>/dev/null)
if [[ -n "$CONTAINER_ID" ]]; then
CONTAINER_SIZE=$(docker inspect "$CONTAINER_ID" --format='{{ "{{.SizeRw}}" }}' 2>/dev/null)
if [[ -n "$CONTAINER_SIZE" && "$CONTAINER_SIZE" != "null" ]]; then
CONTAINER_SIZE_MB=$((CONTAINER_SIZE / 1024 / 1024))
log_disk "CONTAINER_SIZE $service: ${CONTAINER_SIZE_MB}MB"
fi
fi
done
fi
# Large files detection
log_disk "=== LARGE FILES DETECTION ==="
LARGE_FILES=$(find {{ docker_root }} -type f -size +100M 2>/dev/null | head -10)
if [[ -n "$LARGE_FILES" ]]; then
echo "$LARGE_FILES" | while IFS= read -r file; do
SIZE=$(du -sh "$file" 2>/dev/null | cut -f1)
log_disk "LARGE_FILE $file: $SIZE"
done
else
log_disk "LARGE_FILES No files larger than 100MB found in {{ docker_root }}"
fi
# Log files size monitoring
log_disk "=== LOG FILES MONITORING ==="
LOG_DIRS=(
"{{ docker_root }}/logs"
"{{ docker_root }}/sonarr/logs"
"{{ docker_root }}/radarr/logs"
"{{ docker_root }}/lidarr/logs"
"{{ docker_root }}/bazarr/logs"
"{{ docker_root }}/prowlarr/logs"
"/var/log"
)
for log_dir in "${LOG_DIRS[@]}"; do
if [[ -d "$log_dir" ]]; then
LOG_SIZE=$(du -sh "$log_dir" 2>/dev/null | cut -f1)
LOG_COUNT=$(find "$log_dir" -name "*.log" -o -name "*.txt" 2>/dev/null | wc -l)
log_disk "LOG_DIR_SIZE $log_dir: $LOG_SIZE ($LOG_COUNT log files)"
# Find large log files
LARGE_LOGS=$(find "$log_dir" -name "*.log" -o -name "*.txt" -size +10M 2>/dev/null)
if [[ -n "$LARGE_LOGS" ]]; then
echo "$LARGE_LOGS" | while IFS= read -r logfile; do
SIZE=$(du -sh "$logfile" 2>/dev/null | cut -f1)
log_disk "LARGE_LOG $logfile: $SIZE"
done
fi
fi
done
# Disk I/O statistics
if command -v iostat >/dev/null 2>&1; then
log_disk "=== DISK I/O STATISTICS ==="
IOSTAT_OUTPUT=$(iostat -d 1 1 | tail -n +4)
echo "$IOSTAT_OUTPUT" | while IFS= read -r line; do
if [[ -n "$line" && "$line" != *"Device"* ]]; then
log_disk "DISK_IO $line"
fi
done
fi
# Cleanup recommendations
log_disk "=== CLEANUP RECOMMENDATIONS ==="
# Check for old Docker images
if command -v docker >/dev/null 2>&1; then
DANGLING_IMAGES=$(docker images -f "dangling=true" -q | wc -l)
if [[ $DANGLING_IMAGES -gt 0 ]]; then
log_disk "CLEANUP_RECOMMENDATION $DANGLING_IMAGES dangling Docker images can be removed with 'docker image prune'"
fi
UNUSED_VOLUMES=$(docker volume ls -f "dangling=true" -q | wc -l)
if [[ $UNUSED_VOLUMES -gt 0 ]]; then
log_disk "CLEANUP_RECOMMENDATION $UNUSED_VOLUMES unused Docker volumes can be removed with 'docker volume prune'"
fi
fi
# Check for old log files
OLD_LOGS=$(find {{ docker_root }}/logs -name "*.log" -mtime +30 2>/dev/null | wc -l)
if [[ $OLD_LOGS -gt 0 ]]; then
log_disk "CLEANUP_RECOMMENDATION $OLD_LOGS log files older than 30 days can be cleaned up"
fi
# Check for compressed logs
COMPRESSED_LOGS=$(find {{ docker_root }}/logs -name "*.gz" -mtime +90 2>/dev/null | wc -l)
if [[ $COMPRESSED_LOGS -gt 0 ]]; then
log_disk "CLEANUP_RECOMMENDATION $COMPRESSED_LOGS compressed log files older than 90 days can be removed"
fi
log_disk "=== END DISK USAGE MONITORING ==="
# Cleanup old disk usage logs (keep 7 days)
find "$LOG_DIR" -name "disk-usage-*.log" -mtime +7 -delete 2>/dev/null
exit 0