¿Qué es Rsync?

Hoy me preguntaba un amigo un poco confuso con el funcionamiento de rsync, dado que las copias le estaban tardando mucho en hacerse. Rsync es un programa de sincronización de archivos con multitud de opciones y uno de mis preferidos a la hora de transferir información de un lado a otro, tanto en local como entre diferentes servidores. Dispone de dos modos de funcionamiento básicos:

Rsync Local

Rsync funcionará como una herramienta de copiado normal entre el origen y destino locales que se indiquen. En este modo, rsync copia la totalidad de archivos, al presuponerse que es más rápido copiar la información que calcular diferencias entre origen y destino. Esto se aplica igualmente cuando nuestras rutas locales son puntos de montaje por red.

Rsync Remoto

  • Rsync como demonio: Rsync realizará las transferencias utilizando el puerto TCP/873. El demonio RSYNC puede ser ejecutado de forma independiente o mediante la utilización de inetd.
  • Rsync en una shell remota: Rsync utilizará una shell remota como ssh o rsh para ejecutar rsync una vez se haya logado en el equipo remoto.

¿Cómo funciona Rsync?

De forma básica, comenzaremos con que la sintaxis de rsync es de la forma:

rsync -opciones origen destino

Rsync puede realizar transferencias de archivos dentro de nuestros dispositivos locales, por ejemplo:

javi@trabajo:/tmp/rsync$ ls -la
total 1000072
drwxrwxr-x 2 javi javi 4096 jun 8 11:28 .
drwxrwxrwt 21 root root 61440 jun 8 11:28 ..
-rw-rw-r-- 1 javi javi 1024000000 jun 8 11:28 archivo1
javi@trabajo:/tmp/rsync$ rsync archivo1 archivo2
javi@trabajo:/tmp/rsync$ ls -la
total 2000076
drwxrwxr-x 2 javi javi 4096 jun 8 11:29 .
drwxrwxrwt 21 root root 61440 jun 8 11:28 ..
-rw-rw-r-- 1 javi javi 1024000000 jun 8 11:28 archivo1
-rw-rw-r-- 1 javi javi 1024000000 jun 8 11:29 archivo2

Rsync también puede realizar transferencias de archivos entre diferentes hosts, siempre que entre ellos tengan visibilidad usando red y utilizará por defecto el servicio SSH como medio de transporte para mover los datos. Es importante saber que aunque tengamos SSH instalado en ambos equipos, RSYNC es un paquete diferente por lo que debemos asegurarnos de que rsync está instalado incluso aun teniendo un servidor ssh funcionando.

javi@trabajo:/tmp/rsync$ rsync -e "ssh -p 1234" archivo1 usuario@host.dominio:/tmp/
javi@trabajo:/tmp/rsync$

Fíjate que cuando especificamos hosts remotos, tanto en origen como en destino, utilizamos el formato usuario[arroba]host[dos puntos]ruta.

En los ejemplos anteriores hemos visto como funciona rsync de forma totalmente básica. Ahora veremos otras opciones de rsync que pueden hacer mucho más detallada y versátil su utilización.

Ventajas de Rsync

Rsync nos proporciona una interesante lista de opciones que le hacen especialmente adecuado para transferencias repetitivas (o puntuales)

  • Soporta el copiado de permisos de usuarios, grupos, así como enlaces y dispositivos
  • Dispone de opciones de exclusión similares a las de tar.
  • No necesita privilegios de root (salvo que sean necesarias para acceder a los orígenes o destinos)
  • Soporta la utilización de claves públicas para transferencias automatizadas.
  • Si utilizamos el transporte mediante SSH, nuestra transferencia es cifrada de forma automática, dándole mayor seguridad.

Opciones de Rsync

A modo de cheatsheet de opciones, dejo aquí las siguientes opciones que utilizo de forma más o menos habitual y que creo que pueden ser utiles a la hora de usar rsync.

-r
Aplica recursividad al origen de la copia. Se lleva los archivos y directorios que están dentro de la ruta que marquemos como origen.

-u
Modo de actualización, tan sólo se lleva los archivos que sean más nuevos en el origen que en el destino.

-o -g
Transfiere la propiedad de usuario (-o) y grupo (-g). Esto se aplica a los números de UID, no al nombre de usuario concreto. Si en nuestro origen el usuario con UID 3333 es pepito y en el destino el UID 3333 corresponde a javierin, habrá un problema de permisos ya que javierín de repente pasará a tener control sobre esos datos.

-X
Transferir atributos extendidos que tengan aplicados los archivos

-p
Transfiere los permisos del archivo (diferente a la propiedad del mismo)

