Tom Purl’s Web Site

My ’83 Datsun On The Side Of The Information Superhighway

Archive for February 2008

Web Development Toolbox

leave a comment »

A friend of mine recently volunteered to update and maintain a web site for a local non-profit. He basically wants to clean up the formatting on the site (using CSS whenever possible), add more rich media such as flash-based slide shows, and make it more collaborative by adding features like a forum.

Of course, since he has a day job and is doing this in his spare time, he would like to accomplish all of this in a way that is inexpensive, relatively simple, and intuitive for a technical professional who isn’t a web designer.

Since I’ve been in his shoes before, he asked if I knew of any tools that could help him build a professional-looking site easily and inexpensively. Here’s what I came up with, and hopefully it will help other technical professionals/hobbyists get started with web development.

Software

Firefox + Firebug

A vanilla instance of Firefox itself isn’t an inherently superior browser for web development over IE or Opera. Once you add Firebug, however, it turns into the best free web application development environment that I’ve ever seen. Here are some of the things you can do with Firebug:

  • Find which HTML snippet maps to which element on a web site by hovering over the snippet
    • For me, this is the best feature
  • View the document’s HTML or CSS as a tree
  • Debug Javascript
  • Edit HTML and CSS in memory so you can test-drive the addition or removal of features.
  • et cetera

Honestly, this tool easily saved me half of my web development time. It’s worth checking out, even if you’re a dedicated IE or Opera user.

Note: Apparently, there is also a scaled-down version of Firebug that works with Internet Explorer. More information can be found at the Firebug home page.

XAMPP

XAMPP is a “distribution” of web server software that is configured to work very well together, out-of-the-box. It includes Apache2, PHP, MySql, Perl, phpMyAdmin, and a bunch of other things that I’ve never even had any time to use. It’s simply an excellent way to set up a server-side, LAMP development environment on Windows in a hurry.

A Decent Text Editor

There are a lot of integrated development environments (IDE’s) that do a pretty decent job of helping you create robust web sites. Eclipse, for example, has a highly-regarded PHP plugin, and Netbeans has a robust set of “Ruby On Rails” plugins. If you’re working on a very complex web site, or you don’t use a decent text editor on a regular basis, then you’ll probably save time with a decent, free IDE.

However, if you are already using a decent text editor (e.g. Jedit, Vim, Emacs, Textpad, Textmate, etc.) for other tasks, then you should look into using them for HTML editing too. Your favorite editor probably has some excellent plugins to help you write code using HTML, JavaScript, PHP, etc.

The main benefit of using a familiar text editor over an unfamiliar, web-centric IDE is the size of your learning curve. Most IDE’s, while powerful, can be difficult to master. Also, IDE’s usually force you to manage your project in “the Eclipse” way or “the ASP.Net” way, which may be very different from your normal process. A good text editor, however, should already be very familiar to you and flexible enough to allow you to manage your project in a way that works well for you.

This isn’t to say that IDE’s are a bad idea. Just keep the text editor option in mind if you find your IDE to be too bloated, expensive, or difficult to use.

HTML Tidy

HTML Tidy is a great command-line utility for validating web pages. You can use it to automatically format your HTML, but I mostly use it to validate my web pages and point out any mistakes I may have made (such as forgetting to close a tag).

Online Resources

Open Source Web Design

Here are the two hardest tasks for most technologists (sysadmins, programmers, etc.) who aren’t dedicated web developers:

1. Designing the look of the web site

2. Implementing the design

This should be evident by what they wear, but it’s worth stating: most technologists are not good at tasks that require visual creativity. If you need someone to write an efficient sorting algorithm or trace some packets, then they’re the people to call. Designing a clean, good-looking UI, however, is something that most technologists simply can’t do.

And that’s just half the story. Even if the technologist can create a good design on paper, it’s even harder to actually implement the design. CSS is great, don’t get me wrong, but it has a huge learning curve, and just enough browser-based idiosyncrasies to drive you nuts.

In comes the Open Source Web Design project to the rescue. This site has a repository of page designs and the CSS files that implement them, all for free. Just browse the designs, download the ones that work best for you, and your 95% along the path of creating a solid, attractive web site.

