Skip to content

Instantly share code, notes, and snippets.

@walf443
Created March 1, 2012 07:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save walf443/1948000 to your computer and use it in GitHub Desktop.
Save walf443/1948000 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use strict;
use warnings;
use opts;
use Net::SSH;
use Parallel::ForkManager;
use IO::Socket;
use IO::File;
use IO::Select;
main(@ARGV); exit;
sub main {
opts my $host => { isa => "ArrayRef", comment => "host to execute target" },
my $verbose => { isa => "Bool", comment => "show hostname to output or not" },
my $command => { isa => "Str", comment => "execute command" };
my @pids;
my $select = IO::Select->new;
for my $h ( @$host ) {
my ($sock_p, $sock_c) = IO::Socket->socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
my $pid = fork();
die "fork failed: $!" unless defined $pid;
if ( $pid ) {
# parent
$sock_p->close;
$select->add($sock_c);
push @pids, $pid;
} else {
# child
$sock_c->close;
my $out = IO::File->new;
my $error = IO::File->new;
my $pid = Net::SSH::sshopen3($h, undef, $out, $error, $command)
or die "ssh failed!!: $!";
while ( my $line = <$out> ) {
$sock_p->write($h . ":\t" . $line);
}
waitpid $pid, 0;
exit;
}
}
my $num_childs = scalar @pids;
local $SIG{CHLD} = sub {
$num_childs--;
if ( $num_childs < 1 ) {
exit;
}
};
while ( 1 ) {
my @fds = $select->can_read(1);
for my $fd ( @fds ) {
my $line = <$fd>;
if ( $line ) {
my ($h, @l) = split /:/, $line;
my $l = join ":", @l;
if ( $verbose ) {
print "$h:$l";
} else {
print $l;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment