Header Ads

2-Way Sync con Rclone


Hacer una sincronización bidireccional de datos (2-Way Sync), requiere un alto grado de complejidad del algoritmo, ya que debe determinar el estado actual de los archivos, incluso en algunos casos el estado anterior, verificar los tiempos de modificación, el timestamp, etc., etc. 
Muchos clientes de los diferentes servicios en la nube hacen este tipo de sincronización, pero, en Linux, son limitados respecto a su versión de Windows, o ni siquiera existen, y ni hablar de distribuciones sin escritorio. Una pesadilla. Y este problema se puede agravar, si requerimos de varios clientes para manejar múltiples servicios en la nube gratis, por las limitaciones de capacidad que tiene cada uno.
Afortunadamente, contamos con Rclone, una de esas herramientas de antaño que siempre salvan la campana, sobre todo en Linux, y con la cual podemos lograr nuestro 2-Way Sync de los principales servicios en la nube, ahorrándonos la instalación de un montón de clientes.
Para esto, Rclone cuenta con  bisync (ejecute rclone bisync --help) y también están las alternativas syncrclone o rclonesync-V2, pero son experimentales y presentan errores, lentitud, problemas de resincronización y al final puede que no obtengamos los resultados esperados, con una eventual pérdida de datos (puede encontrar una comparativa AQUÍ). Y otras, simplemente están obsoletas, descontinuadas o su desarrollo se ha detenido, como es el caso de RcloneBrowser, RcloneTray, etc. (consulte Third-Party).
Un poco de sentido común
Asumiendo que ya tenemos instalado y configurado Rclone:
# To install
sudo -v ; curl https://rclone.org/install.sh | sudo bash
# To self update
rclone selfupdate
# To config
rclone config
# To remove
local_user=$(who | head -1 | awk '{print $1;}')
sudo rm -rf /home/$local_user/.cache/rclone /home/$local_user/.config/rclone /usr/bin/rclone /usr/local/share/man/man1/rclone*
Remoto Google Drive
A continuación usaremos, a modo de ejemplo, Google Drive (puede ser cualquier otro), por tanto, dentro de la carpeta de Google Drive (que llamaremos igual que el servicio "gdrive") creamos una carpeta llamada "upload" (donde pondremos los archivos a subir al servicio en la nube) y otra llamada "download" (donde están guardados los archivos del servicio en la nube que queremos sincronizar con nuestro PC local); algo similar a lo que hacen algunos servicios en la nube, como Mega, etc. 
Y ahora creamos un bash con el siguiente contenido, le damos permisos y lo ejecutamos:
#!/bin/bash

# Rclone 2-Way Sync

# Local user with sudo privileges (no root)
local_user=$(who | head -1 | awk '{print $1;}')

# Local path for upload
upload_local="/home/$local_user/gdrive/upload"

# Local path for download
download_local="/home/$local_user/gdrive/download"

# Name of your remote in Rclone for Google Drive
remote="gdrive"

# Rclone log
rclonelog="/home/$local_user/gdrive/rclone.log"

echo "Sync gdrive to local"
# ej. download: rclone sync [directorio_remoto] [directorio_local]
rclone sync $remote:download $download_local --verbose --update --no-update-modtime --modify-window 1h --transfers 30 --checkers 8 --contimeout 60s --timeout 300s --retries 3 --low-level-retries 10 --stats 1s --stats-file-name-length 0 --log-file=$rclonelog
echo OK

