SCP with paramiko, using different remote and local directories

11,453

Solution 1

Since the error message says 'No such file or directory', I'd first check to make sure the directory exists on remote system and is writable by the credentials you're using. The SFTPClient class has all sorts of other methods you can call to verify the existence of target paths and create them if they don't exist yet.

For example, calling the stat() method passing in the destination path should give you back a tuple the same as that returned by os.stat. Try running this script (I just hacked up a little path check routine and dropped it into your script):

#!/usr/bin/env python

import paramiko

username = ('user')
password = ('1234')
hostname = ('test-server.com')
ports = 22
localD = ('/var/tmp/testxxxxxxxx.tar.gz')
remoteD = ('/var/tmp/testxxxxxxxx.tar.gz')

def check(sftp, path):
    parts = path.split('/')
    for n in range(2, len(parts) + 1):
        path = '/'.join(parts[:n])
        print 'Path:', path,
        sys.stdout.flush()
        try:
            s = sftp.stat(path)
            print 'mode =', oct(s.st_mode)
        except IOError as e:
            print e

paramiko.util.log_to_file('/tmp/paramiko.log')
transport = paramiko.Transport((hostname, ports))
transport.connect(username = username, password = password)
sftp = paramiko.SFTPClient.from_transport(transport)
check(sftp, remoteD)

sftp.close()
transport.close()

Output should be something like this:

Path: /var mode = 040755
Path: /var/tmp mode = 040700
Path: /var/tmp/testxxxxxxxx.tar.gz [Errno 2] No such file

The mode numbers will most likely differ, but you shouldn't get "No such file" error on any of the parts of the path other than the file name. If you do, then it probably means you need to construct the path down to the point where you want to put the file using sftp.mkdir()

Solution 2

this is sftp, it's not SCP. when connecting to devices which have dropbear (such as those on OpenWRT) there is no sftp sub-system, so sftp fails. instead i use a tar command (paramiko abstracted behind the "connect" function.

i am however looking for actual SCP over paramiko and unfortunately the answer here, which is at the top of a google search, doesn't actually answer the question.

# argh argh argh dropbear on openwrt not compiled with sftp
# have to use some horribleness...

tw = connect(ipaddr, "root", server_root_password, command="tar xvf -",
             debug_level=debug_level)

tf = StringIO()
tar = tarfile.open(mode= "w:", fileobj = tf)
taradd(tar, "etc/tinc/....")
taradd(tar, ".....", ...)
taradd(tar, "....", ...)
taradd(tar, "etc/init.d/tinc", ...., ex=True)
tar.close()

tf.seek(0)
txt = tf.read()
tw.t.write(txt)
tw.t.write('^D')
tw.t.w.close()
tw.t.w = None
tw.close()

Solution 3

https://github.com/jbardin/scp.py

far from not actually answering the question which is asked, the above code provides an actual implementation of scp that is compatible with the openssh SCP protocol. personally i've not tested it with dropbear yet but it is code that actually answers the question that's in the subject line.

SCP != SFTP.

Share:
11,453
Federico Sciarretta
Author by

Federico Sciarretta

Updated on October 07, 2022

Comments

  • Federico Sciarretta
    Federico Sciarretta over 1 year

    I have a Python code that uses Paramiko.

    #!/usr/bin/env python
    
    import paramiko
    
    username = ('user')
    password = ('1234')
    hostname = ('test-server.com')
    ports = 22
    localD = ('/var/tmp/testxxxxxxxx.tar.gz')
    remoteD = ('/var/tmp/testxxxxxxxx.tar.gz')
    
    
    
    paramiko.util.log_to_file('/tmp/paramiko.log')
    transport = paramiko.Transport((hostname, ports))
    transport.connect(username = username, password = password)
    sftp = paramiko.SFTPClient.from_transport(transport)
    sftp.put(remotepath=remoteD, localpath=localD)
    
    sftp.close()
    transport.close()
    

    With this code, the local-dir and the remote-dir should be equals. if not "file not found" How can I change or use another remote-dir different to local-dir? Example:

    localD = ('/var/tmp/testxxxxxxxx.tar.gz')
    remoteD = ('/home/user/testxxxxxxxx.tar.gz')
    

    Thank you

  • Federico Sciarretta
    Federico Sciarretta about 12 years
    This directories exists: localD = ('/var/tmp/testxxxxxxxx.tar.gz') remoteD = ('/home/user/testxxxxxxxx.tar.gz') sftp.put(remotepath=remoteD, localpath=localD) Is likeI can't change the remote dir destination, if the file exist in /var/tmp, is copied in the same dir in the remote server. Maybe I must use os.path.join(os.getcwd() or something, but I don't knoe how
  • Federico Sciarretta
    Federico Sciarretta about 12 years
    Thank you John ! but if the directory exist, why I received an error for the file testxxxxxxxx.tar.gz, obviously is not in the remote server, because is the file to transfer. I must created first ??? I only need send a file via SSH.
  • John Gaines Jr.
    John Gaines Jr. about 12 years
    Is the remote machine a unix machine? If so, ssh into it using the same userid/pw from your script, cd to the destination dir and execute touch foo.bar (the key is that foo.bar doesn't exist yet, this tests your ability to write a file to that dir) if you get any errors back at all either during the cd or as a result of the touch command, you're looking at permissions issues.