HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashMinor

Checking percentage of free memory using top and awk

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
topfreeawkcheckingusingmemoryandpercentage

Problem

The following Awk code was created in order to verify if free memory from the top command is less than 20% of the total.

I've noticed that I actually do not need the top -n1 | grep Mem |, because the FREEM and TOTALM parameters are inside the third awk line.

But on the other hand, I could not run the Awk as:

awk -v FREEM=$FREE_ME MORY -v TOTALM=$TOTAL_MEMORY '{per=int(FREEM)/int(TOTALM)*100; if(per<=20) print "FAIL" ; else print "OK"}'


My current code is:

TOTAL_MEMORY=` top -b -n1 | grep Mem: | awk '{print $2}' `

 FREE_MEMORY=` top -n1 | awk -v RS="[, ]" '/free/{print a}{a=$0}' | head -1 `

 top -n1 | grep Mem | awk -v FREEM=$FREE_MEMORY -v TOTALM=$TOTAL_MEMORY '{per=int(FREEM)/int(TOTALM)*100; if(per<=20) print "FAIL" ; else print "OK"}'


I have a feeling that this code is ugly because of the top -n1 | grep Mem |. Are there any suggestions on running the awk without it?

Solution

On my test system, the output of top -b -n1 | head looks like this:

top - 09:33:08 up 9 days, 23:07,  7 users,  load average: 0.01, 0.10, 0.13
Tasks: 125 total,   1 running, 124 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.2%us,  0.0%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   4054892k total,  3938964k used,   115928k free,       56k buffers
Swap: 10485756k total,   536176k used,  9949580k free,   438836k cached

  PID USER      PR  NI  VIRT  RES  SHR S   %CPU %MEM    TIME+  COMMAND
    1 root      20   0 10548   36    8 S      0  0.0   0:02.69 init
    2 root      20   0     0    0    0 S      0  0.0   0:00.06 kthreadd
    3 root      20   0     0    0    0 S      0  0.0   0:01.22 ksoftirqd/0


I suppose yours is similar.
From your code it looks like you are extracting the values from the Mem: line,
in this example 4054892k and 115928k.
Those values are in the 2nd and 6th column (in Awk terms), so you can get them easily in one command with:

top -b -n1 | awk '/^Mem:/ {total=int($2); free=int($6);}'


Now it's easy to add the percentage calculation and print the result:

top -b -n1 | awk '/^Mem:/ {total = $2; free = $6; per = free / total * 100; print per <= 20 ? "FAIL" : "OK"; exit}'


Some additional points of interest:

  • After printing, we exit to stop processing unnecessarily the rest of the output coming from top



  • The ternary operator ?: can simplify the printing, no need for an if-else



  • I dropped the int(...) calls, as Awk seems to drop the trailing non-numeric values anyway



  • The pattern /^Mem:/ is more strict than in the original code, just to be safe



UPDATE

If you the position of free memory can be in different columns depending on the system, you have (at least) 2 options to work around that:

-
If you can know the position in advance (by detecting based on the system / runtime environment), you could pass that in as a variable, for example:

i=6; top -b -n1 | awk -v i=$i '/^Mem:/ {total = $2; free = $i; per = free / total * 100; print per <= 20 ? "FAIL" : "OK"; exit}'


-
Or, you could use regular expressions, for example:

top -b -n1 | awk '/^Mem:/ {total = $2; match($0, /[0-9]+[a-z] free/); free = substr($0, RSTART); per = free / total * 100; print per <= 20 ? "FAIL" : "OK"; exit}'

Code Snippets

top - 09:33:08 up 9 days, 23:07,  7 users,  load average: 0.01, 0.10, 0.13
Tasks: 125 total,   1 running, 124 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.2%us,  0.0%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   4054892k total,  3938964k used,   115928k free,       56k buffers
Swap: 10485756k total,   536176k used,  9949580k free,   438836k cached

  PID USER      PR  NI  VIRT  RES  SHR S   %CPU %MEM    TIME+  COMMAND
    1 root      20   0 10548   36    8 S      0  0.0   0:02.69 init
    2 root      20   0     0    0    0 S      0  0.0   0:00.06 kthreadd
    3 root      20   0     0    0    0 S      0  0.0   0:01.22 ksoftirqd/0
top -b -n1 | awk '/^Mem:/ {total=int($2); free=int($6);}'
top -b -n1 | awk '/^Mem:/ {total = $2; free = $6; per = free / total * 100; print per <= 20 ? "FAIL" : "OK"; exit}'
i=6; top -b -n1 | awk -v i=$i '/^Mem:/ {total = $2; free = $i; per = free / total * 100; print per <= 20 ? "FAIL" : "OK"; exit}'
top -b -n1 | awk '/^Mem:/ {total = $2; match($0, /[0-9]+[a-z] free/); free = substr($0, RSTART); per = free / total * 100; print per <= 20 ? "FAIL" : "OK"; exit}'

Context

StackExchange Code Review Q#64485, answer score: 5

Revisions (0)

No revisions yet.