When i try to download files from ftp sequentially it works perfectly
import ftplib
import os
import logging
class pyFTPDownload(object):
def __init__(self,
remote_host=None,
port=None,
username=None,
passwd=None,
input_folder=None,
output_folder=None,
ftp_conn_id=None,
timeout=10
):
super(pyFTPDownload, self).__init__()
self.remote_host = remote_host
self.port = port
self.username = username
self.passwd = passwd
self.input_folder = input_folder
self.output_folder = output_folder
self.ftp_conn_id = ftp_conn_id
self.timeout = timeout
self.client = None
def get_conn(self):
if not self.client:
logging.info('creating ftp client for conn_id: {0}'.format(self.ftp_conn_id))
if not self.username:
raise Exception("Missing required param: username")
if not self.passwd:
raise Exception("Missing required param: passwd")
if not self.remote_host:
raise Exception("Missing required param: remote_host")
if not self.ftp_conn_id:
self.ftp_conn_id = str(self.username) + '#' + str(self.remote_host) + ":" + (
str(self.port) if self.port else "")
try:
client = ftplib.FTP()
client.connect(self.remote_host, (self.port if not self.port else None))
client.login(self.username, self.passwd)
self.client = client
except ftplib.all_errors as remote_host_error:
logging.error("Auth failed while connecting to host: {0}, error: {1}"
.format(self.remote_host, remote_host_error))
except Exception as error:
logging.error("Error connecting to host: {0}, error: {1}"
.format(self.remote_host, error))
return self.client
def get_file(self, input_folder, output_folder=None,file_ext=None,thread_nbr=1):
#os.chdir(output_folder)
ftp = self.get_conn()
#print ftp.dir(input_folder)
logging.debug(input_folder)
if not os.path.exists(input_folder):
try:
os.makedirs(output_folder, 0755)
logging.debug("{0} is created".format(output_folder))
except OSError, e:
logging.error("ERROR: {0}".format(e))
logging.info(output_folder)
ftp.cwd(input_folder)
for filename in ftp.nlst(file_ext): # Loop - looking for matching files
try:
logging.debug("filename {0}".format(filename))
local_file=os.path.join(output_folder,filename)
logging.debug("local_file {0}".format(local_file))
with open(local_file, 'wb') as fhandle:
logging.debug('Getting ' + filename) # for confort sake, shows the file that's being retrieved
ftp.retrbinary('RETR ' + filename, fhandle.write)
fhandle.close()
except Exception as e:
logging.error("could not download file:{0}, terminated with error {1}".format(filename,e))
But when i tried to do the same thing in parallel i get
[Errno 9] Bad file descriptor
or when i try to decomment the following two lines
xftp.connect(self.remote_host,self.port)
xftp.login(self.username,self.passwd)
i get this error: a float is required. But without a stacktrace so i can debug it
my full code follow:
# coding=utf-8
from itertools import izip, repeat
import ftplib
import os
import multiprocessing
from pathos.multiprocessing import ProcessingPool as Pool
import logging
import traceback
class pyFTPDownload(object):
def __init__(self,
remote_host,
port,
username,
passwd,
ftp_conn_id=None
):
super(pyFTPDownload, self).__init__()
self.remote_host = remote_host
self.port = port
self.username = username
self.passwd = passwd
self.ftp_conn_id = ftp_conn_id
self.client = None
if not self.client:
logging.info('creating ftp client for conn_id: {0}'.format(self.ftp_conn_id))
if not self.username:
raise Exception("Missing required param: username")
if not self.passwd:
raise Exception("Missing required param: passwd")
if not self.remote_host:
raise Exception("Missing required param: remote_host")
if not self.ftp_conn_id:
self.ftp_conn_id = str(self.username) + '#' + str(self.remote_host) + ":" + (
str(self.port) if self.port else "")
try:
client = ftplib.FTP()
client.connect(self.remote_host, (self.port if self.port else None))
client.login(self.username, self.passwd)
self.client = client
except ftplib.all_errors as remote_host_error:
logging.error("Auth failed while connecting to host: {0}, error: {1}"
.format(self.remote_host, remote_host_error))
except Exception as error:
logging.error("Error connecting to host: {0}, error: {1}"
.format(self.remote_host, error))
def get_conn(self):
return self.client
class loadData(pyFTPDownload):
def __init__(self,
remote_host,
port,
username,
passwd,
input_folder,
output_folder,
file_ext=None,
nbr_processes=None,
ftp_conn_id = None):
super(loadData, self).__init__(remote_host,port,username,passwd)
self.input_folder=input_folder
self.output_folder=output_folder
self.file_ext=file_ext
self.nbr_processes=nbr_processes
if not input_folder:
raise Exception("Missing required params: input_folder")
if not output_folder:
raise Exception("Missing required params: output_folder")
if not file_ext:
logging.warn("All the existing files in {0} will be considered".format(input_folder))
if not nbr_processes:
logging.warn("The number of processes to be started will be set to {0}".format(Pool.ncpus))
self.nbr_processes=multiprocessing.cpu_count()
def downloadfunc(self,a):
return self.downloadf(*a)
def downloadf(self, inputf, filename, outputf):
global xftp
global local_file
global fhandle
print filename
try:
xftp = self.get_conn()
xftp.connect(self.remote_host,self.port)
xftp.login(self.username,self.passwd)
print xftp
except ftplib.all_errors as remote_host_error:
logging.error("Auth failed while connecting to host: {0}, error: {1}"
.format(self.remote_host, remote_host_error))
except Exception as error:
logging.error("Error connecting to host: {0}, error: {1}"
.format(self.remote_host, error))
try:
logging.debug("filename {0}".format(filename))
local_file = os.path.join(outputf, filename)
logging.debug("local_file {0}".format(local_file))
except Exception as sd:
logging.error("Unkmown error: {}".format(sd))
xftp.cwd(inputf)
try:
with open(local_file, 'wb') as fhandle:
logging.debug('Getting ' + filename) # for confort sake, shows the file that's being retrieved
xftp.retrbinary('RETR ' + filename, fhandle.write)
fhandle.close()
except Exception as k:
logging.error("Could not download {0} : {1}".format(local_file,k))
finally:
xftp.quit()
print traceback
def get_file(self):
print "PREPARING FILE DOWNLOAD"
print self.output_folder
if not os.path.exists(self.output_folder):
try:
logging.debug("{} does not exists".format(self.output_folder))
os.makedirs(self.output_folder,0755)
logging.debug("{0} is created".format(self.output_folder))
except OSError, e:
logging.error("ERROR:{0} could not be created {1}, {2}".format(self.output_folder,e,OSError))
except Exception as d:
logging.error(d)
ftpObj=self.get_conn()
ftpObj.cwd(self.input_folder)
files_to_dl=ftpObj.nlst(self.file_ext)
p = Pool(self.nbr_processes)
try:
p.map(self.downloadfunc, izip(repeat(self.input_folder),files_to_dl,repeat(self.output_folder)))
p.close()
p.join()
except Exception as f:
logging.error(f)
I do not have a lot of experience with python, so it would be very nice of you to check my code.
I have also some questions what is the best way to implement multiprocessing in this case?
I have found the problem with my code.
In the downloadf function and exactly in this code part
try:
xftp = self.get_conn()
xftp.connect(self.remote_host,self.port)
xftp.login(self.username,self.passwd)
print xftp
except ftplib.all_errors as remote_host_error:
logging.error("Auth failed while connecting to host: {0}, error: {1}"
.format(self.remote_host, remote_host_error))
except Exception as error:
logging.error("Error connecting to host: {0}, error: {1}"
.format(self.remote_host, error))
The problem was that i used the same ftp connection instance through, xftp = self.get_conn() and that is why i got errors that didn't seem to describe the source problem, how matter what changes did i introduce to my code to fix that.
The solution is to instantiate a new ftp connection for each process, so instead of the above line of code i do the folloying now: xftp = ftplib.FTP()
Maybe there is a kind soul that could bring a more 'pythonic' explanation to this issue. I would be gratefull
Related
I would like to save to file all my output from ssh connection(s). The ssh connection works fine, the output is ok too to a stdout. I want to create a file for every connection individually in a file. I have changed the output lines to the lines below and also moved it above
output_filename = ip_address + ".txt"
file = open(output_filename, 'w')
file.write(output.decode)
file.close()
What is missing?
I receive this error:
line 100, in fractal
except 10060:
TypeError: catching classes that do not inherit from BaseException is not allowed
And it just don't save the output. the file is created, but in blank.
import socket
import paramiko
import time
import sys
def fractal(ip, username, passwd, enapass, command, command2, command3, command4, devtype):
ip_address = ip
user = username
password = passwd
enapw = enapass
commando = command
commando2 = command2
commando3 = command3
commando4 = command4
devtype = devtype
print("Connecting to: "+ip + " on Port 22")
try:
if ip:
global ssh_client
ssh_client = paramiko.client.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip_address, username=user, password=password, compress=True, look_for_keys=False, allow_agent=False, timeout=5)
print("########################## CONNECTED TO: "+ip_address +" ##########################")
remote_connection = ssh_client.invoke_shell()
if devtype == 'CISCO':
results = remote_connection.send("term len 0\n")
print(results)
time.sleep(2)
results = remote_connection.send("show run\n")
print(results)
time.sleep(6)
if devtype == 'F5':
remote_connection.send("term len 0\n")
time.sleep(2)
remote_connection.send("sh ver\n")
time.sleep(6)
if devtype == 'LINUX':
remote_connection.send("pwd\n")
time.sleep(2)
else:
#print("Please set IP Address first!!!")
pass
if enapass:
remote_connection.send("enable\n")
# remote_connection.send("conf t\n")
remote_connection.send(enapw)
remote_connection.send("\n")
else:
pass
if command:
#remote_connection.send("show run\n")
remote_connection.send(commando)
remote_connection.send("\n")
else:
print("Command not found!")
if command2:
remote_connection.send(commando2)
remote_connection.send("\n")
else:
pass
if command3:
remote_connection.send(commando3)
remote_connection.send("\n")
else:
pass
if command4:
remote_connection.send(commando4)
remote_connection.send("\n")
else:
pass
time.sleep(1)
output = remote_connection.recv(65535)
print(output.decode())
print("########################## END OF: " + ip_address + " ##########################")
reader = ssh_client.connect
ssh_client.close
output_filename = ip_address + ".txt"
file = open(output_filename, 'w')
file.write(output)
file.close()
except TypeError:
print('Please check your settings!')
except UnboundLocalError:
print('Please check IP Address!')
except paramiko.AuthenticationException:
print(ip+": Authentication failed, please verify your credentials.")
except paramiko.SSHException as sshException:
print(ip+": Unable to establish SSH connection: %s" % sshException)
except paramiko.BadHostKeyException as badHostKeyException:
print(ip+": Unable to verify server's host key: %s" % badHostKeyException)
except socket.error:
print(ip+": Couldn't connect to server. Check IP Address and Port")
# sys.exit()
except 10060:
print(ip+": The host was not reachable")
except socket.gaierror:
print(ip+': Check IP Address')
except 11004:
print(ip+": The host was not reachable")
except IOError as e:
print("I/O error({0}): {1}".format(e.errno, e.strerror))
except ValueError:
print("Could not convert data to an integer.")
except FileNotFoundError:
print("No File was selected!")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
# countErr = paramiko.AuthenticationException
# countErr = 0
# for countErr in countErr:
# count = count + 1
# print ("Athentication failures: "+countErr)
This happens only in Python3, because except now expects a class that is a subclass of BaseException. And the integer 10060 is not.
>>> try:
... raise ValueError
... except 10080:
... print('dfsdf')
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
TypeError: catching classes that do not inherit from BaseException is not allowed
So Paramiko is raising some other error, but error handling dies when it tries to evaluate the except 10060 statement.
I have a server:
import threading
import paramiko
import subprocess
import sys
import socket
host_key = paramiko.RSAKey(filename='test_rsa.key')
class Server(paramiko.ServerInterface):
def _init_(self):
self.event = threading.Event()
def check_channel_request(self, kind, chanid):
if kind == 'session':
return paramiko.OPEN_SUCCEEDED
return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password):
if(username=='justin') and (password == 'lovesthepython'):
return paramiko.AUTH_SUCCESSFUL
return paramiko.AUTH_FAILED
server = sys.argv[1]
ssh_port = int(sys.argv[2])
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server, ssh_port))
sock.listen(100)
print '[+] Listening for connection ...'
client, addr = sock.accept()
except Exception, e:
print '[-] Listen failed: ' + str(e)
sys.exit(1)
print '[+] Got a connection!'
try:
bhSession = paramiko.Transport(client)
bhSession.add_server_key(host_key)
server = Server()
try:
bhSession.start_server(server=server)
except paramiko.SSHException, x:
print '[-] SSH Negotiation Failed'
chan = bhSession.accept(20)
print '[+] Authenticated!'
print chan.recv(1024)
chan.send('Welcome to bh_ssh')
while True:
try:
command= raw_input("Enter command: ").strip('\n')
if command != 'exit':
chan.send(command)
print chan.recv(1024) + '\n'
else:
chan.send('exit')
print 'exiting'
bhSession.close()
raise Exception ('exit')
except KeyboardInterrupt:
bhSession.close()
except Exception, e:
print '[-] Caught exception: ' + str(e)
try:
bhSession.close()
except:
pass
sys.exit(1)
My code to connect to this is:
import threading
import paramiko
import subprocess
def ssh_command(ip, port, user, passwd, command):
client = paramiko.SSHClient()
#client.load_host_keys('/home/justin/.ssh/known_hosts')
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, port, username=user, password=passwd)
ssh_session = client.get_transport().open_session()
if ssh_session.active:
ssh_session.send(command)
print ssh_session.recv(1024)
while True:
command = ssh_session.recv(1024)
try:
cmd_output = subprocess.check_output(command, shell=True)
ssh_session.send(cmd_output)
except Exception,e:
ssh_session.send(str(e))
client.close()
return
ssh_command('IP_ADDRESS_HERE',PORT_HERE,'justin','lovesthepython','id')
When I try to use these on separate PCs and use public IP addresses it won't connect. The server I bind to 0.0.0.0 and then use the public IP address of the server's computer to the client code. I imagine I am doing something fairly obvious wrong. If anyone can help, it would be very much appreciated.
Im coding a python script that connects to a remote server, and parses the returned response. For some odd reason, 9 out of 10 times, Once the header is read, the script continues and returns before getting the body of the response. Im no expert at python, but im certain that my code is correct on the python side of things. Here is my code:
class miniclient:
"Client support class for simple Internet protocols."
def __init__(self, host, port):
"Connect to an Internet server."
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(30)
try:
self.sock.connect((host, port))
self.file = self.sock.makefile("rb")
except socket.error, e:
#if e[0] == 111:
# print "Connection refused by server %s on port %d" % (host,port)
raise
def writeline(self, line):
"Send a line to the server."
try:
# Updated to sendall to resolve partial data transfer errors
self.sock.sendall(line + CRLF) # unbuffered write
except socket.error, e:
if e[0] == 32 : #broken pipe
self.sock.close() # mutual close
self.sock = None
raise e
except socket.timeout:
self.sock.close() # mutual close
self.sock = None
raise
def readline(self):
"Read a line from the server. Strip trailing CR and/or LF."
s = self.file.readline()
if not s:
raise EOFError
if s[-2:] == CRLF:
s = s[:-2]
elif s[-1:] in CRLF:
s = s[:-1]
return s
def read(self, maxbytes = None):
"Read data from server."
if maxbytes is None:
return self.file.read()
else:
return self.file.read(maxbytes)
def shutdown(self):
if self.sock:
self.sock.shutdown(1)
def close(self):
if self.sock:
self.sock.close()
self.sock = None
I use the ReadLine() method to read through the headers until i reach the empty line (Delimiter between headers and body). From there, my objects just call the "Read()" method to read the body. As stated before, 9 of 10 times, read returns nothing, or just partial data.
Example use:
try:
http = miniclient(host, port)
except Exception, e:
if e[0] == 111:
print "Connection refused by server %s on port %d" % (host,port)
raise
http.writeline("GET %s HTTP/1.1" % str(document))
http.writeline("Host: %s" % host)
http.writeline("Connection: close") # do not keep-alive
http.writeline("")
http.shutdown() # be nice, tell the http server we're done sending the request
# Determine Status
statusCode = 0
status = string.split(http.readline())
if status[0] != "HTTP/1.1":
print "MiniClient: Unknown status response (%s)" % str(status[0])
try:
statusCode = string.atoi(status[1])
except ValueError:
print "MiniClient: Non-numeric status code (%s)" % str(status[1])
#Extract Headers
headers = []
while 1:
line = http.readline()
if not line:
break
headers.append(line)
http.close() # all done
#Check we got a valid HTTP response
if statusCode == 200:
return http.read()
else:
return "E\nH\terr\nD\tHTTP Error %s \"%s\"\n$\tERR\t$" % (str(statusCode), str(status[2]))
You call http.close() before you call http.read(). Delay the call to http.close() until after you have read all of the data.
Hi Im trying to write a Python script to SSH into a remote server and execute a mysqldump. My method so far was to establish portforwarding then run a backup script I already had written. I suspect the issue is in the portforwarding as the backup script is pretty straightforward. Here is the portforwarding:
import getpass
import os
import socket
import select
import SocketServer
import sys
import paramiko
username = 'myusername'
remote_server = 'remote.servername'
remote_port = 3306
local_server = '127.0.0.1'
local_port = 3307
SSH_PORT = 22
password = None
keyfile = 'hosting.pem'
g_verbose = True
class ForwardServer (SocketServer.ThreadingTCPServer):
daemon_threads = True
allow_reuse_address = True
class Handler (SocketServer.BaseRequestHandler):
def handle(self):
try:
chan = self.ssh_transport.open_channel('direct-tcpip',
(self.chain_host, self.chain_port),
self.request.getpeername())
except Exception, e:
verbose('Incoming request to %s:%d failed: %s' % (self.chain_host,
self.chain_port,
repr(e)))
return
if chan is None:
verbose('Incoming request to %s:%d was rejected by the SSH server.' %
(self.chain_host, self.chain_port))
return
verbose('Connected! Tunnel open %r -> %r -> %r' % (self.request.getpeername(),
chan.getpeername(), (self.chain_host, self.chain_port)))
while True:
r, w, x = select.select([self.request, chan], [], [])
if self.request in r:
data = self.request.recv(1024)
if len(data) == 0:
break
chan.send(data)
if chan in r:
data = chan.recv(1024)
if len(data) == 0:
break
self.request.send(data)
chan.close()
self.request.close()
verbose('Tunnel closed from %r' % (self.request.getpeername(),))
def forward_tunnel(local_port, remote_host, remote_port, transport):
# this is a little convoluted, but lets me configure things for the Handler
# object. (SocketServer doesn't give Handlers any way to access the outer
# server normally.)
class SubHander (Handler):
chain_host = remote_host
chain_port = remote_port
ssh_transport = transport
ForwardServer(('', local_port), SubHander).serve_forever()
def verbose(s):
if g_verbose:
print s
def pforward():
paramiko.util.log_to_file('demo.log')
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
try:
client.connect(remote_server, SSH_PORT, username, key_filename=keyfile,
look_for_keys=True)
except Exception, e:
print '*** Failed to connect to %s:%d: %r' % (remote_server, SSH_PORT, e)
sys.exit(1)
verbose('Now forwarding port %d to %s:%d ...' % (local_port, remote_server, remote_port))
try:
forward_tunnel(local_port, remote_server, remote_port, client.get_transport())
except KeyboardInterrupt:
print 'C-c: Port forwarding stopped.'
sys.exit(0)
pforward()
Then once thats run this is my mysql backup script:
import MySQLdb
import os
conn = MySQLdb.connect (
host = "127.0.0.1",
user = "root",
passwd = "password"
port = 3307)
cursor = conn.cursor()
cursor.execute("SHOW DATABASES")
results = cursor.fetchall()
cursor.close()
conn.close()
print results
for result in results:
backupfile=result[0]+".sql.gz"
cmd="echo 'Back up "+result[0]+" database to yourLocation/"+backupfile+"'"
os.system(cmd)
cmd="mysqldump -u "+user+" -h "+host+" -p"+passwd+" --opt --routines --flush-privileges --single-transaction --database "+result[0]+" | gzip -9 --rsyncable > yourlocation/"+backupfile
this is the error that I get:
_mysql_exceptions.OperationalError: (2013, "Lost connection to MySQL server at 'waiting for initial communication packet', system error:
0")
Ok- so I guess I was over-thinking it, no need to set up port forwarding and all that mess. Here is the solution>
# -*- coding: utf-8 -*- # <nbformat>3.0</nbformat>
import paramiko
import os
savefile = 'dump.sql'
mykey = paramiko.RSAKey.from_private_key_file("/users/me/my-host.pem")
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('hungry.turtles.com', username = "turtles", pkey = mykey)
def ssh(cmd):
out = []
msg = [stdin, stdout, stderr] = client.exec_command(cmd)
for item in msg:
try:
for line in item:
out.append(line.strip('\n'))
except: pass
return(list(out))
dump = ssh('mysqldump -u root -ppassword turtleturds')
file = open(savefile, 'w')
file.write(str(dump))
file.close()
print 'The dump had '+ str(len(dump))+ ' lines and was saved to '+ str(os.path.realpath('dump.sql'))
I wrote a simple program to create an SSH Connection through paramiko and then execute a simple command. But it always throws an Exception error:-
Exception in thread Thread-1 (most likely raised during interpreter
shutdown): Traceback (most recent call last): File
"/usr/lib/python2.7/threading.py", line 530, in __bootstrap_inner
File "/usr/lib/python2.7/site-packages/paramiko/transport.py", line
1574, in run : 'NoneType' object has
no attribute 'error'
The program that I wrote is as follows:-
class Session:
def __init__(self, ipaddr, username, password):
self.ipaddr = ipaddr
self.username = username
self.password = password
self.connect()
def connect(self):
try:
time.sleep(1)
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.ssh.connect(self.ipaddr, username=self.username, password=self.password)
time.sleep(2)
except socket.error, e:
print e
self.ssh.close()
sys.exit()
except Exception, e:
print e
def executeCmd(self, cmd):
data = ""
try:
stdin, stdout, stderr = self.ssh.exec_command(cmd)
data = stdout.read()
except SSHException, e:
print "Error: ", e
errorMsg = "Error: %s" %traceback.format_exc()
print errorMsg
return data
def __del__(self):
self.ssh.close()
How to resolve this exception? Please help.
Thanks
Here is a Sample code I have found and used earlier and it looks fine to me.
import os
import tempfile
import paramiko
class Connection(object):
"""Connects and logs into the specified hostname.
Arguments that are not given are guessed from the environment."""
def __init__(self,
host,
username = None,
private_key = None,
password = None,
port = 22,
):
self._sftp_live = False
self._sftp = None
if not username:
username = os.environ['LOGNAME']
# Log to a temporary file.
templog = tempfile.mkstemp('.txt', 'ssh-')[1]
paramiko.util.log_to_file(templog)
# Begin the SSH transport.
self._transport = paramiko.Transport((host, port))
self._tranport_live = True
# Authenticate the transport.
if password:
# Using Password.
self._transport.connect(username = username, password = password)
else:
# Use Private Key.
if not private_key:
# Try to use default key.
if os.path.exists(os.path.expanduser('~/.ssh/id_rsa')):
private_key = '~/.ssh/id_rsa'
elif os.path.exists(os.path.expanduser('~/.ssh/id_dsa')):
private_key = '~/.ssh/id_dsa'
else:
raise TypeError, "You have not specified a password or key."
private_key_file = os.path.expanduser(private_key)
rsa_key = paramiko.RSAKey.from_private_key_file(private_key_file)
self._transport.connect(username = username, pkey = rsa_key)
def _sftp_connect(self):
"""Establish the SFTP connection."""
if not self._sftp_live:
self._sftp = paramiko.SFTPClient.from_transport(self._transport)
self._sftp_live = True
def get(self, remotepath, localpath = None):
"""Copies a file between the remote host and the local host."""
if not localpath:
localpath = os.path.split(remotepath)[1]
self._sftp_connect()
self._sftp.get(remotepath, localpath)
def put(self, localpath, remotepath = None):
"""Copies a file between the local host and the remote host."""
if not remotepath:
remotepath = os.path.split(localpath)[1]
self._sftp_connect()
self._sftp.put(localpath, remotepath)
def execute(self, command):
"""Execute the given commands on a remote machine."""
channel = self._transport.open_session()
channel.exec_command(command)
output = channel.makefile('rb', -1).readlines()
if output:
return output
else:
return channel.makefile_stderr('rb', -1).readlines()
def close(self):
"""Closes the connection and cleans up."""
# Close SFTP Connection.
if self._sftp_live:
self._sftp.close()
self._sftp_live = False
# Close the SSH Transport.
if self._tranport_live:
self._transport.close()
self._tranport_live = False
def __del__(self):
"""Attempt to clean up if not explicitly closed."""
self.close()