Alertbox

Ok, now you site looks pretty good, but it’s just a shell of its future self. It needs content and customization, which brings up a lot of questions. Does my web site need an RSS feed, or should I just use a mailing list? Will a bunch of dancing, AJAX-y crap bring in more traffic or will it just frustrate my users?

Jakob Nielsen’s Alertbox answers questions like this using two guiding principles: usability and quality content. Your site should be usable by your target audience, and it should contain the content that they need. Anything that is contrary to these principles should be avoided at all costs.

Of course, that sort of thing is much more easily said than implemented, so Jakob does tons of research on the subject and then publishes a lot of his results on his web site. Check these out if you want to do a better job of connecting with your “customers”, whomever they may be.

Dead-Tree Resources

Now that I think about it, I’ve only cracked open one actual book on fundamental web design. Not surprisingly, there’s a wealth of information available on HTML, CSS, Javascript, and other web technologies online. If you do need some help with CSS, however, I highly recommend Eric Meyer On CSS. It’s easy-to-read, succinct, and packed with loads of useful examples.

Written by Tom Purl

February 15, 2008 at 4:32 pm

Posted in Tutorial

Tagged with , , , , ,

My First Non-Trivial Groovy App

leave a comment »

I am about to finish my first non-trivial application written in Groovy (a medium-sized suite of administrative scripts), and so far I’m pretty happy with the language. I thought I would share some of my notes in case anyone else is considering the language for a similar application.

Development Environment

One nice thing about Groovy is how well it works with a system administrator’s “toolbox” of applications, i.e. a text editor and command shell. The development tools that I specifically used were Vim, the command shell, and ant, and I found the pace of development to be very rapid.

References

Since Groovy is still pretty new for me, I need to read a lot of reference material. Here’s the resources that provided the most value:

  • Groovy In Action – From my own experiences and what I’ve read on the groovy-user mailing list, GINA is the best Groovy reference manual available. For me, it answered about 95% of my programming questions, with tons of great examples to boot.

Note: This book is a little expensive, so I purchased the electronic version from the Manning web site. If you’re going to be doing most of you reading on a computer screen anyways, I recommend this option.

  • PLEAC-Groovy – The PLEAC project’s goal is to implement the examples in the Perl Cookbook in multiple languages. Groovy is one of those languages and I believe the first one in which 100% of the examples have been implemented. The examples are very useful and easy-to-understand, so I highly recommend this resource.

Note: I recommend downloading a copy of the PLEAC-Groovy web site using something like HTTrack or the Scrapbook plugin for Firefox. You’re probably going to use this reference a lot, so you’ll want to have quick, offline access to it.

  • groovy-user Mailing List – This list is very informative, and most of the people with which I’ve interacted on this list have been very knowledgeable and patient. It is highly recommended.

Application Overview

I can’t really say much about it, other than the following:

  1. It’s designed to run on a server and has a command-line interface.
  2. It performs a lot of filesystem-related operations.
  3. It processes a lot of XML.
  4. It has a lot of unit tests.
  5. It integrates with a proprietary, third-party library.

First, let me say that the Groovy feature that stood out for me the most was it’s excellent, built-in XML processing libraries. I usually hate processing XML since there’s usually so much “heavy-lifting” and debugging, but Groovy makes the task trivial.

Another feature that I didn’t even know I would like be ended up loving was Groovy’s AntBuilder class, which allows you to use ant tasks in your code in a trivially-simple way. This was especially handy when it came to filesystem-related operations. And of course, the icing on the cake is that Groovy allows me to do all of this while integrating with all of the Java libraries (both standard and third-party) that I need to do my job on a daily basis.

Gripes

Of course, such a new language is going to have a few rough spots. Here’s the ones that I encountered most frequently:

Poor Error Messages

Occasionally, you will get error messages that make no sense whatsoever. My favorite is when it told me that I had a null character on a line that didn’t exist in my document in column 0 (which also doesn’t exist). The good news is that error messages in general are pretty decent, especially when you run Groovy with the debug switch.

Non-Intuitive Behavior

