#!/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