在 Cisco 路由器上使用多个命令的 Paramiko exec_command 不提供任何输出

问题描述 投票:0回答:3
login_user = 'xyz'
login_pass = 'xyz'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False, timeout=5)
print "success loggedin"
stdin, stdout, stderr = ssh.exec_command("term len 0 ; show int desc | i Tu ; show ip interface brief | in Tunnel ; show ip bgp vpnv4 vrf AWS summary | i 169.25 ; show ip route vrf AWS bgp")
all_output = stdout.read()
print all_output

上面是我的代码片段,仅传递一个命令就可以很好地打印结果,但是使用上面的多个命令时,它不起作用(无输出)。正在登录的设备是 Cisco ASR1006 - 与该设备有什么关系吗?

非常感谢任何帮助!


由于多个命令不起作用,我将下面的代码与多个 exec_command 一起使用,但这每次执行大约需要 30-40 秒。 每个命令执行都需要ssh.connect?

ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False)
stdin, stdout, stderr = ssh.exec_command('show int desc | i Tu')
vpc_ints = stdout.read()
ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False)
stdin, stdout, stderr = ssh.exec_command('show ip interface brief | in Tunnel')
vpc_peers = stdout.read()
ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False)
stdin, stdout, stderr = ssh.exec_command('show ip bgp vpnv4 vrf AWS summary | i 169.25')
vpc_bgp_routes = stdout.read()
ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False)
stdin, stdout, stderr = ssh.exec_command('show ip route vrf AWS bgp')
ip_routes_list = stdout.read()

正如评论中所建议的,我还尝试通过一个连接多次调用

exec_command

ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False)
stdin, stdout, stderr = ssh.exec_command('show int desc | i Tu')
vpc_ints = stdout.read()
#ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False)
stdin, stdout, stderr = ssh.exec_command('show ip interface brief | in Tunnel')
vpc_peers = stdout.read()
#ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False)
stdin, stdout, stderr = ssh.exec_command('show ip bgp vpnv4 vrf AWS summary | i 169.25')
vpc_bgp_routes = stdout.read()
#ssh.connect(device, username=login_user, password=login_pass, look_for_keys=False)
stdin, stdout, stderr = ssh.exec_command('show ip route vrf AWS bgp')
ip_routes_list = stdout.read()
ssh.close()

但是失败了:

File "C:\Python27\myvpndashboard\myvpnapp\tunnel_summary.py", line 179, in dataset_build
cisco_show(device)
File "C:\Python27\myvpndashboard\myvpnapp\tunnel_summary.py", line 36, in cisco_show
stdin, stdout, stderr = ssh.exec_command('show ip interface brief | in Tunnel')
File "C:\Users\sduraisami\Envs\myvpndashboard\lib\site-packages\paramiko\client.py", line 472, in exec_command
chan = self._transport.open_session(timeout=timeout)
File "C:\Users\sduraisami\Envs\myvpndashboard\lib\site-packages\paramiko\transport.py", line 765, in open_session
timeout=timeout)
File "C:\Users\sduraisami\Envs\myvpndashboard\lib\site-packages\paramiko\transport.py", line 889, in open_channel
raise e
EOFError
python ssh paramiko cisco
3个回答
0
投票

(至少有一些)众所周知,Cisco 路由器不支持一个“exec”请求中的多个命令: https://the.earth.li/~sgtatham/putty/latest/htmldoc/Chapter3.html#using-cmdline-m

对于某些服务器(特别是 Unix 系统),您甚至可以在此文件中放入多行并按顺序执行多个命令,或整个 shell 脚本; 但这可以说是一种滥用,并且不能指望在所有服务器上都有效。特别是,众所周知,它不能与某些“嵌入式”服务器一起使用,例如思科路由器


通常,您可以通过同一连接多次运行

exec_command
。但这对于思科来说似乎也是不可能的。

然后我建议您坚持为每个命令重新打开会话。虽然效率低下,但这是一种可靠的方法。


如果效率低下无法接受,您可以使用 shell 通道,例如:

channel = ssh.invoke_shell()
channel.send('command 1\n')
channel.send('command 2\n')
channel.send('command 3\n')
while not channel.recv_ready():
    time.sleep(3)
out = channel.recv(9999)
print out

但这并不可靠。很难判断一个命令的输出何时完成而另一个命令的输出何时开始。也很难判断您是否已经获得了所有输出。由于 Paramiko 始终使用 PTY,因此您会得到很多不需要的输出,例如提示、命令回显等。


0
投票

我遇到了同样的问题,并且能够解决该问题。我没有使用 exec_command() 函数,而是打开了一个 shell 会话,然后对我创建的 shell 对象使用了 send() 函数。

from time import sleep
import paramiko

username = "username" 
password = "password"

ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())


ssh.connect(
    ip_address, 
    port=22, 
    username=username, 
    password=password, 
    look_for_keys=False, 
    banner_timeout=200
)
connection = ssh.invoke_shell()


connection.send("show int desc | i Tu")
output = connection.recv(65535)
print(output.decode("UTF-8"))
sleep(.5)
connection.send("\n")


connection.send("show ip interface brief | i Tunnel")
output = connection.recv(65535)
print(output.decode("UTF-8"))
sleep(.5)
connection.send("\n")

0
投票

就像马丁所说,“exec_command”不是解决这个问题的方法。 您可以使用“chan.send()”

要确定是否准备好接收下一个命令,您可以执行以下操作(当然,在创建命令列表之后):

buff = ""
while "#" not in buff:
    if channel.recv_ready():
        response = channel.recv(4086).decode("utf-8")
        buff += resp
# then do whatever you want with this output

马丁的回答是正确的,所以我一直在尝试它,这非常适合我的需求。使用 CISCO 设备时,您通常会在提示行中看到“#”,因此您可以不断检查该提示行是否存在(您的情况可能会有所不同,因此您可以包含更多提示行,而不仅仅是“#”)。一旦到达那里,您就会跳出 while 循环。

© www.soinside.com 2019 - 2024. All rights reserved.