Executing SFTP commands using Paramiko in Python

2020-08-04 12:00发布

问题:

I want to connect to SFTP server and execute commands, like ls. But I'm getting an error:

paramiko.ssh_exception.SSHException: Unable to open channel.

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()

回答1:

Answer to my problem is as follow:

how to read rsa key

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

function resturn sftp client

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()


回答2:

It seem that you believe that your code executes SFTP ls command. It does not. It tries to execute ls shell command. Your server probably does not even allow executing shell commands, hence the error.

If you want to use SFTP, you need to use SFTPClient class and its methods like SFTPClient.listdir.


Note that SFTP protocol does not have textual commands like ls. SFTP is a binary protocol. The commands, that you know, are commands of a common SFTP client - the OpenSSH sftp. It maps user text commands to binary SFTP protocol requests. The same way Paramiko SFTPClient class maps calls to its methods to equivalent binary SFTP protocol requests.

For more details, see also my answer to SSH invocation of a subsystem SFTP using command line.