Reputation: 38
I'm trying to take the output of a ps axo uname,pid,etime,time,cmd
and kill all related processes with an etime>=10
I need to kill pids only for on specific users which are stored in a separate file, users.txt
Basically, I want to see all my columns and I want to find all php{5,54} processes that belong to specific users, stored in a file, and kill those processes if the execution time is over ten minutes. (kill -9 not needed)
Example ps output:
username 574 01:37 00:00:18 /ramdisk/bin/php54 /home/username/public_html/index.php
usernum2 1367 10:28 00:00:16 /ramdisk/bin/php54 /home/usernum2/public_html/index.php
user3 3971 1-04:17:31 00:00:14 /ramdisk/bin/php54 /home/user3/public_html/index.php
usernum4 9130 14:05:32 00:00:29 /ramdisk/bin/php54 /home/usernum4/public_html/index.php
username 9189 1-01:31:12 00:00:25 /ramdisk/bin/php54 /home/username/public_html/index.php
My thought has been to put the ps output into a file (say procs.txt), and then grep through that. EG:
ps axo uname,pid,etim,time,cmd | grep 'php5' | tee procs.txt
I could have two separate lines: one that says if column 3 is more than 5 characters kill the pid, which is easy, and then another with something like the following, but that doesn't leave me with the related pids, so I can't kill them:
for i in $( cat users.txt ); do grep $i procs.txt | awk '{print $3}' | awk -F: '{print $(NF-1)}' | awk '$1>=10{print $1}'; done
Upvotes: 1
Views: 1172
Reputation: 70392
The following is a solution in bash
.
To find all processes that match php5
or php54
, for users in a file, I would use the U
option to ps
and egrep
:
ps xo uname,pid,etim,time,cmd U"$(echo $(< users.txt))" | egrep '/php54? '
The U
option will only display the processes that belong to the supplied list of users. The <
is a shell builtin for cat
, and the use of echo
flattens the file entries into a single line that the ps
command expects.
'/php54? '
indicates that the 4
is optional, and the space at the end makes sure it doesn't match (for example) php52
. egrep
uses regular expressions, so it allows the use of the ?
meta character.
The output of this command can then be processed line by line with a while read
:
ps xo uname,pid,etim,time,cmd U"$(echo $(< users.txt))" | egrep '/php54? ' \
| while read a
do cols=($a)
elapsed=${cols[2]}
if [ ${#elapsed} -gt 5 ]
then kill ${cols[1]}
elif [ ${elapsed%%:*} -gt 9 ]
then kill ${cols[1]}
fi
done
cols
gets an array assignment, splitting the line a
on whitespace boundaries. USER is in cols[0]
, PID in cols[1]
, and ELAPSED is in cols[2]
. The PID is killed if the string length of ELAPSED is greater than 5 (indicating an elapsed time of at least an hour), or if the minutes field is greater than 9 (an elapsed time of at least 10 minutes). The %%
expansion operator does a longest match suffix removal.
The solution can be compacted by read
-ing directly into the relevant fields:
ps xo uname,pid,etim,time,cmd U"$(echo $(< users.txt))" | egrep '/php54? ' \
| while read user pid elapsed rest_of_line
do if [ ${#elapsed} -gt 5 ]
then kill $pid
elif [ ${elapsed%%:*} -gt 9 ]
then kill $pid
fi
done
Upvotes: 1