【问题标题】:Paramiko capturing command outputParamiko 捕获命令输出
【发布时间】:2017-02-26 21:55:59
【问题描述】:

我有一个问题让我头疼了好几天。我在 Python 2.7.10 中使用 Paramiko 模块,我想向 Brocade 路由器发出多个命令,但只返回给定命令之一的输出,如下所示:

#!/usr/bin/env python
import paramiko, time

router = 'r1.test.example.com'
password = 'password'
username = 'testuser'

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(router, username=username, password=password)
print('Successfully connected to %s' % router)

remote_conn = ssh.invoke_shell()
output = remote_conn.recv(1000)

# Disable paging on Brocade.
remote_conn.send('terminal length 0\n')
# Check interface status.
remote_conn.send('show interfaces ethernet 0/1\n') # I only want output from this command.
time.sleep(2)
output = remote_conn.recv(5000)
print(output)

如果我要打印完整的输出,它将包含发送给路由器的所有内容,但我只想查看 show interfaces ethernet 0/1\n 命令的输出。

谁能帮忙解决这个问题?

我想问的最后一件事。我想过滤output 变量并检查“up”或“down”等字符串的出现,但我似乎无法让它工作,因为输出中的所有内容似乎都在新行上?

例如:

如果我在 for 循环中迭代 output 变量,我会得到变量中的所有字符,如下所示:

for line in output:
    print(line)

我得到这样的输出:

t

e

r

n

一个

l

l

e

n

g

t

h

0

有什么办法吗?

再次,

提前感谢您的帮助。

最好的问候,

亚伦 C.

【问题讨论】:

  • 可以说,这可以(应该)缩小——手头的问题根本不是 paramiko 所特有的;您可以运行output='terminal length 0',然后运行for line in output: print(line),并使用更少的样板来提出相同的问题。

标签: python python-2.7 ssh paramiko


【解决方案1】:

关于你的第二个问题:虽然我不是 paramiko 的专家,但我看到函数 recv,according to the doc,返回一个字符串。如果您在字符串上应用 for 循环,您将获得字符(而不是人们可能期望的行)。换行是由于您使用了on this page, at paragraph 6.3 解释的打印功能。

我还没有研究 paramiko 建议做什么。但是你为什么不把整个字符串当作一个单一的实体呢?例如,您可以将“up”检查为:

if "up" in output:

或者,如果这更适合您的需求,您可以 split the string into lines 然后进行任何您想做的测试:

for line in output.split('\n'): 

【讨论】:

  • 完美运行。现在对我来说过滤变量会容易得多。非常感谢您的快速回答!
【解决方案2】:

如果可以,exec_command() 调用提供了一种更简单的机制来调用命令。我看到 Cisco 交换机突然断开尝试 exec_command() 的连接,因此这可能无法用于 Brocade 设备。

如果您必须走invoke_shell() 路由,请务必在连接后和send('terminal length 0\n') 之后清除所有挂起的输出,在调用recv() 之前检查recv_ready() 以避免阻塞读取可能永远不会到达的数据。由于您正在控制交互式 shell,因此可能需要调用 sleep() 以使服务器有足够的时间来处理和发送数据,或者可能需要轮询输出字符串以通过识别 shell 提示字符串来确认您的最后一个命令已完成.

【讨论】:

  • 我添加了一个 if 语句来检查 recv_ready() 是否有效。现在我可以从我真正想要的命令中获得输出了!谢谢。
【解决方案3】:

阅读所有评论后,我做了以下更改:

#!/usr/bin/env python
import paramiko, time

router = 'r2.test.example.com'
password = 'password'
username = 'testuser'

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(router, username=username, password=password)
print('Successfully connected to %s' % router)

remote_conn = ssh.invoke_shell()
output = remote_conn.recv(1000)

# Disable paging on Brocade.
remote_conn.send('terminal length 0\n')
time.sleep(2)
# Clearing output.
if remote_conn.recv_ready():
    output = remote_conn.recv(1000)

# Check interface status.
remote_conn.send('show interfaces ethernet 4/1\n') # I only want output from this command.
time.sleep(2)
# Getting output I want.
if remote_conn.recv_ready():
    output = remote_conn.recv(5000)
print(output)

# Test: Check if interface is up.
for line in output.split('\n'):
    if 'line protocol is up' in line:
        print(line)

现在一切都很好。

感谢大家的帮助。

最好的问候,

亚伦 C.

【讨论】:

  • 很好,我很惊讶这篇文章的 +1 很少。真的很有用。
  • 这篇文章很有帮助。我只创建了客户端,而不是 shell 调用。它为我省去了很多麻烦。
猜你喜欢
  • 2012-06-29
  • 2018-01-28
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
  • 1970-01-01
  • 2012-11-22
  • 1970-01-01
  • 2012-02-18
相关资源
最近更新 更多