Created
February 26, 2018 19:29
-
-
Save gregmark/ecd7421271ab3afe7ad2207c50ffaf03 to your computer and use it in GitHub Desktop.
perl subs for node discovery
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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