elidev


Diary of a coder.

Posts Tagged ‘linux’

Posted by eli at 31 October , 2011

A couple of weeks after Dennis Ritchie died, I am sitting at a Windows desktop trying to debug connection problems together with another developer. The web server we are working with establishes a lot of TCP connections to an external web service, and once we put load on the system we start getting connection timeouts or error messages indicating that the sockets cannot be opened. We suspect this may be caused by the system running out of ephemeral ports, and we want to test this hypthesis.

By running netstat we can get a list of all active ports, and we can see what state they are in (the most interesting issue is whether there are lots of sockets in TIME_WAIT). What we would ultimately like to do is to run netstat over and over again counting the number of sockets in TIME_WAIT and correlate this information against the error messages from the web server.

In Linux, this would have been a piece of cake. Write a bash-script that loops netstat | grep TIME_WAIT | wc -l, redirect output to a file or even pipe it to another program, and we are done. How do you accomplish this in Windows? There may be a way, but I am not familiar with it. The corresponding bat script would be much more complicated, so much that the whole approach is probably not advisable. You probably will end up installing or using some software providing exactly the information you want in a cute little UI, but for every single case you would have to repeat this procedure.

For these “ad-hoc” diagnostic tasks, Unix simply outclasses Windows, which is one of  the reasons I vastly prefer Linux to Windows as a server OS. I am amazed with how well the fundamental Unix design principles continue to hold up.

When we think of “design” what we typically think of is the slick GUIs created by the likes of Apple, but the Unix shell is also an example of excellent design. And yes, it is also extremely usable, especially for diagnostic tasks like the one outlined above. Rest in peace, Dennis Ritchie, and thank you for everything.

As a final note I can recommend Joel Spolsky’s excellent article from 2003 about Unix/Windows biculturalism which is well worth a read.

Tags: , ,
Posted in: Uncategorized | No Comments »

Posted by eli at 30 August , 2011

Today at work I ran into some issues with cron. One of my Java programs would run fine when executing manually, but would throw a ClassNotFoundException for StringBuilder when executing under cron. Since StringBuilder is a somewhat “recent” (haha) addition to the Java API, I suspected that it had to do with crontab running an older version of Java, probably the 1.4.2 version bundled in the Linux dist. I could verify this quickly by adding some debug print to the startup script.

A really nice feature of crontab is that you can set environment variables at the top like this:

SHELL=/bin/bash
JAVA_HOME="/opt/java"
#Minute   Hour   Day   Month   DayOfWeek   Command
* * * * * /path/to/script/script.sh > /path/to/script/log 2>&1

and then just have your script use $JAVA_HOME to locate java. This means that the script can be recycled in different environments with different Java versions.

Of course, even better would be to  not have to wory about $JAVA_HOME at all, and just use the “java” command in the script. This assumes that the java command first found in the path references the correct Java version. In the bash shell this is usually set in the file ~/.bash_profile like this:

JAVA_HOME=/opt/java
PATH=$JAVA_HOME/bin:$PATH
export PATH JAVA_HOME

However, cron does not read these settings, so they must be set up manually in the crontab file according to above. Which was exactly what had been done in my case:

SHELL=/bin/bash
JAVA_HOME="/opt/java"
PATH=$JAVA_HOME/bin:$PATH
#Minute   Hour   Day   Month   DayOfWeek   Command
* * * * * /path/to/script/script.sh > /path/to/script/log 2>&1

and this is where it falls apart. This would be nice if it worked, but it does not. Specifically, the leading lines in the cronab syntax are not a script, just a collection of name-value assignments. This means that the expansion of $PATH and $JAVA_HOME fails in the example above. To remedy this you have to repeat the JAVA_HOME variable in the PATH assignment, and also make sure to include everything else of interest, which means you need to do something like this:

SHELL=/bin/bash
JAVA_HOME="/opt/java"
PATH=/opt/java/bin:/sbin:/bin:/usr/sbin:/usr/bin
#Minute   Hour   Day   Month   DayOfWeek   Command
* * * * * /path/to/script/script.sh > /path/to/script/log 2>&1

Of course, this is all detailed in the manual for crontab. It still took me some time (and help) to fully diagnose the error (mostly due to the fact that I missed that the debug print of the $PATH variable did not expand $JAVA_HOME).

Tags: ,
Posted in: Uncategorized | No Comments »