I ran across some truly odd functionality that border on a bug in my opinion. When I asked the mailing list for some clarification, I learned that some of Groovy’s functionality is dependent upon the brand of JDK that you’re using. Yikes. Hopefully the Groovy developers are able to normalize these sorts of anomalies in the future. In the mean time, I recommend decent unit test coverage on any non-trivial application to ensure that everything’s working like you expect it to work.

Conclusion

Even with it’s rough spots, I found Groovy to be incredibly robust, stable, and easy-to-use. Not only did it satisfy 99% of my requirements perfectly, it provided time-saving functionality that I didn’t even know I needed. Now I’m curious to see how the end users like it :)

Written by Tom Purl

February 15, 2008 at 4:23 pm

Posted in Review

Tagged with , , , , ,

Itty-Bitty Classes

leave a comment »

How I learned that using objects, even in a small script, can make you more efficient and you software more flexible and effective.

The Problem

Between work, home, and about a half-dozen operating systems, I use a lot of different backup programs. Most of these programs use some sort of snapshot-based process where you have multiple full backups, each representing a different snapshot in time. The backups have to be rotated on an arbitrary basis, using a process that looks like this:

  1. Compare the current number of snapshot folders with the intended number. Delete folders, from oldest to newest, until the total number of folders equals the intended number minus 1.
    • In practice, this usually means deleting the oldest folder, whose age is indicated by an index number in its name.
  2. In reverse index order, rename each snapshot folder so that it’s index number is incremented by 1.

Here’s how it looks in the shell if you only want two snapshots:

$ ls -i # dirs with inode numbers
17706835 snapshot.0/  19108205 snapshot.1/  21109296 snapshot.2/
$ rm -rf ./snapshot.2
$ mv snapshot.1 snapshot.2
$ mv snapshot.0 snapshot.1
$ ls -i
17706835 snapshot.1/  19108205 snapshot.2/

As simple as this process sounds, I wasn’t able to find any cross-platform scripts that would execute this process on an arbitrary set of snapshot directories. I therefore decided to throw something together myself, and figured it would take me all of 20 minutes. It actually ended up taking me a bit longer, but the entire experience was worth it.

Which Language?

As much as I wanted to hammer something like this out in a 15-line bash script, I saw three big disadvantages:

  1. Bash scripts aren’t cross-platform
    • Cygwin doesn’t count :D
  2. Integration Methods
    • The most popular method of integrating a shell script with something else is using things like pipes, streams, and channels (STDIN, STDOUT, STDERR). This method of integration is very robust and mature, but I’d rather not have it be my only option. Being able to load this functionality into another program as a library with a robust interface would also be nice.
  3. Ease Of Maintenance
    • Most of the non-trivial shell scripts that I’ve ever written or used are comprised of numerous “clever” awk, sed, and grep statements that, while powerful, are difficult to write and even more difficult to maintain. I would therefore prefer using a language that relies less upon “shell magic”.

I’ve been a big fan of Python for a while now, and I’ve written numerous sysadmin scripts using that language, so I decided to use it to solve my problem. I guess I could’ve used a lot of other languages, but this time, Python seemed like a good idea.

Iteration 1 – The Procedural Approach

Ok, so that language decision took way too long (at least 3 minutes), and I really wanted to hammer out this script, so I started hacking. Python is an OO language, but I didn’t have time to design classes and build constructors and such, so I started writing a very procedural program.

Note: One of the cool things about Python is that it gives you a choice between writing your program in an OO way or a procedural way. This is especially handy (like in this case study) when your “simple” procedural script turns into something more complex that would benefit from some of advantages of object-orientation.

I got to my rotate_snapshots method, which started out like this:

import re, os, sys
from distutils import dir_util

def rotate_snapshots(root_dir, snapshot_prefix, num_snapshots):

    # Retrieve your folder list
    files = os.listdir(root_dir)
    dirs = []
    for f in files:
        if os.path.isdir("%s/%s" % (root_dir, f)):
            # I probably need to do some sort of validation here, but
            # that can wait for rev 2 :D
            dirs.append(f)

Ok, I have my folder list. So far, so good. Now I need to delete the unwanted directories (which is usually just the oldest one). Here’s my first stab at satisfying that requirement:

