Reading a file in bash

While working on a maintenance script, I’ve found myself using bash a bit more than using perl for many tasks. While I don’t mind writing in perl or python, sometimes it just seems like overkill.

I needed to read one line of a /proc/loadavg for a monitoring system and was using some code that had been written by one of our programmers in 2002 or so. The old code was written using three scripts, two of which were called from cron. The first script was written in perl, actually included /proc/loadavg as chomp($value=`cat /proc/loadvg`);

Ugh!

Then some math was done, and a decision made of what values to write for nagios’s local process to report back. Suffice it to say that the math done then involved executing a shell script from time to time based on some condition checks and a separate cron that cleaned up the status for nagios.

A literal translation of the script from perl to bash ended up with a snippet of code that looked like this:

#!/bin/bash

  LOAD=`cat /proc/loadavg`
  LOADAVG=${LOAD%%.*}

echo $LOADAVG

We’ll spare the details regarding how badly the existing script converted LOADAVG to an int in perl. While this method works, it does cause a process to be forked needlessly to read /proc/loadavg.

A quick rewrite and we end up with:

#!/bin/bash

  read LOAD < /proc/loadavg
  LOADAVG=${LOAD%%.*}

echo $LOADAVG

While this doesn't seem overly bad for a process executed once a minute, it does cause a larger problem when someone copies that snippet of code and uses it elsewhere.

If we modify the code slightly to:

#!/bin/bash

for i in {1..10000}
do
  LOAD=`cat /proc/loadavg`
  LOADAVG=${LOAD%%.*}
done

echo $LOADAVG

and

#!/bin/bash

for i in {1..10000}
do
  read LOAD < /proc/loadavg
  LOADAVG=${LOAD%%.*}
done

echo $LOADAVG

and run the following benchmark:

root@tsavo:/home/cd34# time ./s.sh 
0

real	0m13.641s
user	0m0.636s
sys	0m2.304s
root@tsavo:/home/cd34# time ./t.sh 
0

real	0m0.485s
user	0m0.332s
sys	0m0.148s

we can see that there is a substantial impact to doing things.

Taking the integer portion of a floating point number also yields a number of terrible solutions involving sed, awk and cut — all forking a separate process or two.

Tags: , ,

Leave a Reply

You must be logged in to post a comment.

Entries (RSS) and Comments (RSS).
Cluster host: li