http://www.perlmonks.org?node_id=796816


in reply to IO::Select & ssh problem

Folks-

After lots of twiddling, and some CB help (thanks ssandv++ clinton++), here is the version that seems to work best. Still have some strange things going on (like stdout seems to be in raw mode, and sometimes I control-c doesn't work), but overall it seems to be doing what I expect.

Use this when you need to run tail -f on a file that exists on a bunch of hosts, and want the output interleaved correctly.

Please make comments and/or give me alternative ways of doing this (under perl5.6 with no other modules but IO::Select).

Thanks

-Craig

use strict; use warnings; use IO::Select; $|++; my $pkey = "$ENV{HOME}/.ssh/PrivateKey"; my @logins = ( qw ( usr@host1 usr@host2 usr@host3) ); my $cmd = "'tail -f /tmp/growingfile'"; my @shell = ( '/usr/bin/ksh' => ( -c => "$cmd" )); my @FDs; # Create ssh tails as FDs on child processes... foreach my $login (@logins) { print STDERR "login=$login\n"; my @sshcmd = ('/usr/bin/ssh' => ( -t => (), #-v => (), -i => $pkey, -o => 'StrictHostKeyChecking no', $login, @shell, )); my $fd; if(my $child = open ($fd, '-|')) { print STDERR "I'm the parent\n"; print STDERR "PARENT: \$!: $!...\n"; print STDERR "Child pid=$child\n"; }else{ $|++; print STDERR "I am the child\n"; exec @sshcmd; } push(@FDs, \*$fd); } my $sel = new IO::Select(@FDs); while(my @ready = $sel->can_read) { foreach my $fh (@ready) { if(eof($fh)) { $sel->remove($fh); close($fh); next; } my $line = <$fh>; print "$fh: $line"; } }