Skip to content

Instantly share code, notes, and snippets.

@melo
Created May 29, 2012 16:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melo/2829330 to your computer and use it in GitHub Desktop.
Save melo/2829330 to your computer and use it in GitHub Desktop.
A sample Net::SSH2 command line talking to a inline remote perl script
#!/usr/bin/env perl
use v5.14;
use strict;
use Net::SSH2;
my $user = shift(@ARGV) || usage('Missing user');
my $host = shift(@ARGV) || usage('Missing host');
my $port = shift(@ARGV) || 22;
## Connect and authenticate using ssh-agent
my $ssh2 = Net::SSH2->new();
$ssh2->connect($host, $port) or die $!;
$ssh2->auth_agent($user);
die "Failed to autenticate: $!" unless $ssh2->auth_ok;
say "Connected to '$host' as '$user'";
## Enable compression, couldn't get it work with my libssh2 though...
for my $dir ('COMP_CS', 'COMP_SC') {
$ssh2->method($dir, 'zlib');
say "Compression $dir: ", $ssh2->method($dir);
}
## Start a channel with a remote perl, send our remote controller
## program
my $chan = $ssh2->channel();
$chan->exec('/usr/bin/perl');
my $perl_program = <<'EOR';
$|++;
print `uname -a`;
print "Start typing remote commands, type ^D to exit\n";
while (<>) {
print "GOT $_";
}
print "Bye now...\n";
__END__
EOR
$chan->write($perl_program);
$chan->flush;
## Read remote controller program header
_read_chan($chan);
## wait for local commands, and send them to the remote side, print
## remote output
{
local @ARGV;
while (<>) {
$chan->write($_);
_read_chan($chan);
}
}
## On local ^D, send EOF to remote side, read goodbye message
$chan->send_eof;
_read_chan($chan);
## close channel and disconnect
$chan->close;
$ssh2->disconnect;
## _read_chan: read all input from chan, dump it to STDOUT
## Hack time! Here be dragons
sub _read_chan {
my ($chan) = @_;
## we switch to non-blocking and sleep between retries because it
## would fail to read anything with a blocking call... Still trying
## to find out why the blocking call would not read nothing.
$chan->blocking(0);
my $done;
while (1) {
my $in;
while (my $bytes = $chan->read($in, 1024)) {
$in =~ s/^/> /gm;
print $in;
$done++;
}
## We leave after one sucessful read, this could be improved...
last if $done;
select(undef, undef, undef, .25); ## sleep 50 ms
}
$chan->blocking(1);
}
sub usage {
my ($msg) = @_;
say STDERR "FATAL: $msg" if $msg;
say STDERR "Usage: ssh.pl user host [port]";
exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment