Hello Perl People....

     I was wondering if someone could enlighten me on an observation I
have been seeing..

A little Background info:
     Where I work we have been seeing very slow ssh connections times
(it's not DNS.  Maybe NIS, NFS, but definitely not DNS).

      Anyways I wanted to write a script that would log the time it
takes to connect to a remote server via ssh and issue a command (uname
-n).  The tricky part was that I wanted the remote connections to kick
off every 60 secs.  (some ssh connections take a lot longer.  120+ in
some cases).  The log should enable me to pinpoint any time
correlation to the long ssh connect occurrences (every 5 minutes?  1/2
past every hour? etc).

     So here we are back to the script..  The script works as
expected, with one item of strangeness.  I was expecting the log
messages to be printed in the order they complete. For example, if the
connection attempt at 12:01 took 75 seconds to return, and the
connection attempt at 12:02 to 5 seconds to return, I would expect the
12:02 message to appear first then the 12:01, but it doesn't.  The
12:02 connection won't print until the 12:01 returns.

Here is my code:

use strict;
use Getopt::Std;
use Sys::Hostname;
use File::Basename;
use Net::SSH qw( sshopen2 );
use Time::HiRes qw( gettimeofday tv_interval );
$|++;

$SIG{CHLD} = 'IGNORE';

my %opts;
getopts('dr:', \%opts);

my $localhost = hostname();
my $r_host    = $opts{'r'} ? $opts{'r'} : die "need remote host <-r>
\n";
my $debug     = $opts{'d'};
my $short_name = basename("$0", ".pl");

# --- set the counter to zero.  We'll print the counter to the log for
easier sorting
# --- of data where the ssh connections take longer than a minute to
return.
my $ct = 0;

while (1) {

    my $pid = fork();

    if ($pid) {
        # parent
    } elsif ($pid == 0) {
        # child
        my $p = _initialize($ct);
        waitpid($p, 0);
        exit 0;
    } else {
        die "couldnt fork: $!\n";
    }

    $ct++;
    sleep 60;
}

# ---
# --- sub:     initialize
# --- descr:   for easier viewing of the code for the fork process.
# --- returns: nothing
# ---
sub _initialize{
    my($count) = @_;

    my $now    = scalar localtime();

    my $start   = [gettimeofday()];

    my $ret = connect_to_remote_host("$r_host");

    my $elapsed = tv_interval( $start );

    if ($count < 10){
        $count = "0$count";
    }

    if ($count < 99){
        $count = "0$count";
    }

    my $msg =  "$count - [$now] $localhost to $r_host Elapsed time:
$elapsed ";
    write_to_log($msg);

    return;

}

# ---
# --- sub:     connect_to_remote_host
# --- descr:   uses ssh to connect to a remote host via ssh keys only.
# --- returns: nothing.
# ---
sub connect_to_remote_host {
    my($host) = @_;

    my $user = 'root';
    my $cmd  = "uname -n";
    my $out  = "";

    sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || die "ssh:
$!";

    while (<READER>) {
        chomp();
        #print "$_\n";
        $out = $_;
    }

    close(READER);
    close(WRITER);

    return $out;
}

# ---
# --- sub:     write_to_log
# --- descr:   write messages to log file or print to stdout when in
debug
# --- returns: nothing
sub write_to_log{
    my ($message) = @_;

    my $log = "/tmp/$short_name.log";

    if ($debug){
        print "$message\n";
    }

    open L, ">>$log" or die "Cannot open $log:$!\n";
    print L "$message\n";
    close L;
}


Just wondering why the messages being printed to the console waits for
the previous pid (or pids) to complete before it's viewable.

FYI - I implemented the Counter thinking the messages weren't always
going to be in order and that I could always to a quick sort on the
counter to get the correct timeline.....

Thanks,
Chad



-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to