我正在尝试通过cisco终端/ comm服务器连接到cisco节点的控制台连接。 为此,我telnet到特定端口上的cisco终端/ comm服务器的IP地址,让我们说X.X.X.X - 端口2068。 当我通过CLI从我的计算机上执行此操作时,它看起来像这样:
[user@computer]$ telnet X.X.X.X 2068
Trying X.X.X.X...
Connected to X.X.X.X (X.X.X.X).
Escape character is '^]'.
Username: <user>
Password:
console-cisco-node>
通过我的计算机上的CLI没问题。 但是当我在我的计算机上运行下面的Python代码时,它似乎不起作用......
#! /usr/bin/env python
import telnetlib
tn = telnetlib.Telnet("X.X.X.X",2068)
tn.set_debuglevel(8)
data = tn.read_some()
tn.close()
if data == '':
print 'variable data is EMPTY'
else:
print data
print "variable data is FILLED !!!"
当我运行此代码时,我只能看到这个,看起来'tn.read_some()'只是等待永远,因为没有来自cisco终端/ comm服务器? [同样适用于tn.read_all()]
PS。我按CTRL-C
停止了正在运行的代码[user@computer]$ ./test.py
Telnet(X.X.X.X,2068): recv '\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f'
Telnet(X.X.X.X,2068): IAC WILL 1
Telnet(X.X.X.X,2068): IAC WILL 3
Telnet(X.X.X.X,2068): IAC DO 24
Telnet(X.X.X.X,2068): IAC DO 31
Telnet(X.X.X.X,2068): recv '\xff\xfc\x01'
Telnet(X.X.X.X,2068): IAC WONT 1
Telnet(X.X.X.X,2068): recv '\xff\xfc\x03'
Telnet(X.X.X.X,2068): IAC WONT 3
Telnet(X.X.X.X,2068): recv '\xff\xfe\x18'
Telnet(X.X.X.X,2068): IAC DONT 24
Telnet(X.X.X.X,2068): recv '\xff\xfe\x1f'
Telnet(X.X.X.X,2068): IAC DONT 31
Traceback (most recent call last):
File "./test.py", line 7, in ?
data = tn.read_some()
File "/usr/lib64/python2.4/telnetlib.py", line 345, in read_some
self.fill_rawq()
File "/usr/lib64/python2.4/telnetlib.py", line 521, in fill_rawq
buf = self.sock.recv(50)
KeyboardInterrupt
当我将代码中的'tn.read_some()'更改为'tn.read_eager()'或'tn.read_very_eager()'或'tn.read_lazy()'或'tn.read_very_lazy()'时再次运行代码它告诉我这个:
[user@computer]$ ./test.py
variable data is EMPTY
当我更改python代码以不连接到cisco节点的控制台连接而是连接到cisco节点的管理连接(正常端口23上的另一个IP地址YYYY)时,如下所示它工作得很好,我看到这个输出:
[user@computer]$ ./test1.py
Telnet(Y.Y.Y.Y,23): recv '\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f'
Telnet(Y.Y.Y.Y,23): IAC WILL 1
Telnet(Y.Y.Y.Y,23): IAC WILL 3
Telnet(Y.Y.Y.Y,23): IAC DO 24
Telnet(Y.Y.Y.Y,23): IAC DO 31
Telnet(Y.Y.Y.Y,23): recv '\r\n************************************************'
************************************************
variable data is FILLED !!!
所以我认为Python代码是可以的。 只是cisco终端/ COMM服务器(X.X.X.X)以一种不同的方式作出反应,然而我觉得Python telnetlib很混乱。
那里的任何人都经历过类似的事情吗?
答案 0 :(得分:0)
在端口2068上看起来你没有真正的telnet协议。来自telnet man 连接到非标准端口时, telnet省略了任何TELNET选项的自动启动。什么时候 端口号前面有一个减号,即初始值 选项协商已完成。。但是telnetlib假设如果你使用它,你需要一个telnet协议。正如您所说,在连接上使用wireshark并不容易,您可以尝试将CLI telnet连接到端口-2068以验证您遇到的问题与使用telnetlib相同。
是否可以选择使用简单的套接字?
s = socket.create_connection(('X.X.X.X', 2068))
data = s.recv(1024)
...
答案 1 :(得分:0)
我找到了另一种方法(感谢Serge Ballesta)
我的情况下的telnetlib对象是不可能的,所以我不得不使用套接字对象通过cisco终端/ comm服务器连接到cisco节点的控制台连接。 在原始基本代码下面,我可以开始编写我需要的程序。
#! /usr/bin/env python
import socket
import time
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("X.X.X.X",2068))
data1 = s.recv(1024)
#
# when the connection with the server is made the server sends some (IAC) commands
#
# '\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f'
#
# as far as I know this means the following:
#
# IAC WILL ECHO
# IAC WILL SUPRESS GO AHEAD
# IAC DO TERMINAL TYPE
# IAC DO WINDOW SIZE
#
# WILL means the server wants to use the indicated facility if the client has the possibilty to use this facility
# (client can reply with DO or DONT)
#
# DO means the server has the possibility for the indicated facility and asks the client if he wants to use this facility
# (client can reply with WILL or WONT)
#
#
# PS.
# WILL = xFB = 251
# WONT = xFC = 252
# DO = xFD = 253
# DONT = xFE = 254
#
#
#
# Python is going to answer as follwos:
#
# IAC DONT ECHO
# IAC DO SUPRESS GO AHEAD
# IAC WONT TERMINAL TYPE
# IAC WONT WINDOW SIZE
#
s.sendall('\xff\xfe\x01\xff\xfd\x03\xff\xfc\x18\xff\xfc\x1f')
data2 = s.recv(1024) # server sends '\xff\xfc\x01' = IAC WONT ECHO as a reply back
# send an enter to make the hop from the terminal server to the console connection of the node we want to be on
s.send('\r')
data3 = ''
while not 'Username: ' in data3:
data3 = s.recv(2048)
s.send('<USERNAME>\r')
time.sleep(0.1)
s.recv(1024)
s.send('<PASSWORD>\r')
time.sleep(0.1)
data5 = s.recv(1024)
s.send('exit\r')
s.close()
#print repr(data1) # '\xff\xfb\x01\xff\xfb\x03\xff\xfd\x18\xff\xfd\x1f' from the server
#print repr(data2) # '\xff\xfc\x01' from the server
#print data3 # banner and Username: from the console connection of the node we want to be on
prompt_console = data5.split()[-1]
print 'prompt van de console = %s' %prompt_console[:len(prompt_console)-1]
except socket.error, e:
print e
except socket.timeout, e:
print e
答案 2 :(得分:0)
我还与思科(和其他路由器)进行互动。对于telnet通信,我扩展了Telnet类并添加了read
方法,如下所示:
def read(self, timeout):
s = time.time()
resp = ""
while True:
res = self.read_eager()
if not res and resp:
return resp
resp += res
if time.time() - s >= timeout:
return resp
time.sleep(0.001)
所以基本上“问题”是各种read_*
方法没有给出“全部”,主要是因为没有“全部”的定义,它将返回它们在“缓冲区”中的任何内容,或者他们将填充缓冲区然后返回内容,具体取决于您调用的方法。我的方法是“阅读时仍有东西可读(在我阅读时停止”)或直到它超过timeout
秒。
另外,您应该调查read_until
方法的工作方式与预期相同。
def read_until(self, match, timeout=None):
"""Read until a given string is encountered or until timeout.
When no match is found, return whatever is available instead,
possibly the empty string. Raise EOFError if the connection
is closed and no cooked data is available.
"""