Last active
December 16, 2020 12:22
-
-
Save zarnovican/9840d171d9a9c6de1766 to your computer and use it in GitHub Desktop.
Telegraf plugin to get summary CPU/mem usage for a tree of processes
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 | |
# | |
# Telegraf input plugin to get summary cpu/mem/io usage for | |
# a tree of processes. Identify top process(es) by | |
# pid file, pgrep pattern or owner. | |
# | |
# Note: it requires root to be able to read 'smaps'. | |
# Note: pattern match (-p) can catch the plugins itself | |
# | |
# Output fields: | |
# cpu_user [ticks] - sum(utime)/100 (see 'man 5 proc' for /proc/<pid>/stat) | |
# cpu_system [ticks] - sum(stime)/100 (see 'man 5 proc' for /proc/<pid>/stat) | |
# nprocess [count] - number of processes (including all children) | |
# mem_pss/rss [B] - sum(pss)*1024 (see 'man 5 proc' for /proc/<pid>/smaps) | |
# io_read/write [B] - sum(read/write_bytes) (see 'man 5 proc' for /proc/<pid>/io) | |
# io_syscr/syscw [count] - sum(syscr/syscw) (see 'man 5 proc' for /proc/<pid>/io) | |
# fd_count [count] - file-descriptor count | |
# | |
function usage() { | |
echo "usage: `basename $0` <options>" | |
echo " -f PIDFILE get pids from PIDFILE" | |
echo " -p PATTERN get pids from pgrep PATTERN" | |
echo " -u USER get pids owned by USER" | |
echo " -h this help screen" | |
} | |
function descendants() { | |
# return all process descendants from a given list of pids | |
# (including pids from input) | |
declare -a pidlist=($*) | |
for ((i=0; i<${#pidlist[@]}; i++)) { | |
p=${pidlist[$i]} | |
[ -z "$p" -o "$p" -eq "$$" ] && continue | |
# append all direct children of $p | |
pidlist+=(`pgrep -P "$p" 2>/dev/null`) | |
} | |
echo ${pidlist[@]} | tr ' ' '\n' | sort -u | |
} | |
function cpustat() { | |
for p in $*; do | |
cat "/proc/$p/stat" 2>/dev/null | |
done | awk ' | |
BEGIN { utime = stime = count = 0 } | |
{ utime += $14; stime += $15; count++ } | |
END { printf "%.2f %.2f %d\n", utime/100, stime/100, count }' | |
} | |
function memstat() { | |
for p in $*; do | |
cat "/proc/$p/smaps" 2>/dev/null | |
done | awk ' | |
BEGIN { pss = rss = cache = 0 } | |
$1 ~ /^[0-9a-f]/ { | |
if ($4 ~ /ca:/ ) { | |
cache = 1 | |
} else { | |
cache = 0 | |
} | |
} | |
$1 == "Pss:" && !cache { pss += $2 } | |
$1 == "Rss:" && !cache { rss += $2 } | |
END { printf "%.0f %.0f\n", pss * 1024, rss * 1024 }' | |
} | |
function iostat() { | |
for p in $*; do | |
cat "/proc/$p/io" 2>/dev/null | |
done | awk ' | |
BEGIN { read_bytes = write_bytes = syscr = syscw = 0 } | |
$1 == "read_bytes:" { read_bytes += $2 } | |
$1 == "write_bytes:" { write_bytes += $2 } | |
$1 == "syscr:" { syscr += $2 } | |
$1 == "syscw:" { syscw += $2 } | |
END { printf "%d %d %d %d\n", read_bytes, write_bytes, syscr, syscw }' | |
} | |
function fdstat() { | |
for p in $*; do | |
ls -1 "/proc/$p/fd" 2>/dev/null | |
done | wc -l | |
} | |
pidfile= | |
pattern= | |
user= | |
while getopts "f:p:u:h" opt; do | |
case $opt in | |
f) pidfile=$OPTARG ;; | |
p) pattern=$OPTARG ;; | |
u) user=$OPTARG ;; | |
h) usage; exit 0 ;; | |
*) exit 2 ;; | |
esac | |
done | |
shift $((OPTIND - 1)) | |
pidlist= | |
if [ -n "$pidfile" ]; then | |
pidlist=$(cat "$pidfile" 2>/dev/null) | |
elif [ -n "$pattern" ]; then | |
pidlist=$(pgrep -f "$pattern") | |
elif [ -n "$user" ]; then | |
pidlist=$(pgrep -U "$user") | |
else | |
echo "Specify either <pidfile>, <pattern> or <user>" 1>&2 | |
usage | |
exit -1 | |
fi | |
if [ -z "$pidlist" ]; then | |
# no match | |
exit 0 | |
fi | |
pidlist2=$(descendants "$pidlist") | |
declare -a cpu=(`cpustat $pidlist2`) | |
declare -a mem=(`memstat $pidlist2`) | |
declare -a io=(`iostat $pidlist2`) | |
fd_count=`fdstat $pidlist2` | |
echo -n "sumproc cpu_user=${cpu[0]},cpu_system=${cpu[1]},nprocess=${cpu[2]}i," | |
echo -n "mem_pss=${mem[0]}i,mem_rss=${mem[1]}i," | |
echo -n "io_read=${io[0]}i,io_write=${io[1]}i,io_syscr=${io[2]}i,io_syscw=${io[3]}i," | |
echo "fd_count=${fd_count}i" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment