rsync, elimine los archivos en el lado receptor que se eliminaron en el lado emisor. (Pero no borres todo)


9

Me gustaría usar rsync para ...

  • eliminar archivos en el lado receptor que también se eliminaron en el lado emisor
  • no elimine otros archivos que están en el directorio rsynced en el lado receptor

Por ejemplo, digamos que tengo un directorio local-src:

ANTES: local-src localmente contiene ...

a.txt
b.txt
c.txt

mi directorio remoto que me gustaría sincronizar con el contenido de local-srcse llama remote-src.

ANTES: remote-src remotamente contiene ...

a.txt
b.txt
c.txt
d.txt
README.md

Digamos que elimino algunos archivos en local-src:

DESPUÉS DE BORRAR LOCAL: local-src localmente contiene ...

c.txt

¿Cómo puedo usar rsync para asegurarme de que los archivos eliminados en el origen también se eliminen en el destino, pero sin eliminar otros archivos en el destino? Por ejemplo, me gustaría tener lo siguiente en el destino:

DESPUÉS DE BORRAR LOCAL: de remote-src forma remota contiene ...

c.txt
d.txt
README.md

Es decir, a.txty b.txtse eliminan de forma remota, así, pero d.txty README.txtse quedan solos.

¿Hay alguna forma de lograr esto con rsync?

EDITAR: El veredicto parece ser que esto podría ser imposible con rsync. Me han preguntado por qué necesito esto, así que para ilustrar mi caso de uso:

Digamos que tengo un servidor web. En ese servidor web, tengo un montón de directorios, digamos que tengo un directorio Ay un public_htmldirectorio desde el que se sirve mi sitio. Digamos que tengo un proceso automatizado que produce archivos en el directorio A. Me gustaría sincronizar (o sincronizar usando alguna otra herramienta) los archivos generados o actualizados en Ael public_htmldirectorio, sin eliminar otros archivos arbitrarios que puedan estar dentro public_html. Ciertamente no quiero que rsync elimine accidentalmente mi sitio web.

Si rsync no es la herramienta para este trabajo, ¿alguien más sabe cómo puedo hacer esto?


2
Después de volver a leer su pregunta, no creo que esto sea posible rsyncya que no hay forma de saber qué archivos ya están en la carpeta remota. Es posible que necesite encontrar otra herramienta.
Spack

rsync no le permitirá hacer esto, pero si scp todo el directorio cada vez que elimina archivos, puede mantenerlos sincronizados, no es una solución, solo una sugerencia.
Aadi Droid

1
Supongo que ya has pensado en esto, pero ¿no podrías simplemente poner estos archivos en un subdirectorio (o en otro lugar) y hacer referencia a ellos desde public_html? De esa manera, tiene un directorio que se sincroniza de manera fácil y explícita, sin afectar los archivos en otras partes del sistema de archivos del servidor web.
MattJenko

Respuestas:


2

Lo que quiere hacer es razonable, pero usarlo rsyncpara hacerlo solo no lo es. Entonces la respuesta es no .

La razón es simple: rsyncno mantiene un historial de lo que había en cada directorio y no tiene forma de saber qué se debe eliminar y qué no. No sin soporte adicional.

Debes preguntarte por qué te gusta hacer esto rsyncy dejarlo más claro. Hay otros programas que usan librsync1.soque son más inteligentes.


Con las restricciones relajadas que no necesita rsyncper se, puede echar un vistazo a rdiff-backup :

mkdir a
touch a/xx
touch a/yy
rdiff-backup a b
ls b 

Esto muestra xxy yyestán en b.

touch b/zz
rm a/xx
rdiff-backup a b

Esto muestra xxy zzestán en b. rdiff-backupTambién mantiene un directorio rdiff-backup-dataen blo que puede deshacer cualquier cambio, debe purgar esto sobre una base regular usando los rdiff-backupcomandos. (El ejemplo es con archivos locales para mostrar que los datos adicionales en el destino no se eliminan, pero rdiff-backup también funciona en una red).


Otra alternativa es configurar algún sistema de control de revisión distribuido (mercurial, bazar, git). Con mercurial, por ejemplo, puede tener un script (utilizo un Makefile para eso), que empuja todos los cambios al servidor y luego actualiza los archivos extraídos allí, ignora cualquier archivo adicional que esté en el servidor remoto (pero que tenga no ha sido puesto bajo control de revisión).

En el servidor harías:

hg init
hg add file_list_excluding_that_should_not_should_be_deleted_if_not_on_client
hg commit -m "initial setup"

En el cliente:

hg clone ssh://username@server/dir_to_repository

Ahora, si elimina un archivo en el cliente y hace:

hg commit -m "removed file"
ssh username@server "cd dir_to_repository; hg update --clean"

Su archivo eliminado se elimina en el servidor, pero cualquier otro dato (no agregado al repositorio) no se elimina.


Puedo aceptar que rsync no hará esto. Pero no estoy de acuerdo en que esto sería imposible con rsync. Si rsync sabe en el lado emisor qué archivos se han eliminado, ¿por qué no puede enviar esa información al lado receptor en el diff? Después de comparar la frescura, no veo por qué el lado receptor no puede simplemente eliminar los archivos que se indicaron que se eliminarán en el diff, sin eliminar todo lo demás en el directorio. Eliminar cualquier otro archivo inocente (no borrado en la fuente) en el directorio me parece irracional.
Heather Miller