echo "Sync local to gdrive"
# ej. upload: rclone sync [directorio_local] [directorio_remoto]
rclone sync $upload_local $remote:upload --verbose --update --modify-window 1h --no-update-modtime --transfers 30 --checkers 8 --contimeout 60s --timeout 300s --retries 3 --low-level-retries 10 --stats 1s --stats-file-name-length 0 --log-file=$rclonelog
echo Done
En el script anterior, se usaron los siguientes flags:
  • sync: Sincroniza el origen con el destino, cambiando solo el destino. No transfiere archivos que sean idénticos en origen y destino, probando por tamaño y tiempo de modificación o MD5SUM. El destino se actualiza para que coincida con el origen, incluida la eliminación de archivos si es necesario (excepto objetos duplicados). Si no desea eliminar archivos del destino, utilice el comando copy en su lugar.
  • --modify-window 1h: Se usa para determinar si un archivo debe actualizarse en el destino en función de las diferencias en los timestamps de modificación. Si la diferencia entre los timestamps de modificación de un archivo en el origen y el destino está dentro de la ventana de tiempo especificada, se considera que los timestamps son iguales y no se actualizará el archivo. El valor "1h" significa que se permitirá una diferencia de hasta 1 hora en los timestamps de modificación antes de que se actualice un archivo en el destino. Básicamente, sirve para compensar los desfases de tiempo entre la fuente y el backend, para backends que no admiten tiempos de modificación y, en su lugar, usan tiempos de carga. Este parámetro es opcional y normalmente se usa con --update, y el tiempo puede ser ajustado a los requerimientos del usuario. Ejemplo "1m" (un minuto).
  • --update: Esta opción asegura que solo se copien archivos si el archivo en el origen es más nuevo que el archivo existente en el destino. Esto evita copiar archivos que ya existen y no han cambiado.
  • --verbose: Habilita la salida detallada en la terminal para que puedas ver información sobre los archivos que se copian.
  • --transfers 30: Esto establece el número máximo de transferencias concurrentes a 30. Significa que Rclone puede copiar hasta 30 archivos al mismo tiempo, lo que puede acelerar el proceso de copia.
  • --checkers 8: Esto establece el número máximo de comprobadores concurrentes a 8. Los comprobadores verifican si los archivos ya existen en el destino y evitan copiarlos innecesariamente.
  • --contimeout 60s: Establece el tiempo de espera para las conexiones a 60 segundos. Si una conexión no se establece en ese tiempo, se considera un error.
  • --timeout 300s: Establece el tiempo de espera global para la operación de copia a 300 segundos. Si la operación no se completa en ese tiempo, se considera un error.
  • --retries 3: Indica que se deben realizar hasta 3 intentos de copia en caso de fallo antes de considerar la operación como fallida.
  • --low-level-retries 10: Establece el número máximo de intentos de bajo nivel a 10. Esto se refiere a los intentos de nivel más bajo para solucionar problemas de red u otros problemas.
  • --stats 1s: Muestra estadísticas cada 1 segundo mientras se ejecuta la operación de copia.
  • --stats-file-name-length 0: Esto establece la longitud máxima del nombre de archivo en las estadísticas a 0, lo que significa que se mostrarán nombres de archivo completos en las estadísticas.
  • --no-update-modtime: Evita que Rclone actualice las marcas de tiempo de modificación de los archivos en el destino durante una operación de sincronización o copia.
  • --log-file=: Especifica el archivo de log personalizado, donde se guardará la salida. También puede enviar los registros al log de Linux con la opción --syslog. También puede omitir el log y usar --progress para ver el progreso de la sincronización en tiempo real.
