Cuando necesitamos mantener dos sistemas de ficheros sincronizados hay varias opciones razonables. Podemos utilizar alguna utilidad tipo rsync, o multitud de aplicaciones de propósito específico. Incluso podemos utilizar un cvs o svn para conseguir este fin. Pero cuando el “servidor remoto” solo es accesible a través de ftp las opciones se reducen bastante.
Cuando es razonable suponer que el tamaño de los datos va a ser escaso, podemos optar por hacer backups periódicos de la totalidad del sistema de ficheros, y luego restaurarlos en el sistema a mantener sincronizado. Pero cuando el sistema de ficheros va a contener ficheros grandes, eso no es una gran idea.
El script perl que se muestra a continuación no es ni mucho menos una solución general de sincronización. Tampoco considera todos los casos posibles, ni hace sincronización recursiva, pero es una solución que funciona correctamente en el escenario para el que fué creada.
El funcionamiento es muy sencillo:
El script se conecta al servidor ftp indicado en las variables de configuración.
Para cada archivo del sistema remoto comprueba si existe en el sistema local. Si no existe lo descarga. Si existe y su fecha es anterior a la instancia del sistema remoto, también lo descarga.
Para cada archivo del sistema local comprueba si existe en el sistema remoto. Si no es así, lo elimina.
Partiendo de la premisa de que en el sistema localNUNCA se realizan cambios sobre los ficheros, al final del proceso tendremos en la carpeta local una réplica del contenido del sistema remoto, minimizando las transferencias de ficheros en la medida de lo posible.
#!/usr/bin/perl -wusestrict;usewarnings;useNet::FTP;# Algunas variablesmy$host="dirección_host";my$user="usuario_ftp";my$pass="contraseña";my$local_app_root="ruta_local";my$remote_app_root="ruta_remota";# Conectamos al servidor ftpprint"Conectando al servidor $host ";my$ftp=Net::FTP->new($host,Passive=>1,Debug=>0)ordie"Imposible conectar al servidor FTP en $host";$ftp->login($user,$pass)ordie"..fallo en la autenticación $!";print"[OK]\n";# Sincronizamos las carpetas de ficherosprint"\n:::: Sincronizando Ficheros ::::\n";repo_sync($ftp,$local_app_root,$remote_app_root);# Desconectamos del ftpprint"\n\nDesconectando...";$ftp->quit;print"[OK]\n";# Funcion para sincronizar FTP<-Localsub repo_sync{my$ftp=shift;my$local_path=shift;my$remote_path=shift;my$rtime;# Obtenemos el listado de ficheros Remotos$ftp->cwd($remote_path);my@remote_files=$ftp->ls();# Bajamos todo lo nuevoformy$file(@remote_files){if(!($rtime=$ftp->mdtm($file))){# Dado quer el archivo SIEMPRE existe, y mdtm solo es false cuando el archivo no existe o # bien cuando es un directorio, en este casp estamos en un directorio. # No hacemos nada en este caso}else{# Es un fichero, comenzamos a sincronizarprint"\nSincronizando: $file\n";if(!(my$ltime=(stat("$local_path/$file"))[9])){# No existe el fichero en el repositorio localprint"-> No existe en repositorio local";print".Actualizando...";# Obtenemos el fichero por ftp$ftp->get($file,"$local_path/$file");print"[OK]";}else{# Existe el fichero en el repositorio localprint"-> Existe en repositorio local";if($rtime>$ltime){# La copia local no está al díaprint". No está al día. Actualizando...";$ftp->get($file,"$local_path/$file");print"[OK]";}else{print". Está al día";}}}}# Borramos lo que ya no está en el repositorio remoto, para ello necesitaremos iterar sobre los ficheros del sistema localmy(@local_files,$f);opendirDIR,$local_pathordie"Imposible abrir $local_path: $!\n";while($f=readdirDIR){if(-d"$local_path/$f"){# Esto son directorios. De nuevo no nos interesa tratarlos en nuestro script,# dejamos este comentario a modo de recordatorio para quien necesite # hacer algo con ellos}else{# Guardamos los ficheros en un arraypush(@local_files,$f);}}# Iteramos sobre los ficherosformy$file(@local_files){if(!($rtime=$ftp->mdtm($file))){# El archivo NO existe en el repositorio remoto, pues mdtm solo es false cuando el fichero no existe o cuando es # un directorio, caso imposible en esta rama.print"\nSincronizando: $file\n->NO existe en el repositorio. Eliminando...";unlink"$local_path/$file";print"[OK]";}}}
Espero que alguien pueda ahorrarse un rato de trabajo gracias a este post :D
Como cabe esperar, las migrations de Ruby on Rails no tienen soporte directo para crear índices fulltext. Esto es bastante lógico, porque son una característica propia de mysql, no un estándar que sigan múltiples SGBD. Sin embargo, las migrations contemplan la posibilidad de ejecutar comandos directamente contra la base de datos. La sintaxis es muy sencilla:
1
execute"comando_a_enviar_a_la_base_de_datos"
Hay que tener en cuenta que en mysql solo es posible definir índices fulltext en tablas MyISAM.Utilizando la sintáxis que acabamos de ver, un ejemplo completo de como crear una tabla con un índice fulltext quedaría de la forma siguiente:
123456
create_table("prueba",:force=>true,:options=>"ENGINE=MyISAM")do|t|t.column("titulo",:string,:limit=>50)t.column("texto",:text)endexecute"CREATE FULLTEXT INDEX FullText_texto_titulo ON prueba (titulo, texto)"
No es una solución portable, pero si es más elegante que tener un script separado para hacer este tipo de cosas.
O día xa 17 pasou, pero Galicia Global segue adiante. Xa somos 746 galegas e galegos globais espallados polo mundo, e a páxina quedará aí para que ese número creza. Moitas grazas a todos os usuarios rexistrados por participar neste proxecto!
El día 17 ha pasado, pero Galicia Global sigue adelante. Ya somos 746 gallegas y gallegos globales esparcidos por el mundo, y la página seguirá ahí para que ese número crezca. ¡Muchas gracias a todos los usuarios registrados por participar en este proyecto!