Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

IO::Pty, Net::Telnet and SSH [SOLVED]

by gonza (Novice)
on Nov 03, 2006 at 22:28 UTC ( #582185=perlquestion: print w/replies, xml ) Need Help??

gonza has asked for the wisdom of the Perl Monks concerning the following question:


I've been trying to get the SSH example on the Net::Telnet manpage to work without success. Here is the script:
## Main program. { my ($pty, $ssh, @lines); my $host = "changeme"; my $user = "changeme"; my $password = "changeme"; my $prompt = '/changeme:~> $/'; ## Start ssh program. $pty = &spawn("ssh", "-l", $user, $host); # spawn() defined b +elow ## Create a Net::Telnet object to perform I/O on ssh's tty. use Net::Telnet; $ssh = new Net::Telnet (-fhopen => $pty, -prompt => $prompt, -telnetmode => 0, -cmd_remove_mode => 1, -output_record_separator => "\r"); ## Login to remote host. $ssh->waitfor(-match => '/password: ?$/i', -errmode => "return") or die "problem connecting to host: ", $ssh->lastline; $ssh->print($password); $ssh->waitfor(-match => $ssh->prompt, -errmode => "return") or die "login failed: ", $ssh->lastline; ## Send command, get and print its output. @lines = $ssh->cmd("who"); print @lines; exit; } # end main program sub spawn { my(@cmd) = @_; my($pid, $pty, $tty, $tty_fd); ## Create a new pseudo terminal. use IO::Pty (); $pty = new IO::Pty or die $!; ## Execute the program in another process. unless ($pid = fork) { # child process die "problem spawning program: $!\n" unless defined $pid; ## Disassociate process from existing controlling terminal +. use POSIX (); POSIX::setsid or die "setsid failed: $!"; ## Associate process with a new controlling terminal. $tty = $pty->slave; $tty_fd = $tty->fileno; close $pty; ## Make stdio use the new controlling terminal. open STDIN, "<&$tty_fd" or die $!; open STDOUT, ">&$tty_fd" or die $!; open STDERR, ">&STDOUT" or die $!; close $tty; ## Execute requested program. exec @cmd or die "problem executing $cmd[0]\n"; } # end child process $pty; } # end sub spawn
Of course I changed the values changeme to the right ones. I've also defined the input_log to be /tmp/inputlog, and all I ever get to see is:
Permission denied, please try again. Permission denied, please try again. Permission denied (publickey,password,keyboard-interactive).

Just to verify the ssh binary is in working order, I can ssh to the server with the username/password I've defined in the script from the shell without probs.

As far as I've been able to troubleshoot the problem, it would seem like the SSH password prompt which is normally sent to the controlling TTY by the ssh binary is not being read' by the Perl script.

I have also tried to read what $tty is reading in and the password prompt is definately not there, only the Permission denied messages.

I'd appreciate any light you Perl monks can shed on this! :-)

Infact, if you have the time, try copying and pasting the above code into a file, modify the changeme values, ensure you have IO::Pty and Net::Telnet installed, and see if it works for you. I've tried it on 2 different systems and the password prompt is simply not read.


Janitored by tye: Add READMORE tags

Replies are listed 'Best First'.
Re: IO::Pty, Net::Telnet and SSH
by duckyd (Hermit) on Nov 04, 2006 at 03:21 UTC
    FWIW, it works for me. Maybe the problem isn't the perl code, but how ssh is setup, E.G. for some reason it doesn't prompt your script at all? What if you try to ssh to localhost instead of a remote host? When you manually ssh in, are you prompted for a password? Should it match the regex /password: ?$/i ?

    You don't mention what error the script is producing exactly....

      Yeah, I don't think it is the Perl code. It must be the way my /etc/ssh/ssh_config is setup or something.

      My test $host has been localhost. I've tried remote hosts as well but same result. When I manually SSH in to localhost, yes I am prompted for a password and yes, it should match the regex /password: ?$/i. I've played around with the regex to try and match anything but then realized the script is not actually getting the prompt, so no matter what I try and match it's not going to work.

      The output of the script is:

      problem connecting to host: Permission denied (publickey,password,keyb +oard-interactive)
      Of course, since it didn't manage to receive the password prompt, it never matched the regex.

      Thanks for your reply and if you have any suggestions, I look forward to reading them. It's one of those problems that has annoyed me enough to keep me trying stuff until it works :)


      Could you please tell me what version of OpenSSH/whatever you're using? also a copy of your /etc/ssh/ssh_config might be handy too, to compare it with mine.

      Thanks in advance!

      Net::Telnet and SSH is worked fine for me too but device not /dev/pts/ entry still exist . its not the $pty->slave device node but its different may be its master device node i have tried $ssh->close but still no lock and process table showns "ssh -l user host " and "sshd user@pts/no" etried Can anyone have the idea what this device node ?
Re: IO::Pty, Net::Telnet and SSH
by f00li5h (Chaplain) on Nov 04, 2006 at 07:54 UTC

    This in no way answers your actual question, but it may be a solution to the problem

    why not skip the keyboard-interactive all together, and use one of the earlier things on the list, one that won't ever let you down...

    How about passwordless Ssh keys? they're quick, fun and easy to use!
    This should be enough to get you going, you may want to restirct the commands that can be run with this key, etc. (ask the man, he'll know)

    Just make sure that your home directory, and your ssh directory are not group or world writable, or ssh will ignore the hey (it's a little paranoid, don't ya know)

    I've made whole bundles of assumptions here, but it still may help. (this is also super handy if you have home directories common to many boxes, because the keys end up on all of the machines)

    will: do{ perl programming } for $cash;


      I'd love to use SSH keys, but I can't. Why? because I manage about 3000 servers (now you can see why this Perl script would be handy!) and about 30% of those use a shared home directory and my key is in $HOME/.ssh/authorized_keys.
      For some reason, the very first time I connect to the server, it asks me for a password. From then on, it works with the key.

      That's not the only problem, there are other servers where my home directory is a symlink to somewhere on the filesystem and SSH refuses to read my key in that sort of scenario, so SSH keys don't work on these systems (and it's a lot of them!!). Only conclusion I came to is that SSH does not read your key if your home dir is a symlink, as I tried changing permissions all over the place and no luck.

      I figured since some work, some don't, I'll just try and work with password prompts and be done with it.

      It's probably worth saying that I don't have root on the 3000 servers, otherwise I could probably fix a lot of these issues I'm having with SSH keys.


        You will also have problems when you use different SSH programs, propietary SSH as for example from works different than OpenSSH...


        fmerges at
Re: IO::Pty, Net::Telnet and SSH
by fmerges (Chaplain) on Nov 04, 2006 at 14:31 UTC


    Question, why you don't try it with Net::SSH::Perl?


    fmerges at


      I had been using Net::SSH::Perl successfully. The problem came when I needed to run some interactive programs on the remote servers and needed Expect to interact with them. Since Expect can either spawn a new program or work with an open filehandle, I thought I'd find a way to open a SSH or Telnet connection to a server, do the login work then let Expect takeover when an interactive script had to be executed on the remote side.

      I'm thinking what I could do is spawn SSH directly from Expect. The thing is I don't *always* need to run interactive scripts on the remote side, hence why I don't *always* need to use Expect. This is why I thought it would be neater to have Net::Telnet open the Telnet or SSH connection (depending on server) then run Expect when I need to.

      I'm open to suggestions, if you have another way in mind of how I can achieve this (preferably non-hackish way as the idea is that the code is maintainable afterwards)


        And why not using something like a dispatch table, so things that don't need to be interactive uses the $ssh->cmd inside of the subroutines that handles the command, and for the ones you need interactive, you just use the $ssh->shell with Expect. Take a look at the shell method on Net::SSH::Perl.


        fmerges at
Re: IO::Pty, Net::Telnet and SSH [SOLVED]
by gonza (Novice) on Nov 06, 2006 at 06:50 UTC

    Looks like all I had to do was:


    .. after calling $tty = $pty->slave.

    Hope it helps somebody else in the same situation!

    Thanks to all who replied and offered help. I appreciate it!

      Thanks for sharing your solution. I'm one of those someone else's in the same situation that you helped!

      I am curious why we needed that line, and so many others seemed to work fine without it?!?! One of those days when I have some free time....
      I got benefit from ur code "$pty->make_slave_controlling_terminal();" also!!! thanks !! good luck, gonza.
      Thanks, It's really helps. Sergei
      Thank you!
        Awesome! You solved my problem as well....was driving me nuts! Thank you!
      Thank you! It worked!

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://582185]
Approved by Paladin
Front-paged by tye
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2021-04-10 22:49 GMT
Find Nodes?
    Voting Booth?

    No recent polls found