Bash script to periodically monitor a process's memory usage

I'm looking for a bash script that allows me to start a process in background, monitor its memory consumption every 10 minutes for example, and if it exceeds a certain value kill it and restart it.
Some idea?
I'm new to bash programming, I started writing a script and after testing it I always get the same error,

syntax error near unexpected token 'fi'

how to proceed? I run the code on an ec2 aws istance

    #note that this code is incomplete while loop missing
    #!/usr/bin/bash
    sudo python3 main.py &
    pidlist=$(pidof python3 main.py)
    read FIRST __ <<< "$pidlist"
    echo "$FIRST"
    #memory in percent
    mem=$(ps -p "$FIRST" -o %mem)
    echo "$mem"
    set -- $mem
    memory="$2"
    if [ "$memory" -gt "20.0" ];then
      echo "killing process"
    fi

Hello and welcome
It's customary to help on this resource, that is, you solve a problem and you don't succeed or you're stuck on something and don't know how to continue. Therefore, if you have a desire to try to write such a script yourself, then everyone here will readily help you. In addition,
creation is much more interesting and useful. The script is quite ordinary and writing will take much less time than finding a ready-made solution. If you are ready to make an effort, it is useful to start by breaking the task down into stages.

First, launching the scheduled task. For this, I think 'crontab' will work well.

Second, getting value of consumption process memory. The 'ps' utility is well suited for this, which can take a command name with the option '-C' or the process id with '-p' option. Using the formatted '-o pmem=' output, you can get memory consumption in percentage terms. This value is of type float, but cutting off the decimal part will not be a problem.

And last, comparing the obtained value with a constant, we determine the need for restarting the process.

My regards

4 Likes

I'm new to bash programming, I started writing a script and after testing it I always get the same error,

syntax error near unexpected token 'fi'

how to proceed? I run the code on an ec2 aws istance

    #note that this code is incomplete while loop missing
    #!/usr/bin/bash
    sudo python3 main.py &
    pidlist=$(pidof python3 main.py)
    read FIRST __ <<< "$pidlist"
    echo "$FIRST"
    #memory in percent
    mem=$(ps -p "$FIRST" -o %mem)
    echo "$mem"
    set -- $mem
    memory="$2"
    if [ "$memory" -gt "20.0" ];then
      echo "killing process"
    fi

I can't reproduce that specific error with the script you posted. Sure you posted the correct and complete one?

Two comments:

  • The #! token ("shebang") HAS to be the first two chars of a script file in order to work.
  • bash doesn't handle floating variables or values - neither $memory which is filled by ps with decimals, nor the "20.0" constant.

EDIT: OK, got it:
your script lines seem to be terminated with DOS line terminators <CR> = \r = 0x0D = ^M. With

if [ "$memory" -gt "20" ];then^M
bash: syntax error near unexpected token `fi'

, I have the same error ...
Use a decent *nix text editor!

1 Like

thanks for the advice it worked now after some tests I have come to write this code

#!/bin/bash
sudo python3 main.py &
sleep 5
pidlist=$(pidof python3 main.py)
echo "$pidlist"
read FIRST __ <<< "$pidlist"
echo "$FIRST"
mem=$(ps -p "$FIRST" -o %mem)
echo "$mem"
set -- $mem
memory="$2"
while true;
do
  sleep 2
  echo "$memory"
  if (( $(echo "${memory} > 20.0" | bc) )); then
    echo "killing process"
    sudo kill "$FIRST"
    break
  fi
  sleep 2
done

I can correctly take the right pid of the process I would like to kill, but the sudo kill "$ FIRST" command does not seem to work and upon exiting the script, typing htop on the console, the process is still alive.
Also if I type sudo kill #pid directly on the console this command works and kills the process

I don't know why sudo kill PID should not work.

Another twothree comments:

  • bash provides the PID of the last process put in background in the $! variable ( man bash ).
  • suppress ps ' heading by supplying a = sign after the %mem so you have a single value.
  • modify the $memory value WITHIN the loop; else you will either immediately break out, or enter an infinite loop.

So your script could be reduced to

sudo python3 main.py &
while true;
  do    if (( $(ps -p "$!" -o %mem=) > 20" | bc) ))
          then  sudo kill "$!"
                break
        fi
  done

I found this thread after googling for a bash script to monitor a process's memory usage and kill it after it reaches a threshold.
The script in this thread was exactly what I needed but I had to change it a bit to suit my usecase better.
The following looks for processes with the name you provide and then iterates through that list and check usage. If it has too high of a usage it will kill the process. I haven't tested it to kill the actual process but from the information found in this thread and the one OP made on stackoverflow it should just work. If it doesn't I can force-kill the process with a sudo kill -9 [process] anyway :slight_smile:

Code:

#set -x
while(true)
do
  pidlist=$(pidof php-fpm)
  echo "$pidlist"
  for process in $pidlist
  do
    echo "$process"
    mem=$(ps -p "$process" -o %mem)
#    echo "$process is using $mem"
    set -- $mem
    memory="$2"
    sleep 2
    echo "$process is using $memory"
    if (( $(echo "${memory} > 20.0" | bc) )); then
      echo "killing process"
      sudo kill "$process"
      break
    fi
    sleep 2
  done
done

I hope someone like me will stumble upon this post and is able to re-purpose what he needs exactly how I did :slight_smile: