I'm trying to connect to SFTP from a notebook with databricks in python. My notebook looks like this:
import pysftp
import paramiko
# set parameters
host_name = 'xx.xxx.xxx.xxx'
username = 'FTP_USERNAME'
file_path_to_rsa_key = "/path/key_rsa"
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
# connect to SFTP
sftp = pysftp.Connection(host_name, username=username, private_key=file_path_to_rsa_key, cnopts=cnopts)
data = sftp.listdir()
sftp.close()
# Prints out the directories and files, line by line
for i in data:
print(i)
I have the following error:
Oops, unhandled type 3 ('unimplemented')
when running the following block:
try:
conn = pysftp.Connection(host_name, username=username, private_key=file_path_to_rsa_key, cnopts=cnopts)
print("connection established successfully")
except:
print('failed to establish connection to targeted server')
It print connection established successfully
What does it mean? What should I do? Is the issue with listdir()?
It seems that the issue is mostly because pysftp. I end up switching entirely to paramiko and everything is working fine. The SFTP server modified the login response and pysftp was too strict in the acceptable responses to take it without trouble. I noticed something similar when I tried to use a non-RSA private key that worked fine for ssh / sftp directly but not pysftp.
There is also some interesting information here pysftp vs. Paramiko
I am writing a program using pysftp, and it wants to verify the SSH host Key against C:\Users\JohnCalvin\.ssh\known_hosts.
Using PuTTY, the terminal program is saving it to the Registry [HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys].
How do I reconcile the difference between pysftp and PuTTY?
My code is:
import pysftp as sftp
def push_file_to_server():
s = sftp.Connection(host='138.99.99.129', username='root', password='*********')
local_path = "testme.txt"
remote_path = "/home/testme.txt"
s.put(local_path, remote_path)
s.close()
push_file_to_server()
The error response I am receiving is:
E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py:61:
UserWarning: Failed to load HostKeys from C:\Users\JohnCalvin\.ssh\known_hosts. You will need to explicitly load HostKeys (cnopts.hostkeys.load(filename)) or disableHostKey checking (cnopts.hostkeys = None).
warnings.warn(wmsg, UserWarning)
Traceback (most recent call last):
File "E:\OneDrive\Python\GIT\DigitalCloud\pysftp_tutorial.py", line 14, in <module>
push_file_to_server()
File "E:\OneDrive\Python\GIT\DigitalCloud\pysftp_tutorial.py", line 7, in push_file_to_server
s = sftp.Connection(host='138.99.99.129', username='root', password='********')
File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py", line 132, in __init__
self._tconnect['hostkey'] = self._cnopts.get_hostkey(host)
File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py", line 71, in get_hostkey
raise SSHException("No hostkey for host %s found." % host) paramiko.ssh_exception.SSHException: No hostkey for host 138.99.99.129 found.
Exception ignored in: <bound method Connection.__del__ of <pysftp.Connection object at 0x00000222FF3A6BE0>>
Traceback (most recent call last):
File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py", line 1013, in __del__
self.close()
File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py", line 784, in close
if self._sftp_live:
AttributeError: 'Connection' object has no attribute '_sftp_live'
The pysftp has some bugs regarding host key handling, as described below. It also seems that the pysftp project was abandoned. Consider using Paramiko directly instead. The pysftp is just a wrapper on top of Paramiko and it does not add anything really significant. See pysftp vs. Paramiko.
For handling of host keys in Paramiko, see:
Paramiko "Unknown Server"
If you want to keep using pysftp, do not set cnopts.hostkeys = None (as the second most upvoted answer shows), unless you do not care about security. You lose a protection against Man-in-the-middle attacks by doing so.
Use CnOpts.hostkeys (returns HostKeys) to manage trusted host keys.
cnopts = pysftp.CnOpts(knownhosts='known_hosts')
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
where the known_hosts contains a server public key(s)] in a format like:
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...
If you do not want to use an external file, you can also use
from base64 import decodebytes
# ...
keydata = b"""AAAAB3NzaC1yc2EAAAADAQAB..."""
key = paramiko.RSAKey(data=decodebytes(keydata))
cnopts = pysftp.CnOpts()
cnopts.hostkeys.add('example.com', 'ssh-rsa', key)
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
Though as of pysftp 0.2.9, this approach will issue a warning, what seems like a bug:
"Failed to load HostKeys" warning while connecting to SFTP server with pysftp
An easy way to retrieve the host key in the needed format is using OpenSSH ssh-keyscan:
$ ssh-keyscan example.com
# example.com SSH-2.0-OpenSSH_5.3
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...
(due to a bug in pysftp, this does not work, if the server uses non-standard port – the entry starts with [example.com]:port + beware of redirecting ssh-keyscan to a file in PowerShell)
You can also make the application do the same automatically:
Use Paramiko AutoAddPolicy with pysftp
(It will automatically add host keys of new hosts to known_hosts, but for known host keys, it will not accept a changed key)
Though for an absolute security, you should not retrieve the host key remotely, as you cannot be sure, if you are not being attacked already.
See my article Where do I get SSH host key fingerprint to authorize the server?
It's for my WinSCP SFTP client, but most information there is valid in general.
If you need to verify the host key using its fingerprint only, see Python - pysftp / paramiko - Verify host key using its fingerprint.
One option is to disable the host key requirement:
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
sftp.put(local_path, remote_path)
You can find more info about that here:
https://stackoverflow.com/a/38355117/1060738
Important note:
By setting cnopts.hostkeys=None you'll lose the protection against Man-in-the-middle attacks by doing so. Use #martin-prikryl answer to avoid that.
Try to use the 0.2.8 version of pysftp library.
$ pip uninstall pysftp && pip install pysftp==0.2.8
And try with this:
try:
ftp = pysftp.Connection(host, username=user, password=password)
except:
print("Couldn't connect to ftp")
return False
Why this?
Basically is a bug with the 0.2.9 of pysftp
here all details
https://github.com/Yenthe666/auto_backup/issues/47
Cook book to use different ways of pysftp.CnOpts() and hostkeys options.
Source : https://pysftp.readthedocs.io/en/release_0.2.9/cookbook.html
Host Key checking is enabled by default. It will use ~/.ssh/known_hosts by default. If you wish to disable host key checking (NOT ADVISED) you will need to modify the default CnOpts and set the .hostkeys to None.
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
# do stuff here
To use a completely different known_hosts file, you can override CnOpts looking for ~/.ssh/known_hosts by specifying the file when instantiating.
import pysftp
cnopts = pysftp.CnOpts(knownhosts='path/to/your/knownhostsfile')
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
# do stuff here
If you wish to use ~/.ssh/known_hosts but add additional known host keys you can merge with update additional known_host format files by using .load method.
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys.load('path/to/your/extra_knownhosts')
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
# do stuff here
If You try to connect by pysftp to "normal" FTP You have to set hostkey to None.
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection(host='****',username='****',password='***',port=22,cnopts=cnopts) as sftp:
print('DO SOMETHING')
Connect to the server first with a Windows ssh client that uses the known_hosts file.
PuTTy stores the data in the windows registry,however OpenSSH uses the known_hosts file, and will add entries in there after you connect.
Default location for the file is %USERPROFILE%.ssh. I hope this helps
I've implemented auto_add_key in my pysftp github fork.
auto_add_key will add the key to known_hosts if auto_add_key=True
Once a key is present for a host in known_hosts this key will be checked.
Please reffer Martin Prikryl -> answer about security concerns.
Though for an absolute security, you should not retrieve the host key remotely, as you cannot be sure, if you are not being attacked already.
import pysftp as sftp
def push_file_to_server():
s = sftp.Connection(host='138.99.99.129', username='root', password='pass', auto_add_key=True)
local_path = "testme.txt"
remote_path = "/home/testme.txt"
s.put(local_path, remote_path)
s.close()
push_file_to_server()
Note: Why using context manager
import pysftp
with pysftp.Connection(host, username="whatever", password="whatever", auto_add_key=True) as sftp:
#do your stuff here
#connection closed
Hi We sort of had the same problem if I understand you well. So check what pysftp version you're using. If it's the latest one which is 0.2.9 downgrade to 0.2.8.
Check this out. https://github.com/Yenthe666/auto_backup/issues/47
FWIR, if authentication is only username & pw, add remote server ip address to known_hosts like ssh-keyscan -H 192.168.1.162 >> ~/.ssh/known_hosts for ref https://www.techrepublic.com/article/how-to-easily-add-an-ssh-fingerprint-to-your-knownhosts-file-in-linux/
I am using pysftp to upload a local file that is processed remotely, then returned to the SFTP, where I can download it. At the moment, I cannot get the code to recognize that the processed remote file has been uploaded. The code just waits forever, despite the remotely processed file successfully being uploaded.
While the code is running, if I refresh the connection on a service such as FileZilla, the code instantly recognizes the file is in and works perfectly. However, I need it to work without manually refreshing on FileZilla. I am not sure why the code cannot recognize itself that the file has been uploaded and is ready to be downloaded.
I've already tried disconnecting then re-connecting to the SFTP using a while statement, which was not successful.
import pysftp
import stat
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
srv = pysftp.Connection(host="host", username="username", password="passowrd", cnopts=cnopts)
print("Connection Made!")
# Put File In
srv.chdir(r'/path_to_remote_directory')
srv.put(r'C:\Path_to_local_file.csv')
print("File Uploaded")
while not srv.isfile(r'/Path_to_newly_uploaded_remote_file.csv'):
time.sleep(3)
print("Still Waiting")
if srv.isfile(r'/Path_to_newly_uploaded_remote_file.csv'):
print("File is Ready!")
srv.get('/Path_to_newly_uploaded_remote_file.csv', r'C:\Local_path_save_to/file.csv')
# Closes the connection
srv.close()
Just remove the /:
srv.isfile(r'/Path_to_newly_uploaded_remote_file.csv'):
->
srv.isfile(r'Path_to_newly_uploaded_remote_file.csv'):
NOTE:
Do not set cnopts.hostkeys = None,
unless you do not care about security. You lose a protection against
Man-in-the-middle attacks by doing so.
I've implemented auto_add_key in my pysftp github fork.
auto_add_key will add the key to known_hosts if auto_add_key=True
Once a key is present for a host in known_hosts this key will be checked.
Please refer to Martin Prikryl -> answer about security concerns.
Why using context manager is a good approach:
import pysftp
with pysftp.Connection(host, username="whatever", password="whatever", auto_add_key=True) as sftp:
#do your stuff here
#connection closed
EDIT:
Checked with my code and / was the problem ... please check spelling of your file and that you are in the correct working dir getcwd()_
import pysftp
import stat
import time
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None #do not do this !!!
srv = pysftp.Connection("host", username="user", password="pass", cnopts=cnopts)
print("Connection Made!")
# Put File In
srv.chdir(r'/upload')
srv.put(r'C:\Users\Fabian\Desktop\SFTP\testcsv.csv')
print("File Uploaded")
print(srv.getcwd()) #get the current folder ! <- you should looking here
while not srv.isfile(r'testcsv.csv'):
time.sleep(3)
print("Still Waiting")
if srv.isfile(r'testcsv.csv'):
print("File is Ready!")
srv.get('testcsv.csv', r'C:\Users\Fabian\Desktop\SFTP\testcsv_new.csv')
# Closes the connection
srv.close()
Found a working solution. I think it was caused by the old directory being cached. By pointing to the new directory every time for an update, it appears to work. Obvious solution now but took me a while. Posting in case anyone else runs into this.
while not srv.isfile(r'/Path_to_newly_uploaded_remote_file.csv'):
time.sleep(3)
srv.chdir(r'/Path_to_newly_uploaded_remote_file')
print("Still Waiting")
i am writing a python script that helps me download files from sftp server to my local folder.
when i run the script it just downloads the blank document
i keep on trying but i am failing
i made a sftp server to test the code and the path specified in remote path is server root directory
i giving code below
import pysftp
myHostname = "192.168.56.1"
myUsername = "new45"
myPassword = "146515"
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection(host=myHostname, username=myUsername, password=myPassword,cnopts=cnopts) as sftp:
# Define the file that you want to download from the remote directory
remoteFilePath = 'C:\\Users\\Simon\\Desktop\\ftp\\testfile.txt'
# Define the local path where the file will be saved
# or absolute "C:\Users\sdkca\Desktop\TUTORIAL.txt"
localFilePath = 'C:\\Users\\Simon\\Desktop\\ftp2\\textfile.txt'
sftp.get(remoteFilePath, localFilePath)
# connection closed automatically at the end of the with-block'''
please tell me whats the error why is blank file is being downloaded
Login to that server using any GUI SFTP client. And observe what path syntax your server is using. It's definitely not C:\Users\Simon\Desktop\ftp\testfile.txt. SFTP uses forward slashes. So it can be like /C:/Users/Simon/Desktop/ftp/testfile.txt. But even something completely different, particularly if the server or your account are chrooted.
You are probably trying to use the path syntax, which you would have used, were you directly on that target Windows system. But your SFTP server presents the files using a different path syntax. You need to adhere to that syntax.
I need some help I'm getting below message when i try to connect. The script Im executing is below. Any suggestions as to how I can fix this issue?
Also, once I get this issue fixed Im looking to add to this script the ability to listen until the result file is available and to download it from a different remote directory.
Thank you, in advance
No hostkey for host mysftpserver.com found.
Exception AttributeError: "'Connection' object has no attribute
'_sftp_live'" in <bound method Connection.__del__ of <pysftp.Connection
object at 0x101d8cd50>> ignored
Process finished with exit code 0
Script
import pysftp as sftp
def sftpExample():
try:
s = sftp.Connection(host='mysftpserver', port=1211, username='myusername', password='mypassword')
remotepath='/Orders/incoming/myfile.csv'
localpath='/Users/myusername/projects/order88.csv'
s.put(localpath,remotepath)
s.close()
except Exception, e:
print str(e)
sftpExample()
The pysftp documentation and other answers on Stack Overflow also seem to suggest that the error can be resolved by setting cnopts.hostkeys = None.
So the full code would be something like:
import pysftp
def sftpExample():
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection('hostname', username='me', password='secret', cnopts=cnopts) as sftp:
sftp.put('/Users/myusername/projects/order88.csv','/Orders/incoming/myfile.csv') # upload file to public/ on remote
sftp.close()
sftpExample()
Hope it helps!
Per the pysftp documentation you need to have the remote host key in your ~/.ssh/known_hosts. You can do this by connecting to the server via the ssh command (it will ask you if you want to add a new key to your hosts file; simply type yes if you trust the remote host's fingerprint).
The official documentation also points out how to disable host checking entirely, but this is NOT recommended as it would defeat critical security features for SSH identification.