When I first experienced an unresponsive server due to an over zealous Apple IMAP-client I found and used this python script.
http://www.patlathem.com/identifying-courier-imap-io-abusers/
This python-script is like iotop, but it focuses on imap and shows the user that's hogging down your server
It wasn't properly working after a Plesk upgrade, so I decided to see what it was doing and rewrite it in bash...
I know bash is a terrible language to script, but it's what I'm good in.
cat /usr/local/sbin/imapio2
http://www.patlathem.com/identifying-courier-imap-io-abusers/
This python-script is like iotop, but it focuses on imap and shows the user that's hogging down your server
It wasn't properly working after a Plesk upgrade, so I decided to see what it was doing and rewrite it in bash...
I know bash is a terrible language to script, but it's what I'm good in.
cat /usr/local/sbin/imapio2
Code:
#!/bin/bash
# Obtain the user that's running the imapd daemon
BIN=imapd
PROG=`which ${BIN}`
IMAPD_USER=`ps aux | grep -i "[0-9] ${PROG}" | awk '{print $1}' | sort | uniq -c | sort -n | tail -n1 | awk '{print $2}'`
# Create a TEMP-folder in /dev/shm (faster) and use its directory as a database (like /proc itself)
TMPDIR1=`mktemp -p /dev/shm -d ${0//*\/}.XXXXXXXXXX`
trap '{ echo "Quit..." ; rm -r ${TMPDIR1} ; exit 0; }' INT
while true ; do
# find all folders in /proc created by imapd
find /proc -mindepth 1 -maxdepth 1 -type d -user ${IMAPD_USER} -mtime -1 2>/dev/null >${TMPDIR1}/PIDS
rm -r ${TMPDIR1}/USERS/ 2>/dev/null
while read PID ; do
if [ ! -d ${TMPDIR1}${PID} ] ; then
# Create a folder in my TEMP-folder with the same name as in /proc
# Also get the IP and EMAIL-address for this connection and save it in that same folder
# set read and write counters to 0
mkdir -p ${TMPDIR1}${PID} 2>/dev/null
echo -n '0' >${TMPDIR1}${PID}/READ
echo -n '0' >${TMPDIR1}${PID}/WRITE
IP=`grep --binary-files=text -o 'TCPREMOTEIP=[0-9a-f.:]*' ${PID}/environ 2>/dev/null | awk -F= '{print$2}' | egrep -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | awk '{ printf("%-17s",$0)}'`
NAME=`grep --binary-files=text -o 'AUTHENTICATED=.*' ${PID}/environ 2>/dev/null | awk -F= '{print$2}'`
# In case the /proc/???? folder vanished while processing the structure skip to next /proc/????
[ -z "${NAME}" ] && continue
echo "${IP}${NAME}" >${TMPDIR1}${PID}/USER
fi
USER=`cat ${TMPDIR1}/${PID}/USER`
# get info out of /proc/????/io
READ=` grep '^read_bytes:' ${PID}/io 2>/dev/null | awk '{print $2}'`
WRITE=`grep '^write_bytes:' ${PID}/io 2>/dev/null | awk '{print $2}'`
# Some sanity checking to avoid runtime errors in case the folder vanishes before it can be processed
[ -z "${READ}" ] && continue
[ -z "${WRITE}" ] && continue
# read old values out of /TMP/proc/???/READ and /TMP/proc/???/WRITE
OLDREAD=`cat ${TMPDIR1}/${PID}/READ`
OLDWRITE=`cat ${TMPDIR1}/${PID}/WRITE`
# calculate the difference since last cycle
DIFF_READ=$((${READ} - ${OLDREAD}))
DIFF_WRITE=$((${WRITE} - ${OLDWRITE}))
# write new values to /TMP/proc/???/READ and /TMP/proc/???/WRITE
echo ${READ} >${TMPDIR1}/${PID}/READ
echo ${WRITE} >${TMPDIR1}/${PID}/WRITE
# create the cumulative folder for this USER/IP in /TMP/USERS/??????
if [ ! -d "${TMPDIR1}/USERS/${USER}" ] ; then
mkdir -p "${TMPDIR1}/USERS/${USER}"
echo -n '0' >"${TMPDIR1}/USERS/${USER}/READ"
echo -n '0' >"${TMPDIR1}/USERS/${USER}/WRITE"
fi
CUM_READ=`cat "${TMPDIR1}/USERS/${USER}/READ"`
CUM_WRITE=`cat "${TMPDIR1}/USERS/${USER}/WRITE"`
echo $(( ${CUM_READ} + ${DIFF_READ})) >"${TMPDIR1}/USERS/${USER}/READ"
echo $(( ${CUM_WRITE} + ${DIFF_WRITE})) >"${TMPDIR1}/USERS/${USER}/WRITE"
done<${TMPDIR1}/PIDS
# get all folders with the cumulative values of this IP/USER combination
find ${TMPDIR1}/USERS/ -mindepth 1 -maxdepth 1 -type d 2>/dev/null >${TMPDIR1}/USERNAMES
echo -n '' >${TMPDIR1}/OUTPUT
while read USERDIR ; do
echo -n "${USERDIR##*/}:" | awk '{ printf("%-50s",$0)}' >>${TMPDIR1}/OUTPUT
echo -e "\t\t`cat "${USERDIR}/READ"`\t\t`cat "${USERDIR}/WRITE"`" >>${TMPDIR1}/OUTPUT
done<${TMPDIR1}/USERNAMES
# Sort on write value and filter non-changed entries
egrep -v '\s+0\s+0' ${TMPDIR1}/OUTPUT | sort -rn -t $'\t' -k5 >${TMPDIR1}/OUTPUTSORTED
if [ -s ${TMPDIR1}/OUTPUTSORTED ] ; then
printf "\ec"
cat ${TMPDIR1}/OUTPUTSORTED
fi
sleep 1
done