### Delete dirs requirement
dirs.sort()
# Grab the index number from the folder's name
pattern = re.compile('.*\.([0-9]{1,10})$')

# Walk through the list of dir names backwards
for dir in reversed(dirs):
    try:
        index = int(pattern.search(dir).groups()[0])
    except:
        # *not* a snapshot dir
        continue
    if index > (int(int(num_snapshots)) - 2):
        # Delete unwanted snashot dir
        dir_util.remove_tree(root_dir + '/' + dir) # Delete the dir
        dirs.pop()                                 # Remove it from the list of dirs
    else:
        # Done looping through unwanted snapshot dirs, drop out
        break

Here’s where I ran into my first snag. This code chunk sorts my directories by name, walks through the list backwards, and if it finds a directory with an index that is too high, it deletes it. Once it finds an index that it wants to keep, it falls out of this loop.

The problem is that this code chunk relies upon a list that sorted by the integer value of the indexes. What we get, however, is a list that is sorted by the string value of the snapshot directory’s name. This is how it looks in the python shell:

In [1]: l = ['dir.1', 'dir.2', 'dir.3', 'dir.10']

In [2]: l
Out[2]: ['dir.1', 'dir.2', 'dir.3', 'dir.10']

In [3]: l.sort()

In [4]: l
Out[4]: ['dir.1', 'dir.10', 'dir.2', 'dir.3']
                   ^^^^^^

Since Python assumes that I’m sorting a list of strings, it places 10-19 before 2. This is ok if you never need to work with more than 10 snapshot directories, but that’s not an assumption that I want to make.

I could just loop through every directory name and delete the unwanted snapshot directories. That’s a little inefficient, but it’s easy and it fixes the problem right? Well, yes, until I then try to rename the snapshot directories. For that operation, it’s absolutely necessary that my list of folder names be sorted based on the index value. I can’t rename dir.9 as dir.10 before I rename dir.10 as dir.11, for example.

Ok, remember that my mind is still in “hammering it out” mode. “Ok”, I thought. “I’ll just sort the list myself with my own algorithm”. And that’s when I moved to my next phase of development.

Iteration 2 – Epiphany

“Why on earth am I manually sorting a list in Python?”, I thought. Python is a very robust language that is easy-to-use. It has all types of cool functionality built-in so that I don’t have to do things like sort arrays. “There’s got to be a better way”, I thought.

Then I remembered that each Python class has a cmp method. This method is invoked when one Python object is compared to another using something like the == operator, for example. I could create a snapshot directory class and override the cmp method so that my objects could be compared by their numeric index, not their full name. Then sorting my list would simply be a matter of invoking the sort method on a list of “snapshot directory” objects.

This, of course, is when the “hammering it out” part of my brain kicked in. “What do you mean you want to create a class?”, I thought. “We already established that that would be way too much work”. After thinking about it for a minute (and pondering why my inner-monologue just said “we”), I realized that it’s also a lot of work to write and test my own algorithm for sorting lists of snapshot directory names. I therefore decided to give the OO approach a stab.

Iteration 3 – OO Is Easy (In Python)

To get started refactoring my script, I first tried to come up with a list of nouns and verbs so I could design my classes and methods. This is usually the part where most procedural programmers run screaming, but it doesn’t have to be that bad, especially on small-to-medium-sized projects. I promise that you won’t have to read a Martin Fowler book or open a graphical modeling tool in a lot of cases :)

Ok first I looked at the 2-step process listed above, and found that I basically have the following entities:

  • Noun(s)
    • snapshot directory
  • Verb(s)
    • delete directory
    • rotate/move directory

That’s it. Based on that “analysis”, I threw together the following stub in my module:

class SnapshotDirectory:
    """Docs go here :) """

    def __init__(self, full_dir_path, snapshot_dir_prefix):

        self.dir_path = full_dir_path
        self.prefix = snapshot_dir_prefix    # Use for validation

        # TODO Validate directory

        self.__is_valid = True

        # TODO Get index value

    def __cmp__(self, snapshot_dir):
        """Override __cmp__ so we can compare directories based on index value,
        not string name.
        """
        pass

    def isValid(self):
        """This returns true if the directory still exists on the filesystem."""
        pass

    def deleteSnapshot(self):
        """Delete the snapshot from the directory."""
        pass

    def changeIndex(self, new_index):
        """This renames the directory with a new index number."""
        pass

