Thursday, September 23, 2010

Servers, clients, logs and shell arithmetics

Hello everyone,

Let's say that we have a client that connects to a server through the network. The application's protocol specifies that the the client should maintain a session and send a message (heartbeat) every 30 seconds to keep the session alive. We have a log file with lines like the one below:

[2010-09-16 08:41:01.966] CLD -> HeartBeat-Sent

If we want to see if everything is OK we could take the last line of the file and examine the timestamp against the local time of the machine. I decide to take only the minutes and seconds and create a number like 1401 and compare that number against the local time in the same format. The line of the shell script that do that part is below:

if [ $(( ${TIME_HERE} - ${TIME_THERE} )) -gt ${INTERVAL} ]
then
    STATUS="ERROR"
else
    STATUS="OK"
fi

There is a potential runtime error in that block of code. Any idea what could be wrong? Assume both machines are time synchronized to the milliseconds resolution.

The problem in that sentence is related to the way the shell interprets integers. When just one of  the operands in the expression (( ${TIME_HERE} - ${TIME_THERE} )) is something like 0008, the shell cries out.

The reason for that cry is that the shell thinks the number is an octal number so the 8 is not a valid digit in that base (0..7). You can see it with a command like:

janeiros@harlie:~$ echo "$(( 1000 - 0008 ))"
-bash: 1000 - 0008: value too great for base (error token is "0008")

You can also verify that the shell is doing octal arithmetic with something like this:

janeiros@harlie:~$ echo "$(( 1000 - 0011 ))"
991

All this could be solve by using the expr command:

janeiros@harlie:~$ echo "$(expr 1000 - 0011)"
989

Octal numbers bring good memories to me, from the time I was in college and I got in touch with the first computer in my life, it was around the beginning of the Eighties. That computer was so primitive that it doesn't have a boot loader, well it doesn't have a disk either! So you have to load a small set of instruction to indicate the paper tape reader to read the monitor program 'cause the machine doesn't even have an operating system! The set of instructions to do that was in the form of octal number that you have to load in the machine as a binary digit representation of the octal number. For doing that you have a series of switches that you can switch to ON/OFF (0,1).

Later I got in touch with UNIX (1991), Interactive UNIX to be more precise (http://en.wikipedia.org/wiki/INTERACTIVE_UNIX). In UNIX I discovered that my useless knowledge of the octal representation was in fact very useful at the time of working with absolute file permission representation in chmod!

Have a good day!

--
J. E. Aneiros
GNU/Linux User #190716 en http://counter.li.org
perl -e '$_=pack(c5,0105,0107,0123,0132,(1<<3)+2);y[A-Z][N-ZA-M];print;'
PK fingerprint: 5179 917E 5B34 F073 E11A  AFB3 4CB3 5301 4A80 F674

No comments: