Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
First off i would like to say that i am not a linux newbie, been using it for 2-3 years now mostly console based. I love scripting in bash, making my own scripts for my server, but i am quite stuck on this one. I am making a #bash script that runs on a sleep timer every 5 seconds and my problem is acually getting the information (checking). I want it to check the "top -b -n 1" (to get one list of the top command) and to see if there is anything using over 80% cpu or 80% memory and if so, kill it. I know this is possible using the grep command, but i am very puzzeled by this :P
How would i get it to only say the PID of things that are using over 80% cpu or 80% memory? "top -b -n 1 | grep ?" Any help would be appreciated! Thanks again!
Awk would work better at extracting certain fields. Look in the top manpage. There is an option to output to a program for file, so you don't have the header.
You might want to look at other programs such as "ps". Using an output format you can display what you want.
What kind of server is this? If the program using up the CPU cycles is important you may not want to kill it. Doing so blindly may not be a good idea.
Since grep doesn't do numerical value comparisons such as less than, equal to, or greater than, you will have a tough time getting it to work. This sounds like it is taylor-made for bash and awk.
In your script, use bash to run the top command and pipe the output to awk. Use awk to inspect the contents of the %CPU and %MEM fields (in awk you can do it with field numbers where $1 would be the PID column from top output, and cpu and mem are something like fileds 9 and 10, on my system an any rate). Using greater than comparison, if either cpu or mem exceeds 80%, pass the PID back to bash to kill the process.
You can download a copy of "Effective AWK Programming" for more info.
Last edited by bigrigdriver; 09-12-2007 at 07:04 AM.
Thanks for the help. Ye, never used awk before, but it sounds pretty usefull in this situation. ALso, this is a Centos 4.4 server, running just some game servers where you can script IN them. This means that if a client scripts a gamemode and does some sortof mistake, i just want it to close it. kill the pid. There are only a couple names for hte application that i want to be checked though, i probably could do that with awk. Well, anyhow, when i get back from school ill check it out. Thanks again for the help.
Look in the top manpage. There is an option to output to a program for file, so you don't have the header.
I'm running an ancient distribution whose top doesn't have that option. If that's true for you, it will complicate things slightly.
Does the following script work for you? It's designed to be portable and paranoid, so you don't have to worry about which field is the %CPU field. It also skips past the header, so it will run on systems whose top always outputs the header. The sed bit near the end is there to get around the annoyance that sometimes "<" appears in top's output surrounded by spaces, so that it qualifies (from awk's viewpoint) as an extra field and throws everything off.
I have tested this, but you may wish to also.
Please be patient. This is my first non-trivial use of awk. Normally I'd use Perl.
Code:
#!/bin/bash
sleep_interval=5
threshold=90
field_name='%CPU'
# Get the field number within the line of the field of interest.
top -b -n 1 > tmp.$$
# Get the number of fields.
nf=$(awk '/PID/{print NF}' tmp.$$)
# Get the relevant field number.
fn=0
field_number=0
while [[ $fn -lt $nf ]]
do
fn=$(($fn+1))
if [ $(awk "/PID/{print \$$fn}" tmp.$$) = "$field_name" ]
then
field_number=$fn
fi
done
rm tmp.$$
if [[ $field_number = "0" ]]
then
echo field $field_name is undefined
exit 1
fi
while true
do
bad_guys=$(top -b -n 1 | sed -e 's/<//g' | awk "/PID/{x=1};x>0{x++};x>2&&\$$field_number>=$threshold{print \$1}")
if [[ "$bad_guys" != "" ]]
then
for one_guy in $bad_guys
do
kill -9 $one_guy
done
fi
sleep $sleep_interval
done
Last edited by wjevans_7d1@yahoo.co; 09-12-2007 at 07:55 AM.
Bad news, it outputs how to use awk first, then outputs how to use gawk. After that it says "./monitor: line 44: /PID/{x=1};x>0{x++};x>2&&$9>=90{print $1}: No such file or directory" and quits. It then restarts every 5 seconds. Dam :P
Nah man, why would i get angry, i appreciate your help very much. And i did cut and paste into a document opened with nano through ssh, but i made sure i have everything. This is what i ran CHMODDED to 777..
Code:
#!/bin/bash
sleep_interval=5
threshold=90
field_name='%CPU'
# Get the field number within the line of the field of interest.
top -b -n 1 > tmp.$$
# Get the number of fields.
nf=$(awk '/PID/{print NF}' tmp.$$)
# Get the relevant field number.
fn=0
field_number=0
while [[ $fn -lt $nf ]]
do
fn=$(($fn+1))
if [ $(awk "/PID/{print \$$fn}" tmp.$$) = "$field_name" ]
then
field_number=$fn
fi
done
rm tmp.$$
if [[ $field_number = "0" ]]
then
echo field $field_name is undefined
exit 1
fi
while true
do
bad_guys=$(top -b -n 1 | sed -e 's/<//g' | awk
"/PID/{x=1};x>0{x++};x>2&&\$$field_number>=$threshold{print \$1}")
if [[ "$bad_guys" != "" ]]
then
for one_guy in $bad_guys
do
kill -9 $one_guy
done
fi
sleep $sleep_interval
done
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.