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: [email protected]
For additional commands, e-mail: [email protected]
http://learn.perl.org/