Created
October 3, 2025 06:13
-
-
Save 20k-ultra/599875e3f6a38d5477841307faee881c to your computer and use it in GitHub Desktop.
Consume inotify watches
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| TARGET_PERCENT=${1:-60} | |
| WATCH_LIMIT=$(cat /proc/sys/fs/inotify/max_user_watches) | |
| TARGET_WATCHES=$((WATCH_LIMIT * TARGET_PERCENT / 100)) | |
| echo "===================================" | |
| echo "Inotify Watch Consumer (Fixed)" | |
| echo "===================================" | |
| echo "System limit: $WATCH_LIMIT watches" | |
| echo "Target: ${TARGET_PERCENT}% ($TARGET_WATCHES watches)" | |
| echo "" | |
| WORK_DIR=$(mktemp -d /tmp/inotify-test-XXXXXX) | |
| echo "Creating test files in $WORK_DIR" | |
| cleanup() { | |
| echo -e "\n\nCleaning up..." | |
| if [[ -n "$INOTIFY_PIDS" ]]; then | |
| kill $INOTIFY_PIDS 2>/dev/null | |
| wait $INOTIFY_PIDS 2>/dev/null | |
| fi | |
| rm -rf "$WORK_DIR" | |
| echo "Cleanup complete" | |
| exit 0 | |
| } | |
| trap cleanup EXIT INT TERM | |
| mkdir -p "$WORK_DIR" | |
| FILES_NEEDED=$TARGET_WATCHES | |
| echo "Creating $FILES_NEEDED files..." | |
| for ((i=1; i<=FILES_NEEDED; i++)); do | |
| if ((i % 1000 == 0)); then | |
| echo " Created $i/$FILES_NEEDED files ($(( i * 100 / FILES_NEEDED ))%)..." | |
| fi | |
| SUBDIR="$WORK_DIR/dir_$((i / 100))" | |
| mkdir -p "$SUBDIR" | |
| touch "$SUBDIR/file_$i" | |
| done | |
| echo -e "\nEstablishing inotify watches on individual files..." | |
| if ! command -v inotifywait &> /dev/null; then | |
| echo "ERROR: inotifywait not found. Installing inotify-tools..." | |
| if command -v apt-get &> /dev/null; then | |
| apt-get update && apt-get install -y inotify-tools | |
| elif command -v yum &> /dev/null; then | |
| yum install -y inotify-tools | |
| elif command -v apk &> /dev/null; then | |
| apk add --no-cache inotify-tools | |
| else | |
| echo "Cannot install inotify-tools. Please install manually." | |
| exit 1 | |
| fi | |
| fi | |
| INOTIFY_PIDS="" | |
| BATCH_SIZE=1000 | |
| BATCH_NUM=0 | |
| for ((start=1; start<=FILES_NEEDED; start+=BATCH_SIZE)); do | |
| end=$((start + BATCH_SIZE - 1)) | |
| if ((end > FILES_NEEDED)); then | |
| end=$FILES_NEEDED | |
| fi | |
| echo " Setting watches on files $start-$end..." | |
| FILE_LIST="" | |
| for ((i=start; i<=end; i++)); do | |
| SUBDIR="$WORK_DIR/dir_$((i / 100))" | |
| FILE_LIST="$FILE_LIST $SUBDIR/file_$i" | |
| done | |
| inotifywait -m -q -e modify $FILE_LIST > /dev/null 2>&1 & | |
| INOTIFY_PIDS="$INOTIFY_PIDS $!" | |
| BATCH_NUM=$((BATCH_NUM + 1)) | |
| sleep 0.1 | |
| done | |
| sleep 3 | |
| get_current_watches() { | |
| local count=0 | |
| for pid in /proc/[0-9]*; do | |
| [[ -d "$pid/fd" ]] || continue | |
| for fd in "$pid"/fd/*; do | |
| [[ -e "$fd" ]] || continue | |
| link=$(readlink "$fd" 2>/dev/null) | |
| if [[ "$link" == "anon_inode:inotify" ]]; then | |
| fdinfo="${fd/\/fd\//\/fdinfo\/}" | |
| if [[ -r "$fdinfo" ]]; then | |
| watches=$(grep -c "^inotify" "$fdinfo" 2>/dev/null || echo 0) | |
| count=$((count + watches)) | |
| fi | |
| fi | |
| done | |
| done | |
| echo $count | |
| } | |
| CURRENT_WATCHES=$(get_current_watches) | |
| USAGE_PERCENT=$(awk "BEGIN {printf \"%.1f\", $CURRENT_WATCHES * 100 / $WATCH_LIMIT}") | |
| echo "" | |
| echo "===================================" | |
| echo "✓ Inotify watches established!" | |
| echo "===================================" | |
| echo "Current system-wide usage:" | |
| echo " Total watches: $CURRENT_WATCHES" | |
| echo " Usage: ${USAGE_PERCENT}%" | |
| echo " Active inotifywait processes: $(echo $INOTIFY_PIDS | wc -w)" | |
| echo "" | |
| echo "This container should trigger your killer if usage >60%" | |
| echo "" | |
| echo "Press Ctrl+C to release watches and exit" | |
| echo "" | |
| while true; do | |
| CURRENT=$(get_current_watches) | |
| PERCENT=$(awk "BEGIN {printf \"%.1f\", $CURRENT * 100 / $WATCH_LIMIT}") | |
| echo "[$(date '+%H:%M:%S')] Current usage: $CURRENT watches (${PERCENT}%)" | |
| sleep 10 | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment