Почему Paramiko поднимает EOFError (), когда объект SFTP хранится в словаре?

у меня проблемы с приложением, которое я пишу, которое загружает и загружает файлы в и из других ящиков через SSH. Проблема, которую я испытываю, заключается в том, что я могу получить (скачать) файлы просто отлично, но когда я пытаюсь поместить (загрузить) их на другой сервер, я получаю исключение EOFError (). Когда я посмотрел на _write_all () в paramikosftp.py казалось, что ошибка была вызвана, когда он не мог записать какие-либо данные в поток? У меня нет опыта сетевого программирования, поэтому, если кто-то знает, что он пытается я был бы признателен, если бы вы сделали и могли сообщить мне это.

Я написал упрощенную версию функции, которая обрабатывает мои соединения как ssh (). runCommand() показывает, как загрузка не выполняется в моем приложении, а simpleTest() показывает, как работает sftp put, но я не вижу никакой разницы между runCommand() и simpleTest (), кроме того, как хранятся мои объекты SFTP. Один хранится в словаре, а другой сам по себе. Кажется, если бы словарь был проблемой, что загрузка файлов не будет работать, но это не так.

кто-нибудь знает, что может вызвать такое поведение или может рекомендовать другой способ управления моими соединениями, если этот способ вызывает проблемы?

Я использую Python 2.7 с Paramiko 1.7.6. Я протестировал этот код как на Linux, так и на Windows и получил те же результаты.

EDIT: код включен сейчас.

import os
import paramiko

class ManageSSH:
     """Manages ssh connections."""
    def __init__(self):
        self.hosts = {"testbox": ['testbox', 'test', 'test']}
        self.sshConnections = {}
        self.sftpConnections = {}
        self.localfile = "C:testfile"
        self.remotefile = "/tmp/tempfile"
        self.fetchedfile = "C:tempdl"

    def ssh(self):
        """Manages ssh connections."""
        for host in self.hosts.keys():
            try:
                self.sshConnections[host]
                print "ssh connection is already open for %s" % host
            except KeyError, e:         # if no ssh connection for the host exists then open one
                # open ssh connection
                ssh = paramiko.SSHClient()
                ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                ssh.connect(self.hosts[host][0], 22, self.hosts[host][1], self.hosts[host][2])
                self.sshConnections[host] = ssh
                print "ssh connection to %s opened" % host
            try:
                self.sftpConnections[host]
                print "sftp connection is already open for %s" % host
            except KeyError, e:
                # open sftp connection
                ssh = paramiko.SSHClient()
                ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                ssh.connect(self.hosts[host][0], 22, self.hosts[host][1], self.hosts[host][2])
                self.sftpConnections[host] = ssh.open_sftp()
                print "sftp connection to %s opened" % host

    def runCommand(self):
        """run commands and return output"""
        for host in self.hosts:
            command = "if [ -d /tmp ]; then echo -n 1; else echo -n 0; fi"
            stdin, stdout, stderr = self.sshConnections[host].exec_command(command)
            print "%s executed on %s" % (command, host)
            print "returned %s" % stdout.read()
            self.sftpConnections.get(self.remotefile, self.fetchedfile)
            print "downloaded %s from %s" % (self.remotefile, host)
            self.sftpConnections[host].put(self.localfile, self.remotefile)
            print "uploaded %s to %s" % (self.localfile, host)
            self.sftpConnections[host].close()
            self.sshConnections[host].close()

    def simpleTest(self):
        host = "testbox"
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(host, 22, 'test', 'test')
        sftp = ssh.open_sftp()
        print "sftp connection to %s opened" % host
        sftp.get(self.remotefile, self.fetchedfile)
        print "downloaded %s from %s" % (self.localfile, host)
        sftp.put(self.localfile, self.remotefile)
        print "uploaded %s to %s" % (self.localfile, host)
        sftp.close()

if __name__ == "__main__":
    test = ManageSSH()
    print "running test that works"
    test.simpleTest()
    print "running test that fails"
    test.ssh()
    test.runCommand()

выход:

running test that works
sftp connection to testbox opened
downloaded C:testfile from testbox
uploaded C:testfile to testbox
running test that fails
ssh connection to testbox opened
sftp connection to testbox opened
if [ -d /tmp ]; then echo -n 1; else echo -n 0; fi executed on testbox
returned 1
downloaded /tmp/tempfile from testbox
Traceback (most recent call last):
  File "paramikotest.py", line 71, in <module>
    test.runCommand()
  File "paramikotest.py", line 47, in runCommand
    self.sftpConnections[host].put(self.localfile, self.remotefile)
  File "C:Python27libsite-packagesparamikosftp_client.py", line 561, in put

    fr = self.file(remotepath, 'wb')
  File "C:Python27libsite-packagesparamikosftp_client.py", line 245, in open
    t, msg = self._request(CMD_OPEN, filename, imode, attrblock)
  File "C:Python27libsite-packagesparamikosftp_client.py", line 627, in _request
    num = self._async_request(type(None), t, *arg)
  File "C:Python27libsite-packagesparamikosftp_client.py", line 649, in _async_request
    self._send_packet(t, str(msg))
  File "C:Python27libsite-packagesparamikosftp.py", line 172, in _send_packet
    self._write_all(out)
  File "C:Python27libsite-packagesparamikosftp.py", line 138, in _write_all

    raise EOFError()
EOFError

3 ответов


я смог решить свою проблему. Я должна была использовать Парамико.Транспорт, а затем создание SFTPClient С paramiko.SFTPClient.from_transport(t) вместо open_sftp() С SSHClient().

работает следующий код:

t = paramiko.Transport((host, 22))  
t.connect(username=username, password=password)  
sftp = paramiko.SFTPClient.from_transport(t)

Как я вижу, с ssh=SSHClient () вы создаете Sshclient-объект, а затем с sftp=ssh.open_sftp () вы создаете sftp-объект. хотя вы хотите использовать sftp, вы храните ssh в локальной переменной, которая затем получает gc'D, но, если ssh является gc'D, sftp волшебным образом перестает работать. не знаю почему, но попробуйте сохранить ssh на время вашей жизни sftp.


после прочтения вашего редактирования, я думаю, проблема здесь

stdin, stdout, stderr = self.sshConnections[host].exec_command(command)

эта строка, по-видимому, отключает ftp-вещь

редактировать