Linux top io processes

I needed a way to find out which process in Linux was doing the most io.  I didn't want to install anything to the server either.  This makes a big constraint.

So, I developed a bash script that will do this on a modern Linux kernel.  It's not perfected yet, but it should help you find the process doing the most io without having to install anything on the server.

#! /bin/bash

function is_number() {
       if [ $1 -eq $1 2> /dev/null ]; then
               return 1
       fi
}

function get_leaf_path() {
       leaf_path=${1##*/}
}

first_flag=1
flip=0
while [[ 1 ]];  do
# loop through running processes
unset DeltaReads
unset DeltaWrites

for p in /proc/*
do
       if [ -d $p ]; then
               #set leaf_path to the last subdirectory name in the path
               get_leaf_path $p
               #check if the leaf_path is numeric
               is_number $leaf_path
               res=$?
               if (( $res > 0 )); then
                       #now we have a PID let's get its stats
                       io=`cat $p/io`
                       cmd=`cat $p/cmdline`
                       cmd=`echo "$cmd"|tr -d '[:cntrl:]\000\040'`
                       #get write_bytes number
                       pattern="write_bytes: ([0-9]+)"
                       [[ $io =~ $pattern ]]
                       #get bytes
                       wbytes=${BASH_REMATCH[1]}
                       #get read_bytes number
                       pattern="read_bytes: ([0-9]+)"
                       [[ $io =~ $pattern ]]
                       rbytes=${BASH_REMATCH[1]}
                       #set Reads element to 0 if it is null or empty
                       if [[ -z "${Reads[$leaf_path]+x}" ]]; then
                               Reads[$leaf_path]=0
                       fi
                       if [[ -z "${Writes[$leaf_path]+x}" ]]; then
                               Writes[$leaf_path]=0
                       fi
                       # is this PID reused?
                       if [[ "$cmd" != "${Cmdline[$leaf_path]}" ]]; then
                               DeltaReads[$leaf_path]=0
                               DeltaWrites[$leaf_path]=0
                               #echo "cmd     " $cmd "||||||||||"
                               #echo "prevcmd " ${Cmdline[$leaf_path]} "||||||||||"
                       else
                               DeltaReads[$leaf_path]=$(($rbytes - Reads[$leaf_path]))
                               DeltaWrites[$leaf_path]=$(($wbytes - Writes[$leaf_path]))
                       fi
                       DeltaTot[$leaf_path]=$((DeltaReads[$leaf_path]+DeltaWrites[$leaf_path]))
                       Reads[$leaf_path]=$rbytes
                       Writes[$leaf_path]=$wbytes
                       Cmdline[$leaf_path]=$cmd
               fi
       fi
done

#remove information for old PIDs
for i in "${!Cmdline[@]}"; do
       if [[ ! -d /proc/$i  ]]; then
               #process $i was not found on this cycle
               unset DeltaTot[$i]
               unset DeltaReads[$i]
               unset DeltaWrites[$i]
               unset Reads[$i]
               unset Writes[$i]
               unset Cmdline[$i]
       fi
done

#Output results
clear
if [[ $first_flag -eq 0 ]]; then
printf "%5s %35s %10s %10s %10s\n" "PID" "CMD" "DeltaTot" "DWrites" "DReads"
deltatoto=0

for i in "${!DeltaTot[@]}"; do
       printf "%5s %35s %10s %10s %10s %10s\n" $i ${Cmdline["$i"]:0:35} ${DeltaTot["$i"]} ${DeltaWrites["$i"]} ${DeltaReads["$i"]}
done |
sort -brn -k4 | head -20

for i in "${!DeltaTot[@]}"; do
       deltatoto=$((${DeltaTot[$i]} + $deltatoto))
done
tput bold
echo "Delta Total: " $deltatoto
tput sgr0
fi
first_flag=0
done

No comments:

Post a Comment