Ok, here’s a quick summary. The __init__ method is like a constructor, and it’s where I parse and validate values and set initial property values. The __cmp__ method is where I will set up my comparison criteria. Everything else mentioned earlier except for the isValid method. I thought that this might end up being a handy helper method. Overall, the entire process of designing and stubbing-out my class took less than 10 minutes, which ain’t bad, especially when you compare it to Java.

Next, I wanted to implement my __init__ and __cmp__ methods. Here’s what I came up with:

def __init__(self, full_dir_path, snapshot_dir_prefix):

    if os.path.exists(full_dir_path) == False:
        raise Exception("Could not find the full_dir_path: %s" % full_dir_path)
    self.dir_path = full_dir_path
    self.prefix = snapshot_dir_prefix

    pattern = re.compile('.*\.([0-9]{1,10})$')
    try:
        self.index = int(pattern.search(self.dir_path).groups()[0])
    except:
        raise Exception("Could not retrieve index number from directory.")
    self.__is_valid = True

Ok, that’s simple enough. Validate the directory and retrieve the index number. Now let’s look at the cmp method:

def __cmp__(self, snapshot_dir):
    """Override __cmp__ so we can compare directories based on index value,
    not string name.
    """
    if isinstance(snapshot_dir, SnapshotDirectory):
        return cmp(self.index, snapshot_dir.index)
    else:
        return cmp(self.index, snapshot_dir)

Methods like this are one of the reasons that I really like Python. In 5 lines of code (not counting comments), I’m able to enable index-based sorting. No muss, no fuss, and definitely no implementation of my own sorting algorithm.

Note: Another great thing about Python is interactive interpreter. It’s great to be able to instantly test your code after you’ve written it.

I then implemented the rest of the methods (plus a few others) and an Exception class called SnapshotParsingError. A dedicated exception class might seem like overkill to non-Python developers, but it only requires two lines of code, and I didn’t even have to create a new file.

Here’s the code for the two classes:

class SnapshotParsingError(Exception):
    pass

class SnapshotDirectory:
    """This class represents a "snapshot"-style (dirprefix.index) directory on a filesystem.

    Example:
        sdir = new SnapshotDirectory('/home/tom/backups/snapshot.1', 'snapshot')

    This class throws a SnapshotParsingError exception if the snapshot
    directory doesn't follow the 'dirprefix.index' naming convention.
    """

    def __init__(self, full_dir_path, snapshot_dir_prefix):

        if os.path.exists(full_dir_path) == False:
            raise SnapshotParsingError("Could not find the full_dir_path: %s" % full_dir_path)
        self.dir_path = full_dir_path
        self.prefix = snapshot_dir_prefix

        pattern = re.compile('.*\.([0-9]{1,10})$')
        try:
            self.index = int(pattern.search(self.dir_path).groups()[0])
        except:
            raise SnapshotParsingError("Could not retrieve index number from directory.")
        self.__is_valid = True

    def __cmp__(self, snapshot_dir):
        """Override __cmp__ so we can compare directories based on index value,
        not string name.
        """
        if isinstance(snapshot_dir, SnapshotDirectory):
            return cmp(self.index, snapshot_dir.index)
        else:
            return cmp(self.index, snapshot_dir)

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        retval = """
        self.dir_path =   %s
        self.prefix =     %s
        self.index =      %s
        self.__is_valid = %s""" % (self.dir_path, self.prefix, self.index, self.__is_valid)
        return retval

    def isValid(self):
        """This returns true if the directory still exists on the filesystem."""
        return self.__is_valid

    def deleteSnapshot(self):
        """Delete the snapshot from the directory."""
        dir_util.remove_tree(self.dir_path)
        self.__is_valid = False

    def changeIndex(self, new_index):
        """This renames the directory with a new index number."""

        pattern = re.compile('(.*\.)[0-9]{1,10}$')
        path_prefix = pattern.match(self.dir_path).groups()[0]
        new_dir_path = path_prefix + str(new_index)
        os.rename(self.dir_path, new_dir_path)

        self.index = int(new_index)
        self.dir_path = new_dir_path

