Sep 2011

Example Wrappers Using Etu 1

Ever have to run a program with a variety of options over and over again? If your a Unix, Linux, BSD, Mac etc. programmer and/or sysadmin then... yes you have. The key to success of course is my favorite sysadmin attribute: laziness. In this text a look at one simple wrapper for cron and a Perl library script wrapper.

First Look: etus Options

etu: invalid option -- u
etu [options][arguments]
etu[-D|--daemonize interval]
etu[-d|--dir   dir][-s|--src][-h|--height height]
etu[-w|--width width][-q|--quality percent]
etu[-f|--file  filename][-o|--output filename]
Single file Options:
 -f|--file   file  Single input image filename
 -o|--output file  Output image filename
Directory Options:
 -s|--src dir   Original images directory
 -d|--dir dir   Output directory
Global  Options:
 -h|--height  size  Height in pixels      default: 96px
 -q|--quality level Quality level (1-100) default: 75px
 -w|--width   size  Width in pixels       default: 128px

Wow that is a lot stuff. Basically etu can do the following (well as of this writing):

  • Rescale up or down a single image
  • Rescale up or down a directory of images to a destination directory of image.
  • Check to see if images in a destination directory should be updated based on timestamps in the source directory.
  • Examine an image file
  • Daemonize and watch a source directory for changes to send to a destination directory.

Armed with all of that information a set of scenarios can be set up which can be solved using wrappers.

The Scenarios

  1. Using cron periodically check up on a source directory to see if thumbnail images in a destination directory need to be updated.
  2. An ultra simplified wrapper that takes the etu options in a single ordered line.
  3. A Perl wrapper library (complete with documentation!) for etu. Note this is not a compiled in glue module or actual Perl module. Just a .pl wrapper.
  4. A daemonize wrapper that reads options in from an rcfile.
  5. A Perl daemonize wrapper.

The fist two are covered in this text. The latter two are covered in part 2.

Calling etu From Cron

The reality of this wrapper script is that it can be done with a single line in the crontab like so:

30 * * * * etu -s somedir/ -d /otherdir -h 100 -w 100 -q 90 2>1

Or the cron entry could just look like this:

30 * * * * /path/to/cron_script /sourcedir /destdir 2>1

Following is an example of what a cron script for it might look like:

#!/bin/bash
# Sample cron script for etu - ultra simple

progname=${0##*/}
toppid=$$


# Config
etu_bin=`whereis etu` # switch to which, locate - whatever

quality=80
height=100
width=120

bomb()
{
        cat >&2 <<ERRORMESSAGE

ERROR: $@
*** ${progname} aborted ***
ERRORMESSAGE
        kill ${toppid}
        exit 1
}


# change the args to src dst for easy entry
src=shift
dst=shift

etu_bin -s $src -d $dst  -h $height -w $width -q $quality ||
        bomb "Cannot execute ${etu_bin}"

exit 0

At the top is the setup then some hard coded parameters. The 2 variables are arguments 1 and 2: the source directory and destination directory. Source and destination are shifted in then the call is made. The idea is the script could be used to keep a set of destination thumbnails up to date. Simply call it different times for different sets of source and destinations:

30 * * * * etu_cron.sh /var/www/img/big/skateboards \
                          /var/www/img/thumbs/skateboards
35 * * * * etu_cron.sh /var/www/img/big/sufboards \
                          /var/www/img/thumbs/surfboards

A Perl Library

Not to be confused with a Perl module, this is a small-ish Perl library wrapper for calling etu:

#!/usr/bin/env perl
# petu.pl - A set of perl routines that set up an etu call.

##
# Make sure a directory exists
##
sub etu_chkdir {
        my ($dir) = shift;

        if (! -d $dir) {
                print "Error: $dir not found\n";
                return 1;
        }

        return 0;
}

##
# Make sure the quality is a valid number between 1 and 100
##
sub etu_setquality {
        my ($quality) = shift;

        if ($quality < 1) {
                print "Error: Quality must be greater than or equal to 1";
                return 1;
        }

        return 0;
}

##
# Check for negative values
##
sub etu_negcheck {
        my ($value) = shift;

        if ($value <= 0) {
                print "Error: Value must be greater than 0\n";
                return 1;
        }

        return 0;
}

##
# Execute etu; the arguments in order are:
# - source directory
# - destination directory (or cache directory)
# - height
# - width
# - quality
##
sub etu_exec {
        my ($src,$dst,$height,$width,$qual) = $@;

        if (!$height) {
                $height=80;
        }

        if (!$width) {
                $width=100;
        }

        if (!$qual) {
                $qual=90;
        }

        system("/usr/local/bin/etu -s $src -d $dst -h $height -w $width -q $qual") 
}


1; # Main - return a true value

__END__
=head1 DESCRIPTION

This is a small example library for Perl over top of etu.
based on the source directory.

The usage for each function is:
        etu_chkdir (directory_name); 
        etu_setquality (quality);
        etu_negcheck(number);
        etu_exec(source_dir, dest_dir, height, width, quality);

Note that etu_exec only requires source_dir and dest_dir - it will pick
reasonable defaults for the remaining arguments.

=head1 EXAMPLES

        etu_exec ($HOME/images-orig, $HOME/images-rescaled, 80, 100, 90);
        etu_negcheck($height);


=head1 PREREQUISITES

etu

=head1 COREREQUISITES

none

=cut

The Perldoc at the end explains what each subroutine is for but the idea is to be able to easily make a call to etu from within another Perl program without having to use the system() call. An example might look like this somewhere in a Perl program:

use /path/to/etu.pl

...

my $source_dir = /var/www/img/hotrods-large
my $dest_dir = /var/www/img/hotrods-thumbs

etu_exec ($source_dir, $dest_dir, 30, 30, 60);

...

Summary

As shown wrapping up something complex can be pretty easy and helpful in the long run.