【问题标题】:Paramiko SSH execute command gets stuck at session.recv_exit_status()Paramiko SSH 执行命令卡在 session.recv_exit_status()
【发布时间】:2015-02-11 05:33:28
【问题描述】:

下面是我的 Python 代码,它运行良好,直到我尝试使用别名获取一些环境变量。从那以后它开始挂在session.recv_exit_status(),现在甚至拒绝执行ls命令。

#!/usr/bin/env/python

import paramiko
trans = paramiko.Transport(('fcd01.force.com',22))
trans.connect(username = 'user',password = 'pwd')
session = trans.open_channel("session")

session.exec_command('ls')
session.recv_exit_status()  # ** hangs **

while True:
    if session.recv_ready():
        break
    time.sleep(2)
session.send('exit\n')

stdout_data = []
try:
    part = session.recv(4096)
while part:
    stdout_data.append(part)
    part = session.recv(4096)
except:
    raise

print 'exit status: ', session.recv_exit_status()
print ''.join(stdout_data)

任何线索如何取得成功?

【问题讨论】:

  • 您是否有理由需要通过字节检索标准输出?另外当它拒绝执行 ls 命令时你得到的错误是什么?
  • 代码只是挂在 recv_exit_status() 处,在那里被阻塞了。
  • 嗯,我知道的第一件事是,paramiko 存在导入错误,如果要连接的代码不在函数中,则会导致导入死锁。见:*.com/questions/443387/…
  • 我的理解是我的 ssh 连接是死锁的,我跟着你的线程运行了以下代码,我仍然卡住:#!/usr/bin/env/python import paramiko if name == "main": ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('fcd01.force.com',username = ' user',password = 'pwd') stdin,stdout,stderr = ssh.exec_command("pwd") print "here" print stdout.readlines() --- 挂在这里 print stderr.readlines() ssh.close()

标签: python python-2.7 python-3.x paramiko


【解决方案1】:

由于以下 SO 帖子,我通过在函数中放置连接和执行命令来解决问题:Why does Paramiko hang if you use it while loading a module?

就代码而言,您需要使用 try-catch 显式关闭连接,例如:

try:
    session.exec_command("ls")
except **some paramiko exception**:
    session.close()

但是,您的代码可以通过使用 SSHClient 来简化。

import paramiko

ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(username="user", password="pwd", hostname="fcd01.force.com", port=22)
try:
    stdin, stdout, stderr = ssh.exec_command("ls")
except SSHException:
    ssh.close()
else:
    **do something with stdout then close the connection**

如果您正在寻找一个交互式终端,您期望特定提示发出更多输入信号,例如 PowerBroker 访问(sudo 访问),则使用该 while 循环并取回字节会更好。 如果您只发送一个命令并获得响应,然后发送另一个命令并获得响应,每个命令都不会在服务器上等待另一个命令的提示,那么您绝对不需要读取块传输回的数据.

另外,请记住 SSHClient 的 exec_command() 实际上会在完成后关闭底层传输,并且每次都会创建一个新传输。您总是需要明确关闭 ssh 连接。

【讨论】:

  • 您好,我发现了一个问题并解除了死锁...问题是当我登录服务器时,在 ~/.bashrc 中我正在执行 /bin/bash。如果我执行 /bin/bash 然后执行命令,肯定有问题。一旦我删除它,代码就开始正常运行。但是,最终目标是在 bash 中运行脚本。我不知道如何继续,但至少这个问题已经解决了。
【解决方案2】:

是的,在尝试运行交互式会话时,我弄乱了 ssh 连接。现在它永久锁定。这是我通过命令行运行时的输出。

*** Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32. ***
*** Remote Python engine  is active ***
>>> import paramiko
>>> ssh = paramiko.SSHClient()
>>> print ssh
<paramiko.client.SSHClient object at 0x02EEDB10>
>>> print ssh.get_transport()
None
>>> ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
>>> ssh.connect('fcd01.force.com',username = 'user',password = 'pwd')
>>> print ssh
<paramiko.client.SSHClient object at 0x02EEDB10>
>>> print ssh.get_transport()
<paramiko.Transport at 0x2ef8f90L (cipher aes128-ctr, 128 bits) (active; 0  open channel(s))>
>>> print ssh.get_transport().is_active()
True
>>> ssh.exec_command('ls')
(<paramiko.ChannelFile from <paramiko.Channel 0 (open) window=2097152 ->    <paramiko.Transport at 0x2ef8f90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>,

>>, >>)

打印 ssh

如果我执行 stdin,stdout stderr = ssh.exec_command('ls') 然后打印 stdout.readlines(),PyScripter 挂起(或者即使我从命令提示符运行脚本,它也会挂起)。看来我首先需要断开或关闭与服务器的现有连接,但我不知道该怎么做。

ssh.exec_command('ls') 的输出在 Pyscripter 中打印了三次(3 次),这里只粘贴了一次。

【讨论】:

    最近更新 更多