in reply to Net::SSH::Perl - Breaking out of a running command?
Here is my final Net::SSH::Perl example of locally breaking out of a running command on a remote host every 5 seconds, shutting down the old command, then starting up a new one (in a new SSH2 channel).
It's based upon using $ssh->channel_mgr->{channels} and $chan->rcvd_ieof neither of which are documented, but seem like the right interfaces to be using (comments?).
I'm thinking of following-up with the module author (Steffen Schwigon) to add and document the following methods to officially support this:
my @channels = $ssh->listChannels();
$ssh->closeChannel($channels[0]);
What do you think?
Thanks to all those who've helped me out on this issue!
-Craig
Title Update - This pretends we got an incoming EOF on the channel. WARNING: if you add a register_handler for stderr (and there is no activity on stderr), it seems to hang. I am investigating...
Update 2: - I like this solution because it is more efficient and elegant. However, there are too many side-effects, and I haven't the time to solve them all (need to get the author to advise). Here are some of the notes that helped me solve some of the side-effects that I discovered:
Re^4: Net::SSH::Perl hangs(during cmd), but only in Mason environment
Re^3: Net::SSH::Perl ConnectTimeout (ssh -o option)
use strict; use warnings; use Net::SSH::Perl; my $HOST='MYHOST'; my $ID='MYLOGIN'; my $PW='MYPW'; my $DEBUG=0; # 1 - provides ssh debug output my $perlcmd = join('', <DATA>); my $cmd = "/bin/perl - -heartbeat "; # Login to host... my $myssh = Net::SSH::Perl->new( $HOST, protocol=>2, debug=>$DEBUG ); $myssh->login($ID, $PW) or die "Failed to login: $!\n"; listchannels($myssh); # Alarm Handler... $SIG{ALRM} = sub { print STDERR "\nALARM\n"; listchannels($myssh); # Close latest channel (pretend we received an EOF)... my $chanp = getchannels($myssh); $chanp->[-1]->rcvd_ieof; }; # Startup a new command channel on HOST every 5 seconds... while(1) { print STDERR "============================\n"; alarm 5; remcount($myssh); # Add new channel print STDERR "NEXT...\n"; } sub listchannels { my $ssh = shift || die "Missing ssh object"; my $x=0; foreach my $c (@{getchannels($ssh)}) { if($c) { print STDERR "CHAN $x($c->{id}) :$c\n" } else { print STDERR "CHAN $x(X) --CLOSED--\n" }; $x++; } } sub getchannels { my $ssh = shift || die "Missing ssh object"; return($myssh->channel_mgr->{channels}); } sub remcount { my $ssh = shift || die "Missing ssh object"; # STDOUT handler (protocol 2 only)... $ssh->register_handler('stdout', sub { my ($channel, $buffer) = @_; print STDERR "CHAN $channel->{id}: ", $buffer->bytes, "\n"; }); print STDERR "REMOTE: $cmd\n"; my ($stdout, $stderr, $exit) = $ssh->cmd($cmd, $perlcmd); print STDERR "DONE WITH COMMAND!!!\n"; } __DATA__ use strict; use warnings; $|++; my $c='a'; while(1) { print $c++; sleep 1; }
|
|---|