20

I need the command to kill processes that have been running since at least 5 minutes for a given process.

I will have to run that command every five minutes or so.

Thanks a million !

(system is Centos5)

7 Answers 7

23
kill -9 $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print $2}}')

where "procname" is a process name and 300 is running time threshold

4
  • Great oneliner. I've used it without -9 to be a little friendlier to my processes and added a grep -v defunct | before awk as otherwhise you may see procname <defunct> in your output which would make the awk command not return a valid PID. And this would break the kill command. Commented Jul 9, 2016 at 9:15
  • i would say $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}') is a little bit smoother but the answer is great anyway Commented Mar 1, 2018 at 20:52
  • @WhiteHat how would do the same thing but for a process with certain pid? Commented Feb 16, 2019 at 19:17
  • one thing wasted my time is that: should use ' with awk NOT " Commented Feb 28, 2019 at 12:34
8

Maybe run the long running command like this in a crontab?

timeout -k 300 command
7

My version of kill script, taking benefits from both previous answers:

#!/bin/bash

#Email to send report
MY_EMAIL="[email protected]"

#Process name to kill
NAME_KILL="php"

#UID to kill
UID_KILL=33.

#Time in seconds which the process is allowed to run
KILL_TIME=60

KILL_LIST=()
EMAIL_LIST=()
while read PROC_UID PROC_PID PROC_ETIMES PROC_ETIME PROC_COMM PROC_ARGS; do
    if [ $PROC_UID -eq $UID_KILL -a "$PROC_COMM" == "$NAME_KILL" -a $PROC_ETIMES -gt $KILL_TIME ]; then
    KILL_LIST+=("$PROC_PID");
    MSG="Killing '$PROC_ARGS' which runs for $PROC_ETIME";
    EMAIL_LIST+=("$MSG");
    echo "$MSG";
    fi
done < <(ps eaxo uid,pid,etimes,etime,comm,args | tail -n+2)
if [ ${#KILL_LIST[*]} -gt 0 ]; then
    kill -9 ${KILL_LIST[@]}
    printf '%s\n' "${EMAIL_LIST[@]}" | mail -s "Long running processes killed" $MY_EMAIL
fi

It filters process by UID, NAME and if execution time exceeds limit - kills processes and sends report to email. If you don't need that email - you can just comment last line.

2

I found the solution on this page: http://www.directadmin.com/forum/showthread.php?t=26179

Make a empty file and call it killlongproc.sh

Copy this:

#!/bin/bash
# This script will kill process which running more than X hours
# egrep: the selected process; grep: hours
PIDS="`ps eaxo bsdtime,pid,comm | egrep "spamd|exim|mysqld|httpd" | grep " 1:" | awk '{print $2}'`"

# Kill the process
echo "Killing spamd, exim, mysqld and httpd processes running more than one hour..."
for i in ${PIDS}; do { echo "Killing $i"; kill -9 $i; }; done;

Stop this in your cronjob

15 * * * * * root /{directory}/./killongproc.sh
3
  • 5
    It's usually a bad idea to do this. What problem are you really trying to solve? Also, you shouldn't use kill -9 since it doesn't give processes a chance to do a graceful cleanup before exiting. Commented Aug 1, 2010 at 14:10
  • 1
    This kills processes which consumed some amount of CPU time (user+system), not processes which are running for some amount of real time (e.g. started before 1 hour). Commented Oct 7, 2014 at 9:37
  • how would I find the process older than 30 minutes and not an hour Commented May 17, 2021 at 20:32
2

There is a script here that you could modify to do what you want.

EDIT added the script below

#!/bin/bash
#
#Put the UID to kill on the next line
UID_KILL=1001

#Put the time in seconds which the process is allowed to run below
KILL_TIME=300

KILL_LIST=`{
ps -eo uid,pid,lstart | tail -n+2 |
    while read PROC_UID PROC_PID PROC_LSTART; do
        SECONDS=$[$(date +%s) - $(date -d"$PROC_LSTART" +%s)]
        if [ $PROC_UID -eq $UID_KILL -a $SECONDS -gt $KILL_TIME ]; then
        echo -n "$PROC_PID "
        fi
     done 
}`

if [[ -n $KILL_LIST ]]
then
        kill $KILL_LIST
fi
3
  • I have no enought knowledge to modify it, that's why I'm asking you Commented Aug 1, 2010 at 12:52
  • 2
    Too complicated. You can use column etimes of ps to show you directly the elapsed seconds since process start (no need to compute it from start time). Commented Oct 7, 2014 at 9:42
  • @Marki555 yes this is true. However on systems with versions of ps that do not support etimes (only etime) then this is a great alternative. I just used it when the top answer gave me an error from ps Commented Nov 22, 2018 at 1:54
0

I had to solve a similar task, and it doesn't need a script. For terminating (signal SIGTERM) processes of executable "THECOMMAND":

killall -u $USER --older-than 5m THECOMMAND

The restriction to current user -u $USER is necessary only to avoid unnecessary error messages if other users also run "THECOMMAND". In your own user crontab you would enter the following:

*/5 * * * *     killall -u $USER --older-than 5m THECOMMAND

In a system crontab (user 'root') you would add the following:

*/5 * * * *     killall --older-than 5m THECOMMAND

If you want to kill (SIGKILL) the processes instead of terminating (SIGTERM) them, explicitly send the SIGKILL signal by adding --signal SIGKILL to the parameters. Example for a system crontab:

*/5 * * * *     killall --older-than 5m --signal SIGKILL THECOMMAND
-4

For httpd

ps eaxo pid,time,comm | tail -n+2 | grep ' httpd' | awk 'substr($0,9,1)>0' | awk '{print $1}'

You must log in to answer this question.