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

Greetings Brothers, I am seeking a method to call an external .ksh script, using the contents of a file as an argument. The .ksh script is set up to send email to a mailing list. Here is what I have...
my ($LOGFILE) = "/home/admin/logs/check_jvm/check_jvm_$LOGTIME.log"; my @args = ("/home/admin/bin/email.ksh", "$LOGFILE", "Web Server Issue +", "PROD", "/home/admin/logs/check_jvm/EmailAlert.log"); system(@args) == 0 or die "system @args failed: $?"
The second field "$LOGFILE" is the body of the email. The file is the contents of an error log file. Instead of getting the contents of the log file as the body of the email, I get "11:04:00 $LOGFILE". Thanks for your help.
  • Comment on Passing the contents of a file in a "system" call to a .ksh script
  • Download Code

Replies are listed 'Best First'.
Re: Passing the contents of a file in a "system" call to a .ksh script
by hbm (Hermit) on Jan 08, 2009 at 17:45 UTC
    Have you considered sending the email from your perl script? Something like this:
    my $log; ## Oops! Need this line, so $log is scoped beyond the {} my $LOGTIME = ... my @emails = qw(brother@elwood.com sister@elwood.com); my $LOGFILE = "/home/admin/logs/check_jvm/check_jvm_$LOGTIME.log"; open(LOG,"$LOGFILE") or die; { undef $/; $log = <LOG>; } close LOG; if (open(SENDMAIL, "|/usr/lib/sendmail -oi -t -odq")) { print SENDMAIL "From: PROD\@elwood.com\n" . "To: " . join(" ", @emails) . "\n" . "Subject: Web Server Issue\n" . "$log\n"; close(SENDMAIL); }
      hbm, I couldn't figure it out. Here is some background. If we can send the email within the script, great! I have a list of users and email addresses kept in a file. We use a single file to make it simple to add/remove people on the list. If I start putting a separate list in every script, I will have a lot to maintain. The file uses the ":" character as a field separator, with the email address in field #5. The .ksh script is set up to use this properly with:
      for foo in `awk -F: '/ADMIN/ {print $5 }' $ADMINLIST`
      If I can set up Perl to read the config file in a similar fashion, awesome. Calling the external script seemed easier at the time.
        Elwood-- Here's one way:
        my @emails; my $ADMINLIST = '/path/to/admin.lst'; open(IN,"$ADMINLIST") or die("Can't open $ADMINLIST: $!"); while (<IN>){ if (my $addr = (split(/:/,$_))[4]) { push(@emails,$addr); } } close IN;

        That grabs the 5th element (numbered from zero) of each line; then you can print the list to the SENDMAIL pipe as I did earlier.

Re: Passing the contents of a file in a "system" call to a .ksh script
by kennethk (Abbot) on Jan 08, 2009 at 17:21 UTC

    Your post title and contents make me think perhaps you expect perl to pass the log file contents in place of the log file name. In that case, you need to specifically read the file contents and pass that - perlopentut goes through basic Perl file handling and includes examples that will do what you need. A basic read might look like:

    use strict; use warnings; my $LOGFILE = 'file.log'; my @contents = (); open my $fh, "<$LOGFILE" or die "Failed to open $LOGFILE"; while (my $line = <$fh>) { push @contents, $line; } close $fh; print @contents;

    If instead you expect to pass the file name, this would seem to be more of an issue with the shell script that with your Perl code. As you have written it, the system call should issue the following OS command:

    /home/admin/bin/email.ksh /home/admin/logs/check_jvm/check_jvm_$LOGTIME.log Web Server Issue PROD /home/admin/logs/check_jvm/EmailAlert.log

    where $LOGTIME should get interpolated assuming you assign it prior to your $LOGFILE assignment. Have you tried subbing your system call with print join ' ', @args to make sure you are passing what you think?

    Update: Forgot to test my open. Fixed.

      I may have missed something, it doesn't work. And yes, I am trying to send the contents of the log file to the script.
      open my $FH, "<$LOGFILE" or die "Failed to open $LOGFILE"; while ($LINE = <$FH>) { push @contents, $LINE; } close $FH; print LOG "$FORMATTEDTIME @contents \n"; my @args = ("/home/admin/bin/email.ksh", "@contents", "Web Server +Issue", "PROD", "/home/admin/logs/check_jvm/EmailAlert.log"); system(@args) == 0 or die "system @args failed: $?"

        The following is a cut/paste of your code with the addition of use strict;use warnings;, the addition of variable declaration, removing your LOG line and substituting "echo" for "/home/admin/bin/email.ksh".

        use strict; use warnings; my $LOGFILE = 'junk.txt'; open my $FH, "<$LOGFILE" or die "Failed to open $LOGFILE"; my @contents = (); while (my $LINE = <$FH>) { push @contents, $LINE; } close $FH; my @args = ("echo", "@contents", "Web Server Issue", "PROD", "/home/ad +min/logs/check_jvm/EmailAlert.log"); system(@args) == 0 or die "system @args failed: $?"

        It echos The contents of the file. Web Server Issue PROD /home/admin/logs/check_jvm/EmailAlert.log as expected. Are you sure you are invoking your shell script properly? Can you invoke it successfully from the command line? If it comes down to debugging a shell script or perl, I'd be inclined to suggest putting time in on hbm's suggestion.

Re: Passing the contents of a file in a "system" call to a .ksh script
by Bloodnok (Vicar) on Jan 08, 2009 at 20:26 UTC
    As previous posters have pointed out, you are passing the name, not the content, of the log file to the command - a more concise means (than shown elsewhere in this thread) of achieving the same end would be along the lines of...
    my ($LOGFILE, @content) = ("/home/admin/logs/check_jvm/check_jvm_$LOGT +IME.log"); open LOG, "<$LOGFILE" or die "open($LOGFILE) failed - $!"; chomp(@content = <LOG>); close LOG; my @args = ("/home/admin/bin/email.ksh", @content, "Web Server Issue", + "PROD", "/home/admin/logs/check_jvm/EmailAlert.log"); system(@args) == 0 or die "system @args failed: $?"
    Update: Added call to chomp ... for, hopefully obvious reasons ;-)

    Thanx to fullermd - changed @LOG to @content & removed quotes (it's already in list context) in assignment of/to <c>@args>/c>

    A user level that continues to overstate my experience :-))
      my @args = ("/home/admin/bin/email.ksh", "@LOG", "Web Server Issue", " +PROD", "/home/admin/logs/check_jvm/EmailAlert.log");

      ITYM

      my @args = ("/home/admin/bin/email.ksh", @content, "Web Server Issue", + "PROD", "/home/admin/logs/check_jvm/EmailAlert.log");

      (and the @content up at the top by $LOGFILE doesn't do anything either...)

        In that context yes, TFT fullermd - I forgot the whole thing's in list context so @content doesn't need stringifying. As for the the occurrence (of @content) at the top, it does do something, it satisfies the strictures (I assumed they were present but not shown).

        A user level that continues to overstate my experience :-))