Created
September 22, 2014 14:45
-
-
Save cosimo/6a8b37c18278ac2f6ef8 to your computer and use it in GitHub Desktop.
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 | |
=head1 NAME | |
rtail - tail multiple files remotely | |
=head1 SYNOPSIS | |
./rtail --host h1 --host h2 --command 'tail -f /var/log/syslog' | |
./rtail --user someuser --host h1 --host h2 --command 'uname -a' | |
./rtail -u someuser -h h1 -h h2 -c 'uname -a' | |
=head1 DESCRIPTION | |
Runs any command (by default tails the current access log) on multiple | |
hosts and reports back the output of all of them mixed together. | |
Apply the usual grep, awk, etc... to slice and dice at will. | |
Options can be shortened: --user works as well as -u, --host as -h and | |
--command as -c. | |
=cut | |
BEGIN { | |
$| = 1; | |
} | |
use 5.010; | |
use strict; | |
use warnings; | |
use IO::Select (); | |
use IPC::Open3 (); | |
use Symbol (); | |
use Getopt::Long (); | |
Getopt::Long::GetOptions( | |
'user:s' => \(my $user = $ENV{USER}), | |
'host:s' => \my @hosts, | |
'command:s' => \(my $command = 'ta -n 50'), | |
); | |
my @pid; | |
my @ready; | |
my @commands = map { "ssh -l '${user}' '$_' ${command}" } @hosts; | |
my $io = IO::Select->new(); | |
$io->add($_) for open_fh(@commands); | |
while (any_alive(@pid) and @ready = $io->can_read) { | |
for my $read_fh (@ready) { | |
my $c = ""; | |
my $line = readline $read_fh; | |
print $line if defined $line; | |
} | |
} | |
# If at least one of them is alive, stay alive | |
sub any_alive { | |
my @pid = @_; | |
my $alive = 0; | |
for (@pid) { | |
if (kill 0, $_) { $alive++ } | |
} | |
return $alive > 0; | |
} | |
sub open_fh { | |
my @commands = @_; | |
my @fh; | |
for my $cmd (@commands) { | |
my $rd_fh = Symbol::gensym(); | |
my $wr_fh = Symbol::gensym(); | |
my $err_fh = Symbol::gensym(); | |
my $pid = IPC::Open3::open3($wr_fh, $rd_fh, $rd_fh, $cmd) | |
or die "Can't run command '$cmd': $!"; | |
push @fh, $rd_fh; | |
warn "Opened filehandle $pid := $rd_fh ($cmd)\n"; | |
push @pid, $pid; | |
#waitpid($pid, 0); | |
} | |
return @fh; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment