netmiko invoke_shell installing instalar example conexion como python paramiko

python - invoke_shell - paramiko sftp



Transferencias de directorio en paramiko (8)

¿Cómo se utiliza paramiko para transferir directorios completos? Estoy tratando de usar:

sftp.put("/Folder1","/Folder2")

que me esta dando este error

Error : [Errno 21] Is a directory


Aquí está mi pieza de código:

import errno import os import stat def download_files(sftp_client, remote_dir, local_dir): if not exists_remote(sftp_client, remote_dir): return if not os.path.exists(local_dir): os.mkdir(local_dir) for filename in sftp_client.listdir(remote_dir): if stat.S_ISDIR(sftp_client.stat(remote_dir + filename).st_mode): # uses ''/'' path delimiter for remote server download_files(sftp_client, remote_dir + filename + ''/'', os.path.join(local_dir, filename)) else: if not os.path.isfile(os.path.join(local_dir, filename)): sftp_client.get(remote_dir + filename, os.path.join(local_dir, filename)) def exists_remote(sftp_client, path): try: sftp_client.stat(path) except IOError, e: if e.errno == errno.ENOENT: return False raise else: return True


Esta es mi primera respuesta . Tuve una tarea hoy que es similar a esto. Por lo tanto, traté de encontrar una forma directa de copiar una carpeta completa desde windows a linux usando python y paramiko. Después de una pequeña investigación, se me ocurrió esta solución que funciona para carpetas de tamaño más pequeño con subcarpetas y archivos en ella.

Esta solución primero crea el archivo zip para la carpeta actual (os.walk () es muy útil aquí), luego copia al servidor de destino y descomprime allí.

zipHere = zipfile.ZipFile("file_to_copy.zip", "w") for root, folders, files in os.walk(FILE_TO_COPY_PATH): for file in files: zipHere.write(os.path.join(root, file), arcname=os.path.join(os.path.relpath(root, os.path.dirname(FILE_TO_COPY_PATH)), file)) for folder in folders: zipHere.write(os.path.join(root, folder), arcname=os.path.join(os.path.relpath(root, os.path.dirname(FILE_TO_COPY_PATH)), folder)) zipHere.close() # sftp is the paramiko.SFTPClient connection sftp.put(''local_zip_file_location'',''remote_zip_file_location'') # telnet_conn is the telnetlib.Telnet connection telnet_conn.write(''cd cd_to_zip_file_location'') telnet_conn.write(''unzip -o file_to_copy.zip'')


Funciona para mí haciendo algo como esto, todas las carpetas y archivos se copian en el servidor remoto.

parent = os.path.expanduser("~") for dirpath, dirnames, filenames in os.walk(parent): remote_path = os.path.join(remote_location, dirpath[len(parent)+1:]) try: ftp.listdir(remote_path) except IOError: ftp.mkdir(remote_path) for filename in filenames: ftp.put(os.path.join(dirpath, filename), os.path.join(remote_path, filename))


No creo que puedas hacer eso. Busque la documentación de os.walk y copie cada archivo "manualmente".


Por lo que sé, Paramiko no admite la carga de archivos recursivos . Sin embargo, he encontrado una solución para la carga recursiva utilizando Paramiko aquí . Sigue un extracto de su función de carga recursiva:

def _send_recursive(self, files): for base in files: lastdir = base for root, dirs, fls in os.walk(base): # pop back out to the next dir in the walk while lastdir != os.path.commonprefix([lastdir, root]): self._send_popd() lastdir = os.path.split(lastdir)[0] self._send_pushd(root) lastdir = root self._send_files([os.path.join(root, f) for f in fls])

Puede intentar utilizar su función SCPClient.put invocando la función anterior para la carga recursiva o implementarla por su cuenta.


Puede crear una subclase de paramiko.SFTPClient y agregarle el siguiente método:

import paramiko import os class MySFTPClient(paramiko.SFTPClient): def put_dir(self, source, target): '''''' Uploads the contents of the source directory to the target path. The target directory needs to exists. All subdirectories in source are created under target. '''''' for item in os.listdir(source): if os.path.isfile(os.path.join(source, item)): self.put(os.path.join(source, item), ''%s/%s'' % (target, item)) else: self.mkdir(''%s/%s'' % (target, item), ignore_existing=True) self.put_dir(os.path.join(source, item), ''%s/%s'' % (target, item)) def mkdir(self, path, mode=511, ignore_existing=False): '''''' Augments mkdir by adding an option to not fail if the folder exists '''''' try: super(MySFTPClient, self).mkdir(path, mode) except IOError: if ignore_existing: pass else: raise

Para usarlo:

transport = paramiko.Transport((HOST, PORT)) transport.connect(username=USERNAME, password=PASSWORD) sftp = MySFTPClient.from_transport(transport) sftp.mkdir(target_path, ignore_existing=True) sftp.put_dir(source_path, target_path) sftp.close()


Puede reemplazar sftp = self.client.open_sftp() con paramiko''s one y deshacerse de libcloud aquí.

import os.path from stat import S_ISDIR from libcloud.compute.ssh import SSHClient from paramiko.sftp import SFTPError class CloudSSHClient(SSHClient): @staticmethod def normalize_dirpath(dirpath): while dirpath.endswith("/"): dirpath = dirpath[:-1] return dirpath def mkdir(self, sftp, remotepath, mode=0777, intermediate=False): remotepath = self.normalize_dirpath(remotepath) if intermediate: try: sftp.mkdir(remotepath, mode=mode) except IOError, e: self.mkdir(sftp, remotepath.rsplit("/", 1)[0], mode=mode, intermediate=True) return sftp.mkdir(remotepath, mode=mode) else: sftp.mkdir(remotepath, mode=mode) def put_dir_recursively(self, localpath, remotepath, preserve_perm=True): "upload local directory to remote recursively" assert remotepath.startswith("/"), "%s must be absolute path" % remotepath # normalize localpath = self.normalize_dirpath(localpath) remotepath = self.normalize_dirpath(remotepath) sftp = self.client.open_sftp() try: sftp.chdir(remotepath) localsuffix = localpath.rsplit("/", 1)[1] remotesuffix = remotepath.rsplit("/", 1)[1] if localsuffix != remotesuffix: remotepath = os.path.join(remotepath, localsuffix) except IOError, e: pass for root, dirs, fls in os.walk(localpath): prefix = os.path.commonprefix([localpath, root]) suffix = root.split(prefix, 1)[1] if suffix.startswith("/"): suffix = suffix[1:] remroot = os.path.join(remotepath, suffix) try: sftp.chdir(remroot) except IOError, e: if preserve_perm: mode = os.stat(root).st_mode & 0777 else: mode = 0777 self.mkdir(sftp, remroot, mode=mode, intermediate=True) sftp.chdir(remroot) for f in fls: remfile = os.path.join(remroot, f) localfile = os.path.join(root, f) sftp.put(localfile, remfile) if preserve_perm: sftp.chmod(remfile, os.stat(localfile).st_mode & 0777)


Tendrá que hacer esto como lo haría localmente con python (si no estuviera usando shutils).

Combine os.walk() , con sftp.mkdir() y sftp.put() . También es posible que desee verificar cada archivo y directorio con os.path.islink() dependiendo de si desea resolver los enlaces simbólicos o no.