2011-11-30 96 views
5

Estoy tratando de descargar diariamente un archivo de copia de seguridad de mi servidor a mi servidor de almacenamiento local, pero tengo algunos problemas.Descargar archivos grandes a través de FTP con python

escribí este código (eliminado las partes inútiles, ya que la función de correo electrónico):

import os 
from time import strftime 
from ftplib import FTP 
import smtplib 
from email.MIMEMultipart import MIMEMultipart 
from email.MIMEBase import MIMEBase 
from email.MIMEText import MIMEText 
from email import Encoders 

day = strftime("%d") 
today = strftime("%d-%m-%Y") 

link = FTP(ftphost) 
link.login(passwd = ftp_pass, user = ftp_user) 
link.cwd(file_path) 
link.retrbinary('RETR ' + file_name, open('/var/backups/backup-%s.tgz' % today, 'wb').write) 
link.delete(file_name) #delete the file from online server 
link.close() 
mail(user_mail, "Download database %s" % today, "Database sucessfully downloaded: %s" % file_name) 
exit() 

y corro esto con un crontab como:

40 23 * * * python /usr/bin/backup-transfer.py >> /var/log/backup-transfer.log 2>&1 

Funciona con archivos pequeños, pero con los archivos de respaldo (aproximadamente 1.7Gb) se congela, el archivo descargado obtiene aproximadamente 1.2Gb y luego nunca crece (esperé alrededor de un día), y el archivo de registro está vacío.

¿Alguna idea?

p.s: im usando Python 2.6.5

+0

Para seguir solucionando el problema, quizás pueda utilizar el argumento 'callback' de' FTP.retrbinary' para recopilar más información sobre el progreso de la descarga. Además, jugar con 'maxblocksize' podría revelar algún problema de red. – jcollado

Respuesta

6

sentimos si contesto a mi propia pregunta, pero he encontrado la solución.

He probado ftputil sin éxito, por lo que He probado muchas maneras y, finalmente, esto funciona:

def ftp_connect(path): 
    link = FTP(host = 'example.com', timeout = 5) #Keep low timeout 
    link.login(passwd = 'ftppass', user = 'ftpuser') 
    debug("%s - Connected to FTP" % strftime("%d-%m-%Y %H.%M")) 
    link.cwd(path) 
    return link 

downloaded = open('/local/path/to/file.tgz', 'wb') 

def debug(txt): 
    print txt 

link = ftp_connect(path) 
file_size = link.size(filename) 

max_attempts = 5 #I dont want death loops. 

while file_size != downloaded.tell(): 
    try: 
     debug("%s while > try, run retrbinary\n" % strftime("%d-%m-%Y %H.%M")) 
     if downloaded.tell() != 0: 
      link.retrbinary('RETR ' + filename, downloaded.write, downloaded.tell()) 
     else: 
      link.retrbinary('RETR ' + filename, downloaded.write) 
    except Exception as myerror: 
     if max_attempts != 0: 
      debug("%s while > except, something going wrong: %s\n \tfile lenght is: %i > %i\n" % 
       (strftime("%d-%m-%Y %H.%M"), myerror, file_size, downloaded.tell()) 
      ) 
      link = ftp_connect(path) 
      max_attempts -= 1 
     else: 
      break 
debug("Done with file, attempt to download m5dsum") 
[...] 

En mi archivo de registro que encontré:

01-12-2011 23.30 - Connected to FTP 
01-12-2011 23.30 while > try, run retrbinary 
02-12-2011 00.31 while > except, something going wrong: timed out 
    file lenght is: 1754695793 > 1754695793 
02-12-2011 00.31 - Connected to FTP 
Done with file, attempt to download m5dsum 

Lamentablemente, tengo que volver a conectarse a FTP incluso si el archivo ha sido descargado completamente, eso en mi cas no es un problema, porque tengo que descargar también el md5sum.

Como puede ver, no he podido detectar el tiempo de espera y volver a intentar la conexión, pero cuando obtuve el tiempo de espera, simplemente volví a conectar; Si alguien sabe cómo reconectarse sin crear una nueva instancia ftplib.FTP, hágamelo saber;)

2

Usted puede tratar de establecer el tiempo de espera. Desde el docs:

# timeout in seconds 
link = FTP(host=ftp_host, user=ftp_user, passwd=ftp_pass, acct='', timeout=3600) 
2

Implementé código con ftplib que puede supervisar la conexión, volver a conectar y volver a descargar el archivo en caso de error. Detalles aquí: How to download big file in python via ftp (with monitoring & reconnect)?

+0

gracias, lo echaré un vistazo cuando encuentre algo de tiempo libre;) – Strae

+0

@roman estoy usando su script, estoy descargando un archivo de 2GB mientras ejecuté su script, se atascó cuando alcanzó el tamaño de 'dst_filesize'. – ashim888

Cuestiones relacionadas