FAQ
Hi all,

This is my first real go at a perl script. Thoughts?

Thanks.

--
Just getting into the best language ever...
Fancy a [email protected]? Just ask!!!

Search Discussions

  • Chris Devers at Aug 30, 2004 at 11:43 pm

    On Tue, 31 Aug 2004, Gavin Henry wrote:

    This is my first real go at a perl script. Thoughts?
    Don't send attachments?

    There's no telling what an attachment contains these days; if it's just
    a plain text Perl script then please paste it inline with your message.

    Thanks :-)


    --
    Chris Devers [email protected]
    http://devers.homeip.net:8080/blog/

    np: 'Movin' Right Along (lo-fi midi version)'
    by The Muppets
    from 'The Muppet Movie Soundtrack'
  • Gavin Henry at Aug 31, 2004 at 1:34 am

    On Tuesday 31 Aug 2004 00:43, Chris Devers wrote:
    On Tue, 31 Aug 2004, Gavin Henry wrote:
    This is my first real go at a perl script. Thoughts?
    Don't send attachments?

    There's no telling what an attachment contains these days; if it's just
    a plain text Perl script then please paste it inline with your message.

    Thanks :-)
    #!/usr/bin/perl

    use strict;
    use warnings;
    use Mail::Sendmail;
    use POSIX qw(strftime);

    #################################################
    # program: suretec-backup #
    # license: GPL #
    # author: Gavin Henry #
    # company: Suretec Systems Ltd. #
    # url: http://www.suretecsystems.com #
    # version: v1.0 #
    # #
    # first draft : 30-08-04 #
    # last update : 31-08-04 #
    #################################################

    # Globals
    my $rdiff = '/usr/bin/rdiff-backup';
    my $localdir = '/home/ghenry/perl';
    my $userhost = "slim_jim\@ssh.magicfx.co.uk";
    my $remotedir = '/home/slim_jim/perl';
    my $args = "$localdir $userhost\:\:$remotedir";
    my $to = "ghenry\@perl.me.uk";
    my $from = "ghenry\@perl.me.uk";
    my $time = localtime;
    my $datestamp = strftime "%d.%m.%y.%T", localtime;


    # Suretec Message
    print
    "\n----------------------------------------------------------------------------\n";
    print "Brought to you by Suretec Systems Ltd.\n";
    print
    "----------------------------------------------------------------------------\n";

    # Start message
    print
    "\n----------------------------------------------------------------------------\n";
    print "Initialising remote backup synchronsation on $time.\n";
    print
    "----------------------------------------------------------------------------\n";

    # Using system command call to give us a return code, with die after
    if{}else{} block.
    my $backup = system($rdiff, $args);

    # Send e-mail with a few details for success and failures
    # Success
    if ($backup == 0) {
    my %mails = ( To => "$to",
    From => "$from",
    Subject => "Remote backup complete from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has been completed on $ENV{HOSTNAME} on $time
    with the command:\n\n $rdiff $args\n" );
    sendmail(%mails);
    # Success finish message
    print
    "\n----------------------------------------------------------------------------\n";
    print "Remote backup complete on $time. E-mail sent with details.\n";
    print
    "----------------------------------------------------------------------------\n";

    # Create a success logfile
    open LOG, ">>$datestamp-suretec-backup-success.log"
    or die "Cannot create logfile: $!";
    print LOG "Remote backup completed on $time, with the command:\n\n$rdiff
    $args\n\nAn e-mail has been sent.\n";
    close LOG;
    print "Logfile created on $time.\n\n";

    # Failure
    } else {
    my %mailf = ( To => "$to",
    From => "$from",
    Subject => "Remote backup failed from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has failed on $ENV{HOSTNAME} on $time with the
    command:\n\n$rdiff $args\n" );
    sendmail(%mailf);
    # Failure finish message
    print
    "\n----------------------------------------------------------------------------\n";
    print "Remote backup failed on $time. E-mail sent with details.\n";
    print
    "----------------------------------------------------------------------------\n";

    # Create a failure logfile
    open LOG, ">>$datestamp-suretec-backup-failed.log"
    or die "Cannot create logfile: $!";
    print LOG "Remote backup failed on $time, with the command:\n\n$rdiff
    $args\n\nAn e-mail has been sent.\n";
    close LOG;
    print "Logfile created on $time.\n\n";
    }

    # Did it work?
    die "Backup exited funny: $?" unless $backup == 0;

    # Program complete.

    --
    Just getting into the best language ever...
    Fancy a [email protected]? Just ask!!!
  • Chris Devers at Aug 31, 2004 at 3:48 am

    On Tue, 31 Aug 2004, Gavin Henry wrote:

    # Globals
    my $rdiff = '/usr/bin/rdiff-backup';
    my $localdir = '/home/ghenry/perl';
    my $userhost = "slim_jim\@ssh.magicfx.co.uk";
    my $remotedir = '/home/slim_jim/perl';
    my $args = "$localdir $userhost\:\:$remotedir";
    my $to = "ghenry\@perl.me.uk";
    my $from = "ghenry\@perl.me.uk";
    my $time = localtime;
    my $datestamp = strftime "%d.%m.%y.%T", localtime;
    It's nitpicking, but I like lining repetitive lines like these up so
    that the differences stand out better, like so:

    my $rdiff = '/usr/bin/rdiff-backup';
    my $localdir = '/home/ghenry/perl';
    my $userhost = "slim_jim\@ssh.magicfx.co.uk";
    my $remotedir = '/home/slim_jim/perl';
    my $args = "$localdir $userhost\:\:$remotedir";
    my $to = "ghenry\@perl.me.uk";
    my $from = "ghenry\@perl.me.uk";
    my $time = localtime;
    my $datestamp = strftime "%d.%m.%y.%T", localtime;

    Also, it seems to me like a good habit to minimize putting in literals
    when you can help it -- typos are all too easy to make. Therefore,

    my $to = "ghenry\@perl.me.uk";
    my $from = $to;

    If $from needs to be something else later, you can change it. (This is
    kind of a thin example, but I'm trying to point out a broader idea.)
    # Suretec Message
    print "\n----------------------------------------------------------------------------\n";
    print "Brought to you by Suretec Systems Ltd.\n";
    print "----------------------------------------------------------------------------\n";
    Heredocs are popular for statements like this, but I prefer this idiom:

    print qq[
    ------------------------------------------------------
    Brought to you by Suretec Systems Ltd.
    ------------------------------------------------------

    ------------------------------------------------------
    Initialising remote backup synchronsation on $time.B
    ------------------------------------------------------
    ];

    Less typing; more readable. IMO.
    # Send e-mail with a few details for success and failures
    # Success
    if ($backup == 0) {
    my %mails = ( To => "$to",
    From => "$from",
    Subject => "Remote backup complete from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has been completed on $ENV{HOSTNAME} on $time
    with the command:\n\n $rdiff $args\n" );
    Again, whitespace makes stuff like this a lot easier to read:

    my %mails = (
    To => "$to",
    From => "$from",
    Subject => "Remote backup complete from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has been completed on $ENV{HOSTNAME}"
    . " on $time with the command:\n\n $rdiff $args\n"
    );
    sendmail(%mails);
    A lot of people like avoiding temp variables like this, and would rather
    just combine the `my %mails` declaration into the `sendmail(...)` call.
    But whatever, that's a judgement call -- it may make the code a hair
    faster, but probably not enough to care about; the bigger issue is
    whether the temp variable is more readable, but that's a judgement call.
    # Create a success logfile
    open LOG, ">>$datestamp-suretec-backup-success.log"
    or die "Cannot create logfile: $!";
    print LOG "Remote backup completed on $time, with the command:\n\n$rdiff
    $args\n\nAn e-mail has been sent.\n";
    Again, I think the qq{...} syntax can make this kind of thing cleaner:

    print LOG qq{Remote backup completed on $time, with the command:

    $rdiff $args

    An e-mail has been sent.
    };
    # Did it work?
    die "Backup exited funny: $?" unless $backup == 0;
    A lot of people like to `die` immediately when an error comes up, rather
    than waiting until the end of the script like this. The common idiom is:

    some_risky_thing(...) or die "You sunk my battleship! $!";

    or

    die "You sunk my battleship! $!" unless some_risky_thing(...);

    which, again, comes down to which seems more readable. This can depend a
    lot on the particular example -- in this case, I think the first version
    looks cleaner, because it puts the common case first, while the second
    puts the exceptional case first and so looks backwards. In other cases,
    that might be fine though.



    --
    Chris Devers [email protected]
    http://devers.homeip.net:8080/blog/

    np: 'Movin' Right Along (lo-fi midi version)'
    by The Muppets
    from 'The Muppet Movie Soundtrack'
  • Gunnar Hjalmarsson at Aug 31, 2004 at 1:37 am

    Chris Devers wrote:
    Don't send attachments?

    There's no telling what an attachment contains these days;
    A simple check of the message source is sufficient to preclude virus etc.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
  • Chris Devers at Aug 31, 2004 at 3:32 am

    On Tue, 31 Aug 2004, Gunnar Hjalmarsson wrote:

    Chris Devers wrote:
    Don't send attachments?

    There's no telling what an attachment contains these days;
    A simple check of the message source is sufficient to preclude virus etc.
    But why should people have to do that? A simple check of the source in,
    say, Outlook might be enough to fire off a worm these days -- why make
    people risk it when inline plain text isn't a question at all?

    Just say no to mailing list attachments -- if you have a document longer
    than can reasonably fit into an email, put it on the web & post a URL.

    :-)


    --
    Chris Devers [email protected]
    http://devers.homeip.net:8080/blog/

    np: 'Sesame Street Theme Song'
    by Sesame Street
    from 'Sesame Street'
  • Gunnar Hjalmarsson at Aug 31, 2004 at 6:26 am

    Chris Devers wrote:
    Gunnar Hjalmarsson wrote:
    Chris Devers wrote:
    Don't send attachments?

    There's no telling what an attachment contains these days;
    A simple check of the message source is sufficient to preclude
    virus etc.
    But why should people have to do that? A simple check of the source
    in, say, Outlook might be enough to fire off a worm these days --
    why make people risk it when inline plain text isn't a question at
    all?

    Just say no to mailing list attachments -- if you have a document
    longer than can reasonably fit into an email, put it on the web &
    post a URL.
    Makes a lot of sense. Please forget my remark. :)

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
  • Jenda Krynicky at Aug 31, 2004 at 11:36 am
    From: Chris Devers <[email protected]>
    On Tue, 31 Aug 2004, Gunnar Hjalmarsson wrote:

    Chris Devers wrote:
    Don't send attachments?

    There's no telling what an attachment contains these days;
    A simple check of the message source is sufficient to preclude virus
    etc.
    But why should people have to do that? A simple check of the source
    in, say, Outlook might be enough to fire off a worm these days -- why
    make people risk it when inline plain text isn't a question at all?
    Previewing the message could fire of a worm in Outlook, whether there
    is an attachment or not is irrelevant.

    - Don't use Outlook
    - Install an antivirus
    Just say no to mailing list attachments -- if you have a document
    longer than can reasonably fit into an email, put it on the web & post
    a URL.
    Not everyone has his own pages to put that to and registering on a
    free web hosting just to be able to ask for help on a script looks a
    bit too much to me.

    Besides ... how do you know the URL doesn't point to a malevolent
    page that'll abuse a hole in the browser and install a worm or
    something?

    Anyway if the code is too long to fit in the body of the email it's
    too long for people to read. We are all busy people here and if
    someone posts a ten pages long script few people will care to read
    it.

    Jenda
    ===== [email protected] === http://Jenda.Krynicky.cz =====
    When it comes to wine, women and song, wizards are allowed
    to get drunk and croon as much as they like.
    -- Terry Pratchett in Sourcery
  • Gunnar Hjalmarsson at Aug 31, 2004 at 12:55 pm

    Jenda Krynicky wrote:
    From: Chris Devers <[email protected]>
    Just say no to mailing list attachments -- if you have a document
    longer than can reasonably fit into an email, put it on the web
    & post a URL.
    Not everyone has his own pages to put that to and registering on a
    free web hosting just to be able to ask for help on a script looks
    a bit too much to me.
    Does it? To me it does not.
    Anyway if the code is too long to fit in the body of the email it's
    too long for people to read.
    True in most cases. But for those rare occations when it's motivated
    to make a long script available, it's reasonable to require that the
    person who seeks help make sufficient efforts to make it both easy and
    secure to assist.

    ( I did change my mind, didn't I? :) )

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
  • Bob Showalter at Aug 31, 2004 at 12:51 am

    Gavin Henry wrote:
    Hi all,

    This is my first real go at a perl script. Thoughts?
    Congrats on your first script.

    Suggestions:

    1. Indent code inside blocks.

    2. The way you're calling system() looks odd. You're using more than one
    arg, which is a signal to bypass the shell. But your second arg looks like
    it needs shell processing. Does this actually work?

    3. Why not put the die() inside the else block?
  • Gavin Henry at Aug 31, 2004 at 1:36 am

    On Tuesday 31 Aug 2004 01:51, you wrote:
    Gavin Henry wrote:
    Hi all,

    This is my first real go at a perl script. Thoughts?
    Congrats on your first script.

    Suggestions:

    1. Indent code inside blocks. ok.
    2. The way you're calling system() looks odd. You're using more than one
    arg, which is a signal to bypass the shell. But your second arg looks like
    it needs shell processing. Does this actually work?
    Yup, out of the cookbook.
    3. Why not put the die() inside the else block?
    yeah.

    --
    Just getting into the best language ever...
    Fancy a [email protected]? Just ask!!!
  • John W. Krahn at Aug 31, 2004 at 6:58 am

    Gavin Henry wrote:
    Hi all, Hello,
    This is my first real go at a perl script. Thoughts?
    Subject: Could this be made shorter and cleaner? Yes.
    # Globals
    my $rdiff = '/usr/bin/rdiff-backup';
    my $localdir = '/home/ghenry/perl';
    my $userhost = "slim_jim\@ssh.magicfx.co.uk";
    my $remotedir = '/home/slim_jim/perl';
    my $args = "$localdir $userhost\:\:$remotedir";
    my $to = "ghenry\@perl.me.uk";
    my $from = "ghenry\@perl.me.uk";
    my $time = localtime;
    my $datestamp = strftime "%d.%m.%y.%T", localtime;
    You are using single quotes on strings that do not interpolate but you are
    using double quotes on strings that have characters that interpolate? Use
    single quotes unless you *need* double quotes. Make $args an array because
    system() may invoke the shell if you pass it a scalar.

    # Globals
    my $rdiff = '/usr/bin/rdiff-backup';
    my $localdir = '/home/ghenry/perl';
    my $userhost = '[email protected]';
    my $remotedir = '/home/slim_jim/perl';
    my @args = ( $localdir, "$userhost\::$remotedir" );
    my $to = '[email protected]';
    my $from = '[email protected]';
    my $time = localtime;
    my $datestamp = strftime '%d.%m.%y.%T', localtime;

    # Suretec Message
    print "\n----------------------------------------------------------------------------\n";
    print "Brought to you by Suretec Systems Ltd.\n";
    print "----------------------------------------------------------------------------\n";
    Your hyphen-separator is used multiple times so you may want to store it in a
    variable.

    my $separator = '-' x 76 . "\n";

    # Suretec Message
    print "\n", $separator, "Brought to you by Suretec Systems Ltd.\n", $separator;

    # Using system command call to give us a return code, with die after if{}else{} block.
    my $backup = system( $rdiff, $args );
    Using a list instead of scalar:

    my $backup = system $rdiff, @args;

    # Send e-mail with a few details for success and failures
    # Success
    if ( $backup == 0 ) {
    my %mails = (
    To => "$to",
    From => "$from",
    Subject => "Remote backup complete from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has been completed on $ENV{HOSTNAME} on $time with the command:\n\n $rdiff $args\n" );
    sendmail( %mails );
    # Success finish message
    print "\n----------------------------------------------------------------------------\n";
    print "Remote backup complete on $time. E-mail sent with details.\n";
    print "----------------------------------------------------------------------------\n";

    # Create a success logfile
    open LOG, ">>$datestamp-suretec-backup-success.log"
    or die "Cannot create logfile: $!";
    print LOG "Remote backup completed on $time, with the command:\n\n$rdiff $args\n\nAn e-mail has been sent.\n";
    close LOG;
    print "Logfile created on $time.\n\n";

    # Failure
    }
    else {
    my %mailf = (
    To => "$to",
    From => "$from",
    Subject => "Remote backup failed from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has failed on $ENV{HOSTNAME} on $time with the command:\n\n$rdiff $args\n" );
    sendmail( %mailf );
    # Failure finish message
    print "\n----------------------------------------------------------------------------\n";
    print "Remote backup failed on $time. E-mail sent with details.\n";
    print "----------------------------------------------------------------------------\n";

    # Create a failure logfile
    open LOG, ">>$datestamp-suretec-backup-failed.log"
    or die "Cannot create logfile: $!";
    print LOG "Remote backup failed on $time, with the command:\n\n$rdiff $args\n\nAn e-mail has been sent.\n";
    close LOG;
    print "Logfile created on $time.\n\n";
    }
    It looks like 99% of the code in both blocks is exactly the same. You should
    factor out duplicated code.

    my $msg = $backup ? 'failed' : 'completed';

    my %mails = (
    To => $to,
    From => $from,
    Subject => "Remote backup $msg from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has $msg on $ENV{HOSTNAME} on $time with
    the command:\n\n $rdiff @args\n"
    );
    sendmail( %mails );
    # finish message
    print "\n", $separator, "Remote backup $msg on $time. E-mail sent with
    details.\n", $separator;

    # Create a logfile
    open LOG, ">>$datestamp-suretec-backup-success.log" or die "Cannot create
    logfile: $!";
    print LOG "Remote backup $msg on $time, with the command:\n\n$rdiff
    $args\n\nAn e-mail has been sent.\n";
    close LOG;
    print "Logfile created on $time.\n\n";




    John
    --
    use Perl;
    program
    fulfillment
  • Gavin Henry at Aug 31, 2004 at 9:08 am

    It looks like 99% of the code in both blocks is exactly the same. You
    should
    factor out duplicated code.

    my $msg = $backup ? 'failed' : 'completed';

    my %mails = (
    To => $to,
    From => $from,
    Subject => "Remote backup $msg from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has $msg on $ENV{HOSTNAME} on $time
    with
    the command:\n\n $rdiff @args\n"
    );
    sendmail( %mails );
    # finish message
    print "\n", $separator, "Remote backup $msg on $time. E-mail sent with
    details.\n", $separator;
    Thanks John and Chris. Chris, I have gone for John method of using the
    $seperator, as I will use that more in this script when I add more
    features, thanks for the pointer on here documents though.

    I have taken on board all your suggestions, but I still have two questions:

    1. How does the above code get the return code from rdiff to tell if it
    failed or passed? Is this the $backup ? part, i.e. failed first, then
    completed second?

    2. use POSIX qw(strftime); I got this from Perl Cookbook. I take it this
    is calling the POSIX strftime and putting it in a list, so when I select
    %T etc. it is picking it from the list? Why does it fail if I put use
    POSIX; and put qw(strftime); somewhere else.


    Oh, and I have the bug now :-) It's a great felling when your script works!!!

    You will be seeing much more of my code in here, so hopefully I will be
    learning and not pasting the same mistakes.

    P.S. I am now a programmer or a scripter, I am not sure is perl is
    programming or scripting? I think programming.

    Gavin.

    Would anyone actually like a [email protected] e-mail address?



    --
    Just getting into the best language ever...
    Fancy a [email protected]? Just ask!!!
  • John W. Krahn at Aug 31, 2004 at 12:05 pm

    Gavin Henry wrote:
    It looks like 99% of the code in both blocks is exactly the same. You
    should
    factor out duplicated code.

    my $msg = $backup ? 'failed' : 'completed';

    my %mails = (
    To => $to,
    From => $from,
    Subject => "Remote backup $msg from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has $msg on $ENV{HOSTNAME} on $time
    with
    the command:\n\n $rdiff @args\n"
    );
    sendmail( %mails );
    # finish message
    print "\n", $separator, "Remote backup $msg on $time. E-mail sent with
    details.\n", $separator;
    Thanks John and Chris. Chris, I have gone for John method of using the
    $seperator, as I will use that more in this script when I add more
    features, thanks for the pointer on here documents though.

    I have taken on board all your suggestions, but I still have two questions:

    1. How does the above code get the return code from rdiff to tell if it
    failed or passed?
    The same way it did before.
    Is this the $backup ? part, i.e. failed first, then
    completed second?
    It seems like you may be confused by the conditional operator. The statement:

    my $msg = $backup ? 'failed' : 'completed';

    Is short for:

    my $msg;
    if ( $backup == 0 ) {
    $msg = 'completed';
    }
    else {
    $msg = 'failed';
    }
    2. use POSIX qw(strftime); I got this from Perl Cookbook. I take it this
    is calling the POSIX strftime and putting it in a list,
    No, this is telling perl that the only function we want to import from the
    POSIX module is 'strftime'.
    so when I select
    %T etc. it is picking it from the list? Why does it fail if I put use
    POSIX; and put qw(strftime); somewhere else.
    Because the list of function names must follow the module name.

    perldoc -f use



    John
    --
    use Perl;
    program
    fulfillment
  • Gavin Henry at Aug 31, 2004 at 12:34 pm

    John W. Krahn said:
    Gavin Henry wrote:
    It looks like 99% of the code in both blocks is exactly the same. You
    should
    factor out duplicated code.

    my $msg = $backup ? 'failed' : 'completed';

    my %mails = (
    To => $to,
    From => $from,
    Subject => "Remote backup $msg from $ENV{HOSTNAME} on $time",
    Message => "The remote backup has $msg on $ENV{HOSTNAME} on $time
    with
    the command:\n\n $rdiff @args\n"
    );
    sendmail( %mails );
    # finish message
    print "\n", $separator, "Remote backup $msg on $time. E-mail sent with
    details.\n", $separator;
    Thanks John and Chris. Chris, I have gone for John method of using the
    $seperator, as I will use that more in this script when I add more
    features, thanks for the pointer on here documents though.

    I have taken on board all your suggestions, but I still have two
    questions:

    1. How does the above code get the return code from rdiff to tell if it
    failed or passed?
    The same way it did before.
    Is this the $backup ? part, i.e. failed first, then
    completed second?
    It seems like you may be confused by the conditional operator. The
    statement:

    my $msg = $backup ? 'failed' : 'completed';

    Is short for:

    my $msg;
    if ( $backup == 0 ) {
    $msg = 'completed';
    }
    else {
    $msg = 'failed';
    }
    Ah, got it. Do I just expand on the failure and completed message and add
    in what I had before?
    2. use POSIX qw(strftime); I got this from Perl Cookbook. I take it this
    is calling the POSIX strftime and putting it in a list,
    No, this is telling perl that the only function we want to import from the
    POSIX module is 'strftime'.
    Got it.
    so when I select
    %T etc. it is picking it from the list? Why does it fail if I put use
    POSIX; and put qw(strftime); somewhere else.
    Because the list of function names must follow the module name.

    perldoc -f use
    Will do.

    Lastly, the scripts fails when I uncomment $options, saying verbosity
    needs a number, when I have it -v5 --print-statistics. Is this the wrong
    way to pass the option?

    Gavin.


    --
    Just getting into the best language ever...
    Fancy a [email protected]? Just ask!!!
  • Daniel Staal at Aug 31, 2004 at 2:58 pm
    --As of Tuesday, August 31, 2004 10:07 AM +0100, Gavin Henry is alleged to
    have said:
    P.S. I am now a programmer or a scripter, I am not sure is perl is
    programming or scripting? I think programming.
    --As for the rest, it is mine.

    Short answer: Yes. (It is at least one of the two.) ;)

    Long answer... You honestly don't want to get into it. You start
    devolving into arguments over what is 'scripting' versus what is
    'programming', and from there what is best...

    To me, scripting is a sub-class of programming anyway, so why should it
    matter? ;)

    Daniel T. Staal

    ---------------------------------------------------------------
    This email copyright the author. Unless otherwise noted, you
    are expressly allowed to retransmit, quote, or otherwise use
    the contents for non-commercial purposes. This copyright will
    expire 5 years after the author's death, or in 30 years,
    whichever is longer, unless such a period is in excess of
    local copyright law.
    ---------------------------------------------------------------
  • Gavin Henry at Aug 31, 2004 at 3:08 pm

    Daniel Staal said:
    --As of Tuesday, August 31, 2004 10:07 AM +0100, Gavin Henry is alleged to
    have said:
    P.S. I am now a programmer or a scripter, I am not sure is perl is
    programming or scripting? I think programming.
    --As for the rest, it is mine.

    Short answer: Yes. (It is at least one of the two.) ;)

    Long answer... You honestly don't want to get into it. You start
    devolving into arguments over what is 'scripting' versus what is
    'programming', and from there what is best...

    To me, scripting is a sub-class of programming anyway, so why should it
    matter? ;)
    Yeah, I'm a programmer ;-)

    --
    Just getting into the best language ever...
    Fancy a [email protected]? Just ask!!!
  • Shawn at Aug 31, 2004 at 5:14 pm

    On Tue, 2004-08-31 at 10:57 -0400, Daniel Staal wrote:
    --As of Tuesday, August 31, 2004 10:07 AM +0100, Gavin Henry is alleged to
    have said:
    P.S. I am now a programmer or a scripter, I am not sure is perl is
    programming or scripting? I think programming.
    --As for the rest, it is mine.

    Short answer: Yes. (It is at least one of the two.) ;)

    Long answer... You honestly don't want to get into it. You start
    devolving into arguments over what is 'scripting' versus what is
    'programming', and from there what is best...
    I would say Perl is at least both. Allow me to devolve..

    The act of writing a perl program is script in in that you're simply (or
    not so simply) instructing /usr/bin/perl to do stuff based on you
    "script". You're running the source code with an interpreter, so to
    speak.

    Perl programing is programing in that the word "programing" is loosely
    defined enough such that even COBOL is a programming language. So long
    as the "language" has constructs that allow you to tell the machine it's
    running on to do something and not just a parsing specification, I'd say
    you'd be hard pressed to argue it's not a language. Whoever said that
    just because your handiwork isn't converted to a format that the kernel
    itself parses into machine code which it then feeds to a CPU that you're
    code isn't a program? What's java? It has an interpreter, and it isn't
    machine code, right? Oh yeah, it's a "run time system"... Oh, I forgot.

    There. Hopefully that made enough sense, and will end all devolving.
  • Bob Showalter at Aug 31, 2004 at 1:14 pm

    Gavin Henry wrote:
    On Tuesday 31 Aug 2004 01:51, you wrote:
    2. The way you're calling system() looks odd. You're using more
    than one arg, which is a signal to bypass the shell. But your
    second arg looks like it needs shell processing. Does this actually
    work?
    Yup, out of the cookbook.
    Odd. Which cookbook?

    Here's a simple illustration of what I'm talking about.

    Consider a simple command like

    head /etc/services /etc/protocols

    This works, as it passes the command line to the shell for processing

    $ perl -e 'system "head /etc/services /etc/protocols"'

    This also works, as I'm splitting the arguments myself:

    $ perl -e 'system "head", "/etc/services", "/etc/protocols"'

    But this (which is similar to what you're doing) doesn't work:

    $ perl -e 'system "head", "/etc/services /etc/protocols"'
    head: /etc/services /etc/protocols: No such file or directory

    Since there's more than one argument to system(), the shell is bypassed, and
    execve(2) sees a single file name "/etc/services /etc/protocols" instead of
    two separate file names. Hence, the error message.
  • Gavin Henry at Aug 31, 2004 at 1:47 pm

    Bob Showalter said:
    Gavin Henry wrote:
    On Tuesday 31 Aug 2004 01:51, you wrote:
    2. The way you're calling system() looks odd. You're using more
    than one arg, which is a signal to bypass the shell. But your
    second arg looks like it needs shell processing. Does this actually
    work?
    Yup, out of the cookbook.
    Odd. Which cookbook?
    2 and 3:

    Recipe 16.2 in version ":

    To avoid the shell, call system with a list of arguments:

    $status = system($program, $arg1, $arg);
    die "$program exited funny: $?" unless $status == 0;

    The returned status value is not just the exit value: it includes the
    signal number (if any) that the process died from. This is the same value
    that wait sets $? to. See Recipe 16.19 to learn how to decode this value.
    Here's a simple illustration of what I'm talking about.

    Consider a simple command like

    head /etc/services /etc/protocols

    This works, as it passes the command line to the shell for processing

    $ perl -e 'system "head /etc/services /etc/protocols"'

    This also works, as I'm splitting the arguments myself:

    $ perl -e 'system "head", "/etc/services", "/etc/protocols"'

    But this (which is similar to what you're doing) doesn't work:

    $ perl -e 'system "head", "/etc/services /etc/protocols"'
    head: /etc/services /etc/protocols: No such file or directory

    Since there's more than one argument to system(), the shell is bypassed,
    and
    execve(2) sees a single file name "/etc/services /etc/protocols" instead
    of
    two separate file names. Hence, the error message.
    I get you now. rdiff-backup thinks -v5 --print-statistics in one arg, not
    two.
    --
    To unsubscribe, e-mail: [email protected]
    For additional commands, e-mail: [email protected]
    <http://learn.perl.org/> <http://learn.perl.org/first-response>

  • Gavin Henry at Aug 31, 2004 at 1:55 pm

    Since there's more than one argument to system(), the shell is bypassed,
    and
    execve(2) sees a single file name "/etc/services /etc/protocols" instead
    of
    two separate file names. Hence, the error message.
    I have split the options up tp $option1 and $option2:

    http://www.perl.me.uk/downloads/rdiff-script

    Is this messy?

    Gavin.


    --
    Just getting into the best language ever...
    Fancy a [email protected]? Just ask!!!
  • Chris Devers at Aug 31, 2004 at 2:44 pm
  • Gavin Henry at Aug 31, 2004 at 2:47 pm
    Thanks for your time Chris.

    I will do the same when I get a bit better for others.

    Let me digest this and get back to you.

    Gavin.

    Chris Devers said:
    On Tue, 31 Aug 2004, Gavin Henry wrote:

    I have split the options up tp $option1 and $option2:

    http://www.perl.me.uk/downloads/rdiff-script

    Is this messy?
    It's not bad, but it still has a lot of repeated code, which should be a
    warning flag: if you have a lot of code repetition, it should probably
    be moved out into a subroutine.

    Hence, instead of this (with adjusted whitespace):

    if ($backup == 0) {
    my %mails = (
    To => "$to",
    From => "$from",
    Subject => "Remote backup complete from $ENV{HOSTNAME} on
    $time",
    Message => "The remote backup has been completed on
    $ENV{HOSTNAME}"
    . " on $time with the command:\n\n $rdiff
    @args\n"
    );
    sendmail(%mails);
    # Success finish message
    print "\n", $sep, "Remote backup complete on $time. E-mail sent
    with details.\n", $sep;


    # Create a success logfile
    open LOG, ">>$datestamp-rdiff-backup-success.log"
    or die "Cannot create logfile: $!";
    print LOG "Remote backup completed on $time, with the
    command:\n\n$rdiff @args\n\nAn e-mail has been sent.\n";
    close LOG;
    print "Logfile created on $time.\n\n";

    } else { # Failure
    my %mailf = (
    To => "$to",
    From => "$from",
    Subject => "Remote backup failed from $ENV{HOSTNAME} on
    $time",
    Message => "The remote backup has failed on $ENV{HOSTNAME}"
    . " on $time with the command:\n\n$rdiff @args\n"
    );
    sendmail(%mailf);
    # Failure finish message
    print "\n", $sep, "Remote backup failed on $time. E-mail sent
    with details.\n", $sep;

    # Create a failure logfile
    open LOG, ">>$datestamp-rdiff-backup-failed.log"
    or die "Cannot create logfile: $!";
    print LOG "Remote backup failed on $time, with the
    command:\n\n$rdiff @args\n\nAn e-mail has been sent.\n";
    close LOG;
    print "Logfile created on $time.\n\n";
    die "Backup exited funny: $?" unless $backup == 0;
    }

    Try this:

    my $to = $to;
    my $from = $from;
    my ( $subject, $message, $log, $logmessage, %stat );
    if ( $backup == 0 ) {
    # The backup worked
    $subject = "Remote backup complete from $ENV{HOSTNAME} on
    $time";
    $message = "The remote backup has been completed on
    $ENV{HOSTNAME}"
    . " on $time with the command:\n\n $rdiff @args\n"
    $log = "$datestamp-rdiff-backup-success.log";
    $logmessage = "Remote backup completed on $time, with the
    command:\n\n"
    . "$rdiff @args\n\nAn e-mail has been sent.\n";
    $stat{now} = "complete";
    $stat{then} = "completed";
    } else {
    # The backup failed
    $subject = "Remote backup failed from $ENV{HOSTNAME} on
    $time";
    $message = ""The remote backup has failed on $ENV{HOSTNAME}"
    . " on $time with the command:\n\n$rdiff @args\n";
    $log = "$datestamp-rdiff-backup-failed.log";
    $logmessage = "Remote backup failed on $time, with the
    command:\n\n"
    . "$rdiff @args\n\nAn e-mail has been sent.\n";
    $stat{now} = "fail";
    $stat{then} = "failed";
    }

    # Report status to console, send a status report, write to log
    print "\n", $sep, $message, $sep;
    sendmail(
    To => "$to",
    From => "$from",
    Subject => "$subject",
    Message => "$message"
    );

    open LOG, ">>$log" or die "Cannot open logfile $log for writing:
    $!";
    print LOG $logmessage;
    close LOG;
    print "Logfile $log created on $time.\n\n";
    die "Backup exited funny: $?" unless $backup == 0;


    By keeping the if { ... } else { ... } construct as short as I could get
    it, the code should become easier to read. Because the section that
    actually does work at the end isn't duplicated, I've reduced the chances
    of introducing typos.

    You could even (debatably) make things a bit more terse & clear by using
    the %stat variable I introduced, with, e.g.

    # Report status to console, send a status report, write to log
    print "\n", $sep, $message, $sep;
    sendmail(
    To => "$to",
    From => "$from",
    Subject => "$subject",
    Message => "The remote backup has $stat{now} on $ENV{HOSTNAME}"
    . " on $time with the command:\n\n $rdiff @args\n"
    );

    open LOG, ">>$log" or die "Cannot open logfile $log for writing:
    $!";
    print LOG "Remote backup $stat{then} on $time, with the command:\n\n"
    . "$rdiff @args\n\nAn e-mail has been sent.\n";
    close LOG;
    print "Logfile $log created on $time.\n\n";
    die "Backup exited funny: $?" unless $backup == 0;

    The main benefit of this is that you can then eliminate the $message and
    $logmessage variables, so the "if { ... } else { ... }" block gets even
    shorter, and you move even closer to having the common code -- or common
    text in this case -- not being duplicated unnecessarily.



    --
    Chris Devers [email protected]
    http://devers.homeip.net:8080/blog/

    np: 'Mah-na Mah-na'
    by Barrio Sésamo
    from 'Sesame Street'
  • Gavin Henry at Aug 31, 2004 at 2:55 pm
    stat is a new one for me, am only on Chapter 7 in Learning Perl.

    I will have to come back to this script when I get a bit further.

    All good though :-)




    --
    Just getting into the best language ever...
    Fancy a [email protected]? Just ask!!!
  • Bob Showalter at Aug 31, 2004 at 5:21 pm

    Gavin Henry wrote:
    P.S. I am now a programmer or a scripter, I am not sure is perl is
    programming or scripting? I think programming.
    You are a programmer. No such thing as a "scripter".

    You're using a scripting language, which simply means you don't have to use
    a compiler and linker to produce an executable; you just feed your script to
    perl and it runs.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedAug 30, '04 at 11:27p
activeAug 31, '04 at 5:21p
posts25
users8
websiteperl.org

People

Translate

site design / logo © 2023 Grokbase