#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Net::OpenSSH::Parallel; #$Net::OpenSSH::Parallel::debug = -1; my %hosts = ( localhost => { host => "localhost", user => "user", port => "22", # default 22 psw => "psw", # use only if no ssh keys key => "/home/user/.ssh/id_rsa", # linux default dir dir => "/home/user/LOG", log => "output1.txt", error => "error1.txt", }, localhost_2 => { host => "127.0.0.1", user => "user", port => "22", psw => "psw", key => "/home/user/.ssh/id_rsa", dir => "/home/user/LOG", log => "output2.txt", error => "error2.txt", }, ); my @commands = ( 'echo %HOST%' , 'df -h' ); # Remove first command if unecessary # is the maximun number of remote commands that can be running concurrently. my $maximum_workers = @commands; # it is recomended that maximum_connections >= 2 * maximum_workers my $maximum_connections = 2 * $maximum_workers; my $maximum_reconnections = 0; my %opts = ( workers => $maximum_workers, connections => $maximum_connections, reconnections => $maximum_reconnections ); my $pssh = Net::OpenSSH::Parallel->new( %opts ); my $num = 0; my @stdout_fh = (); my @stderr_fh = (); foreach my $label (keys %hosts) { mkdir $hosts{$label}{dir} unless -d $hosts{$label}{dir}; # Open file and append open($stdout_fh[$num], '>', $hosts{$label}{dir}."/".$hosts{$label}{log}) or die "Could not open file '$hosts{$label}{dir}/$hosts{$label}{log}' $!"; # Open file and append write open($stderr_fh[$num], '>>', $hosts{$label}{dir}."/".$hosts{$label}{error}) or die "Could not open file '$hosts{$label}{dir}/$hosts{$label}{error}' $!"; $pssh->add_host( $hosts{$label}{host}, user => $hosts{$label}{user}, port => $hosts{$label}{port}, #password => $hosts{$label}{psw}, default_stdout_fh => $stdout_fh[$num], default_stderr_fh => $stderr_fh[$num], key_path => $hosts{$label}{key}, ); $num++; } # Assigning all commands to all hosts $pssh->push('*', command => $_ ) for @commands; $pssh->run; closeFH ( @stdout_fh , @stderr_fh ); print Dumper fileProcessing(); sub closeFH { foreach my $fh (@_) { close $fh or die "Error closing $!\n"; } } sub fileProcessing { my $ref_hash = {}; foreach my $label (keys %hosts ) { # Open file to read open(my $fh, '<', $hosts{$label}{dir}."/".$hosts{$label}{log}) or die "Could not open file '$hosts{$label}{dir}/$hosts{$label}{log}' $!"; chomp( my @data = <$fh> ); close $fh or die "Could not close file '".$hosts{$label}{dir}."/".$hosts{$label}{log}."' $!";; $$ref_hash{$label} = \@data; } return $ref_hash; } __END__ $VAR1 = { 'localhost' => [ 'localhost', 'Filesystem Size Used Avail Use% Mounted on', 'udev 7.8G 0 7.8G 0% /dev', 'tmpfs 1.6G 9.7M 1.6G 1% /run', '/dev/mapper/ubuntu--vg-root 218G 15G 193G 8% /', 'tmpfs 7.8G 86M 7.8G 2% /dev/shm', 'tmpfs 5.0M 4.0K 5.0M 1% /run/lock', 'tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup', '/dev/sda2 473M 125M 324M 28% /boot', '/dev/sda1 511M 3.6M 508M 1% /boot/efi', 'cgmfs 100K 0 100K 0% /run/cgmanager/fs', 'tmpfs 1.6G 68K 1.6G 1% /run/user/1000' ], 'localhost_2' => [ '127.0.0.1', 'Filesystem Size Used Avail Use% Mounted on', 'udev 7.8G 0 7.8G 0% /dev', 'tmpfs 1.6G 9.7M 1.6G 1% /run', '/dev/mapper/ubuntu--vg-root 218G 15G 193G 8% /', 'tmpfs 7.8G 86M 7.8G 2% /dev/shm', 'tmpfs 5.0M 4.0K 5.0M 1% /run/lock', 'tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup', '/dev/sda2 473M 125M 324M 28% /boot', '/dev/sda1 511M 3.6M 508M 1% /boot/efi', 'cgmfs 100K 0 100K 0% /run/cgmanager/fs', 'tmpfs 1.6G 68K 1.6G 1% /run/user/1000' ] };