Ok, now that my classes are written and functionally tested, I can rewrite my rotate_snapshots method:

def rotate_snapshots(root_dir, snapshot_prefix, num_snapshots):
    """Please see module-level help for details about how this function works"""
    files = os.listdir(root_dir)

    dirs = []
    for f in files:
        if os.path.isdir("%s/%s" % (root_dir, f)):
            print "Found the following dir: %s" % f
            dirs.append(SnapshotDirectory(root_dir + "/" + f, 'snapshot'))

    dirs.sort() # It works!!!

    if len(dirs) > 0:
        while dirs[-1].index > (int(int(num_snapshots) - 2)):
            print "Deleting dir: %s" % dirs[-1].dir_path
            dirs[-1].deleteSnapshot()
            dirs.pop()

        dirs.reverse()
        for dir in dirs:
            print "Incrementing the index of %s by 1" % dir.dir_path
            dir.changeIndex(dir.index + 1)
    else:
        print "No directories are available for rotation"

Ok, here’s some of the differences between the previously-attempted version of this function and the current version:

  1. The new one is a lot clearer. The class constructor takes care of validation, the sort method works, and, in general, it’s just really easy to read. I barely even added any comments because I didn’t think they were necessary. If I come back to maintain this thing in a year, I’ll definitely know what’s it doing.
  2. It’s shorter than the previous version would have been, which is also nice.
    • I realize that the creation of a class probably adds more total lines of code to this script, but that’s ok if it means less code duplication and easier maintenance.

Conclusion

So that’s how I learned to stop worrying and love OO Python. Even in small scripts, it can really make the task of programming easier, faster, and more flexible.

Also, please note that the code chunks in this script are alpha-quality and incomplete. When I’m done writing this script and have tested it for a little while, I’ll post it to this site.

Written by Tom Purl

February 14, 2008 at 4:19 pm

Posted in Tutorial

Tagged with , , ,

Groovy For Sysadmins

with 2 comments

I’ve been using the Groovy programming language a lot lately at work to programmatically interact with systems that have Java interfaces. Simply put, it’s great, and it really makes my job as a sysadmin of Java middleware easier. Also, if you’ve tried other Java-based scripting languages like Jython in the past but have been disappointed (like me), then I definitely recommend that you check Groovy out.

I think that the admin angle of the language is lost on most potential users, however. Groovy is a great language for writing small-to-medium-sized administrative scripts, and it’s even a great language for non-”real” programmers who want to start dipping their toes into the pool of Java. For those who are considering whether they want to put in the time to learn a little about Groovy, here are some of the advantages that I see as a sysadmin:

No More Compiling & Building

First of all, if you’re still compiling your Java apps using javac, then stop reading this article and start using Apache Ant. You’re wasting your time with javac, even if most of your scripts are pretty small. Ant is a great tool that has saved me a ton of time, but it’s definitely not without it’s own learning curve and occasional problems, however.

With Groovy, there is no explicit compilation step, just like with Perl and the Korn Shell. You just write your script, run it, fix and problems, run your script again, and then rinse and repeat if necessary. This is a much more intuitive programming workflow for most sysadmins.

Easier Deployments

If your script is going to eventually run on a server, all you have to do to deploy it is to upload it to the server. From there, you can run it like any other Perl or shell script. You don’t have to worry about writing or deploying wrapper scripts for your class or jar files that actually invoke your program.

Simpler Syntax

Here are some of the syntactic niceties offered by Groovy:

  • Like Python and the Korn Shell, Groovy doesn’t force you to end every line with a semi-colon if it only contains a single statement.
  • Loose typing, so you don’t have to declare a variable’s type when you create it.
  • Fewer brackets
  • No forced classes
    • In Java, every file is explicitly defined as being a class. You don’t have to do this with Groovy.
  • Multiple Classes In One File
    • Tired of following OO design standards that force you to create 8 separate class files for a relatively simple program? Put them all in a single file in Groovy and simplify your life.
  • More features that I’m just now discovering like closures and Javabean-like accessors.

