How I pass parameters to my programs in perl

Posted by Chris on August 4th, 2009 filed in programming

I often want to change what a program does with parameters.  Anything from changing a date (very very common) to a log location, to email addresses, etc.  Combined with another favorite unix command line trick, it’s super easy.

Just a couple of notes here – I don’t like the usual unix-style for some reason.  I’m not going to remember that -d is debug, and that -a <email address> is email address.  Plus, one of the problems with programmers is that the first way we learn to do something is the way we’ll do it forever.  When I started with cgi, we did the full “my $cgi = new CGI; my $thing=$cgi->param(‘thing’)”.  You *can* do  just the standara param(‘thing’) but then you have to use “use CGI qw/:standard/;” which I can never remember.  No big deal either way.

So here goes.  For this one, I have a program that gets a bunch of stuff from a bunch of machines and does some manipulation of the data.  I want to be able to limit the machines it goes to, whether or not debug is on, how many threads, how many concurrent inserts, where it logs, and the date it runs for.  (assuming it gets the list of machines from a DB if not specified).

perl host=all_hosts threads=10 inserts=15000 logfile=~/logs/`date +\%y-\%m-\%d` debug=0 date=`date +\%y-\%m-\%d`

And the code that runs:

#!/usr/bin/env  perl
use CGI;
my $cgi = new CGI;
my $date = $cgi->param('date') || `date +\%y-\%m-\%d`; chomp($date); #gives a default, with no newline
my $debug = $cgi->param('debug') || 0;
my $host = $cgi->param('host') || usage();  # you have to pass at least one!
my @hosts = $host eq 'all_hosts' ? all_hosts() : split(',',$host);   #ternary test, gets a list, depending on what's passed
my $threads = $cgi->param('threads') || 10;
my $inserts = $cgi->param('inserts') || 15000;
my $logfile = $cgi->param('logfile') || "~/logs/$date";

#do something
foreach my $hostname(@hosts)
  #get some data and insert it, log, etc.

sub usage()
  print "Usage: perl host= [threads=10 inserts=15000 logfile=<logfile> debug=1 date=<YYYY-MM-DD>]\n";

While somewhat on the subject, that date hack is a great one to remember. A lot of the time you want to be explicit about the date to run for. Alternatively, I have a lot of programs I want to run for yesterday. It’s almost as simple.

`date +\%Y-\%m-\%d --date='1 days ago'`

The above line returns the date in YYYY-MM-DD format for yesterday. That’s it! Put it into a cron job the next morning for yesterday and look cool to those windows guys.

2 Responses to “How I pass parameters to my programs in perl”

  1. Chas. Owens Says:

    Your code leaves me with 3 questions:

    1. why shell out to the date command (making the script slower and less portable) when we have localtime and POSIX::strftime?
    2. why are you escaping %? (it doesn’t interpolate)?
    3. why use a non-standard date option to get yesterday?

    What is so wrong with

        my $today = DateTime->now->ymd;


        use POSIX qw/strftime/;
        my $today = strftime “%Y-%m-%d”, localtime;


        my $yesterday = DateTime->now->subtract( days => 1 )->ymd;


        $ENV{TZ} = “EST+28”;
        my $yesterday = strftime(“%Y-%m-%d”, localtime), “\n”;

  2. admin Says:

    Two reasons, neither good.

    1- Was just lazy and copied the code from the calling cron job.
    2- Didn’t know about most of those, and now I do, and will probably switch to one of them really soon.

    Thanks, this is helpful!

Leave a Comment