#!/usr/bin/perl -wT use lib "/daten/http/toolbox_dev/cgi-bin/bambi/pw/server"; # add source folder to path. use warnings; use strict; use config; # load configuration. use Expect; # load expect routines. use process; # load multi process routines. use tools; # use Data::Dumper; # ###################################### # The Remote Class is used to execute commands on hosts. ###################################### package Remote; my $user = "XXX"; my $pass = "XXX"; my $prompt = '^\w+#'; # regular expression that matches the command prompt (currently rough). my $timeout = 10; # seconds before the connection is aborted. # start a ssh connection and handle login dialog. # :param 0: host to connect to. # :return: established ssh connection. sub open_ssh { my ($host) = @_; my $ssh_cmd = "ssh ".$user."@".$host; Debug::dlog("connecting to $host"); my $exp = Expect->spawn($ssh_cmd) or return; Debug::dlog("$exp spawned ssh"); $exp->restart_timeout_upon_receive(1); $exp->log_stdout(0); $exp->expect($timeout, ["yes/no", \&send_yes, $exp], ["assword", \&send_pass, $exp], [$prompt]); return $exp; } # send the user name to a host. # :param 0: established ssh connection. # :return: sub send_user { my ($exp) = @_; $exp->send("$user\n"); Debug::dlog("$exp send user"); $exp->exp_continue; } # send the password to the host. # :param 0: established ssh connection. # :return: sub send_pass { my ($exp) = @_; $exp->send("$pass\n"); Debug::dlog("$exp send password"); $exp->exp_continue; } # send yes to the host. # :param 0: established ssh connection. # :return: sub send_yes { my ($exp) = @_; $exp->send("yes\n"); Debug::dlog("$exp send yes"); $exp->exp_continue; } # execute a command on the host and retrieve its response.. # :param 0: established ssh connection. # :param 1: command to execute. # :return: response of the host. sub exec_cmd { my ($exp, $cmd) = @_; $exp->send("$cmd\n"); await_prompt($exp); my $response = $exp->before(); Debug::dlog("$exp executed $cmd, retrieved ".length($response)." chars"); return $response; } # wait for acknowlegment of the host (currently rough) # :param 0: established ssh connection. # :return: sub await_prompt { my ($exp) = @_; $exp->expect($timeout, [$prompt]); } # disconnect from the host. # :param 0: established ssh connection. # :return: sub quit { my ($exp) = @_; $exp->send("exit\n"); $exp->soft_close(); Debug::dlog("$exp disconnected"); } # executes multiple commands on a host and retrieve the responses. # :param 0: array of commands to execute. # :param 1: host to connect to. # :return: dictionary with the commands as keys and the responses as values. sub exec_on { my ($cmds, $host) = @_; my $ssh = open_ssh($host); if($ssh) { my %cmd_resp = (); foreach my $cmd (@$cmds) { $cmd_resp{$cmd} = exec_cmd($ssh, $cmd); } quit($ssh); return \%cmd_resp; } else { Debug::dlog("failed to connect to $host"); return "Couldn't start SSH"; } } # executes multiple commands on multiple hosts and retrieve the responses. # :param 0: array of commands to execute. # :param 1: array of hosts to connect to. # :return: dictionary with the host names as keys and the command dictionary as value. sub exec_on_each { my ($cmds, $hosts) = @_; my %host_resp = (); foreach my $host (@$hosts) { $host_resp{$host} = exec_on($cmds, $host); } return \%host_resp; }