En cualquier caso, la razón por la que necesito esto es la siguiente. Tengo un directorio, llamémoslo A, donde algunos procesos están automatizados y los archivos se generan automáticamente allí. Tengo un servidor web, y me gustaría que los archivos Aque contengan se envíen al public_htmldirectorio del servidor web, por supuesto, sin eliminar todo lo demás en la public_htmlcarpeta del servidor web. Si alguien tiene alguna idea para lograr esto con otra herramienta, sería más que bienvenido. Actualizaré mi pregunta para reflejar esto.
Heather Miller

Para aclarar mi primer comentario anterior, debería haber dicho "No estoy de acuerdo en que algo como esto sea imposible con una herramienta como rsync". Intuitivamente, parece que esto no puede ser demasiado difícil de lograr (a menos que me falte algo).
Heather Miller

Mmm, ok. Creo que veo ahora, ¿cómo puede saber rsync cuando algo se eliminó en el local-srcdirectorio sin tener algún proceso mirando cambios en ese directorio? Quizás esto sería difícil.
Heather Miller

@HeatherMiller Como escribí, su solicitud es razonable, pero rsyncno es la herramienta. Por favor, darse cuenta de que syncen rsyncproviene de sincronización y que no es exactamente lo que quiere hacer. En el desarrollo del rsyncenfoque se ha centrado en la transferencia eficiente (minimización) de datos. Otras herramientas como rdiff-backup(y posibles cvsup) han utilizado sus técnicas para eso, pero se basan en él con características adicionales.
Anthon

1

No creo que esto sea posible sin excluir explícitamente los archivos en el lado receptor como parte del comando rsync. Consulte la sección de la página de manual para rsync: "REGLAS Y BORRADO POR DIRECTORIO".

Sin una opción de eliminación, las reglas por directorio solo son relevantes en el lado de envío, por lo que puede excluir los archivos de fusión sin afectar la transferencia. Para facilitar esto, el modificador 'e' agrega esta exclusión para usted, como se ve en estos dos comandos equivalentes:

          rsync -av --filter=': .excl' --exclude=.excl host:src/dir /dest
          rsync -av --filter=':e .excl' host:src/dir /dest

Sin embargo, si desea eliminar en el lado receptor Y desea que algunos archivos se excluyan de la eliminación, deberá asegurarse de que el lado receptor sepa qué archivos excluir. La forma más fácil es incluir los archivos de fusión por directorio en la transferencia y usar --delete-after, porque esto asegura que el lado receptor obtenga las mismas reglas de exclusión que el lado emisor antes de intentar eliminar algo:

          rsync -avF --delete-after host:src/dir /dest

Sin embargo, si los archivos de combinación no forman parte de la transferencia, deberá especificar algunas reglas de exclusión global (es decir, especificadas en la línea de comando) o deberá mantener sus propios archivos de combinación por directorio en el lado receptor Un ejemplo de lo primero es esto (suponga que los archivos .rules remotos se excluyen a sí mismos):

   rsync -av --filter=’: .rules’ --filter=’. /my/extra.rules’
      --delete host:src/dir /dest

En el ejemplo anterior, el archivo extra.rules puede afectar a ambos lados de la transferencia, pero (en el lado de envío) las reglas están subordinadas a las reglas fusionadas de los archivos .rules porque se especificaron después de la regla de fusión por directorio.

En un último ejemplo, el lado remoto excluye los archivos .rsync-filter de la transferencia, pero queremos usar nuestros propios archivos .rsync-filter para controlar lo que se elimina en el lado receptor. Para hacer esto, debemos excluir específicamente los archivos de fusión por directorio (para que no se eliminen) y luego poner reglas en los archivos locales para controlar qué más no se debe eliminar. Como uno de estos comandos:

       rsync -av --filter=':e /.rsync-filter' --delete \
           host:src/dir /dest
       rsync -avFF --delete host:src/dir /dest

0

Si entendí correctamente, --excludepodría ser lo que estás buscando:

$ ls src dst
dst:
a.txt  b.txt  c.txt  d.txt  README.md

src:
c.txt
$ rsync --update --delete --recursive --exclude="d.txt" --exclude="README.md" src/ dst
$ ls src dst
dst:
c.txt  d.txt  README.md

src:
c.txt

Bueno no. No quiero tener que enumerar manualmente todos los archivos que me gustaría excluir. Solo me gustaría que rsync solo elimine los archivos que he eliminado en la fuente; no debería tener que saber en la fuente qué otros archivos posibles existen en el mismo directorio en el destino.
Heather Miller

0

Tengo una respuesta para eso. Creo que funciona Y funciona para mi . Primero deberías tener rsyncarchivos remotos a archivos locales. Entonces el lado local contiene todos los archivos.

sudo rsync -r -a -v --delete /root@xx.xx.xx.xx:/remote_dir/ /local_dir/

ahora en el lado local

a.txt
b.txt
c.txt
d.txt
README.md

Luego puede eliminar los archivos o hacer lo que quiera (en el lado local). En su pregunta, elimina estos archivos.

archivos borrados

a.txt
b.txt

Después de eso, puede rsynccolocar archivos locales en el lado remoto. Luego, ambos lados tienen los mismos archivos.

sudo rsync -r -a -v --delete /local_dir/ root@xx.xx.xx.xx:/remote_dir/

da

c.txt
d.txt
README.md

archivos en el lado remoto y en el lado local. (Al usar --delete, elimina otros archivos en el lado remoto que no coinciden con el lado local ).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.