Text Editor Friendly

I was reading a blog article by a Sun developer the other day where he said that he didn’t like Groovy because it didn’t integrate very well in Netbeans (an IDE). He mentioned that there was no decent code completion module for Groovy yet like there is for Java. It therefore took him longer to write the following print statement in Groovy:

println "hello"

…than it did to write the equivalent (and much longer) statement in Java with the help of code completion:

System.out.println("Hello");

Although this statement is a little short-sighted in my opinion (“I don’t like cars because there’s no place to hook up my horse”), it points out one of Groovy’s strengths: it can be used very well with only a text editor and a command prompt. Groovy, like Perl and shell languages, was never designed with whiz-bang IDE’s in mind. It’s brief, powerful syntax and development tools were designed to make programming with it so easy that you could do it using Notepad and the command prompt if you wanted and still be very efficient and effective.

Groovy’s ease-of-use outside of an IDE is good news for most sysadmins for a couple of reasons. First, they spend a good portion of their days using text editors to do things like view log files, change config files, et cetera. Being able to use the same text editor to also write scripts lowers the learning curve and is very synergistic. Also, most sysadmins usually don’t have IDE’s like Eclipse or Netbeans installed on their system. For the type of Java programming that they typically do, they view IDE’s as being bloated and having an unnecessarily high learning curve.

Groovy Shell

One of Python’s greatest strengths is the fact that it comes with an interactive interpreter. Groovy also includes an interactive interpreter, and its major benefit is that it allows you to evaluate small snippets of code quickly and easily. This comes in handy when you’re having problems getting a chunk of code to work, and also when you’re “kicking the tires” on a new third-party library or language feature.

Conclusion

There are a lot of new scripting languages out there that are Java-based, and their potential benefits are numerous. However, it can be difficult to pick one that is worth the time and attention necessary to achieve proficiency. In my opinion, Groovy fits the bill and then some, and is especially good for people who need to write small-to-medium-sized programs that interact with Java systems.

Written by Tom Purl

February 14, 2008 at 4:08 pm

Posted in Review

Tagged with , , , , ,

Cool GNU Screen Helper Functions

leave a comment »

I’m a big fan of using GNU Screen, a terminal multiplexer. At any given time, I could be interacting with a dozen different Unix servers at work. I therefore group servers into logical, named groups and jump back and forth between them using screen.

I find the following one-liner functions to be incredibly helpful to me when it comes to managing multiple screen sessions simultaneously. Hopefully someone else will also benefit from them. I currently run these one-liners using the Bash shell, and store them in my ~/.bashrc file. Each function should be runnable from a shell prompt.

getscreenpids

function getscreenpids() { ps auxww | grep screen | grep -v grep | awk '{print $2}'; }

This function simply returns a list of process id’s (pid’s) for each screen process. This is nice info to have if you want to kill a screen session, since each session uses it’s own screen process.

clearscreen

function clearscreen() { for pid in $(getscreenpids); do kill -9 $pid; done; screen -wipe; }

This function kills every screen session into which I am logged. This is nice if things get flaky and I just want to kill all of my screen processes quickly.

killscreen

function killscreen() { screen -ls | grep $1 | awk '{print $1}' | cut -f1 -d. | xargs kill -9; screen -wipe; }

This function kills every screen session that uses the title that you pass as the first parameter. So if you have one or more screen sessions titled “envA”, and you pass that string to this function, all of those screen sessions will be killed.

Written by Tom Purl

February 14, 2008 at 3:58 pm

Best Bookkeeping App On Linux

leave a comment »

Well, it’s a new year, and what’s a new year without a “get your financial shtuff in order” resolution. Every year, I blame part of my bookkeeping incompetence on my favorite accounting app, GnuCash , so I’m usually looking for something newer and better every January. So here’s my options this year:

Choices

GnuCash

http://www.gnucash.org

