【问题标题】:Executing SFTP commands using Paramiko in Python在 Python 中使用 Paramiko 执行 SFTP 命令
【发布时间】:2019-02-19 08:27:57
【问题描述】:

我想连接到 SFTP 服务器并执行命令,例如 ls。但我收到一个错误:

paramiko.ssh_exception.SSHException: 无法打开频道。

import paramiko
import pysftp
ssh = paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

ssh.connect('xxxxxxxx', username='xxxxxxx', password='xxxxxxxx', key_filename='xxxxxxxxxxx')
stdin, stdout, stderr = ssh.exec_command('ls')
print stdout.readlines()
ssh.close()
exit()

【问题讨论】:

    标签: python sftp paramiko


    【解决方案1】:

    您似乎认为您的代码执行了 SFTP ls 命令。它不是。它尝试执行ls shell 命令。您的服务器可能甚至不允许执行 shell 命令,因此会出现错误。

    如果你想使用SFTP,你需要使用SFTPClient class和它的方法比如SFTPClient.listdir


    请注意,SFTP 协议没有像 ls 这样的文本命令。 SFTP 是一种二进制协议。您知道的命令是commands of a common SFTP client – the OpenSSH sftp。 OpenSSH sftp 将用户文本命令映射到二进制 SFTP 协议请求。与 Paramiko SFTPClient 类将对其方法的调用映射到等效的二进制 SFTP 协议请求的方式相同。

    更多详情,另见我对SSH invocation of a subsystem SFTP using command line的回复。

    【讨论】:

      【解决方案2】:

      我的问题的答案如下:

      如何读取 rsa 密钥

          pkey = paramiko.RSAKey.from_private_key_file('/Users/rajesh.maulekhi/Downloads/id_rsa')
      

      函数返回 sftp 客户端

      def multifactor_auth_sftp_client(host, port, username, key, password):
      #Create an SSH transport configured to the host
      transport = paramiko.Transport((host, port))
      #Negotiate an SSH2 session
      transport.connect()
      #Attempt authenticating using a private key
      transport.auth_publickey(username, key)
      #Create an event for password auth
      password_auth_event = threading.Event()
      #Create password auth handler from transport
      password_auth_handler = paramiko.auth_handler.AuthHandler(transport)
      #Set transport auth_handler to password handler
      transport.auth_handler = password_auth_handler
      #Aquire lock on transport
      transport.lock.acquire()
      #Register the password auth event with handler
      password_auth_handler.auth_event = password_auth_event
      #Set the auth handler method to 'password'
      password_auth_handler.auth_method = 'password'
      #Set auth handler username
      password_auth_handler.username = username
      #Set auth handler password
      password_auth_handler.password = password
      #Create an SSH user auth message
      userauth_message = paramiko.message.Message()
      userauth_message.add_string('ssh-userauth')
      userauth_message.rewind()
      #Make the password auth attempt
      password_auth_handler._parse_service_accept(userauth_message)
      #Release lock on transport
      transport.lock.release()
      #Wait for password auth response
      password_auth_handler.wait_for_response(password_auth_event)
      #Create an open SFTP client channel
      return transport.open_sftp_client()
      

      【讨论】: