Problems using Perl Net::SSH:Perl lib and Mikrotik

I’ve made this script:

use Net::SSH::Perl;
$ssh = Net::SSH::Perl->new("host", port => 22, protocol => 1, use_pty => 0);

$ssh->login('admin', 'pass') or die("Cannot connect to host");

($out, $err, $exit) = $ssh->cmd('/ppp active print count-only');

print $out;

But when running it I’ve got “/ppp?” as output, and $error is set to 127.

Same script just changeing the host to remote Linux machine, and the command to execute and everyting is OK.

Any Ideas??

P.S.: I saw that the script doesn’t connect to the router

If I change the scipt to the source bellow it makes an remote session:

use Net::SSH::Perl;
$ssh = Net::SSH::Perl->new("host", port => 22, protocol => 1, use_pty => 0);

$ssh->login('admin', 'pass') or die("Cannot connect to host");
use Term::ReadKey;
ReadMode('ultra-raw');
$ssh->shell;
ReadMode('restore');

I’d go with Expect.

I saw it but have some problems running it.. I also want to make some scripts that make some string parsing and things like that… I’m not sure where is the problem and I wanna now why it works with Linux, but not with Mikrotik :slight_smile:

  1. Seems MikroTik does not support executing commands via $ ssh user@host command interface.
  2. Expect allows you regexp string parsing. If it is not sufficient, call Expect from Perl scripts.

I’m not Expect adept, just don’t see other reliable way :slight_smile:

I have the same problem before a couple of months, but I’ve made it work. I can’t remember how I’ve made it :slight_smile:

There is a big difference between Net::SSH and Net::SSH::Perl.

Net::SSH uses the ssh command. Net::SSH::Perl is SSH client fully written in Perl.

When I make it, I’ll post here.

Seems that the same script works with RouterOS version 2.7.18

Any ideas? (It seems me like a RouterOS related bug)

I’ve lied you a little. The script that works with 2.7.18 has use_pty => 1. If I set it to zero I’ve got the same result as 2.8.18. But 2.8.18 doesn’t work even with use_pty => 1.

I’ve made a walkaround :slight_smile:

Just add this code in Net/Perl/SSH1.pm somewhere after line 339:

sub shell_cmd {                                                                                     
    my $ssh = shift;                                                                                
                                                                                                    
    my($prompt, $cmd) = @_;                                                                         
                                                                                                    
    require Net::SSH::Perl::Handle::SSH1;                                                           
                                                                                                    
    unless ($cmd) {                                                                                 
        $ssh->{config}->set('use_pty', 1)                                                           
            unless defined $ssh->{config}->get('use_pty');                                          
    }                                                                                               
    $ssh->_setup_connection;                                                                        
                                                                                                    
    $ssh->debug("Requesting shell.");                                                               
    my $packet = $ssh->packet_start(SSH_CMSG_EXEC_SHELL);                                           
    $packet->send;                                                                                  
                                                                                                    
    my ($packet,$pr);                                                                               
    do {                                                                                            
        $packet = Net::SSH::Perl::Packet->read($ssh);                                               
        $pr = $packet->get_str;                                                                     
    } while ( ($pr =~ /$prompt/ ) == 0 );                                                           
                                                                                                    
    $ssh->debug("Sending command.");                                                                
    my $packet = $ssh->packet_start(SSH_CMSG_STDIN_DATA);                                           
    $packet->put_str($cmd);                                                                         
    $packet->send;                                                                                  
                                                                                                    
    $ssh->debug("Command sended");                                                                  
                                                                                                    
    my $out = "";                                                                                   
                                                                                                    
    do {                                                                                            
        $packet = Net::SSH::Perl::Packet->read($ssh);                                               
        $out .= $packet->get_str;                                                                   
    } while ( ($out =~ /$prompt/ ) == 0 );                                                          
    $ssh->_disconnect;                                                                              
    ($out);                                                                                         
}

The script looks like that:

#!/usr/bin/perl
use Net::SSH::Perl;
$ssh = Net::SSH::Perl->new("host_here", port => 22, protocol => 1, use_pty => 1, debug => 0 );

$ssh->login('admin', 'password_here');

($out) = $ssh->shell_cmd("] >","/ppp active print count-only\r");

($out =~ /(\d+)/) && (($out) = ($1));

print $out;

I’ve created the function shell_cmd. It takes 2 parameters. First is the promt to wait for, and the second is commang to execute.

Known bugs:

  1. The command executed is at the first line of output.
  2. Last line is command prompt.

Because I’ve forgoten the PERL language any help for removing the bugs is welcomed :slight_smile: :slight_smile: :slight_smile:

arghhhhhhhhhhhhhhhhh a nasty bug in Mikrotik… I saw it before a long time ago…

When you log to the console on some host happens that after the first \r sended it starts working normaly.. before that you can type a command, but you cann’t erase and use “tab” key, because 94A shows… and nothing happens after that… If you press enter, the command is not executed, but It starts working again normaly… arghhhhhhhhh

In the end of shell_cmd match $out with regexp, something like:
$out =~ /[1]\n([\S\s])\n[\s\w/>]$/;
$out = $1;


  1. \s\w/ ↩︎

expect is a good tool (“language”) to learn, it makes life much easier for any “interactive” style connection, but of course, everyone is tempted to use other tools such as plain ssh or various programming languages.

One particular thing to be aware of is the treatment of stderr by the local/remote computer. This is rarely handled properly, because “visually”, when the session is interactive, everything appears to be “output” from the remote side.

Daniel