Fcd45b7de93cc8fa417fa43426973e06

So I use thin to serve my rails projects, php, and nginx as a back end for everything. I am on slicehost, and have a limited amount of memory to use. I know there are utilities like top and ps that are already out there, and I use them in this script, but I wanted to make something nice and easy for myself (mostly because I have never used a lot of these things)... I have never really made a shell script, used awk, parsed files with perl, etc. So bear that in mind while taking a look at this.

I was wondering what I could do to improve on this code, or if there was a better way to go about this in general. I actually looked a libproc, because I was going to do this in either c or c++, but I couldn't find any documentation on it.

To use the script you run it like: <name of script> {nginx|thin|php|top [number]}

If the first argument is either nginx, thin, or php it prints all of the information for those processes, and tells you how much memory each one of those processes are using, and gives it to you as a percentage based on how much RAM you have in your machine.

If you put in top as the first argument, you get the top ten memory using processes, also with the same information. But if you put in a number X as the second argument, then you get the top X memory using processes...

It's pretty self explanatory, but I thought I would give a brief description... Anyway let me know what you think.

Thanks,
Jon

mem

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#!/bin/sh

# 2008 Jon Mulder <mulderje@muohio.edu>

AWK=/usr/bin/awk
EGREP=/bin/egrep
FREE=/usr/bin/free
GREP=/bin/grep
HEAD=/usr/bin/head
PERL=/usr/bin/perl
PS=/bin/ps
SORT=/usr/bin/sort

TOTALMEM=`$FREE -m | $GREP Mem | $PERL -pe 's/Mem:\s+([0-9]+).*/$1/'`
RETVAL=0
case "$1" in
    nginx)
          $PS aux | $GREP nginx | $EGREP -v 'grep|/bin/sh' |
          $AWK -v totalmem="$TOTALMEM" 'BEGIN { total=0; printf "%-10s %-10s %-10s %s\n", "USER", "%MEM", "PID", "PROCESS TYPE"
                                   print "---------------------------------------------" }
                                   { printf "%-10s %-10.2f %-10s %s\n", $1, $4, $2, $12; total+=$4; }
                  END { printf "%-10s %-10.2f %-0.0f MB used\n", "TOTAL:", total, (total/100)*totalmem }'
      RETVAL=$?
  ;;
    thin)
          $PS aux | $GREP thin | $EGREP -v 'grep|/bin/sh' |
          $AWK -v totalmem="$TOTALMEM" 'BEGIN { total=0; printf "%-10s %-10s %-10s %s\n", "USER", "%MEM", "PID", "SERVER:PORT"
                                   print "--------------------------------------------" }
                                   { printf "%-10s %-10.2f %-10s %s\n", $1, $4, $2, $13; total+=$4; }
                  END { printf "%-10s %-10.2f %-0.0f MB used\n", "TOTAL:", total, (total/100)*totalmem }'
      RETVAL=$?
  ;;
    php)
        $PS aux | $GREP php5 | $EGREP -v 'grep|/bin/sh' |
        $AWK -v totalmem="$TOTALMEM" 'BEGIN { total=0; printf "%-10s %-10s %-10s %s\n", "USER", "%MEM", "PID", "EXECUTABLE"
                         print "-------------------------------------------" }
                         { printf "%-10s %-10.2f %-10s %s\n", $1, $4, $2, $11; total+=$4; }
                END { printf "%-10s %-10.2f %-0.0f MB used\n", "TOTAL:", total, (total/100)*totalmem }'
    RETVAL=$?
  ;;
        top)
        [ -n $2 ] && [ $2 -eq $2 2> /dev/null ] && NUM=$2 || ( NUM=10 && echo "$2 is not a number - Using 10 by default" )
        $PS aux | $SORT -nr -k 4 | $HEAD -$NUM |
        $AWK -v totalmem="$TOTALMEM" 'BEGIN { total=0; printf "%-10s %-10s %-10s %-10s %s\n", "USER", "%MEM", "MEM", "PID", "EXECUTABLE"
                         print "------------------------------------------------------" }
                         { printf "%-10s %-10s %-10.2f %-10s %s\n", $1, $4, ($4/100)*totalmem, $2, $11; total+=$4; }
                END { printf "%-10s %-10.2f %-0.0f MB used\n", "TOTAL:", total, (total/100)*totalmem }'
    RETVAL=$?
        ;;
    *)
      echo "Usage: mem {nginx|thin|php|top [number]}"
      exit 1
  ;;
esac
exit $RETVAL

Refactorings

No refactoring yet !

B8d457d2c39911ea4c74ba7d66b9c3f7

Marco Valtas

July 31, 2008, July 31, 2008 03:24, permalink

1 rating. Login to rate!

I think is a very good script, solves your problem and will be solely maintained by you. I have a handful of this kind of script in my ~/bin directory. But there's somethings I probably change. First is the reuse of you format string, you can make it less redundant just putting in a variable. Second, I don't fell comfortable mixing too much languages so, as a exercise, I tried to do this all in Perl. The problem was that I have a mac and could not paste the code here so you can use on your Linux without some tweaks here and there. If have some time you can look at the Perl module "Proc::ProcessTable" (http://is.gd/19PZ) which can provide a OO way to access this kind of information, this way you can expand your script more easily.
The third thing is that you can use VAR=`which perl` if you have all programs in your path and don't worry where they are in the system.

The thing is, your script is very good for some reasons I wrote before, I personally wouldn't bother to more flexible if not necessary. If you pick yourself adding more processes and for each one more redundancy then is time to fix.

Hope this helps.

Fcd45b7de93cc8fa417fa43426973e06

JonM1827

July 31, 2008, July 31, 2008 04:32, permalink

No rating. Login to rate!

Thanks a lot for the suggestions. I especially like the VAR=`which perl` idea. I never would have thought of that, yet it makes so much sense :)

I would have put the format string in a variable, but its a pain in the ass to pass variables to awk from the shell script; at least the way I was doing it... I hear what you are saying about the multiple languages, I just wanted to try out a few things that I had never really used.

And as far as the perl module goes, that looks really interesting!

Thanks for the help,
-Jon

Your refactoring





Format Copy from initial code

or Cancel