JaneD
JaneD

Reputation: 199

Ruby - telnet behaving inconsistently

I am experiencing some funny behaviour with telnet. Below is my code:

#!/usr/bin/env ruby

require 'net/telnet'

ipaddress = "182.201.120.218" 

j = Net::Telnet::new("Host" => '127.0.0.1',
  "Port" => 2605,
  "Output_log" => "output.log", 
  "Dump_log"   => "dump.log",   
  "Prompt"     => /[#>]/ , 
  "Telnetmode" => true,      
  "Timeout"    => 10,         
)

response = j.cmd("show ip bgp 182.201.120.218\n")
puts response

This is the output I get trying to run it a few times (dont worry no sensitive info there, all sanitized):

[root@dummyserver tmp]# ./telnet.rb 
dummyserver.com.au> 
[root@dummyserver tmp]# ./telnet.rb 
dummyserver.com.au> 
[root@dummyserver tmp]# ./telnet.rb 
dummyserver.com.au> 
[root@dummyserver tmp]# ./telnet.rb 
dummyserver.com.au> 
[root@dummyserver tmp]# ./telnet.rb 
dummyserver.com.au> 
[root@dummyserver tmp]# ./telnet.rb 
dummyserver.com.au> show ip bgp 182.255.120.248
BGP routing table entry for 182.235.96.0/19
Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Not advertised to any peer
  Local
    202.158.215.52 from 202.158.215.52 (202.158.215.6)
      Origin IGP, localpref 100, valid, internal, best
      Community: 7575:1000 7575:2406 7575:3002
      Originator: 202.158.215.6, Cluster list: 202.158.215.52 202.158.215.10 
      Last update: Mon Sep 21 06:46:58 2020

[root@dummyserver tmp]# ./telnet.rb 
dummyserver.com.au> 

As you can see above, telnet refuses to run the command show ip bgp 182.201.120.218\n even though the telnet session was established/connected. It finally succeeded in the 6th run but 7th failed etc. If I run it another random times it works again, only to fail. Manual telnet is always successful, aka :

[root@dummyserver]# telnet 127.0.0.1 2605
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
dummyserver.com.au>show ip bgp 182.255.120.248
BGP routing table entry for 182.255.96.0/19
Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Not advertised to any peer
  Local
    202.158.215.52 from 202.158.215.52 (202.158.215.6)
      Origin IGP, localpref 100, valid, internal, best
      Community: 7575:1000 7575:2406 7575:3002
      Originator: 202.158.215.6, Cluster list: 202.158.215.52 202.158.215.10 
      Last update: Mon Sep 21 06:46:58 2020

dummyserver.com.au> 

Output log shows the following:

dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> show ip bgp 182.255.120.248
BGP routing table entry for 182.255.96.0/19
Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Not advertised to any peer
  Local
    202.158.215.52 from 202.158.215.52 (202.158.215.6)
      Origin IGP, localpref 100, valid, internal, best
      Community: 7575:1000 7575:2406 7575:3002
      Originator: 202.158.215.6, Cluster list: 202.158.215.52 202.158.215.10 
      Last update: Mon Sep 21 06:46:58 2020

dummyserver.com.au> 
dummyserver.com.au> 
dummyserver.com.au> 
dummyserver.com.au> Trying 127.0.0.1...
Connected to 127.0.0.1.
dummyserver.com.au> 

I'm scratching my head trying to understand why telnet is behaving this way when normal telnet has got no issues.

Rvm version : # rvm version rvm 1.29.10 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]

Running on Redhat 7.8

If anyone have any idea or would like to provide more details, let me know. I'm stumped :( (If you are curious - I'm trying to query BGP route info from Quagga/zebra using telnet to run the commands with no credentials required. I could do this easily and with no issue with Perl, but we have to port the scripts to Ruby for internal reasons).

Upvotes: 1

Views: 109

Answers (2)

JaneD
JaneD

Reputation: 199

OK, not sure if this is the best way, but I appear to have resolved it by the adding waitfor. Complete code :

#!/usr/bin/env ruby

require 'net/telnet'

ipaddress = "182.255.120.248"

j = Net::Telnet::new("Host" => '127.0.0.1',
  "Port" => 2605,
  "Output_log" => "output.log", # default: nil (no output)
  "Dump_log"   => "dump.log",   # default: nil (no output)
  "Prompt" =>  /[$%#>] \z/n ,
  "Telnetmode" => true,         # default: true
  "Timeout"    => 10,           # default: 10
)

j.waitfor(/[\>\# ]$/) {
response = j.cmd("show ip bgp 182.255.120.248")
puts response
}

Upvotes: 0

Holger Just
Holger Just

Reputation: 55778

With your :Prompt specification, you tell the telnet client that the telnet prompt of the server is any line which contains a # or > character.

The telnet client reads all received output of the server until it has observed a line looking like a prompt. Now in your case, your first line of the show ip bgp command output already contains a # character, matching your prompt specification.

With that, you are now running into a race-condition. You will see some output if the server send more than the first line in the first TCP packet of its response, which results in the telnet client to read all of this sent output. If the server sends each line separately in one packet, the telnet client bails out quicker since it already sees the designated prompt.

To fix this, it might already be sufficient to specify a stricter :Prompt, e.g. /[$%#>] \z/n as shown in the example at https://github.com/ruby/net-telnet#usage

Upvotes: 2

Related Questions