it-swarm-es.tech

¿Cómo copiar un archivo que todavía se está escribiendo sobre ssh?

Aquí está la situación:

  1. Estoy cargando un archivo grande del cliente A a un servidor usando sftp.
  2. También necesito descargar este archivo desde el servidor al cliente B a través de ssh.

Lo que me gustaría hacer es iniciar la transferencia desde el servidor al cliente B cuando la carga todavía se está realizando desde el cliente A.

¿Cuál es el mejor método/herramienta para hacer esto?

ACTUALIZAR :

Las respuestas hasta ahora son interesantes. Me aseguraré de leerlas y probarlas todas. Puntos de bonificación por respuestas que no dependen de controlar cómo el Cliente A está cargando el archivo. (es decir, lo único que sabemos del cliente A es que el archivo se está escribiendo con un nombre de archivo conocido).

20
Steven D

Para un solo archivo en lugar de usar SFTP, puede canalizar el archivo a través de ssh usando cat o pv en el lado de envío y usando tee en el servidor intermedio para enviar los datos a un archivo allí y envíe una copia a través del otro enlace ssh, cuyo otro lado simplemente escribe los datos en un archivo. El vudú exacto requería lo dejaré como ejercicio para el lector, ya que no tengo tiempo para jugar ahora mismo (lo siento). Este método solo funcionaría si el segundo destino es de acceso público a través de SSH, lo que puede no ser el caso como lo describe como una máquina cliente.

Otro enfoque, que es menos "ejecutar y esperar", pero de lo contrario puede ser más fácil, es usar rsync entre el servidor y el cliente B. La primera vez que ejecuta esto, puede obtener una copia parcial de los datos, pero puede volver a ejecutarlo para obtener más datos después (con una ejecución final una vez que se complete la transferencia Cliente1-> Servidor). Esto solo funcionará si el servidor coloca los datos directamente en el nombre de archivo correcto durante la transferencia SFTP (a veces verá que los datos van a un archivo temporal que luego se renombra una vez que el archivo se transfiere por completo; esto se hace para hacer que el archivo la actualización del archivo es más atómica pero inutilizará la idea de rsync). También puede usar rsync para la transferencia C1-> S en lugar de scp (si usa el --inplace opción para evitar el problema mencionado anteriormente) - el uso de rsync también le brindaría protección contra la necesidad de reenviar todo si la conexión C1-> Servidor experimenta problemas durante una transferencia grande (tiendo a usar rsync --inplace -a --progress <source> <dest> en lugar de scp/sftp cuando rsync está disponible, para este comportamiento de "transferencia de reanudación").

Para resumir lo anterior, ejecutando:

rsync --inplace -a --progress <source> [email protected]:/<destination_file_or_folder>

en client1 luego se ejecuta

rsync --inplace -a --progress [email protected]:/<destination_file_or_folder> <destination_on_cli2>

en client2 repetidamente hasta que se complete la primera transferencia (luego se ejecuta una vez más para asegurarse de que tiene todo). rsync es muy bueno para transferir solo el mínimo absoluto que necesita para actualizar una ubicación en lugar de transferir todo el lote cada vez. Para la paranoia, es posible que desee agregar el --checksum a los comandos rsync (que tomará mucho más tiempo de CPU para archivos grandes pero no resultará en una transferencia de datos significativamente mayor a menos que sea necesario) y para acelerar el --compress La opción le ayudará si los datos que está transfiriendo aún no están en formato comprimido.

10
David Spillett

No puedo probarlo en este momento, por lo que esto podría fallar: Mi idea es esta: Monte el directorio donde llega el archivo en el cliente B, por ejemplo con sshfs a/mnt/server en el sistema de archivos del cliente b. Luego

tail -c +0 -f /mnt/server/thefileinquestion > ~/finalfile
5
fschmitt

Le vendría bien un quince para ello. Para simplificar primero sin ssh que solo involucre dos xterms:

En xterm A:

$ mkfifo fif
$ cat test.tar.gz | tee copy.tar.gz > fif

En xterm B:

