123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- #!/bin/bash
- # Get the procs sorted by the number of inotify watches
- # @author Carl-Erik Kopseng
- # @latest https://github.com/fatso83/dotfiles/blob/master/utils/scripts/inotify-consumers
- # Discussion leading up to answer: https://unix.stackexchange.com/questions/15509/whos-consuming-my-inotify-resources
- #
- # If you need ultimate speed, use https://github.com/fatso83/dotfiles/commit/inotify-consumers-v1-fastest
- # # Speed enhancements by Simon Matter <[email protected]>
- #
- # A later PR introduced a significant slowdown to gain better output, but it is insignificant on most machines
- # See this for details: https://github.com/fatso83/dotfiles/pull/10#issuecomment-1122374716
- main(){
- printf "\n%${WLEN}s %${WLEN}s\n" "INOTIFY" "INSTANCES"
- printf "%${WLEN}s %${WLEN}s\n" "WATCHES" "PER "
- printf "%${WLEN}s %${WLEN}s %s\n" " COUNT " "PROCESS " "PID USER COMMAND"
- printf -- "------------------------------------------------------------\n"
- generateData
- }
- usage(){
- cat << EOF
- Usage: $0 [--help|--limits]
- -l, --limits Will print the current related limits and how to change them
- -h, --help Show this help
- FYI: Check out Michael Sartain's C++ take on this script. The native executable
- is much faster, modern and feature rich. It can be found at
- https://github.com/mikesart/inotify-info
- EOF
- }
- limits(){
- printf "\nCurrent limits\n-------------\n"
- sysctl fs.inotify.max_user_instances fs.inotify.max_user_watches
- cat <<- EOF
- Changing settings permanently
- -----------------------------
- echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
- sudo sysctl -p # re-read config
- EOF
- }
- generateData() {
- local -i PROC
- local -i PID
- local -i CNT
- local -i INSTANCES
- local -i TOT
- local -i TOTINSTANCES
- # read process list into cache
- local PSLIST="$(ps ax -o pid,user=WIDE-COLUMN,command $COLSTRING)"
- local INOTIFY="$(find /proc/[0-9]*/fdinfo -type f 2>/dev/null | xargs grep ^inotify 2>/dev/null)"
- local INOTIFYCNT="$(echo "$INOTIFY" | cut -d "/" -s --output-delimiter=" " -f 3 |uniq -c | sed -e 's/:.*//')"
- # unique instances per process is denoted by number of inotify FDs
- local INOTIFYINSTANCES="$(echo "$INOTIFY" | cut -d "/" -s --output-delimiter=" " -f 3,5 | sed -e 's/:.*//'| uniq |awk '{print $1}' |uniq -c)"
- local INOTIFYUSERINSTANCES="$(echo "$INOTIFY" | cut -d "/" -s --output-delimiter=" " -f 3,5 | sed -e 's/:.*//' | uniq |
- while read PID FD; do echo $PID $FD $(grep -e "^ *${PID} " <<< "$PSLIST"|awk '{print $2}'); done | cut -d" " -f 3 | sort | uniq -c |sort -nr)"
- set -e
- cat <<< "$INOTIFYCNT" |
- {
- while read -rs CNT PROC; do # count watches of processes found
- echo "${PROC},${CNT},$(echo "$INOTIFYINSTANCES" | grep " ${PROC}$" |awk '{print $1}')"
- done
- } |
- grep -v ",0," | # remove entires without watches
- sort -n -t "," -k 2,3 -r | # sort to begin with highest numbers
- { # group commands so that $TOT is visible in the printf
- IFS=","
- while read -rs PID CNT INSTANCES; do # show watches and corresponding process info
- printf "%$(( WLEN - 2 ))d %$(( WLEN - 2 ))d %s\n" "$CNT" "$INSTANCES" "$(grep -e "^ *${PID} " <<< "$PSLIST")"
- TOT=$(( TOT + CNT ))
- TOTINSTANCES=$(( TOTINSTANCES + INSTANCES))
- done
- # These stats should be per-user as well, since inotify limits are per-user..
- printf "\n%$(( WLEN - 2 ))d %s\n" "$TOT" "WATCHES TOTAL COUNT"
- # the total across different users is somewhat meaningless, not printing for now.
- # printf "\n%$(( WLEN - 2 ))d %s\n" "$TOTINSTANCES" "TOTAL INSTANCES COUNT"
- }
- echo ""
- echo "INotify instances per user (e.g. limits specified by fs.inotify.max_user_instances): "
- echo ""
- (
- echo "INSTANCES USER"
- echo "----------- ------------------"
- echo "$INOTIFYUSERINSTANCES"
- ) | column -t
- echo ""
- exit 0
- }
- # get terminal width
- declare -i COLS=$(tput cols 2>/dev/null || echo 80)
- declare -i WLEN=10
- declare COLSTRING="--columns $(( COLS - WLEN ))" # get terminal width
- if [ "$1" = "--limits" -o "$1" = "-l" ]; then
- limits
- exit 0
- fi
- if [ "$1" = "--help" -o "$1" = "-h" ]; then
- usage
- exit 0
- fi
- # added this line and moved some declarations to allow for the full display instead of a truncated version
- if [ "$1" = "--full" -o "$1" = "-f" ]; then
- unset COLSTRING
- main
- fi
- if [ -n "$1" ]; then
- printf "\nUnknown parameter '$1'\n" >&2
- usage
- exit 1
- fi
- main
|