Ruby — telnet ведет себя непоследовательно

#ruby

#ruby

Вопрос:

Я испытываю некоторое забавное поведение с telnet. Ниже приведен мой код:

 #!/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.218n")
puts response
  

Это результат, который я получаю, пытаясь запустить его несколько раз (не волнуйтесь, там нет конфиденциальной информации, все очищено):

 [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> 
  

Как вы можете видеть выше, telnet отказывается выполнять команду show ip bgp 182.201.120.218n , даже если сеанс telnet был установлен / подключен. Наконец, это удалось в 6-м запуске, но 7-й сбой и т. Д. Если я запускаю его еще один случайный раз, он снова работает, только для сбоя. Ручная telnet всегда успешна, иначе :

 [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> 
  

Выходной журнал показывает следующее:

 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> 
  

Я ломаю голову, пытаясь понять, почему telnet ведет себя таким образом, когда у обычного telnet нет проблем.

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

Работает на Redhat 7.8

Если у кого-нибудь есть какие-либо идеи или вы хотели бы предоставить более подробную информацию, дайте мне знать. Я в тупике:( (Если вам интересно — я пытаюсь запросить информацию о маршруте BGP из Quagga / zebra, используя telnet для запуска команд без требуемых учетных данных. Я мог бы сделать это легко и без проблем с Perl, но мы должны перенести скрипты на Ruby по внутренним причинам).

Ответ №1:

С помощью вашей :Prompt спецификации вы сообщаете клиенту telnet, что приглашение telnet сервера — это любая строка, содержащая символ # или > .

Клиент telnet считывает все полученные выходные данные сервера до тех пор, пока не увидит строку, похожую на приглашение. Теперь в вашем случае ваша первая строка вывода show ip bgp команды уже содержит # символ, соответствующий вашей спецификации запроса.

При этом вы теперь сталкиваетесь с состоянием гонки. Вы увидите некоторый вывод, если сервер отправит больше первой строки в первом TCP-пакете своего ответа, что приведет к тому, что клиент telnet прочитает весь этот отправленный вывод. Если сервер отправляет каждую строку отдельно в одном пакете, клиент telnet завершает работу быстрее, поскольку он уже видит указанное приглашение.

Чтобы исправить это, возможно, уже достаточно указать более строгий :Prompt , например /[$%#>] z/n , как показано в примере на https://github.com/ruby/net-telnet#usage

Комментарии:

1. Спасибо за это, Хольгер! Это имеет смысл. Я изменил свое приглашение, чтобы оно /[$%#>] z/n соответствовало рекомендациям. Но, к сожалению, telnet по-прежнему ведет себя так же. Есть еще идеи? Я экспериментирую waitfor прямо сейчас, но пока безуспешно.

Ответ №2:

Хорошо, не уверен, что это лучший способ, но, похоже, я решил его путем добавления waitfor . Полный код :

 #!/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
}