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. 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
    – Yevgen
    Mar 1, 2018 at 20:52
  • @WhiteHat how would do the same thing but for a process with certain pid? Feb 16, 2019 at 19:17
  • one thing wasted my time is that: should use ' with awk NOT "
    – cn123h
    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. 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).
    – Marki555
    Oct 7, 2014 at 9:37
  • how would I find the process older than 30 minutes and not an hour 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
    – Pierre
    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).
    – Marki555
    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
    – mike
    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.