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

20

Aquí está la situación:

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

Lo que me gustaría hacer es comenzar la transferencia desde el servidor al cliente B cuando la carga aún se realiza desde el cliente A.

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

ACTUALIZACIÓN :

Las respuestas hasta ahora son interesantes: me aseguraré de leerlas y evaluarlas 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).

Steven D
fuente
Ooo, buena pregunta. Esto es ciertamente posible, pero no estoy al tanto de nada que lo implemente
Michael Mrozek

Respuestas:

10

Para un solo archivo en lugar de usar SFTP, puede canalizar el archivo a través de ssh usando cato pven el lado de envío y usando teeen el servidor central para enviar los datos a un archivo allí y enviar una copia sobre el otro enlace ssh al otro lado del cual solo escribe los datos en un archivo. El vudú exacto requerido lo dejaré como ejercicio para el lector, ya que no tengo tiempo para jugar en este momento (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, ya que lo describe como una máquina cliente.

Otro enfoque, que es menos "ejecutar y esperar" pero que de otro modo puede ser más fácil, es usarlo rsyncentre el servidor y el cliente B. La primera vez que ejecute esto, puede obtener una copia parcial de los datos, pero puede volver a ejecutar 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 la actualización del archivo es más atómica pero hará que la idea de rsync sea inutilizable). También puede usar rsync para la transferencia C1-> S en lugar de scp (si usa--inplaceopción para evitar el problema mencionado anteriormente): el uso de rsync también le daría protección contra la necesidad de reenviar todo si la conexión C1-> Server experimenta problemas durante una transferencia grande (tiendo a usar en rsync --inplace -a --progress <source> <dest>lugar de scp / sftp cuando rsync está disponible, por este comportamiento de "currículum de transferencia").

Para resumir lo anterior, ejecutando:

rsync --inplace -a --progress <source> user@server:/<destination_file_or_folder>

en el cliente1 y luego en ejecución

rsync --inplace -a --progress user@server:/<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). rsynces 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 la --checksumopción a los comandos rsync (que tomará mucho más tiempo de CPU para archivos grandes pero no generará una transferencia de datos significativamente mayor a menos que sea necesario) y para la velocidad, la --compressopción ayudará si los datos que está transfiriendo aún no está en formato comprimido.

David Spillett
fuente
5

No puedo probarlo en este momento, así que esto podría fallar: mi idea es esta: montar 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
fschmitt
fuente
/ usr / bin / tail: no se puede abrir `+0 'para leer: No
existe
Lo sentimos, faltaba un -c. Lo arreglé en la respuesta anterior.
fschmitt
ok, un problema que veo con esto es que el comando no termina (-f -> follow ...). Uno tiene que emitir un sigQUIT o algo por el estilo, cuando está seguro de que la pregunta del archivo está completamente escrita. Por cierto, dependiendo de su versión de cola y fs, cola internamente sondea el archivo (por ejemplo, cada segundo).
maxschlepzig 01 de
Tenía un caso: grabar un archivo de video en mi HDD, pero quería copiarlo en una memoria Flash USB externa para poder entregarlo a una persona tan pronto como se detenga la grabación. Intenté múltiples rsync --appendy luego verifiqué, md5sumpero los archivos nunca coincidieron. tail -c +0hizo el trabajo por mí También solía pv -pteramonitorear el progreso de la cola, me permite ver si está funcionando. Todavía no terminé de revisar los md5 para verificar que funcionó, pero se ve muy bien.
unfa
@unfa Actualice su comentario agregando una respuesta a continuación (es decir, no un comentario).
Xofo
1

Creo que esto debería funcionar:

user@clientA:~$ cat file | ssh server "cat > dest"

y entonces

user@clientB:~$ ssh server "tail +0 -f dest" > file

Agregue el comando pv si desea ver su rendimiento.

interceptado
fuente
¿Querías escribir tail -c +0?
postre
1

Podrías usar un fifo para ello. Por simplicidad primero sin ssh que solo involucra 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 así: 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
maxschlepzig
fuente
1

Tengo una situación que necesita una solución como el póster original solicitado. Estoy grabando un juego 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 vaya a aproximadamente 1.3Mb / sy el video de grabación es de aproximadamente 1.5Mb / 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 comience. Entonces puedo verlo sin interrupciones, casi en tiempo real. Es decir, siempre que pueda hacer que 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 el siguiente rsync termina, reconstruye el archivo de destino y eso mata mi reproductor de video y tengo que reiniciar la visualización y avanzar rápidamente a donde sea que esté en el programa cuando de repente lo mató. Quería una mejor solución y no he podido encontrar una, así que en su lugar, armé esto:

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. Luego, lo canalizo a "pipe viewer (pv)" y le doy una estimación de cuán grande será el archivo en función de qué tan grandes son 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 se usa -Cpara la compresión (para reducir el ancho de banda de la red e intentar acelerarlo), -c arcfour,blowfish-cbcpara el cifrado menos costoso (nuevamente para acelerar un poco las cosas), el-pes para mi puerto de firewall que estoy usando en el destino, y el 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 juego de hockey mientras el archivo se está creando y copiando con solo un breve retraso.

Neophraz
fuente
0

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

Si sftp transfiere la metainformación primero y tail -f se basa en la metainformación para indicarle que no hay más archivos, entonces la cola puede dañar el final 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 utilizar bittorent en lugar de sftp. Parece que para eso fue diseñado.

HandyGandy
fuente
0

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

Tim Connor
fuente