paramiko SFTP在执行get命令时卡住了

3
我将使用paramiko通过SFTP获取文件。它已经连接,我可以列出目录并下载文件的前几个MB,但是之后就一直处于挂起状态,没有任何异常、错误或其他信息。以下是我的代码:
import paramiko
t = paramiko.Transport( host )
t.connect( username=uname, password=passwd )
f = paramiko.SFTPClient.from_transport( t )
print f.listdir()
f.get( fname, fname ) #it hangs on this line :\

我可以通过sftp访问该主机,但无法使用shell。

该主机包含一个文件,我需要定期获取并在Python脚本中处理。

如有任何帮助解决此问题或其他在Python中进行SFTP的替代方案,将不胜感激 :)

2个回答

5
我跟Ulfur经历了相同的问题。他在另一个答案下发布了自己的修复/解决方法,所以我决定将其作为一个正式的答案添加,以使其更加明显。
基本思路是不使用.get()方法,而是循环遍历各行。以下是Python 3 的实现。
transport = None
sftp = None

sftp_path = 'some/sftp/path'
dst_path = '/some/local/path'

try:
    transport = paramiko.Transport((SFTP_HOST, SFTP_PORT))
    transport.set_log_channel('delapi')
    transport.connect(username=SFTP_USER, password=SFTP_PASS)
    sftp = paramiko.SFTPClient.from_transport(transport)

    with sftp.open(sftp_path, 'r') as remote:
        with open(dst_path, 'w') as local:
            for line in remote:
                local.write(line)

except SSHException:
    print("SSH error")
finally:
    if sftp:
        sftp.close()
    if transport:
        transport.close()

非常感谢。我最初在使用基于paramiko构建的pysftp时也遇到了相同的症状。遵循您的方法帮助我从旧的遗留系统中下载文件。 - Leon

1
我建议你在客户端上启动Wireshark,查看协议级别上发生了什么。由于数据已加密,因此您将无法读取数据包中的数据,但是您可以看到TCP/IP级别上正在发生的事情,这可能会提供一些线索。

谢谢你的建议。我安装了Wireshark(不知道Ethereal已经被强制更改名称),并在我的程序实际下载东西的过程中运行了捕获。然而,我担心我对低级别的ssh和tcp不够熟悉,无法理解其中的意义。虽然似乎没有任何错误,但它似乎只是停止了! - Ulfur
你能否将捕获文件上传到一个服务器上,以便我们可以下载并进行检查? - Jim Garrison
请看这里:http://drop.io/ulfur_dump 希望能有所帮助,我对这个问题完全不知所措 :\ - Ulfur
您的一侧似乎正常接收和确认数据包。然后,在第1631个数据包时,它发送了一个请求数据包,但未收到服务器的响应。它等待了16秒钟,然后关闭连接。您能否查看服务器日志,看看是否有任何异常情况? - Jim Garrison
确切地说,1631数据包的等待是我所说的“挂起”。 连接关闭是因为我杀死了进程,否则它将无限期地等待。不幸的是,我无法访问有关服务器的日志,因此无法检查它们。我只有对单个目录的SFTP访问权限。我想我必须联系服务器端的支持人员并看看他们能否解决问题。如果有任何结果,我会在这里发布。 - Ulfur
好的,我没有联系客服,所以原来的问题仍未解决。但是,我一直在编码并决定尝试不同的方法。现在的代码是:import paramiko t = paramiko.Transport( host ) t.connect( username=uname, password=passwd ) f = paramiko.SFTPClient.from_transport( t ) #f.get( fname, fname ) #it hangs on this line :
local = open( fname, 'w' ) remote = f.open( fname, 'r' ) for line in remote.xreadlines(): local.write( line ) local.close() remote.close() f.close() t.close()这个可以工作,所以现在我会用它。Jim,感谢你的帮助 :)
- Ulfur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接