LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This 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


Reply
  Search this Thread
Old 09-12-2007, 06:09 AM   #1
Tommis
LQ Newbie
 
Registered: Sep 2007
Posts: 6

Rep: Reputation: 0
Linux > #bash Scripting Help


Hello,

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!

Cya,
Tommis
 
Old 09-12-2007, 06:41 AM   #2
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
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.
 
Old 09-12-2007, 06:47 AM   #3
bigrigdriver
LQ Addict
 
Registered: Jul 2002
Location: East Centra Illinois, USA
Distribution: Debian stable
Posts: 5,908

Rep: Reputation: 356Reputation: 356Reputation: 356Reputation: 356
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.
 
Old 09-12-2007, 07:19 AM   #4
Tommis
LQ Newbie
 
Registered: Sep 2007
Posts: 6

Original Poster
Rep: Reputation: 0
Hey,

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.

Cya,
Tommis
 
Old 09-12-2007, 07:48 AM   #5
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
Quoth the highly esteemed jschiwal:
Quote:
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.
 
Old 09-12-2007, 03:57 PM   #6
Tommis
LQ Newbie
 
Registered: Sep 2007
Posts: 6

Original Poster
Rep: Reputation: 0
Hey,

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

Cya,
Tommis
 
Old 09-13-2007, 05:48 AM   #7
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
Please don't be angry with me about what I'm about to say, but:

Did you do a cut and paste of the code I suggested,, or did you enter the code by hand?

And ...

Could you cut and paste the code back here the code exactly as it was run?

(If you're pissed at these questions, I'll understand.)
 
Old 09-13-2007, 06:41 AM   #8
Tommis
LQ Newbie
 
Registered: Sep 2007
Posts: 6

Original Poster
Rep: Reputation: 0
Hey,

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
 
Old 09-14-2007, 07:03 AM   #9
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
Quoth Tommis:
Quote:
Nah man, why would i get angry
There are people out there with awfully thin skins. ("Of course I copied and pasted your code accurately! GRRRRRRRRR!")

I'm glad you're not one of them!

But I see the problem. One of the lines got split into two.

At approximately line 42, there should be this long line:
Code:
  bad_guys=$(top -b -n 1 | sed -e 's/<//g' | awk "/PID/{x=1};x>0{x++};x>2&&\$$field_number>=$threshold{print \$1}")
Your copy of the code has split that line into two:
Code:
  bad_guys=$(top -b -n 1 | sed -e 's/<//g' | awk
"/PID/{x=1};x>0{x++};x>2&&\$$field_number>=$threshold{print \$1}")
I'm guessing that nano has some sort of line wrap option.
 
Old 09-15-2007, 06:49 AM   #10
Tommis
LQ Newbie
 
Registered: Sep 2007
Posts: 6

Original Poster
Rep: Reputation: 0
Hey,

Yes, my bad, nano does that very often, argh ;p Now it is copied correctly, and i get this error,

"

[root@GERMANY home]# ./monitor
: bad interpreter: No such file or directory

"

(It is copied correctly now)


Cya,
Tommis
 
Old 09-16-2007, 06:02 PM   #11
wjevans_7d1@yahoo.co
Member
 
Registered: Jun 2006
Location: Mariposa
Distribution: Slackware 9.1
Posts: 938

Rep: Reputation: 31
If that's the error you're getting, then at the shell prompt, do this please:
Code:
od -t -x1 thenameofyourscript | head
and post the results back here.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How To Make Installer In Linux Bash Scripting pak_abdul Programming 1 05-24-2005 08:37 AM
Bash Scripting Help Aioth Linux - Newbie 8 09-21-2004 11:21 AM
Linux Shell Scripting using BASH Help! fooforon Programming 5 02-05-2004 09:16 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 03:47 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration