Bash script checking CPU usage by a specific process

First, I am new to this. I have experience with windows scripting and apple script, but not much with bash. What I am trying to do is grab the PID and% CPU of a particular process. then compare the% CPU with the set number, and if it is higher, kill the process. I feel like I'm close, but now I am getting the following error:

[[: 0.0: syntax error: invalid arithmetic operator (error token ".0")

what am I doing wrong? here's my code:

#!/bin/bash
declare -i app_pid
declare -i app_cpu
declare -i cpu_limit
app_name="top"
cpu_limit="50"
app_pid=`ps aux | grep $app_name | grep -v grep | awk {'print $2'}`
app_cpu=`ps aux | grep $app_name | grep -v grep | awk {'print $3'}`
if [[ ! $app_cpu -gt $cpu_limit ]]; then
     echo "crap"
else
     echo "we're good"
fi

      

Obviously I'm going to replace the echo in the if / then statement, but it acts like the statement is true no matter what the CPU load actually is (I tested this by changing -gt to -lt and it still echoes " shit"

Thanks for the help. Oh, and that's on OS X 10.7, in case that matters.

+3


source to share


7 replies


The problem is that bash cannot handle decimals. You can simply multiply them by 100 and work with equal integers instead:

#!/bin/bash
declare -i app_pid
declare -i app_cpu
declare -i cpu_limit
app_name="top"
cpu_limit="5000"
app_pid=`ps aux | grep $app_name | grep -v grep | awk {'print $2'}`
app_cpu=`ps aux | grep $app_name | grep -v grep | awk {'print $3*100'}`
if [[ $app_cpu -gt $cpu_limit ]]; then
     echo "crap"
else
     echo "we're good"
fi

      



Keep in mind that CPU percentage is not an optimal measure of an application's health. If you have two processes with infinite loops on the same base system, no other application with the same priority will ever exceed 33%, even if they are bypassed.

+5


source


I recommend looking at the possibilities ps

to avoid a few terrible things you do.

On my system ( ps

from procps on linux, GNU awk) I would do the following:



ps -C "$app-name" -o pid=,pcpu= | 
    awk --assign maxcpu="$cpu_limit" '$2>maxcpu {print "crappy pid",$1}'

      

+6


source


#!/bin/sh
PROCESS="java"
PID=`pgrep $PROCESS | tail -n 1`
CPU=`top -b -p $PID -n 1 | tail -n 1 | awk '{print $9}'`
echo $CPU

      

+2


source


I am using top

to check some details. It provides a bit more detail like CPU time.

top -l 1  | grep $app_name

      

0


source


I came up with this using top and bc.

Use it by going to ex: ./script apache2 50 # max 50%

If there are many PIDs that match your program argument, only one will be calculated based on how they are listed. I could extend the script to catch them all and increase the percentage or something, but that would have to be done.

You can also pass in a number, ./script.sh 12345 50

which will force it to use the exact PID.

#!/bin/bash

# 1: ['command\ name' or PID number(,s)] 2: MAX_CPU_PERCENT

[[ $# -ne 2 ]] && exit 1
PID_NAMES=$1
# get all PIDS as nn,nn,nn
if [[ ! "$PID_NAMES" =~ ^[0-9,]+$ ]] ; then
    PIDS=$(pgrep -d ',' -x $PID_NAMES)
else
    PIDS=$PID_NAMES
fi
#  echo "$PIDS $MAX_CPU"
MAX_CPU="$2"
MAX_CPU="$(echo "($MAX_CPU+0.5)/1" | bc)"
LOOP=1
while [[ $LOOP -eq 1 ]] ; do
    sleep 0.3s
    # Depending on your 'top' version and OS you might have
    #   to change head and tail line-numbers
    LINE="$(top -b -d 0 -n 1 -p $PIDS | head -n 8 \
        | tail -n 1 | sed -r 's/[ ]+/,/g' | \
        sed -r 's/^\,|\,$//')"
    # If multiple processes in $PIDS, $LINE will only match\
    #   the most active process
    CURR_PID=$(echo "$LINE" | cut -d ',' -f 1)
    # calculate cpu limits
    CURR_CPU_FLOAT=$(echo "$LINE"| cut -d ',' -f 9)
    CURR_CPU=$(echo "($CURR_CPU_FLOAT+0.5)/1" | bc)
    echo "PID $CURR_PID: $CURR_CPU""%"
    if [[ $CURR_CPU -ge $MAX_CPU ]] ; then
        echo "PID $CURR_PID ($PID_NAMES) went over $MAX_CPU""%"
        echo "[[ $CURR_CPU""% -ge $MAX_CPU""% ]]"
        LOOP=0
        break
    fi
done
echo "Stopped"

      

0


source


Eric, I used a modified version of your code to create a new script that does something like this. I hope you don't mind.

A bash script to get the CPU usage by process Usage:

nohup ./check_proc bwengine 70 &

      

bwegnine

- this is the name of the process we want to monitor 70 - this is only logged when the process is using more than 70% of the CPU.

Check the logs: /var/log/check_procs.log

The output should look like this:

DATE | TOTAL CPU | CPU USAGE | Process details

      

Example:

03/12/14 17:11 |20.99|98| ProdPROXY-ProdProxyPA.tra

03/12/14 17:11 |20.99|100| ProdPROXY-ProdProxyPA.tra

      

Full blog link: http://felipeferreira.net/?p=1453

0


source


It is also useful to have app_user

information available to check if the current user has permission to kill / modify the current process. This information can be obtained along with the necessary app_pid

and app_cpu

with the help read

, eliminating the need for awk

or any other parser parser:

read app_user app_pid tmp_cpu stuff <<< \
$( ps aux | grep "$app_name" | grep -v "grep\|defunct\|${0##*/}" )

      

Then you can get app_cpu * 100

with

app_cpu=$((${tmp_cpu%.*} * 100))

      

Note. Inclusion defunct

and ${0##*/}

in grep -v

prevents multiple processes matching $app_name

.

0


source







All Articles