$ cat fif > dest.tar.gz
$ cmp test.tar.gz dest.tar.gz
$ echo $?
0
$ cmp test.tar.gz copy.tar.gz
$ echo $?
0

Con ssh debería ser algo similar a esto, tal vez tenga que deshabilitar el carácter de escape en ssh (-e none):

cliente A:

 $ ssh server mkfifo fif
 $ cat src.tar.gz | ssh "tee fif > copy.tar.gz"

cliente B:

 $ ssh server cat fif > dest.tar.gz
1
maxschlepzig

Tengo una situación que necesita una solución como la que pedía el cartel original. Estoy grabando un partido de hockey en mi computadora en un lugar y me gustaría verlo en mi televisor en otro lugar. El enlace entre las dos ubicaciones permite que la copia sea de aproximadamente 1,3 Mb/sy la grabación de video sea de aproximadamente 1,5 Mb/s. Entonces, quiero copiar el archivo cuando comienza a grabar. De esta manera, mi juego de 3 horas se copiará en aproximadamente 3,5 horas. Entonces, lo copio cuando comienza a grabar y puedo comenzar a verlo 30 minutos después de que comienza. Entonces puedo verlo sin interrupciones, casi en tiempo real. Es decir, siempre que pueda hacer que se copie mientras escribe el nuevo archivo. El problema con herramientas como rsync y scp es que miran el tamaño del archivo cuando inicia la copia y una vez que copia esa cantidad de datos, se cierra; incluso si el archivo ha crecido más del doble durante esa copia. Y, si solo estoy usando rsync en un bucle para copiarlo una vez que se detiene, cuando finaliza el siguiente rsync, reconstruye el archivo de destino y eso mata mi reproductor de video y tengo que reiniciar la visualización y avanzar rápidamente hasta donde esté. en el programa cuando de repente lo mató. Quería una mejor solución y no he podido encontrar una, así que armé esto en su lugar:

dd if=2031_20160514030000.mpg |
pv --size 4653819304 |
ssh -C -c arcfour,blowfish-cbc -p 5555 myserver.com 'dd of=/media/TV/2031_20160514030000.mpg'

Entonces que hace esto?

Primero, uso dd para copiar el archivo a medida que crece. Dado que el archivo crece más rápido de lo que dd puede enviarlo a través de la red, dd nunca alcanza el final del archivo. A continuación, lo canalizo a "pipe viewer (pv)" y le doy una estimación del tamaño del archivo en función del tamaño que suelen tener estos archivos. Esto no es necesario, pero me gusta ver un medidor de progreso. Luego, canalizo la transmisión a mi conexión ssh. La conexión ssh usa -C para compresión (para reducir el ancho de banda de la red e intentar acelerarlo), -c arcfour,blowfish-cbc para el cifrado menos costoso (nuevamente para acelerar un poco las cosas), el -p es para el puerto de mi firewall que estoy usando en el destino, y ssh finalmente ejecuta el comando dd en el destino para recrear el archivo a medida que lo recibe. Me alegra decir que esta solución funciona muy bien. Puedo ver el partido de hockey mientras se crea y copia el archivo con solo un breve retraso.

1
Neophraz

Creo que esto debería funcionar:

[email protected]:~$ cat file | ssh server "cat > dest"

y entonces

[email protected]:~$ ssh server "tail +0 -f dest" > file

Agregue el comando pv si desea ver su rendimiento.

1
wiretapped

No estoy seguro de que el método tail -f funcione (aunque probablemente lo haga si el archivo es texto). La razón es que no sé cómo se transfieren tail -f y sftp y se basan en la metainformación.

Si sftp transfiere primero la metainformación y tail -f se basa en la metainformación para decirle que no hay más archivos, tail puede terminar con EOF o nulos.

Si no le importa la ruta de carga, es decir, la computadora 1 carga a la computadora 2 carga a la computadora 3, entonces puede intentar usar bittorent en lugar de sftp. Parece que para eso fue diseñado.

0
HandyGandy

Puede intentar leer el archivo desde el principio, pero debe asegurarse de poder escribirlo al menos a la misma velocidad.

0
Tim Connor