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

Having difficult time getting a response from my perl script when using Net::Telnet. The server is not actually a telnet server, but responses to print command from perl. I do get all the correct responses in the "recieved_data.txt" file, but need the returned value.

#!/usr/bin/perl use Net::Telnet (); $host='192.168.1.181'; {$t = new Net::Telnet (Timeout => 10,Input_log => "received_data.txt" +, Prompt => '/bash\$ $/'); $t->open($host); $t->print("AT"); #this is just used to make sure it connects## $t->waitfor('/AT/'); #this is just an echo back of what is sent## $t->waitfor('/OK/i'); #send this to say I'm ready## } {$t->print("AT%23=1234"); #This basically the password to the system# +# $t->waitfor('/AT%23=1234/i'); #Echo back## $t->waitfor('/OK/i'); } { $oid = $t->print("AT1122"); #This is the command to see the state## $oid = $t->waitfor('/AT1122/i'); #Echo back## $oid = $t->waitfor('//'); #this could be 0,1,2...need to converto oid +### #Need this value to check state in SNMP## $t->waitfor('/OK/i'); } $t->close();

Replies are listed 'Best First'.
Re: Telnet responses
by choroba (Cardinal) on Oct 19, 2023 at 17:39 UTC
    What's the question? Do you want to know how to get the number returned after the last command? According to the documentation, it should be something like
    my (undef, $oid) = $t->waifor('/^[0-9]+$/');

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      choroba, yes I know it will be an 1,2,3 or some number. But, displaying or "doing something" with that seems to be the problem. Here is the "received_data.txt"

      AT OK AT%23=1234 OK AT1122 2 ####This is the digit I need to "do something with" or Relay to a +n SNMP server later. OK
Re: Telnet responses
by cavac (Prior) on Oct 20, 2023 at 08:02 UTC

    If it's not a telnet server but a plain connection, you might be better off using something like IO::Socket::IP

    It's simple enough and there are many examples/explainythings out there already. But basically, you'd do something like this (untested pseudo-code):

    use v5.36; ... # Connect in "blocking" mode my $socket = IO::Socket::IP->new( PeerHost => '192.168.1.181', PeerPort => 12345, Proto => 'tcp', ); if(!defined($socket)) { die("Connection failed"); } # Switch to non-blocking send/receive mode so we can implement timeout +s $socket->blocking(0); $socket->send("AT\n"); waitFor($socket, 'AT'); $socket->send("AT1122\n"); my $oid = waitFor($socket, 'AT%23=1234', 1); ... sub waitFor($socket, $searchstring, $caseinsensitive = 0) { while(1) { my $line = readsocketline($socket, 20); if($casesensitive) { if($line =~ /$searchstring/i) { return $line; } } elsif($line =~ /$searchstring/) { return $line; } } } sub readsocketline($socket, $timeout = 30) { if(!defined($timeout) || !$timeout) { $timeout = 30; }; my $failat = time + $timeout; my $line = ''; while(1) { my $char = ''; $socket->recv($char, 1); if(time > $failat) { die("Network timeout"); } next if(!defined($char) || $char eq ''); next if($char eq "\r"); last if($char eq "\n"); $failat = time + $timeout; $line .= $char; } return $line; }

    If you need an ecrypted connection, you can use IO::Socket::SSL as a base for your connection. (For more complex protocols/connection that use optional encryption and/or use something like Unix Domain Sockets, you'd connect normally first, then use IO::Socket::SSL->start_SSL() to upgrade).

    PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP

        You are right, of course. If you can go higher level, you should.

        I usually go relatively low level on answers to SoPW and avoid using any frameworks that have their own control loops. This makes it easier for OP to integrate it into their own software that may have their own control loop already.

        (Besides, i love doing low level protocol stuff. It's a cavac thing.)

        PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
Re: Telnet responses
by tybalt89 (Monsignor) on Oct 20, 2023 at 20:23 UTC

    If I understand your question, the response you are looking for is in the prematch of the last OK.

    Something like this:

    #!/usr/bin/perl use strict; # https://www.perlmonks.org/?node_id=11155061 use warnings; use Net::Telnet (); my $host='192.168.1.13'; # FIXME my $t; my $oid; {$t = new Net::Telnet (Timeout => 10,Input_log => "received_data.txt" +, Port => 12345, # FIXME Prompt => '/bash\$ $/'); $t->open($host); $t->print("AT"); #this is just used to make sure it connects## $t->waitfor('/AT/'); #this is just an echo back of what is sent## $t->waitfor('/OK/i'); #send this to say I'm ready## } {$t->print("AT%23=1234"); #This basically the password to the system# +# $t->waitfor('/AT%23=1234/i'); #Echo back## $t->waitfor('/OK/i'); } { $oid = $t->print("AT1122"); #This is the command to see the state## $oid = $t->waitfor('/AT1122/i'); #Echo back## #$oid = $t->waitfor('//'); #this could be 0,1,2...need to converto oi +d### # #Need this value to check state in SNMP## my ($returnedvalue, $match) = $t->waitfor('/OK/i'); $returnedvalue =~ tr/0-9//cd; # delete everything except digits print "this is what I think you are looking for: $returnedvalue\n"; } $t->close()

    Outputs:

    this is what I think you are looking for: 2

    Note: a few tweaks were made to run it on my machine...

      Thank you tybalt89...works great. I new I was close. ($returnedvalue, $match) was what I was missing. Thanks all for your wisdom!

        Maybe one more question. While using $ARGV and setting global value string with "my $string=$ARGV[0]. How would I use the "$t->waitfor ($string); instead of $t->waitfor ('//');