0

I am trying to write a shell script to kill a specified process if it runs more than specified time and get process information before killing.

Note: Script should take process name and time as input. What I have tried so far is as below:

#!/bin/sh
ps -eaf |
awk '{print $7, $8}' |
sort -n |
grep -v TIME |
grep -v 00:00:00 |
awk -F ":" '{if ( $2 >= 01 ) print}'

the o/p prints as follows:

00:08:15 /usr/bin/dockerd
00:17:41 /usr/bin/kubelet

this is where I stuck ... I need to kill which are more than 01 min so the above process needs to be killed using a script input as process name and time.

1
  • Why don't you just run the process with timeout (from GNU coreutils)?
    – Kusalananda
    Aug 8 '19 at 16:34
0

IMHO, you are in a cul-de-sac and there is no way to do what do you want that way.

The problem is that your TIME information is stale because, probably, the TIME property of that processes changed while the script is running. The couple TIME, CMD cannot identify a process.

Why do you do awk '{print $7, $8}'? At that point you do not need the CMD, you need only the PID to identify the process, so simply change it to awk '{print $7, $2}'.

You could change your code as follows to print the PIDs of the processes you are searching for:

ps -eaf \
| awk '{print $7, $2}' \
| sort -n \
| grep -v TIME \
| grep -v 00:00:00 \
| awk -F ":" '{if ( $2 >= 01 ) print}' \
| awk '{print $2}'

In addition, your code has a subtle bug: what happens if a process has 04:00:23 as TIME? Your code will skip it because checks only minutes field in TIME. You can fix it this way:

ps -eaf \
| awk '{print $7, $2}' \
| sort -n \
| grep -v TIME \
| grep -v 00:00:00 \
| awk -F ":" '{if (( $1 >= 01 ) || ( $2 >= 01 )) print}' \
| awk '{print $2}'

Some suggestions to improve your skills:

  • You should check the -o option of ps and the -F option of awk and, perhaps, the meaning of TIME column of ps.
  • Try to understand how the following line works:

    ps -eo time,pid --no-headers | awk -F '[ :]*' '$1>0 || $2>0 {print $4}' | xargs kill
    
0

You can get the CPU time in second along with pid and command with:

ps -Ao time= -o pid= -o comm= |
  perl -lpe 's/^(\d+-)?(\d\d):(\d\d):(\d\d)/(($1*24+$2)*60+$3)*60+$4/e'

You can do the killing with perl as well:

ps -Ao time= -o pid= -o comm= |
  perl -lne '
    if (/^(\d+-)?(\d\d):(\d\d):(\d\d)\s+(\d+)\s+(.*)/) {
      $cputime = (($1*24+$2)*60+$3)*60+$4;
      $pid = $5;
      $comm = $6;
      if ($cputime > 60) {
        print "$pid ($comm) has used $cputime seconds of CPU, killing it";
        kill "TERM", $pid or warn "kill($pid): $!\n";
      }
    }'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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