Skip to content

Instantly share code, notes, and snippets.

@gregmark
Created February 26, 2018 19:29
Show Gist options
  • Save gregmark/ecd7421271ab3afe7ad2207c50ffaf03 to your computer and use it in GitHub Desktop.
Save gregmark/ecd7421271ab3afe7ad2207c50ffaf03 to your computer and use it in GitHub Desktop.
perl subs for node discovery
#!/usr/bin/perl
#############################################################################
### poll_subs.pl: Net:SSH or Func guts
#############################################################################
use Data::Dumper;
our $SHELL_TRUE = 0;
our $DEBUG = 0;
sub test_ping {
my ($host, $count, $deadline) = @_[0,1,2];
$count = 2 unless $count; # stop after $count packets sent
$deadline = 4 unless $deadline; # max test time, regardless of $count
my $ping_x = "ping -c $count -w $deadline $host >/dev/null 2>&1";
if ( system($ping_x) == $SHELL_TRUE ) {
return 1;
} else {
return 0;
}
}
sub test_ssh {
my ($host, $wait) = @_[0,1];
$wait = 2 unless $wait;
my $SSH_BANNER = `nc -w $wait $host 22 2>&1`;
chomp $SSH_BANNER;
$SSH_BANNER = "connection failed" unless $SSH_BANNER;
if ($SSH_BANNER =~ /SSH/) {
return 1;
} else {
warn "[WARN] test_ssh -> $host: $SSH_BANNER\n";
return 0;
}
}
sub is_ipaddr {
my $str = shift;
my $ip_regex = qr/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[-,]?\b/;
$str =~ $ip_regex ? return 1 : return 0;
}
sub run_cmd {
my ( $x_host, $x_cmd, ) = @_[0,1];
use Net::SSH::Perl;
###### Commenting this out for now, main script should test for ssh banner
### Net::SSH::Perl will not die if connection succeeds but then hangs
### Return NULL
#unless ( test_ssh($x_host) ) {
# return;
#}
### Need way to move on if the login fails
my $test = 0;
$test = 1 if $x_cmd eq "test-net-ssh-perl";
### SSH options & Net::SSH paramaters
# RSA keys default to $HOME/.ssh/identity, so we must use the
# 'identity_files' param to involve OpenSSH default $HOME/.ssh/id_rsa
#
my $id_options = [
"$ENV{HOME}/.ssh/id_rsa",
"$ENV{HOME}/.ssh/id_dsa",
"$ENV{HOME}/.ssh/identity",
];
my $ssh_options = [
"StrictHostKeyChecking no",
"BatchMode yes",
"PasswordAuthentication no",
];
my %ssh_params = (
protocol => 2,
debug => 0,
identity_files => $id_options,
options => $ssh_options,
);
### SSH login
# eval necessary to trap Net::SSH's die calls which we don't want
my $ssh;
eval {
$ssh = Net::SSH::Perl->new($x_host, %ssh_params);
$ssh->login;
};
if ($@) {
if ($test) {
warn "[WARN] run_cmd -> $x_host: login failed\n";
return 0;
}
my $err = $@;
$err =~ s/Net::SSH: //; # Massage Net::SSH die msg
$err =~ s/ at \S+ line \d+$//; # More
warn "[WARN] run_cmd -> Net::SSH: $x_host: $err"; # Just warn and move on
return; # Return value NULL
} elsif ($DEBUG) {
return 1 if $test;
print "[run_cmd] HOST -> $x_host, CMD -> $x_cmd, SH_EXIT -> ";
}
### Run command, capture return data
my ($stdout, $stderr, $sh_exit) = $ssh->cmd($x_cmd);
print "$sh_exit\n" if $DEBUG;
### Create return data structure (modeled after Func)
#* arr-of-arr data struct as single return value
#* [0]: shell return, [1]: STDOUT arr/scalar, [2]: STDERR arr/scalar
#* if return is 0, STDERR is undef
#* if return is 1, STDOUT is undef
my $rdata = [];
push @$rdata, $sh_exit;
foreach my $string ($stdout, $stderr) {
if ($string) {
push @$rdata, [ split("\n", $string) ]; # push array ref
} else {
push @$rdata, $string; # push scalar (should just be undef)
}
}
return $rdata;
}
### SUB: get_return
sub get_return {
local $out = shift;
warn "Improper usage of get_return() function"
if ref($out) ne "ARRAY";
if ( ${$out}[0] == $SHELL_TRUE ) {
return 1;
} else {
return 0;
}
}
### SUB: get_data
sub get_data {
local $out = shift;
local $type = shift;
warn "Improper usage of get_data() function"
if ref($out) ne "ARRAY";
if ( ! defined($type)|| $type eq "out" ) {
return @{${$out}[1]};
} elsif ( $type eq "err" ) {
return @{${$out}[2]};
} else {
warn "Improper usage of get_data() function";
}
}
### SUB: get_simple
### ---------------
# ARGS: hostname, shell command, mode (opt)
# () if mode is empty, will only return the first line of output
# () if mode == "all", the entire output is returned as a list
sub get_simple {
my $host = shift;
my $cmd = shift;
my $mode = shift; $mode = "none" unless defined($mode);
#print "[get_simple] HOST -> $host, CMD -> $cmd, MODE -> $mode\n" if $DEBUG;
# Run
my $out = run_cmd($host, $cmd);
# Return NULL if Net::SSH::Perl fails silently
return -1 unless $out;
if (get_return($out)) {
my @data = get_data($out);
if ($mode eq "all") {
return @data;
} else {
return $data[0];
}
} else {
# will want to reconsider this output if/when this gets put in db
my @err = get_data($out, "err");
#print "[ERROR] get_simple -> host: $host cmd: $cmd\n";
return 0;
}
}
return 1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment