library example python ssh automation scp

example - ¿Cómo copiar un archivo a un servidor remoto en Python usando SCP o SSH?



python ssh library (11)

Tengo un archivo de texto en mi equipo local que se genera mediante un script diario de Python ejecutado en cron.

Me gustaría agregar un poco de código para que ese archivo se envíe de forma segura a mi servidor a través de SSH.


Alcanzó el mismo problema, pero en lugar de "piratear" o emular la línea de comandos:

Encontré esta respuesta here .

from paramiko import SSHClient from scp import SCPClient ssh = SSHClient() ssh.load_system_host_keys() ssh.connect(''example.com'') with SCPClient(ssh.get_transport()) as scp: scp.put(''test.txt'', ''test2.txt'') scp.get(''test2.txt'')


Hay un par de formas diferentes de abordar el problema:

  1. Ajustar programas de línea de comandos
  2. use una biblioteca de Python que proporcione capacidades SSH (p. ej., Paramiko o concha retorcida )

Cada enfoque tiene sus propias peculiaridades. Tendrá que configurar las claves SSH para habilitar inicios de sesión sin contraseña si está envolviendo comandos del sistema como "ssh", "scp" o "rsync". Puede insertar una contraseña en un script utilizando Paramiko o alguna otra biblioteca, pero puede encontrar frustrante la falta de documentación, especialmente si no está familiarizado con los conceptos básicos de la conexión SSH (por ejemplo, intercambios de claves, agentes, etc.). Probablemente no hace falta decir que las claves SSH son casi siempre una mejor idea que las contraseñas para este tipo de cosas.

NOTA: es difícil de superar rsync si planea transferir archivos a través de SSH, especialmente si la alternativa es simple viejo scp.

Utilicé Paramiko con miras a reemplazar las llamadas al sistema, pero me di cuenta de que me sentía atraído por los comandos envueltos debido a su facilidad de uso y familiaridad inmediata. Usted puede ser diferente. Le di la vuelta a Conch hace algún tiempo pero no me atraía.

Si opta por la ruta de la llamada al sistema, Python ofrece una matriz de opciones, como os.system o los comandos / subprocesos. Iré con el módulo de subproceso si uso la versión 2.4+.


Llamar al comando scp través de un subproceso no permite recibir el informe de progreso dentro del script. pexpect podría usarse para extraer esa información:

import pipes import re import pexpect # $ pip install pexpect def progress(locals): # extract percents print(int(re.search(br''(/d+)%$'', locals[''child''].after).group(1))) command = "scp %s %s" % tuple(map(pipes.quote, [srcfile, destination])) pexpect.run(command, events={r''/d+%'': progress})

Ver el archivo de copia Python en la red local (linux -> linux)


Para hacer esto en Python (es decir, no envolviendo scp a través del subproceso.Popen o similar) con la biblioteca Paramiko , harías algo como esto:

import os import paramiko ssh = paramiko.SSHClient() ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts"))) ssh.connect(server, username=username, password=password) sftp = ssh.open_sftp() sftp.put(localpath, remotepath) sftp.close() ssh.close()

(Probablemente desee tratar con hosts desconocidos, errores, crear directorios necesarios, etc.).


Probablemente usaría el módulo de subproceso . Algo como esto:

import subprocess p = subprocess.Popen(["scp", myfile, destination]) sts = os.waitpid(p.pid, 0)

Donde el destination es probablemente del formulario user@remotehost:remotepath . Gracias a @Charles Duffy por señalar la debilidad en mi respuesta original, que usaba un argumento de cadena simple para especificar la operación de scp shell=True - eso no manejaría el espacio en blanco en las rutas.

La documentación del módulo contiene ejemplos de verificación de errores que es posible que desee realizar junto con esta operación.

Asegúrese de haber configurado las credenciales adecuadas para que pueda realizar un scp desatendido sin contraseña entre las máquinas . Ya hay una pregunta de para esto .


Si quieres un enfoque simple, esto debería funcionar.

Querrá ".close ()" el ​​archivo primero para que sepa que está en el disco de Python.

import os os.system("scp FILE USER@SERVER:PATH") #e.g. os.system("scp foo.bar [email protected]:/path/to/foo.bar")

Necesita generar (en la máquina fuente) e instalar (en la máquina de destino) una clave ssh de antemano para que el scp se autentique automáticamente con su clave ssh pública (en otras palabras, para que su script no solicite una contraseña) .

Ejemplo de ssh-keygen


Tipo de hacky, pero el siguiente debería funcionar :)

import os filePath = "/foo/bar/baz.py" serverPath = "/blah/boo/boom.py" os.system("scp "+filePath+" [email protected]:"+serverPath)


un enfoque muy simple es el siguiente:

import os sshpass -p "password" scp user@host:/path/to/file ./

no se requiere ninguna biblioteca de Python (solo sistema operativo) y funciona


fabric se puede usar para cargar archivos vis ssh:

#!/usr/bin/env python from fabric.api import execute, put from fabric.network import disconnect_all if __name__=="__main__": import sys # specify hostname to connect to and the remote/local paths srcdir, remote_dirname, hostname = sys.argv[1:] try: s = execute(put, srcdir, remote_dirname, host=hostname) print(repr(s)) finally: disconnect_all()


sshfs para montar el directorio remoto a través de ssh y shutil para copiar los archivos:

$ mkdir ~/sshmount $ sshfs user@remotehost:/path/to/remote/dst ~/sshmount

Luego en Python:

import shutil shutil.copy(''a.txt'', ''~/sshmount'')

Este método tiene la ventaja de que puede transmitir datos si está generando datos en lugar de almacenar en caché localmente y enviar un solo archivo grande.


from paramiko import SSHClient from scp import SCPClient import os ssh = SSHClient() ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts"))) ssh.connect(server, username=''username'', password=''password'') with SCPClient(ssh.get_transport()) as scp: scp.put(''test.txt'', ''test2.txt'')