126 lines
5.5 KiB
Bash
126 lines
5.5 KiB
Bash
#!/bin/bash
|
|
# -----------------------------------------------------------------------------------------------
|
|
# --------------------------------- inotify Tuning --------------------------------------------
|
|
# -----------------------------------------------------------------------------------------------
|
|
# Increases Linux inotify limits to prevent "too many open files" and inotify exhaustion.
|
|
# Run once at array start via ARRAY_START_SCRIPTS in Master.conf.
|
|
#
|
|
# Why this matters:
|
|
# Each Docker container that watches files (Sonarr, Radarr, Lidarr, NextCloud etc.)
|
|
# consumes inotify instances and watches. unRAID defaults are very low — with many
|
|
# containers running you can exhaust the limit silently, causing containers to miss
|
|
# file events (new downloads not detected, library not updated etc.)
|
|
#
|
|
# max_user_instances = max number of inotify instances per user (default: 128)
|
|
# max_user_watches = max number of files/dirs watched per instance (default: 8192)
|
|
# max_queued_events = max events queued before dropping (default: 16384)
|
|
#
|
|
# These settings are lost on reboot — this script reapplies them at every array start.
|
|
# All values configurable in Master.conf under unRAID Essentials.
|
|
# -----------------------------------------------------------------------------------------------
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
source "$SCRIPT_DIR/../Master.conf"
|
|
source "$SCRIPT_DIR/../common.sh"
|
|
|
|
parse_args "$@"
|
|
|
|
# -----------------------------------------------------------------------------------------------
|
|
# ━━━ $ICON_GEAR Setup ━━━
|
|
# -----------------------------------------------------------------------------------------------
|
|
echo ""
|
|
echo "━━━ $ICON_GEAR inotify Tuning ━━━"
|
|
|
|
if [[ "$EUID" -ne 0 ]]; then
|
|
error "Must be run as root"
|
|
exit 1
|
|
fi
|
|
|
|
success "Running as root"
|
|
|
|
# -----------------------------------------------------------------------------------------------
|
|
# ━━━ Current Values ━━━
|
|
# -----------------------------------------------------------------------------------------------
|
|
CURRENT_INSTANCES=$(sysctl -n fs.inotify.max_user_instances 2>/dev/null || echo "?")
|
|
CURRENT_WATCHES=$(sysctl -n fs.inotify.max_user_watches 2>/dev/null || echo "?")
|
|
CURRENT_EVENTS=$(sysctl -n fs.inotify.max_queued_events 2>/dev/null || echo "?")
|
|
|
|
info "Current: instances=$CURRENT_INSTANCES watches=$CURRENT_WATCHES queued=$CURRENT_EVENTS"
|
|
info "Target: instances=${INOTIFY_MAX_INSTANCES} watches=${INOTIFY_MAX_WATCHES} queued=${INOTIFY_MAX_QUEUED_EVENTS}"
|
|
|
|
if [[ "$SHOW_STATUS" == true ]]; then
|
|
echo ""
|
|
echo "━━━━━ $ICON_SUMMARY INOTIFY STATUS ━━━━━"
|
|
echo " max_user_instances: $CURRENT_INSTANCES (target: ${INOTIFY_MAX_INSTANCES})"
|
|
echo " max_user_watches: $CURRENT_WATCHES (target: ${INOTIFY_MAX_WATCHES})"
|
|
echo " max_queued_events: $CURRENT_EVENTS (target: ${INOTIFY_MAX_QUEUED_EVENTS})"
|
|
echo ""
|
|
echo " Active inotify instances in use:"
|
|
find /proc/*/fd -lname "anon_inode:inotify" 2>/dev/null | \
|
|
awk -F/ '{print $3}' | sort -u | while read -r pid; do
|
|
cmd=$(cat /proc/$pid/comm 2>/dev/null || echo "?")
|
|
echo " PID $pid ($cmd)"
|
|
done | head -20
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━"
|
|
exit 0
|
|
fi
|
|
|
|
# -----------------------------------------------------------------------------------------------
|
|
# ━━━ Apply Settings ━━━
|
|
# -----------------------------------------------------------------------------------------------
|
|
echo ""
|
|
CHANGED=0
|
|
FAILED=0
|
|
|
|
apply_sysctl() {
|
|
local key="$1"
|
|
local value="$2"
|
|
local current
|
|
current=$(sysctl -n "$key" 2>/dev/null || echo 0)
|
|
|
|
if [[ "$current" -eq "$value" ]]; then
|
|
success "$key = $value (already set)"
|
|
return
|
|
fi
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
warn "DRY RUN — would set $key = $value (currently $current)"
|
|
return
|
|
fi
|
|
|
|
if sysctl -w "${key}=${value}" >/dev/null 2>&1; then
|
|
success "$key = $value (was $current)"
|
|
((CHANGED++))
|
|
else
|
|
error "Failed to set $key = $value"
|
|
((FAILED++))
|
|
fi
|
|
}
|
|
|
|
apply_sysctl "fs.inotify.max_user_instances" "$INOTIFY_MAX_INSTANCES"
|
|
apply_sysctl "fs.inotify.max_user_watches" "$INOTIFY_MAX_WATCHES"
|
|
apply_sysctl "fs.inotify.max_queued_events" "$INOTIFY_MAX_QUEUED_EVENTS"
|
|
|
|
# -----------------------------------------------------------------------------------------------
|
|
# ━━━ $ICON_SUMMARY Summary ━━━
|
|
# -----------------------------------------------------------------------------------------------
|
|
echo ""
|
|
echo "━━━━━ $ICON_SUMMARY INOTIFY TUNING SUMMARY ━━━━━"
|
|
echo " max_user_instances: $(sysctl -n fs.inotify.max_user_instances 2>/dev/null)"
|
|
echo " max_user_watches: $(sysctl -n fs.inotify.max_user_watches 2>/dev/null)"
|
|
echo " max_queued_events: $(sysctl -n fs.inotify.max_queued_events 2>/dev/null)"
|
|
echo ""
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
echo "$ICON_WARN Status: DRY RUN — no changes made"
|
|
elif [[ "$FAILED" -gt 0 ]]; then
|
|
echo "$ICON_ERROR Status: $FAILED setting(s) failed"
|
|
notify "inotify tuning failed on $(hostname) — $FAILED setting(s) could not be applied" "inotify Tuning" "warning"
|
|
exit 1
|
|
elif [[ "$CHANGED" -gt 0 ]]; then
|
|
echo "$ICON_DONE Status: $ICON_SUCCESS $CHANGED setting(s) applied"
|
|
else
|
|
echo "$ICON_DONE Status: $ICON_SUCCESS All settings already correct"
|
|
fi
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" |