-t
Conserva las fechas de modificación, haciendo que rsync marque en el destino la misma fecha de modificación que tenía el archivo en origen.

-l
Conserva los enlaces simbólicos copiándolos como tales y apuntando al mismo destino, exista o no.

-D
Copia dispositivos especiales

-S
Manejar archivos sparse de forma eficiente, de tal manera que si tenemos un archivo sparse que tiene marcados 4GB como tamaño pero solo usa 100MB, lo transfiera con mayor efectividad.

-x
No cruzar filesystems. Es útil cuando tenemos un punto de montaje dentro de nuestro origen y no queremos llevarnos su contenido.

--remove-source-files
Elimina los archivos del <strong>ORIGEN</strong> una vez copiados. Interesante a la hora de archivados.

--delete
Borrará los archivos que haya en <strong>DESTINO</strong> y que no estén en origen. Útil para mantener una copia exacta 1:1 del origen )

-z
Aplica compresión a los datos durante la transferencia. Muy util si se transfieren logs.

--progress
Mostrará información del archivo que se está transfiriendo, así como del tiempo que se espera que tardará la transferencia en terminar. Si no hay cambios en los archivos, --progress no mostrará nada.

-e
Permite especificar opciones al comando que usaremos de shell remota. Por ejemplo, si tenemos el servidor ssh remoto en el puerto 1234, ejecutaremos
rsync -e "ssh -p 1234" -otrasopciones origen destino

-a
Esta es una metaopción, que activa de golpe las opciones -rlptgoD.

-W
Esta opción activa la copia completa de los archivos, para que no haya que dedicar tiempo a calcular los diferenciales.

-c
Esta opción desactiva la comprobación de checksum de datos, es decir, solo utiliza fecha de modificación y tamaño para determinar si un archivo se transfiere o no.

Por lo general, un rsync -avz –progress origen destino es una buena elección a la hora de utilizar rsync.

¿Qué transfiere Rsync?

Rsync realiza una comparación de tamaño y fecha de modificación antes de comenzar a transferir un fichero. Si ambos son iguales, considera el archivo no-cambiado y lo ignora. (Esto puede llevar a problemas si la aplicación que genera o modifica los archivos mantiene siempre la misma fecha de modificación).

Si encuentra cambios en tamaño o fecha de modicación, rsync actúa diferente en caso de funcionamiento local o remoto.

Rsync local con modificaciones

Dado que comparar los archivos para copiar en local puede ser más lento que copiarlos completos, rsync copiará la totalidad del archivo. Veamos un ejemplo:

Partimos de un archivo de 100M y realizamos la copia con rsync a un nuevo archivo2.

