roswell1329 has asked for the wisdom of the Perl Monks concerning the following question:
I recently read a great article on production-level scripting in the August 2005 issue of Sys Admin Magazine. In it, the author advocated the use of a template to make production-script rollout much faster. In an example template, the author included multiple levels of verbosity, options to email execution reports and error reports, and a test mode that would perform a test run of the code without actually committing to any changes. The example the author provided in the article was a bash shell script, but said the same techniques could be applied to perl or other administrative languages.
I have attempted to do the same thing in perl, but I have encountered 2 problems:
Any suggestions you have would be greatly appreciated! My template script in it's entirety is below:
#!/usr/bin/perl ############################################################## # Script : template # Author : roswell1329 # Date : 08/31/2005 # Last Edited: 09/07/2005, roswell1329 # Description: working template for fast production rollout ############################################################## # Purpose: # - create a working template with logging, and emailed # reports to make production development of scripts # faster # Requirements: # - error code checking # - different debugging/logging levels # - option for email execution report delivery # - option for email error delivery # - option for TEST (go through motions and logging with no # actual changes made # Method: # - make a script 'shell' with some of the standard options # already implemented # Syntax: template [-h] # template [-m email] [-e email] [-t] [-d] # template [-m email] [-e email] [-t] [-v] # Notes: # - not happy with execution logging or failure checking ############################################################## ###################################### #### Opening Initializations #### ###################################### use strict; use Getopt::Std; my $ex_status = 0; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; $ENV{PATH} = '/bin:/usr/bin'; $SIG{INT} = sub { $ex_status = 1; die }; $SIG{PIPE} = sub { $ex_status = 2; die }; my $cmdname = (split /\//,$0)[-1]; my $basedir = (split /\/$cmdname/,$0)[0]; my $cfgfile = "$basedir/$cmdname.cfg"; my $logfile = "$basedir/$cmdname.log"; my $maillog = ""; my $thread = $$; my $user = (getpwuid $<)[0]; my %opts = (); my %configs = (); getopts('de:hm:tv', \%opts); &usage if ($opts{h}); &usage if (exists($opts{m}) && (!$opts{m})); &usage if (exists($opts{e}) && (!$opts{e})); &usage if (exists($opts{d}) && exists($opts{v})); if(-e $cfgfile) { open(CONFIG,"$cfgfile") or die "Cannot open config file $cfgfile\n"; foreach my $attrib (<CONFIG>) { next if ($attrib =~ /^$/); next if ($attrib =~ /^#/); my ($attrib_name,$attrib_val) = split /\s*=\s*/,$attrib; chomp($attrib_name,$attrib_val); $configs{$attrib_name} = $attrib_val; } &debugger("Config file found. Values loaded"); while(my($k,$v) = each %configs) { &debugger("|- $k attribute loaded with '$v'"); } } else { &debugger("No config file found. Proceeding with internal values"); } ###################################### #### Main Loop #### ###################################### &debugger("Initializations complete"); &debugger("Starting main routine"); ###################################### #### Support Functions #### ###################################### sub debugger($) { if(!exists($opts{v}) && !exists($opts{d})) { return; } my $dbstring = shift @_; my ($dsec,$dmin,$dhour,$dday,$dmon,$dyear,$dwday)=(localtime)[0..6]; my $monname = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug', 'Sep','Oct','Nov','Dec')[$dmon]; my $dayname = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[$dwday]; open(LOG,">>$logfile") or die "Cannot open logfile $logfile\n"; if(exists($opts{d})) { warn "[DEBUG]: $dbstring\n"; $maillog .= $dbstring . "\n" if ($opts{m}); printf LOG "%s %s %02d %02d:%02d:%02d thread[%5d]: %s\n", + ($dayname,$monname,$dday,$dhour,$dmin,$dsec,$thread,$dbstring); } elsif(exists($opts{v})) { next if($dbstring =~ /\|-/); $maillog .= $dbstring . "\n" if ($opts{m}); printf LOG "%s %s %02d %02d:%02d:%02d thread[%5d]: %s\n", ($dayname,$monname,$dday,$dhour,$dmin,$dsec,$thread,$dbstring); } close(LOG); } sub mail_report($$) { my ($mesg,$mailsubj) = @_; my $mailfrom = $user; open(MAIL, "| sendmail -oi -t") or die "Cannot start sendmail\n"; print MAIL "To:$opts{m}\nFrom:$mailfrom\nSubject:$mailsubj\n\n"; print MAIL $mesg; close(MAIL); } sub usage { print <<EOF; Usage: $cmdname [-h] $cmdname [-m email] [-e email] [-t] [-v] $cmdname [-m email] [-e email] [-t] [-d] Options: -d debugging mode. This mode will verbosely describe the current execution of $cmdname. -e [EMAIL] error reporting. This option will send any errors detected by $cmdname to email address EMAIL. -h help. This option will display this help message. -m [EMAIL] execution reporting. This option will send a $cmdname execution report to the supplied email address. -t test mode. This allows you to run the script without making any critical changes. -v verbose mode. This option will enable logging for this execution of $cmdname EOF } END { $ex_status > 0 ? &debugger("Program killed!") : &debugger("Exiting normally"); &debugger("Mailing reports"); &mail_report($maillog,"$cmdname Execution Report") if ($opts{m}); if($opts{e}) { if(($!) || ($?)) { my $mesg = "Internal Failures:\n------------------\n$!\n\n" . "External Failures:\n-----------------\n$?\n"; &mail_report($mesg,"$cmdname Error Report"); } } exit; }
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Production level script template
by tomhukins (Curate) on Sep 07, 2005 at 15:58 UTC | |
Re: Production level script template
by Fletch (Bishop) on Sep 07, 2005 at 17:27 UTC | |
by del (Pilgrim) on Sep 08, 2005 at 19:10 UTC | |
by Tanktalus (Canon) on Sep 08, 2005 at 19:21 UTC | |
Re: Production level script template
by roswell1329 (Acolyte) on Sep 07, 2005 at 17:57 UTC | |
by rvosa (Curate) on Oct 26, 2005 at 20:46 UTC |