4

I am sometimes stuck in a situation where a script/command kept in Cron runs more than once because of some reasons (the first instance is not completed fully, the second instance of the same process starts) and at some point of time these processes increase a lot and show system hanging etc. So, what I want as a temporary solution here is to check if there are more than one instances of the script/command say,

ps -ef | pgrep -f 'DELETE OPERATION_CONTEXT'

or directly kill all the processes of this command

ps -ef | pkill -f 'DELETE OPERATION_CONTEXT'

But I want an idea how I can kill all the processes of pgrepped command except for the first process (this would let one of the process to keep working and all other duplicates to get killed).

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Ankit Vashistha
  • 3,487
  • 12
  • 31
  • 36
  • if you post , output of pgrep then it would be easy using `xargs` – Rahul Patil Jan 02 '13 at 12:08
  • 2
    Preventing the duplicates might be a better idea? Check if file exist with a valid PID at startup (possibly event check its name vs $0). If it is invalid or doesn't exist, create a file with the PID and run the script. Delete file when script is complete. (Finding that a file is missing is much quicker than reading its contents, checking if it is a valid PID, etc...) – Gert van den Berg Jan 02 '13 at 12:14
  • You do not need `ps -ef |` in front of pgrep/pkill. – jofel Jan 02 '13 at 12:14
  • As Gert wrote, it would be easier and more useful to ensure that only one instance of the cron job is running. See [Quick-and-dirty way to ensure only one instance of a shell script is running at a time](http://stackoverflow.com/q/185451) – Gilles 'SO- stop being evil' Jan 02 '13 at 23:21

4 Answers4

3

Below Example of apache2 process, it will kill all PID's except first one

pgrep apache2 |awk 'NR >= 2' | xargs -n1  echo kill

if output of above command looks fine , then you can remove echo

Rahul Patil
  • 24,281
  • 25
  • 80
  • 96
2

you can try this out:

ps -e --sort=start -o start,pid,cmd|grep <cmd>|egrep -v grep |sed 1d

this will give you the following formatted output:

start time, PID, command being executed

for i in `ps -e --sort=start -o start,pid,cmd|grep <cmd>|egrep -v grep |sed 1d`
do
     kill -9 $i
done

replace the kill by echo first to ensure that it will kill the news ones.

BitsOfNix
  • 5,057
  • 2
  • 25
  • 34
2

You can do this for example with:

OLDEST_PID=$(pgrep -o 'DELETE OPERATION_CONTEXT')
test $OLDEST_PID && pgrep 'DELETE OPERATION_CONTEXT' | grep -vw $OLDEST_PID | xargs -r kill

The first line finds the oldest PID. The second line checks first if $OLDEST_PID contains something. If yes, it list all matching processes, filters the $OLDEST_PID out and kill them (if any remain).

A better way is to avoid duplicated processes by adding lockfiles to the cron script like in this question.

jofel
  • 26,513
  • 6
  • 65
  • 92
0

if you have java crons and want to check before execution of that cron then try this : System.out.println("Checking for previous sessions for this cron: "+cronname);

            String proname=ManagementFactory.getRuntimeMXBean().getName();
            String pid=proname.split("@")[0];
            System.out.println("Current PID:"+pid);

            Process proc = Runtime.getRuntime().exec(new String[]{"bash","-c"," ps aux | grep "+cronname+" | awk '{print $2}' "});

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String s = null;
            String killid="";

            while ((s = stdInput.readLine()) != null ) {                                        
                if(s.equals(pid)==false)
                {
                    killid=killid+s+" ";    
                }
            }
            System.out.println("Running PID'S except current:"+killid);

            proc.waitFor();             

            Process proc1 = Runtime.getRuntime().exec(new String[]{"bash","-c","kill -9 "+killid});
            proc1.waitFor();                

            System.out.println("Previous duplicate sessions closed for: "+cronname);        

pass cronname as ur cronname.jar