SCP on paramiko
import paramiko class SCPClient(paramiko.SSHClient): def read_response(self, stdout): c = ord(stdout.read(1)) if c == 0: return if c == -1: raise paramiko.SSHException("Remote scp terminated unexpectedly") if c != 1 and c != 2: raise paramiko.SSHException("Remote scp sent illegal error code") if c == 2: raise paramiko.SSHException("Remote scp terminated with error(%s)") err = stdout.readline() raise paramiko.SSHException("Remote scp terminated with error(%s)" % err) def send(self, localpath=None, remotepath=None, preserve=False, mode="0644"): if localpath is None: raise Exception("localpath must be specified") if remotepath is None: raise Exception("remotepath must be specified") if not os.path.exists(localpath): raise Exception("%s doesn't exist" % localpath) rdname = os.path.dirname(remotepath) rbname = os.path.basename(remotepath) if not rbname: rbname = os.path.basename(localpath) fsize = os.path.getsize(localpath) st = os.stat(localpath) cmd = "scp -t %s" % (remotepath) stdin, stdout, stderr = self.exec_command(cmd) if preserve: mtime = st.st_mtime atime = st.st_atime tline = "T%d %ld %d %ld\n" % ( long(mtime), long(mtime*1000000), # not sure long(atime), long(atime*1000000)) # not sure stdin.write(tline) cline = "C%s %d %s\n" % (mode, fsize, rbname) stdin.write(cline) stdin.flush() self.read_response(stdout) fh = open(localpath, "rb") while True: s = fh.read(4096) if not s: break stdin.write(s) stdin.flush() fh.close() stdin.write("\0") stdin.flush() self.read_response(stdout) stdin.write("E\n") stdin.close() # use it like: client = SCPClient() client.connect(host, username="user1", password="password1") client.send(localpath="/home/foo/foo.txt", remotepath="/home/bar/bar.txt")
I've just ported it from SSH2 implementation of Java, Ganymed. And this experimental code can only send file, not receive -:)
Read OpenSSH/scp.c for more details!
Wondering how you can get remote stderr on error occuring...