This is always what I come back to, so why even look, right?

  • Advantages
  • FOSS!
  • The new 2.0 version is so much better than the previous 1.8 version from usability and stability perspectives.
  • Fairly robust and intuitive
  • The standard on Linux (did I mention that I’m a Linux user?)
  • Will probably be around forever, so I don’t have to worry about being forced to convert all of my historical financial data to a new app any time soon.
  • New budgeting interface!
  • Tons of great reporting features
  • Reporting API using a variant of Lisp. Now if only I knew how to program in Lisp :)
  • Disadvantages
  • Can still be a little flaky at times
  • Only really installs easily on Linux. OS X and Windows users have a much more difficult time.
  • Please note that you can install GnuCash on both Mac OS X and Windows. It’s just hard to do. Also, the Windows port of GnuCash is very new, and would be considered alpha software in my opinion.
  • Since it’s a “real” accounting app, it may be more than I need, meaning that I sometimes have to deal with complexity that is unnecessary for my needs.

Quicken

This only runs on Linux is I use Crossover or Wine, and apparently it doesn’t run very well. The same thing is true with MS Money, so no thanks.

Wesabe

http://www.wesabe.com

This is a online-only bookkeeping app with some cool folksonomy features and a slick, AJAX-y interface.

  • Advantages
  • Seems very easy-to-use, especially when it comes to budgeting and report-generating
  • There’s a free version, but I don’t know if that will work for me.
  • Multi-user: very easy for myself and my wife to use this app at the same time.
  • Very collaborative, which is nice if you’re fairly ignorant about the world of personal finance.
  • Disadvantages
  • Seems to force you to use a very non-intuitive interface (if you’re used to apps like Quickbooks or Quicken).
  • You can’t add new transactions manually – you have to download a qif file from your bank and upload it into Wesabe.
  • You can’t use Expense accounts or categories in Wesabe, just “tags”. This, to me, is very non-intuitive.
  • I spend a lot of time on a train each day, and I can’t use this app offline, so that’s a big disadvantage for me.
  • Very limited reporting functionality.
  • You can basically get three types of reports. This may be enough for most people, but seems a bit limiting to me.

Moneydance

http://www.moneydance.com

This is a Quicken-like bookkeeping app that isn’t quite as bloated and can run on nearly any OS that supports Java.

  • Advantages
  • Will pretty much run on any OS.
  • Fairly robust
  • Seems to have a plugin architecture that is compatible with Java and Python. Nice!
  • Disadvantages
  • Not free (bad), but inexpensive (good!)
  • The budgeting interface seems a bit overly-simplistic. I’m hesitant to switch to a new bookkeeping app if this particular feature doesn’t really wow me.
  • How long will this non-FOSS app survive?
  • Please note that you can export all of your data to a qif format, so it’s fairly portable, even if MoneyDance were to fold tomorrow.

Jgnash

http://jgnash.sourceforge.net/wiki/index.php

This seems to be someone’s copy of GnuCash, but with a simpler interface and written in Java.

  • Advantages
  • FOSS!
  • Will pretty much run on any OS.
  • Beanshell scripting interface, which is incredibly cool
  • Stable and somewhat robust
  • Disadvantages
  • No budgeting module, which really is a show-stopper for me
  • That’s really it. This is definitely my second choice.

Conclusion

In the end, you should choose a program that best compliments your bookkeeping process, not one that “just takes care of it automatically”. The latter type of applications often impose a process on you that, more often than not, doesn’t really “fit”. Ideally, you should be able to fulfill your process completely using pencil and paper; your bookkeeping app should simply make your process more efficient.

I’d love to therefore say that I have defined my bookkeeping process from A-Z and therefore can confidently choose one of the apps above, but my process is still a work-in-progress. So since I need to make a decision soon, I’ll go with the app that imposes the fewest constraints on my process while still making me more efficient that I would be otherwise. For me, that app is still GnuCash, although jGnash comes in a close second.

Update – 7/21/09

After trying to install the stable version of GnuCash for windows about 20 times, I finally just switched over to jGnash 2.0 and haven’t looked back. The interface has improved dramatically, and I find it to be much simpler and more stable than GnuCash.

Written by Tom Purl

February 14, 2008 at 3:51 pm