hextor has asked for the wisdom of the Perl Monks concerning the following question:

Please excuse my uber noob and sometimes redundant questions, however I am new to Perl so I have run into a few road blocks, specifically with getopt::std. I created an rsync perl script that will transfer gz files from a local destination to a remote destination using a key, a semaphore, etc. Anyway, what I am currently trying to do is to pass arguments to the command line using getopt::std that would allow to just drop flags if I wish to rsync data using different IP/host, key, username, etc. I have been told that this is possible but I don't quite understand how to implement that with getopt::std. I was going to go with ARGV, but my team would prefer I go with getopt. I have read up on getopt::std but to be honest, there isnt much covered on the module. That or I am not quite understanding how it works in a script if I don't have specify variables for the flags. Below is the script I am trying to implement getopt::std to. Any help towards the right direction would be greatly appreciated.

#!/usr/bin/perl -w ### set initial variables $user = '<USERNAME>'; $host = '<IP/HOSTNAME>'; $priv_key = '</KEY/DIR/FILE>'; $remote_dir = "<REMOTEDIR>"; $source_dir = '<SOURCEDIR>'; $log_dir = '<LOGDIR>'; ### set system commands/configs/flags my $rm_cmd = '/bin/rm -rf'; my $touch_cmd = '/bin/touch'; my $ssh_cmd = '/usr/bin/ssh -i'; my $DEBUG = 2; ### set rsync commands/flags my $rsync_cmd = '/usr/bin/rsync -Pav -e'; my $del_flag = "--remove-source-files"; ### set file names/extensions my $semaphore = "rsync_running.lock"; my $log_file = "rsync.output.log"; my $file_ext = "*.gz"; sub filesize { use File::Find; find( sub { -f and ( $size += -s ) }, $source_dir ); $size = sprintf( "%.02f", $size / 1024 / 1024 ); open STDOUT, ">> $log_dir/$log_file" or die "$0: open: $!"; open STDERR, ">>& STDOUT" or die "$0: dup: $!"; print "Directory '$source_dir' contains $size MB\n"; } sub getLoggingTime { ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = gmtime(time); $nice_timestamp = sprintf( "%04d%02d%02d %02d:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec ); return $nice_timestamp; } sub rsyncfiles { if ( -f "$source_dir/$semaphore" ) { print "Rsync running, skipping this session.\n" if ( $DEBUG > +2 ); } else { system("$touch_cmd $source_dir/$semaphore"); my $push_cmd = "$rsync_cmd \"$ssh_cmd $priv_key\" $del_flag $source_dir/$file_ext $us +er\@$host:$remote_dir"; print "Running: $push_cmd\n" if ( $DEBUG > 1 ); my $return = system($push_cmd); if ($return) { print "rsync failed"; } } system("$rm_cmd $source_dir/$semaphore"); } @timeData = gmtime(time); my $timestamp = getLoggingTime(); open STDOUT, ">> $log_dir/$log_file" or die "$0: open: $!"; open STDERR, ">>& STDOUT" or die "$0: dup: $!"; print "The script ran at $timestamp \n"; &filesize; &getLoggingTime; &rsyncfiles;

Thanks all!

Replies are listed 'Best First'.
Re: getopt::std to pass arguments to command line help
by toolic (Bishop) on Jan 20, 2015 at 17:31 UTC
    I recommend Getopt::Long, storing all options in a hash:
    use warnings; use strict; use Getopt::Long qw(GetOptions); my %opt = (logdir => 'foo'); GetOptions(\%opt, qw(logdir=s)) or die; print "logdir=$opt{logdir}\n"; __END__ Run it like: myprog.pl -logdir bar Output: logdir=bar
      hextor look at that good example by toolic and pay attention to the GetOptions ... or die; part.
      This is very important because you dont want your program to execute with wrong or not accepted args.
      Personally i ended using everytime yet another idiom, even more cautious:
      use Getopt::Long; use Pod::Usage; # if you have documentation embedded is better unless (GetOptions( "option=s" => \$option ... )) { pod2usage(-verbose => 1,-exitval => 'NOEXIT'); # automatic u +sage printing (if you have an usage section in POD) &wait_for_input; # if the prog + was opend in a 'double click' fashion there is no time # to review e +rrors, if so you can just use something like: # sub wait_fo +r_input{ # print "\n +\nPress Return when ready\n"; # while (<S +TDIN>){last if $_ } # } exit; # now you can + exit or die with yet another error string }

      HtH
      L*
      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      Thank you. I will look into getopt::long.
Re: getopt::std to pass arguments to command line help
by karlgoethebier (Abbot) on Jan 20, 2015 at 18:49 UTC
Re: getopt::std to pass arguments to command line help
by Anonymous Monk on Jan 20, 2015 at 17:29 UTC
    I have been told that this is possible but I don't quite understand how to implement that with getopt::std.
    That's because you should use Getopt::Long. Also
    open STDOUT, ">> $log_dir/$log_file
    Don't open files like this if you don't know what Perl does with two-argument open. Especially if $log_dir and $log_file come from user input. Do it like this:
    open STDOUT, '>>', $log_dir/$log_file
    Consider using File::Spec::Functions for manupilating file names.
    &filesize;
    Don't call functions like this if you don't know what it actually does. Call them like this:
    filesize();

    use warnings; instead of -w. Also use strict;

      open STDOUT, '>>', "$log_dir/$log_file", but really
      use File::Spec::Functions; ... open STDOUT, '>>', catfile( $log_dir, $log_file ) or die "Can't open $log_file - $!\n";
      That makes sense. I see how that works better, thank you. The log file is created if it doesn't exist, however is there a way to specify permissions when the file is being created? Example, what if I wanted to the file to have 755 perms? I know it's not recommended, but for the sake of the question, what would you recommend?
Re: getopt::std to pass arguments to command line help
by jellisii2 (Hermit) on Jan 21, 2015 at 13:04 UTC