En algunos casos, se recomienda crear una lista para excluir o incluir archivos y directorios. Por ejemplo, a continuación una lista de exclusión de archivos problemáticos (exclude.txt):
*encryptable*
*.fuse_hidden*
*Zone.Identifier*
*goutputstream*
*.spotlight-*
*.fseventsd*
*.ds_store*
*~lock.*
*Thumbs.db*
*attributes*
Y agregar al comando propuesto en el script el siguiente flag:
# Exclude list
filter="/home/$local_user/gdrive/exclude.txt"
--exclude-from $filter --ignore-case
Nota: Tenga en cuenta que esto eliminará cualquier archivo que contenga estos patrones en mayúscula o minúscula, por tanto, pruebe primero agregando al final del comando el flag --dry-run, así verá los cambios que hará Rclone sin modificar nada (consulte filtering). O, si no quiere arriesgarse, más bien haga esta limpieza después que concluya el proceso de sincronización con un bash script (consulte Find and Destroy).
Con estas opciones se sincronizan archivos entre el remoto especificado (Google Drive) y una ubicación local, con varias opciones para controlar la operación de copia, incluyendo límites de velocidad, tiempo de espera y estadísticas detalladas, que finalmente se envían a un log, para su posterior revisión y control de cambios. Puede hacer esto mismo con cualquier otro servicio en la nube, siempre y cuando sea aceptado por Rclone.
No es necesario ejecutar este script con privilegios. Prográmelo en el crontab del usuario, para que se ejecute las veces que considere, sin embargo, no abuse de la API de algunos servicios en la nube, ya que no todos admiten sincronización en tiempo real y tampoco 2FA (Time-based One-time Password TOTP), como mega (issue 3165, aunque ya hay un borrador para su implementación). Para mayor información, consulte la documentación oficial.
Lo malo
Lo ideal sería un log que mostrara los registros de archivos y carpetas (creación, modificación, eliminación, etc) y de alertas o errores. Desafortunadamente, esto no sucede en Rclone. 
Los logs se especifican con --log-level y solo tiene 4 opciones: NOTICE, ERROR, INFO y DEBUG. Con el flag "-q", Rclone solo mostrará errores (si los hay). Con el flag "-v" Rclone mostrará NOTICE, ERROR, INFO (los dos primeros no hay casi información e INFO es limitado, e incluye bastante basura de la caché) y finalmente, si usamos la bandera flag "--vv" tendremos los 4 juntos, que incluirá la salida deseada, pero acompañada de toneladas de basura de proporciones bíblicas, llenando el log en cuestión de minutos.
2023/10/08 21:05:11 INFO  : vfs cache: cleaned: objects 2 (was 2) in use 0, to upload 0, uploading 0, total size 1.210Ki (was 1.210Ki)
2023/10/08 21:06:08 INFO  : vfs cache: cleaned: objects 1 (was 1) in use 0, to upload 0, uploading 0, total size 0 (was 0)
2023/10/08 21:06:11 INFO  : vfs cache: cleaned: objects 2 (was 2) in use 0, to upload 0, uploading 0, total size 1.210Ki (was 1.210Ki)
2023/10/08 21:07:08 INFO  : vfs cache: cleaned: objects 1 (was 1) in use 0, to upload 0, uploading 0, total size 0 (was 0)
2023/10/08 21:07:11 INFO  : vfs cache: cleaned: objects 2 (was 2) in use 0, to upload 0, uploading 0, total size 1.210Ki (was 1.210Ki)
2023/10/08 21:08:08 INFO  : vfs cache: cleaned: objects 1 (was 1) in use 0, to upload 0, uploading 0, total size 0 (was 0)
2023/10/08 21:08:11 INFO  : vfs cache: cleaned: objects 2 (was 2) in use 0, to upload 0, uploading 0, total size 1.210Ki (was 1.210Ki)
Así que no recomendamos usar syslog, en modo DEBUG y reemplazarlo por un log personalizado, que se pueda vaciar cada X tiempo con un cat /dev/null > rclone.log, o filtrarlo con grep u otra cosa, o, en el peor de los casos, no usar log, pero no es lo recomendable.
Conclusión
Entendemos que esta solución está lejos del ideal GUI que querríamos para sincronizar nuestros archivos locales y en la nube, pero, desafortunadamente, alternativas FOSS que hagan 2-Way Sync con diferentes servicios en la nube son difíciles de conseguir (por no decir imposibles) y FreeFileSync, que es a nuestro juicio es la mejor herramienta de su tipo, de momento, solo cuenta con sincronización local y Google Drive, y syncthing (con su cliente SyncTrayzor), otro buen candidato, no cuenta con sincronización en la nube, ya que solo está pensado para sincronizar datos entre PC vía p2p... y para qué seguir mencionando.
Workaround
Y si no se puede por la vía normal, siempre habrá una manera de hacerlo. Creamos un bash para montar las unidades en la nube al inicio del sistema (o creando un servicio o en fstab). Ejemplo:
crontab -e
@reboot rclone mount gdrive: $HOME/gdrive &
Nota: Algunos servicios exigen la caché activada. Por defecto, viene desactivada (off). El modo "writes" es para que los archivos se lean directamente desde el remoto y "full" para que los archivos abiertos se almacenen en caché. Ejemplo:
@reboot rclone mount pcloud: $HOME/pcloud --vfs-cache-mode writes &
También puede parametrizar el tamaño de la caché, el vaciado, etc. (consulte  vfs-file-caching
Importante: Es muy probable que si programa el comando anterior en crontab y no tiene internet al iniciar su PC, la carga del escritorio de su sistema operativo se ralentizará, ya que intenta hacer la operación y no puede completarla. En ese caso, se recomienda correr el comando en un bash script, que verifique primero si hay internet, y si hay, verifique si existe el servicio y la carpeta de montaje. Y si estas 3 condiciones se dan, entonces proceda con el montaje, caso contrario aborte y programar este script en crontab, cada X tiempo. 
Nota: Para automatizar los procesos de montaje | desmontaje de servicios y two-way sync, puede consultar los bash scripts de Rclone en nuestro repositorio Vault.
Y luego, con FreeFileSync, creamos otro bash y lo programamos en crontab para que sincronice el directorio local elegido con la unidad montada de la nube.
RealTimeSync
O con también podemos usar la herramienta  RealTimeSync (incluida en FreeFileSync) para una sincronización en tiempo real (consulte  Sincronización Espejo).

Imágenes cortesía de AOMEI
Con la tecnología de Blogger.