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

I have a "check for bad" ping script here that works but it cuts off the last bad IP address when it emails me. The file (called myfil in the script) that I am writing the bad ping addresses shows all the IP addresses.

For example the 4 IP addresses below do not ping and my output file shows:
888.333.333.33 156.343.333.99 888.323.222.223 888.222.222.111
BUT my email message excludes the last bad IP address (in this case 888.222.222.111) such as:
888.333.333.33 did not respond. 156.343.333.99 did not respond. 888.323.222.223 did not respond.
Here is my script. I know it is something with my send mail part that is cutting out my output. Anyone have any suggestions???
@a = (<DATA>); #$s = system("$?"); $myfil = "myfil"; foreach (@a) { system("/usr/sbin/ping $_"); if ( $? != 0) { open(FIL,">>$myfil") || "Can't open $myfil: $! \n"; print FIL "$_ did not respond.\n"; } else { print "good\n"; } } system("cat $myfil | mailx -s 'Did not ping mail' myemail\@here\.com") +; system("rm myfil"); close(FIL); close(DATA); __DATA__ 888.333.333.33 156.343.333.99 888.323.222.223 888.222.222.111

Replies are listed 'Best First'.
Re: Mail script is cutting out data.
by Abigail-II (Bishop) on Jul 08, 2002 at 16:48 UTC
    You never close FIL. Hence, the last line is still in a buffer cache somewhere when you cat it to mail it. Close the file before you use it from another program.

    Abigail

Re: Mail script is cutting out data.
by rattusillegitimus (Friar) on Jul 08, 2002 at 16:47 UTC

    Not sure if this will help anything, but you might want to move the line:

    open(FIL,">>$myfil") || "Can't open $myfil: $! \n";

    up outside the foreach loop. I noticed you're opening the file multiple times but only closing it once. Similarly, I'd close the FIL filehandle before using the system command to pile the file to mailx.

    Have you commented out the line that removed the file and checked to make sure all the appropriate lines appear there? That way you could determine if your loop is at fault or the call to mailx.


    He seemed like such a nice guy to his neighbors / Kept to himself and never bothered them with favors
    - Jefferson Airplane, "Assassin"

Re: Mail script is cutting out data.
by fruiture (Curate) on Jul 08, 2002 at 16:49 UTC
    well, you're using so few Perl things in that script that it's not really a Perl-related problem.

    But you're lucky: It _is_ a Perl problem :-) You didn't close the file, so the output "might have not been flushed" and that's the case: the last print() has not been flushed, so your file doesn't contain the contents yet.

    2 ways to solve the problem: 1. say "$|=1" at the beginning of your script and read perlvar to understand it 2. (=recommended) close your file before the system("cat ...").

      $|=1 only sets autoflush on the currently selected filehandle, which is STDOUT, and won't solve the issue for the FIL handle.

      Instead, he wants to
      open(FIL,">>$myfil") || "Can't open $myfil: $! \n"; select((select(FIL), $|=1)[0]);
      or alternatively, and much easier on the eyes,
      use IO::Handle; open(FIL,">>$myfil") || "Can't open $myfil: $! \n"; FIL->autoflush();
      ____________
      Makeshifts last the longest.
      Thank you for quick responses. I looked at this for hours and you all solved it fast. Thanks for another lesson in Perl that I needed.
Re: Mail script is cutting out data.
by Aristotle (Chancellor) on Jul 08, 2002 at 17:01 UTC
Re: Mail script is cutting out data.
by DamnDirtyApe (Curate) on Jul 08, 2002 at 17:44 UTC

    The two operations you perform in your script, pinging a remote host and sending an email, can and probably should be done from within Perl, using the Net::Ping and MIME::Lite modules. This gives you several advantages:

    • The buffering issues you are presently encountering will cease to be a problem;
    • No need to create temporary files;
    • Flexibility -- a pure-Perl implementation will be much easier to adapt to different situations than a Perl/Unix hybrid;
    • Portability -- If you want to run your Ping reporter from Windows, you need something that doesn't rely on Unix system calls.

    With that said, consider using something like the following code:

    #! /usr/bin/perl use strict ; use warnings ; use MIME::Lite ; use Net::Ping::External qw/ ping / ; # Ping all the IP addresses. my $output = '' ; while ( <DATA> ) { chomp ; next unless $_ ; $output .= "$_: " . ( ping( host => $_ ) ? 'OK' : 'FAILED' ) . "\n +" ; } # Compose & send the email. my $msg = MIME::Lite->new( From => 'somemail@example.com', To => 'yourmail@example.com', Subject => 'Ping Report', Data => $output ) ; $msg->send ; __DATA__ 888.333.333.33 156.343.333.99 888.323.222.223 888.222.222.111

    _______________
    D a m n D i r t y A p e
    Home Node | Email