class Scenario: def __init__(self): pass # Formulaire du scénario # Par défaut, renvoie None (pas de formulaire) # Sinon, renvoie le widget Qt correspondant @property def form(self): return None # Préparation de la connexion (création instance) def setup_conec(self): print("Préparation connexion à " + self.ordinateur.ssh_address) self.conec = Connection(self.ordinateur.ssh_address, connect_timeout=2) def run(self, ordinateur): self.ordinateur = ordinateur self.setup_conec() return self.execute() # @todo Nettoyage (fermeture connexion) automatique après exécution # actuellement implémenté manuellement dans chaque scénario def execute(self): raise NotImplementedError( "La méthode execute() de ce scénario n'a pas été implémentée") # Erreurs possibles : # TimeoutError # UnexpectedExit (commande invalide ?) def close(self): print("Fermeture de la connexion avec " + self.ordinateur.ssh_address) self.conec.close()
def runMain(clientName="./posix-client", size=1024, iterations=1000000, totalConns=1): fullHosts = [ "demeter2", "demeter4", "demeter7", "demeter5", "demeter6", "demeter1" ] myHosts = fullHosts[0:totalConns] print("Using hosts: {}\n".format(myHosts)) threads = [] # Initial setup not part of the experiment for host in myHosts: conn = Connection(host) conn.run("sudo mount /opt/demeter") conn.run("sudo sysctl -w vm.nr_hugepages=512") conn.close() # Experiment runs parallel in threads for host in myHosts: newThread = myThread(host, clientName, size, iterations) newThread.start() threads.append(newThread) print("Done starting the runs!\n") for t in threads: t.join() print("Runs think they are done!\n") time.sleep(1)
def connect(host): ''' :param host: ("[email protected]", "password" or "", <port>) :return: ''' cnt_kwargs = {} if host[1]: cnt_kwargs.update({"password": host[1]}) else: cnt_kwargs.update({ "key_filename": "<ssh key>", "look_for_keys": False, }) cnt_kwargs.update({ "banner_timeout": 60, # prevent :SSHException: Error reading SSH protocol banner "compress": True, }) cnn = SSHConnection( host=host[0], port=host[2], connect_kwargs=cnt_kwargs, connect_timeout=60, # forward_agent=True # if not, rsync always error Host key verification fail ) try: yield cnn finally: cnn.close()
def __init__(self, credentials): """ credentials: ip user password """ self.user = user = credentials[1] args = dict(password=credentials[2]) conn = Connection(host=credentials[0], user=user, port=22, connect_kwargs=args) # TODO: Create a ready zip-files, which will be downloaded without the necessity to perform a lot of operations for common distros distro_info = conn.run("cat /etc/*-release", hide=True).stdout.strip() self.install_os_deps(conn, distro_info) conn.close() os.makedirs("./.known_machines", exist_ok=True) with open(f"./.known_machines/{credentials[0]}.txt", 'a+') as key_file: key_file.write("some key")
def deploy(c): remote_user = "******" remote_password = "******" remote_host = "159.65.6.97" config = Config(overrides={'sudo': {'password': remote_password}}) connect_kwarg = {'password': remote_password, 'allow_agent': False} conn = Connection(host=remote_host, user=remote_user, config=config, connect_kwargs=connect_kwarg) print("Success") conn.put("app.py") conn.put("config.json") conn.put("meal.json") conn.put("orders.json") conn.put("promo.json") conn.put("users.json") conn.put("promotions.json") print("Success!") print("Install requirements:") conn.sudo("pip3 install Flask Flask-CORS") conn.sudo("pip3 install twilio") print("Killdown") conn.sudo("pkill -F server.pid", warn=True) print("Start server") conn.sudo("nohup python3 app.py &> logs.txt & echo $! > server.pid") conn.close()
def storeids(number, username): """ Get the files for the archive. However, since this is potentially just a local test which is unable to process large amounts of files, save only a small subset. If the number is less than 1 return the full set """ connection = Connection(host=DATA_SERVER, user=username) head_command = '' if int(number) > 0: head_command = ' | head -n ' + str(number) indata = StringIO() errdata = StringIO() data = connection.run('find {} -name "*.xml" {}'.format( CORPUS_ROOT, head_command), echo=False, err_stream=errdata, out_stream=indata) if data.return_code != 0: print('Error in retrieving list of oids') errdata.seek(SEEK_SET) print(errdata.read()) Exit(-1) indata.seek(SEEK_SET) with open(join(LOCAL_DEPLOY_DIR, OID_FILE), 'w') as oid_file: while True: line = indata.readline() if not line: break oid_file.write(line) connection.close()
def stop_vid(request): print('a=', a) sleep(10) cmd = " sudo pkill motion" c = Connection(host=pi_ip, user='******', connect_kwargs={'password': '******'}) c.run(cmd) if a == 1: var = UserVids(author=request.user, postdate=timezone.now(),session=request.user.logged_in_user.session_key) os.system("mkdir ./runcode/data/videos/"+filename_global) f2save = c.get('/home/pi/runcode/data/videos/' + filename_global +'/' + f + '.mp4','./runcode/data/videos/'+filename_global+'/'+f + '.mp4') fopen = open('./runcode/data/videos/' + filename_global +'/' + f + '.mp4', 'rb') var.uservid.save('videos/'+filename_global+'/'+ f + '.mp4', File(fopen)) cmd2 = "echo rpi | sudo -S rm -rf ./runcode/data/videos" c.run(cmd2) c.close() cmd2 = " python3 /home/pi/runcode/stopit.py" p = subprocess.Popen("sshpass -p rpi ssh -p22 pi@" + pi_ip + cmd2, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) p.communicate() #os.remove(os.getcwd() + ') #return HttpResponseRedirect('/runcode/') return redirect('/runcode') else: #return HttpResponseRedirect('/runcode/') return redirect('/runcode')
def main(): hosts=[ ] upgrade_commands =[ ] commands=[ 'lscpu' ] for host in hosts: cnn = SSHConnection(host=host[0], user=host[1], port=22, connect_kwargs={'password': host[2]}) for command in commands: # hide is not show the result auto rc = cnn.run(command, hide=True) print('{} {} return_code={} stderr={} stdout={}'.format( rc.connection.host, rc.command, rc.return_code, rc.stderr, rc.stdout)) print('\n\n') cnn.close()
def deploy(c): remote_user = '******' remote_password = '******' remote_host = '178.62.2.141' config = Config(overrides={'sudo': {'password': remote_password}}) connect_kwarg = {'password': remote_password, 'allow_agent': False} conn = Connection(host=remote_host, user=remote_user, config=config, connect_kwargs=connect_kwarg) print("Connected with remote machine") print("Copy sources") conn.put("app.py") conn.put("config.json") print("Install requirements") conn.sudo("pip3 install Flask Flask-CORS") print("Shutdown previous server") conn.sudo("pkill -F server.pid", warn=True) print("Start server") conn.sudo("nohup python3 app.py &> logs.txt & echo $! > server.pid") print("Success!") conn.close()
def add_zone(self): zone_content = DNS['ZONE_TEMPLATE'].format( email='admin.' + self.zone_name, serial=self.zone_serial ) con = Connection(DNS['MASTER_SERVER'], connect_kwargs={ 'key_filename': '/root/.ssh/id_rsa'}) try: con.run("echo '{}' > /var/named/data/db.{}".format( zone_content, self.zone_name)) add_zone_cmd = ( "/usr/sbin/rndc addzone %(zone_name)s IN %(view_name)s " "\'{type master;file \"data/db.%(zone_name)s\"; allow-update " "{ 192.168.137.134; key %(key_name)s;};};\'") con.run(add_zone_cmd % { 'zone_name': self.zone_name, 'view_name': self.view_name, 'key_name': self.server.default_transfer_key.name }) # con.run('/usr/sbin/rndc reload') except UnexpectedExit as exc: logging.error('exec command failed for {}, exit code {}'.format( exc.result.command, exc.result.exited)) con.close()
def check_if_neci_completed(remote_ip, neci_work_dir, job_id): from time import sleep from datetime import datetime from fabric import Connection c = Connection(remote_ip) result = c.run('llq -j {0}'.format(job_id)) status = result.stdout.split()[19] while status != "R": if status == "I": print('Job waiting in queue') if status == "I": print('Job waiting in queue') sleep(10) result = c.run('llq -j {0}'.format(job_id)) status = result.stdout.split()[19] print('Job running ....') print('NECI is running: {0}'.format(datetime.now())) print('checking if RDMs are created ....') file_name_with_full_path = neci_work_dir + 'TwoRDM_aaaa.1' c.close() while if_file_exists_in_remote(remote_ip, file_name_with_full_path) == False: sleep(20) if if_file_exists_in_remote(remote_ip, file_name_with_full_path): print('NECI created RDMs, getting them for MOLCAS to continue') return True
def deploy(c): remote_user = '******' remote_password = '******' remote_host = '165.22.105.187' config = Config(overrides={'sudo': {'password': remote_password}}) connect_kwarg = {'password': remote_password, 'allow_agent': False} conn = Connection(host = remote_host, user=remote_user, config=config, connect_kwargs=connect_kwarg) print('Connected with remote machine') print('Copy sources') conn.put('app.py') conn.put("config.json") print("install requirements") conn.sudo("pip3 install Flask Flask-CORS") print("Shutdown previous server") conn.sudo('pkill -F server.pid', warn=True) print('Start server') conn.sudo("nohup python3 app.py &> logs.txt & echo $! > server.pid") print("Sucsess!") conn.close()
def exec_mpstat(self): try: if (self.jumpbox_ip != None): # with a jumpbox_ip, targeting a vpn gateway proxyCommand = "ssh -i " + self.jumpbox_key_filename + " -v -W " + \ self.ip + ":" + str(self.vpn_port) + " " + \ self.jumpbox_user + "@" + self.jumpbox_ip; conn = Connection(self.ip,user=self.user, port=self.vpn_port, gateway=proxyCommand, connect_kwargs={ "key_filename":self.key_filename, }, ) else: conn = Connection(self.ip,user=self.user, connect_kwargs={ "key_filename":self.key_filename, }, ) except ValueError as e: print("Value error while connecting to ",self.ip); exit(-1); current_time = datetime.datetime.utcnow().strftime("%d-%m-%Y_%H-%M-%S"); output_file = self.ip + "_mpstat_" + current_time + ".out"; self.command = "nohup " + self.command + " " + self.args[0] + output_file + self.args[1]; result = conn.run(self.command,hide=True); print(self.command,' returned ',result.exited); conn.close(); if (result.exited != 0): print('Failed to run command: ',self.command, ' Exiting..'); exit(-1);
def startCon(hostname, username, port, password): c = Connection(host=hostname, user=username, port=portnum, connect_kwargs={'password': password}) result = c.run('ifconfig re0', hide='stdout').stdout.split('\n') c.close() return result
def ssh_con_fabric(test_vars): """Create an SSH connection to the controller.""" log = logging.getLogger("ssh_con_fabric") # SSH connection/client to the public IP. pub_client = Connection(test_vars["public_ip"], user=test_vars["controller_user"], connect_kwargs={ "key_filename": test_vars["ssh_priv_key"], }) # If the controller's IP is not the same as the public IP, then we are # using a jumpbox to get into the VNET containing the controller. In that # case, create an SSH tunnel before connecting to the controller. msg_con = "SSH connection to controller ({})".format( test_vars["controller_ip"]) if test_vars["public_ip"] != test_vars["controller_ip"]: for port_attempt in range(1, 11): tunnel_local_port = get_unused_local_port() tunnel_remote_port = 22 msg_con += " via jumpbox ({0}), local port {1}".format( test_vars["public_ip"], tunnel_local_port) log.debug("Opening {}".format(msg_con)) with pub_client.forward_local( local_port=tunnel_local_port, remote_port=tunnel_remote_port, remote_host=test_vars["controller_ip"]): client = Connection("127.0.0.1", user=test_vars["controller_user"], port=tunnel_local_port, connect_kwargs={ "key_filename": test_vars["ssh_priv_key"], }) try: client.open() except NoValidConnectionsError as ex: exp_err = "Unable to connect to port {} on 127.0.0.1".format( tunnel_local_port) if exp_err not in str(ex): raise else: log.warning("{0} (attempt #{1}, retrying)".format( exp_err, str(port_attempt))) continue yield client log.debug("{} closed".format(msg_con)) break # no need to iterate again else: log.debug("Opening {}".format(msg_con)) pub_client.open() yield pub_client log.debug("Closing {}".format(msg_con)) pub_client.close()
def wait_until_running(self, public_ip=None, private_key=None): if public_ip is None: public_ip = self.public_ip if self.cloud_session is None: raise Exception( 'VM has no session associated. This is almost sure because it has not been ' 'successfully instantiated.') if self.vm_id is None: raise Exception( 'VM has no id associated. This is almost sure because it has not been ' 'successfully instantiated.') if public_ip is None: raise Exception( "VM has no public IP associated. A valid gateway to access to the machine has not been " "supplied") one = self.cloud_session.one user = self.base_user vm_id = self.vm_id public_ip = self.public_ip if private_key is None: private_key = self.private_key print("Waiting until vm with id %d and name %s is running" % (vm_id, one.vmpool.info(-1, vm_id, vm_id, -1).VM[0].NAME), end="") # ACTIVE and RUNNING while not (one.vm.info(vm_id).STATE == 3 and one.vm.info(vm_id).LCM_STATE == 3): print(".", end="") sys.stdout.flush() sleep(1) print("") print("Waiting until vm with id %d and name %s has ssh reachable" % (vm_id, one.vmpool.info(-1, vm_id, vm_id, -1).VM[0].NAME), end="") keep_trying = True connection_args = {} if private_key is not None: connection_args["connect_kwargs"] = {"key_filename": private_key} if user is not None: connection_args["user"] = user curr_conn = Connection(public_ip, **connection_args) while keep_trying: print(".", end="") sys.stdout.flush() try: curr_conn.open() curr_conn.close() keep_trying = False except paramiko.ssh_exception.NoValidConnectionsError as e: if "Unable to connect to port 22" not in str(e): raise e sleep(1) print("")
class SshWorker: """ Wrap operations at work via ssh """ def __init__(self, ip_address, private_key_path, user='******'): self.ip = ip_address self.logger = logging.getLogger('ssh_worker') self.logger.debug(f"Establishing connection to {ip_address}") self.connection = Connection( ip_address, user=user, connect_kwargs={"key_filename": [private_key_path]}) def __del__(self): self.logger.debug("Closing SSH connection") self.connection.close() def is_alive(self): retries = 5 while retries > 0: self.logger.debug( f"Trying to connect to {self.ip} ({retries} left)") retries = retries - 1 try: self.connection.open() assert self.hostname().ok except ConnectionRefusedError: self.logger.info(f"Worker {self.ip} refused connection.") time.sleep(5) except AssertionError: self.logger.info(f"Worker {self.ip} returned invalid output.") time.sleep(5) except: self.logger.info( f"Worker {self.ip} returned unknown exception.") time.sleep(5) return True def hostname(self): return self.connection.run('hostname ; whoami ; id') def bootstrap_host(self): return self.connection.run( 'export DEBIAN_FRONTEND=noninteractive; ' 'apt-get update && ' 'apt-get install --no-install-recommends -yy ' 'masscan nmap;') def masscan(self): return self.connection.run( 'export NOBANNER_TCP_PORTS="[80, 443, 8080]"; ' 'masscan -iL /tmp/targets.list' ' --open-only' ' -oJ /tmp/output.json' ' --rate 10000' ' -p 1-65535 -p U:1-65535')
def delete_zone(self): con = Connection(DNS['MASTER_SERVER'], connect_kwargs={ 'key_filename': '/root/.ssh/id_rsa'}) try: con.run('/usr/sbin/rndc delzone {}'.format(self.zone_name)) con.run('rm -rf /var/named/data/db.{}'.format(self.zone_name)) except UnexpectedExit as exc: logging.error('exec command failed for {}, exit code {}'.format( exc.result.command, exc.result.exited)) con.close()
def _connection(): connection = FabricConnection( "localhost", user=config.user_name, port=config.get_config(config.Key.ssh_port), connect_kwargs={"key_filename": config.ssh_private_key_file} ) try: yield connection finally: connection.close()
def conToLinux(self): # host='[email protected]:60022' host = '[email protected]:22' command = 'reboot' # c=Connection(host,gateway=Connection(gatewayhost,connect_kwargs={'key_filename':'/home/chry/.ssh/id_rsa'})) c = Connection( host=host, connect_kwargs={'key_filename': '/home/chry/.ssh/id_rsa'}) result = c.run(command=command) c.close()
def if_file_exists_in_remote(remote_ip, file_name_with_full_path): from fabric import Connection from patchwork.files import exists # remote_ip=os.getenv('REMOTE_MACHINE_IP') user = os.getenv('USER') c = Connection(remote_ip, user=user) if exists(c, file_name_with_full_path): c.close() return True else: c.close() return False
def main(configs): for host_config in configs: conn = Connection(host_config['host'], connect_kwargs={"password": host_config['password']}) for upload_dict in host_config['uploadList']: base_server_path = "/home/Application/fileStore/maimai/{}/default".format(upload_dict['env_no']) # 上传移动端app if 'android' in upload_dict.keys(): uploadApp(conn, upload_dict['android'], "{}/maimai.apk".format(base_server_path)) if 'ios' in upload_dict.keys(): uploadApp(conn, upload_dict['ios'], "{}/maimai.ipa".format(base_server_path)) conn.close() print('finish>>>>')
def run_py_code(self, code=None): filename = "./runcode/running/a.py" if not code: code = self.code with open(filename, "w") as f: f.write(code) c = Connection(host=pi_ip, user='******', connect_kwargs={'password': '******'}) c.put("./runcode/running/a.py", './runcode/running/a.py') c.close() self.test_py_code(filename) return self.stderr, self.stdout
class FabricProcess(multiprocessing.Process): def __init__(self, user, host, cmd, privileged): super(FabricProcess, self).__init__() self.ctx = Connection(host, user=user) self.operation = (self.ctx.sudo if (user != "root" and privileged) else self.ctx.run) self.cmd = cmd self.return_code = multiprocessing.Value("i", -1) def run(self): res = self.operation(self.cmd, shell=False, hide=True, warn=True) self.ctx.close() self.return_code.value = res.return_code
def ssh_connection(self): try: contained = Connection(host=self.f5_host, user=self.userid, connect_kwargs={'password': self.passwd}, port=self.f5_port) contained.run(self.runcmd) contained.close() return str(contained) except invoke.exceptions.UnexpectedExit: print( "\nInvoke exception occurred!\nCommand may not exist on the remote" )
def run_command(self, command, print_message=None, verbose=False): private_ip = self.get_private_ip() public_ip_login_node = self.get_public_ip() local_private = self.get_local_rsa_private() base_user = self.get_base_user() conn = Connection(host=public_ip_login_node, user=base_user, connect_kwargs={"key_filename": local_private}, forward_agent=True) if print_message is not None: print(print_message, end="") out, err = run_command_ssh_gateway(conn, base_user, private_ip, command) if verbose: print(out, err) conn.close() return out, err
class SSH(): """ SSH context manager for creating an SSH connection. On enter an SSH connection is attempted every 5 seconds until successful. An exception is raised after 5 minutes. On exit the connection is closed. Arguments: host: Host to connect to. user: User to connect with. private_key: RSA private key. """ def __init__(self, host: str, user: str, private_key: RSAKey): self.host = host self.user = user self.private_key = RSAKey.from_private_key(StringIO(private_key)) def __enter__(self): self.connection = Connection( host=self.host, user=self.user, connect_kwargs={'pkey': self.private_key}, ) logger.info(f'Waiting for SSH to become available on {self.host}...') self.wait_for_ssh(default_timer()) return self.connection def __exit__(self, type, value, traceback): logger.info(f'Closing SSH connection to {self.host}...') self.connection.close() def wait_for_ssh(self, start): try: self.connection.open() except NoValidConnectionsError: # Error after 5 minutes. Otherwise retry. now = default_timer() if now - start > 300: raise sleep(5) self.wait_for_ssh(start)
class SSH_Manager: connection = None def get_connection(self): if not self.connection: self.connection = Connection( host=c.SSH_HOSTNAME, user=c.SSH_USERNAME, connect_kwargs={"key_filename": c.SSH_KEY_PATH}, ) self.connection.config.sudo.password = c.SSH_PASSWORD return self.connection def close_connection(self): if not self.connection: return self.connection.close() self.connection = None def scp_copy(self, invoice_path, new_file_path): conn = self.get_connection() directory_exists = True with conn.cd(c.SCP_BASE_PATH): if exists(conn, new_file_path): return None directories = f'{c.SCP_BASE_PATH}/{os.path.dirname(new_file_path)}' if not exists(conn, directories): print('Directory non existent. Creating...') directory_exists = False if not directory_exists: conn.sudo(f'mkdir -p {directories}') # temporarily move te file to the user's $HOME directory filename = os.path.basename(invoice_path) tmp_file_path = f'/Users/{c.SSH_USERNAME}/{filename}' conn.put(invoice_path, tmp_file_path) conn.sudo(f'mv {tmp_file_path} {c.SCP_BASE_PATH}/{new_file_path}') return filename
def remote_connection(self): """ Remote connection context manager """ gateway = None if self._gw_host: gateway = Connection( self._gw_host, user=self._gw_user, connect_kwargs=self.connect_kwargs_gateway) conn = Connection(self._host, user=self._username, gateway=gateway, connect_kwargs=self.connect_kwargs_remote) self.log.info("Connection is created successfully.") try: yield conn finally: conn.close()
def ssh_con_fabric(test_vars): """Create an SSH connection to the controller.""" log = logging.getLogger("ssh_con_fabric") # SSH connection/client to the public IP. pub_client = Connection(test_vars["public_ip"], user=test_vars["controller_user"], connect_kwargs={ "key_filename": test_vars["ssh_priv_key"], }) # If the controller's IP is not the same as the public IP, then we are # using a jumpbox to get into the VNET containing the controller. In that # case, create an SSH tunnel before connecting to the controller. msg_con = "SSH connection to controller ({})".format( test_vars["controller_ip"]) if test_vars["public_ip"] != test_vars["controller_ip"]: tunnel_local_port = get_unused_local_port() tunnel_remote_port = 22 msg_con += " via jumpbox ({0}), local port {1}".format( test_vars["public_ip"], tunnel_local_port) log.debug("Opening {}".format(msg_con)) with pub_client.forward_local(local_port=tunnel_local_port, remote_port=tunnel_remote_port, remote_host=test_vars["controller_ip"]): client = Connection("127.0.0.1", user=test_vars["controller_user"], port=tunnel_local_port, connect_kwargs={ "key_filename": test_vars["ssh_priv_key"], }) client.open() yield client log.debug("{} closed".format(msg_con)) else: log.debug("Opening {}".format(msg_con)) pub_client.open() yield pub_client log.debug("Closing {}".format(msg_con)) pub_client.close()
class RemoteCommandExecutor: """Execute remote commands on the cluster master node.""" USERNAMES = { "alinux": "ec2-user", "centos6": "centos", "centos7": "centos", "ubuntu1404": "ubuntu", "ubuntu1604": "ubuntu", } def __init__(self, cluster): self.__connection = Connection( host=cluster.master_ip, user=self.USERNAMES[cluster.os], forward_agent=True, connect_kwargs={"key_filename": cluster.ssh_key}, ) self.__user_at_hostname = "{0}@{1}".format(self.USERNAMES[cluster.os], cluster.master_ip) def __del__(self): try: self.__connection.close() except Exception as e: # Catch all exceptions if we fail to close the clients logging.warning("Exception raised when closing remote ssh client: {0}".format(e)) def run_remote_command(self, command, log_error=True, additional_files=None, raise_on_error=True, login_shell=True): """ Execute remote command on the cluster master node. :param command: command to execute. :param log_error: log errors. :param additional_files: additional files to copy before executing script. :param raise_on_error: if True raises a RemoteCommandExecutionError on failures :param login_shell: if True prepends /bin/bash --login -c to the given command :return: result of the execution. """ if isinstance(command, list): command = " ".join(command) self._copy_additional_files(additional_files) logging.info("Executing remote command command on {0}: {1}".format(self.__user_at_hostname, command)) if login_shell: command = "/bin/bash --login -c {0}".format(shlex.quote(command)) result = self.__connection.run(command, warn=True, pty=True, hide=False) result.stdout = "\n".join(result.stdout.splitlines()) result.stderr = "\n".join(result.stderr.splitlines()) if result.failed and raise_on_error: if log_error: logging.error( "Command {0} failed with error:\n{1}\nand output:\n{2}".format( command, result.stderr, result.stdout ) ) raise RemoteCommandExecutionError(result) return result def run_remote_script(self, script_file, args=None, log_error=True, additional_files=None): """ Execute a script remotely on the cluster master node. Script is copied to the master home dir before being executed. :param script_file: local path to the script to execute remotely. :param args: args to pass to the script when invoked. :param log_error: log errors. :param additional_files: additional files to copy before executing script. :return: result of the execution. """ script_name = os.path.basename(script_file) self.__connection.put(script_file, script_name) if not args: args = [] return self.run_remote_command( ["/bin/bash", "--login", script_name] + args, log_error=log_error, additional_files=additional_files ) def _copy_additional_files(self, files): for file in files or []: self.__connection.put(file, os.path.basename(file))