The Problem
Scripts need to be portable and flexible. Most scripts use arguments to give the user run time options. Defaults should be the most common value for each argument. Sometimes, the most common value can change or be different at each installation.
Here is some typical code to define defaults and accept run time options:
#!/usr/bin/perl
use Getopt::Long;
# Define defaults
$color = "red";
$license = '1717@lic.company.com';
# Get arguments from user
if (! &GetOptions('color=s', 'license=s')) {
die "Fatal error parsing arguments\n";
}
if ($opt_color ne "") { $color = $opt_color; }
if ($opt_license ne "") { $license = $opt_license; }
print "Debug: Color = $color\n";
print "Debug: License = $license\n";
exit 0;
The problem is that this script is not inherently configurable. To change the default values for color or license, a programmer has to edit this script (you don't want ordinary users editing scripts, trust me on that!)
We need a way to separate the changeable data values from the script. We need to create a configuration file in a well advertized location, containing our soft defaults. Non-programmers can easily edit this config file without messing up any code.
We can still have the internal defaults at the top of the script; the soft defaults will override them.
It's also important to make our script resilient to user mistakes. If the config file is missing data - or if the file is completely missing - we need to survive that and continue running. Adding soft defaults should not impose another point-of-failure for our script.
The Solution
#!/usr/bin/perl
use Getopt::Long;
# read optional soft defaults
%defList = readKeyFile("/etc/myprogram/defaults");
# Define defaults
$color = "red";
$color = $defList{color} if defined($defList{color});
$license = '1717@lic.company.com';
$license = $defList{license} if defined($defList{license});
# Get arguments from user
if (! &GetOptions('color=s', 'license=s')) {
die "Fatal error parsing arguments\n";
}
if ($opt_color ne "") { $color = $opt_color; }
if ($opt_license ne "") { $license = $opt_license; }
print "Debug: Color = $color\n";
print "Debug: License = $license\n";
exit 0;
sub readKeyFile {
my ($infile) = @_;
my ($key, $value);
my (%retList);
open(IF, $infile) || return undef;
while (<IF>) {
chomp;
s/^\s+//; s/\s+$//;
if (! /^\#/ && ! /^$/) {
($key, $value) = split(/\s+/,$_,2);
$retList{lc($key)} = $value;
}
}
close IF;
return %retList;
}
Where /etc/myprogram/defaults could contain:
# # This is the default file. Blank lines are allowed. # color green license 2334@lic.company.com
The simple subroutine called readKeyFile will read in the configuration file ignore preceding and ending white space, ignore blank lines, ignore comment lines and return the key/value pairs as a hash.
If the defaults file exists, it overrides the hard-coded defaults. If it doesn't exist, no harm done, the internal defaults will be used. Any command-line arguments the user specifies will override all defaults.
The left-hand keys in the config file can be any combination of upper/lowercase, because we force them lowercase before using them in the code.
The value portion of the key-value pairs in the config file may contain spaces, if needed. This is possible because of the 3rd option to the "split" - we specify "2", which means we want no more than 2 pieces returned. It splits on the first whitespace, and everything to the right of that is considered the value.
Practical Usage
A perfect example use for this trick is a software application that requires a license. Perhaps the most installations use the central license server "1717@lic.company.com", but there are a few exceptions around your computing environment. Each installation might want their own license to be the default. An override like that is the exception, not the norm.
You can now distribute this script all around your computing environment, with instructions on how to create the central configuration file. No code has to change at any of those locations.
Many companies assign owners to particular software systems. The owner may be responsible for maintaining that software across many installations, at many sites, with many local sysadmins who can mess things up by modifying the code without the owner's permission. Software owners in this situation should strive to provide flexibility in their code, so no localized code changes are required. This way they can maintain 1 code base across the entire corporation, and detect local changes that could break the software.
Caveat
If a user is not aware that the default could be different between installations, they might expect one default value, but get another. This method needs to be used only when the user community is aware of the situation.
The Bottom Line
Whenever you write a script with options that allow the user to override a value, you may find that different user communities prefer different default values. This soft default method gives you the ability to give the user what they want, which increases the chances that they will use your software in the future.
Don't miss the latest perl tips and tricks!
Subscribe to our low-volume mailing list:
Privacy Policy
| Copyright © 2006 Fastech Learning LLC, all rights reserved. |
| Phone toll free 1-866-464-6688, Phoenix Metro area 480-895-6688 |
| Problem with this web site? please let us know |