Using perl to connect to remote hosts via telnet
Did you think it was easy?
Suppose you needed to open a connection to a remote host from within your perl program. One
thing you would probably think of doing at first is the following:
open TELNET "|telnet $hostname";
print TELNET "$username\n";
print TELNET "$password\n";
Unfortunately, if you try this, you'll find it doesn't work. The telnet program connects to the remote
host but it completely ignores any commands you pipe to it. That's because the telnet program
reads its input only from the terminal and not from standard input.
The most cunning among you might then think a workaround for this: Open a socket to port 23
(the default telnet port) of the remote machine and write directly to it, thus, bypassing the telnet
program altogether. Well, although that might sound like a neat idea, it's not. And that's because
the telnet protocol requires that certain control data be exchanged between the two machines by
sending them along through the same socket connection.
So, it turns out that the problem is much more complicated than it seemed at first. We don't just
need to write code to perform socket I/O, but also we need to write code that speaks the TELNET
protocol. This is the bad news. The good news is that this code has already been written, and
that its author was kind enough to bundle it in a useful module, Net::Telnet, available at
Using Net::Telnet is pretty straightforward and simple. Let's first see a no-thrills example:
$telnet = new Net::Telnet ( Timeout=>10,
$output = $telnet->waitfor('/\$ $/i');
This simple program connects to camel.perlfect.com with username and password, 'bilbo' and
'baggins' respectively, and the issues the command 'who' to get a list of logged in users. It then
retrieves and prints the output. Although the code is self explanatory, here are a few things worth
- The Errmode option in the constructor for the telnet object specifies what kind of
behaviour we want the object to have when it encounters an error. die means that the
program will die with an error message. The other option is return. This will cause the
method that caused the error to return a false value. The error message can then be
retrieved from Net::Telnet->errmsg.
- The method waitfor() takes a regular expression as an argument and tries to match it in
the stream that is transmitted from the remote host. Upon a successful match, the method
returns all input before the match.
You might notice that issuing commands involves repeating print() and waitfor() calls in a
very much similar manner. We print a command and then we try to match a shell prompt.
Net::Telnet provides a very nice mode of operation that rids you of some of the repetitive tt.
All you need to do is to specify the regular expression that matches a prompt as a parameter in
the object's constructor and then use the cmd() method to issue commands. Similarly to command
issuing, Net::Telnet provides a handy method to simplify the login process, namely login(). The
following example demonstrates these shortcuts.
$telnet = new Net::Telnet ( Timeout=>10,
Prompt => '/\$ $/i');
This does the same as the previous example, but with much less typing. Note that the login()
method matches the login and password prompts with the regular expressions
/(login|username)[: ]*$/i and /password[: ]*$/i respectively.
So far we have covered the basics of the Net::Telnet module, enough to get you going with your
first telnetting scripts. The module is rich with other features, so make sure you take the time to
have a look at the documentation.
- The Net::Telnet documentation that comes with its distribution (Net::Telnet comes as part of the libnet bundle at CPAN)
covers just about anything you would need to know about
Warning: mysql_connect() [function.mysql-connect]: Access denied for user 'perlfect'@'188.8.131.52' (using password: YES) in /home/content/g/i/o/giorgoszervas/html/comments/comments_include.php on line 6
Connection Error: Access denied for user 'perlfect'@'184.108.40.206' (using password: YES)