Skip to content

Instantly share code, notes, and snippets.

@cosimo
Created September 22, 2014 14:45
Show Gist options
  • Save cosimo/6a8b37c18278ac2f6ef8 to your computer and use it in GitHub Desktop.
Save cosimo/6a8b37c18278ac2f6ef8 to your computer and use it in GitHub Desktop.
#!/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