Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am currently using Monit to monitor Apache and restart it if its memory usage is too high. However, I'd also like to be able to monitor the individual apache2 subprocesses that are spawned, and kill any subprocess whose memory usage is too high over a period of a few minutes. How can I do that?

share|improve this question
up vote 3 down vote accepted

Monit's documentation suggests that you can natively monitor the total memory used by Apahce and its child processes, not any individual child process.

However, you can check the return status of a script using the check program test:

So, you can do something like this as a check script:

threshold=10000 # 10MB

for childmem in $(ps h orss p $(pgrep -P $(cat /var/run/
  if [ $childmem -gt $threshold ]; then
     exit 1
exit 0

If that script is /usr/local/bin/, then you can do something like:

 check program myscript with path "/usr/local/bin/"
       if status != 0 then exec "/usr/local/bin/"

The kill script will presumably look like the check script, but with a kill on the PID instead of an exit.

The scripts are, of course, illustrative, and should be modified to your environment.

share|improve this answer
Nice workaround. – ewwhite Jul 17 '12 at 16:57
Monit = nice and simple if you can work within the provided primitives. If not, then you have more and more complicated workarounds, and then you think, "why didn't I use Nagios?" – cjc Jul 17 '12 at 17:42
Thanks, this is exactly what I needed. I'm going to post the exact solution I used below, in case it helps anyone else. – Matt White Jul 17 '12 at 19:28

I accepted cjc's answer above, but wanted to post exactly how I used his suggestion to solve this problem. Note that you will need to use at least Monit 5.3 to use Monit's "check program". I am running Debian.


#!/usr/bin/env bash


date_nice=$(date +'%Y-%m-%d %H:%M:%S')
date_seconds=$(date +'%s')
apache_children=$(ps h -o pid,%mem p $(pgrep -P $(cat /var/run/ | sed 's/^ *//' | tr ' ' ',' | sed 's/,,/,/g')

for apache_child in $apache_children; do
  pid=`echo $apache_child | awk -F, '{ print $1 }'`
  mem=`echo $apache_child | awk -F, '{ print $2 }'`
  mem_rounded=`echo $apache_child | awk -F, '{ printf("%d\n", $2 + 0.5) }'`

  if [ $mem_rounded -ge $mem_limit ]; then
    log_entry_count=$(cat $log_file | grep -v 'KILLED' | grep " $pid; " | wc -l)
    log_entry_time=$(cat $log_file | grep -v 'KILLED' | grep " $pid; " | tail -$kill_after_minutes | head -1 | awk '{ print $3 }')

    if [ "$1" != "kill" ]; then
      echo "$date_nice $date_seconds Process: $pid; Memory Usage: $mem" >> $log_file

    if [ $((date_seconds - log_entry_time)) -le $(((kill_after_minutes * 60) + 30)) ] && [ $log_entry_count -ge $kill_after_minutes ]; then
      if [ "$1" = "kill" ]; then
        kill -9 $pid
        echo "$date_nice $date_seconds ***** KILLED APACHE2 PROCESS: $pid; MEMORY USAGE: $mem" >> $log_file

exit $exit_code


check program apache2_children
  with path "/usr/local/bin/monit_check_apache2_children"
  if status != 0 then exec "/usr/local/bin/monit_check_apache2_children kill"
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.