javi@trabajo:/tmp/rsync$ rsync -av --progress archivo1 archivo2
sending incremental file list
archivo1
102,400,002 100% 287.98MB/s 0:00:00 (xfr#1, to-chk=0/1)

sent 102,425,105 bytes received 35 bytes 68,283,426.67 bytes/sec
total size is 102,400,002 speedup is 1.00

En el resumen podemos ver que se han transferido los 100 megas completos. Esto es normal ya que archivo2 no existía en esta prueba.

Inmediatamente, añadimos un 0 a archivo1, para que cambie su tamaño y fecha de modificación.

javi@trabajo:/tmp/rsync$ echo "0" >> archivo1

Ahora repetimos el rsync

javi@trabajo:/tmp/rsync$ rsync -av --progress archivo1 archivo2
sending incremental file list
archivo1
102,400,004 100% 233.00MB/s 0:00:00 (xfr#1, to-chk=0/1)

sent 102,425,107 bytes received 35 bytes 68,283,428.00 bytes/sec
total size is 102,400,004 speedup is 1.00

Como podemos ver, se han copiado la totalidad de los 100 MB que ocupa el archivo, aunque solo se hayan modificado 4 bytes.

Rsync Remoto con modificaciones

Partiremos del archivo de 100MB y 4 bytes que nos ha quedado de la prueba anterior. Haremos un rsync inicial a remoto, por red.

javi@trabajo:/tmp/rsync$ rsync -av --progress archivo1 usuario@host:/tmp/
sending incremental file list
archivo1
102,400,000 100% 1.36MB/s 0:01:12 (xfr#1, to-chk=0/1)

sent 102,425,098 bytes received 35 bytes 1,374,834.00 bytes/sec
total size is 102,400,000 speedup is 1.00

Inmediatamente, añadimos un caracter al origen (realmente 2 porque estoy añadiendo un salto de línea al final del echo).

javi@trabajo:/tmp/rsync$ echo "0" >> archivo1

Volvemos a realizar exactamente la misma copia que anteriormente

javi@trabajo:/tmp/rsync$ rsync -av --progress archivo1 usuario@host:/tmp/
sending incremental file list
archivo1
102,400,002 100% 219.92MB/s 0:00:00 (xfr#1, to-chk=0/1)

sent 46,501 bytes received 70,928 bytes 46,971.60 bytes/sec
total size is 102,400,002 speedup is 872.02

En el resumen de la transferencia vemos como rsync solo ha necesitado enviar 46KB en vez de todos los 100MB del archivo.

Como puedes ver, rsync se comporta de forma diferente en local que en remoto. Esto tiene como finalidad ahorrar ancho de banda y tiempos de transferencia, que tradicionalmente en transferencias por red son más costosos, tanto en dinero, como en tiempo.

¿Conviene usar la compresión con rsync?

La respuesta rápida es: Depende de lo que vayas a transferir.

En local, casi seguramente no te conviene usarla porque te ralentizará, ya que el cuello de botella en LAN suele ser la CPU de origen comprimiendo.

En remoto, depende de tus datos, la velocidad de la línea y los recursos de CPU que tengas libres:

  • Datos multimedia o ya comprimidos – Obtendrás poca compresión con este tipo de datos
  • Datos de texto sin comprimir – Activa siempre la compresión para ahorrar tiempo.
  • Línea muy lenta o con velocidad muy variable –  Cada byte que puedas ahorrarte transferír acortará los tiempos de copia, activa la compresión.
  • Línea muy rápida – Ten cuidado al activar la compresión en una línea rápida, ya que usarás muchos más recursos de compresión al poder enviar los datos más rápido. En estos casos el cuello de botella puede llegar a ser la propia CPU.
  • Veamos una comparativa a continuación:

Para las pruebas de datos aleatorios he generado un archivo de 100MB con datos pseudoaleatorios de /dev/urandom.

Rsync de datos aleatorios sin compresion

javi@trabajo:/tmp/rsync$ rsync -av --progress archivo1 usuario@host:/tmp/
sending incremental file list
archivo1
102,400,000 100% 2.02MB/s 0:00:48 (xfr#1, to-chk=0/1)

sent 102,425,099 bytes received 35 bytes 2,028,220.48 bytes/sec
total size is 102,400,000 speedup is 1.00

Rsync de datos aleatorios con compresion

javi@trabajo:/tmp/rsync$ rsync -avz --progress archivo1 root@host:/tmp/
sending incremental file list
archivo1
102,400,000 100% 1.44MB/s 0:01:07 (xfr#1, to-chk=0/1)

sent 102,458,413 bytes received 35 bytes 1,474,222.27 bytes/sec
total size is 102,400,000 speedup is 1.00

Para las pruebas de rsync con texto, he utilizado un archivo txt con el quijote repetido 47 veces (que hacen aproximadamente 100 MB)

Rsync de texto sin compresión

javi@trabajo:/tmp/rsync$ rsync -av --progress 100M-quijote.txt usuario@host:/tmp/
sending incremental file list
100M-quijote.txt
103,349,569 100% 2.73MB/s 0:00:36 (xfr#1, to-chk=0/1)

sent 103,374,904 bytes received 35 bytes 2,756,665.04 bytes/sec
total size is 103,349,569 speedup is 1.00

Rsync de texto con compresión

javi@trabajo:/tmp/rsync$ rsync -avz --progress 100M-quijote.txt usuario@host:/tmp/
sending incremental file list
100M-quijote.txt
103,349,569 100% 5.92MB/s 0:00:16 (xfr#1, to-chk=0/1)

sent 38,253,783 bytes received 35 bytes 2,067,773.95 bytes/sec
total size is 103,349,569 speedup is 2.70

¿Vale la pena activar la compresión máxima en Rsync?

La compresión máxima usa más recursos de CPU que la normal, así que cuanto más lenta sea tu línea, más te compensará, ya que comprimirás a suficiente velocidad para no saturar la CPU. Si tienes un ancho de banda de red de 1 Gbit/segundo, seguramente te resulte más lento activar la compresión máxima.

javi@trabajo:/tmp/rsync$ rsync -avz --compress-level=9 --progress 100M-quijote.txt usuario@host:/tmp/
sending incremental file list
100M-quijote.txt
103,349,569 100% 6.53MB/s 0:00:15 (xfr#1, to-chk=0/1)

sent 38,054,446 bytes received 35 bytes 2,174,541.77 bytes/sec
total size is 103,349,569 speedup is 2.72

Como puedes ver, hemos conseguido ahorrar un segundo activando la compresión máxima, que no resulta ser demasiado.

Serán bienvenidos comentarios con otras opciones que consideréis útiles en el día a día o cualquier duda que podáis tener.