Come copiare un file che è ancora in fase di scrittura su SSH?


20

Ecco la situazione:

  1. Sto caricando un file di grandi dimensioni dal client A su un server usando sftp.
  2. Devo anche scaricare questo file dal server al client B su ssh.

Quello che vorrei fare è avviare il trasferimento dal server al client B quando il caricamento è ancora in corso dal client A.

Qual è il metodo / strumento migliore per farlo?

AGGIORNAMENTO :

Le risposte finora sono interessanti: sarò sicuro di leggerle e testarle tutte. Punti bonus per le risposte che non dipendono dal controllo del modo in cui il Cliente A sta caricando il file. (vale a dire, l'unica cosa che sappiamo dal client A è che il file viene scritto con un nome file noto.)


Ooo, bella domanda. Questo è certamente possibile, ma non sono a conoscenza di nulla che lo attui
Michael Mrozek

Risposte:


10

Per un singolo file invece di utilizzare SFTP è possibile reindirizzare il file su ssh utilizzando cato pvsul lato di invio e utilizzando teesul server centrale sia per inviare i dati a un file lì sia per inviarne una copia sull'altro collegamento ssh dall'altro lato del quale scrive solo i dati in un file. L'esatto voodoo richiesto partirò come esercizio per il lettore, dato che non ho tempo di giocare in questo momento (scusa). Questo metodo funzionerebbe solo se la seconda destinazione è accessibile pubblicamente tramite SSH, il che potrebbe non essere il caso in cui viene descritta come una macchina client.

Un altro approccio, che è meno "esegui e attendi" ma potrebbe essere più semplice da utilizzare rsynctra il server e il client B. La prima volta che esegui questa operazione potresti ottenere una copia parziale dei dati, ma puoi semplicemente rieseguire per ottenere più dati in seguito (con un'ultima esecuzione una volta completato il trasferimento Client1-> Server). Funzionerà solo se il server inserisce i dati direttamente nel nome file corretto durante il trasferimento SFTP (a volte vedrai i dati andare in un file temporaneo che viene quindi rinominato una volta che il file è stato trasferito completamente - questo viene fatto per rendere il l'aggiornamento del file è più atomico ma renderà inutilizzabile l'idea rsync). Puoi anche usare rsync per il trasferimento C1-> S invece di scp (se usi--inplaceopzione per evitare il problema menzionato sopra) - l'uso di rsync ti darebbe anche protezione contro la necessità di reinviare tutto se la connessione C1-> Server riscontra problemi durante un trasferimento di grandi dimensioni (tendo a usare al rsync --inplace -a --progress <source> <dest>posto di scp / sftp quando rsync è disponibile, per questo comportamento "riprendi trasferimento").

Per riassumere quanto sopra, eseguendo:

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

su client1 quindi in esecuzione

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

su client2 ripetutamente fino al completamento del primo trasferimento (quindi eseguendolo ancora una volta per assicurarti di avere tutto). rsyncè molto bravo a trasferire solo il minimo assoluto necessario per aggiornare una posizione anziché trasferire l'intero lotto ogni volta. Per la paranoia potresti voler aggiungere l' --checksumopzione ai comandi rsync (che richiederà molto più tempo della CPU per file di grandi dimensioni ma non comporterà il trasferimento di molti più dati a meno che non sia necessario) e per velocità l' --compressopzione aiuterà se i dati che stai trasferendo non è già in un formato compresso.


5

Al momento non posso provarlo, quindi potrebbe non riuscire: la mia idea è questa: montare la directory in cui il file arriva nel client B, ad esempio con sshfs su / mnt / server nel filesystem del client b. Poi

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

/ usr / bin / tail: impossibile aprire `+0 'per la lettura: nessun file o directory simile - coreutils 7.4
maxschlepzig

Spiacente, mancava un -c. L'ho risolto nella risposta sopra.
fschmitt,

ok, un problema che vedo in questo è che il comando non termina (-f -> follow ...). Bisogna emettere un sigQUIT o qualcosa del genere, quando si è sicuri che la domanda del file sia completamente scritta. A seconda della versione di coda e di fs, tail esegue internamente il polling del file (ad es. Ogni secondo).
maxschlepzig,

Ho avuto un caso: registrare un file video sul mio HDD, ma volevo copiarlo su una memoria flash USB esterna in modo da poterlo consegnare a una persona non appena la registrazione è stata interrotta. Ho provato più rsync --appende poi verificato con md5summa i file non corrispondono mai. tail -c +0ha fatto il lavoro per me. Ho anche usato pv -pteraper monitorare l'avanzamento della coda, mi permette di vedere se funziona. Non ho ancora finito di controllare gli md5 per verificare che funzionasse, ma sembra fantastico.
unfa,

@unfa Aggiorna il tuo commento aggiungendo una risposta di seguito (ovvero non un commento).
Xofo

1

Penso che dovrebbe funzionare:

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

e poi

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

Aggiungi il comando pv se vuoi vedere il tuo throughput.


Intendevi scrivere tail -c +0?
dessert

1

Potresti usare un fifo per questo. Per semplicità prima senza ssh che coinvolge solo due xterm:

Al xterm A:

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

Al 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 dovrebbe essere qualcosa del genere - forse devi disabilitare il carattere escape in 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

Ho una situazione che richiede una soluzione come il poster originale richiesto. Sto registrando una partita di hockey sul mio computer in una posizione e mi piacerebbe guardarla sulla mia TV in un'altra posizione. Il collegamento tra le due posizioni consente alla copia di andare a circa 1,3 Mb / se il video di registrazione è di circa 1,5 Mb / s. Quindi, voglio copiare il file non appena inizia la registrazione. In questo modo il mio gioco di 3 ore verrà copiato in circa 3,5 ore. Quindi, lo copio mentre inizia la registrazione e posso iniziare a guardarlo 30 minuti dopo l'avvio. Quindi posso guardarlo senza interruzioni, quasi in tempo reale. Cioè, finché riesco a farlo copiare mentre sta scrivendo il nuovo file. Il problema con strumenti come rsync e scp è che guardano la dimensione del file quando si avvia la copia e una volta che copia quella quantità di dati, si chiude; anche se il file è cresciuto di oltre il doppio durante quella copia. E, se, sto solo usando rsync in un ciclo per copiarlo una volta che si ferma, quando il prossimo rsync termina ricostruisce il file di destinazione e questo uccide il mio lettore video e devo ricominciare a guardarlo e andare avanti veloce ovunque io fossi nel programma quando improvvisamente lo ha ucciso. Volevo una soluzione migliore e non sono stato in grado di trovarne una, quindi ho messo insieme questo invece:

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'

Quindi cosa fa questo?

Innanzitutto, utilizzo dd per copiare il file man mano che cresce. Poiché il file cresce più velocemente di quanto dd possa inviarlo in rete, dd non raggiunge mai la fine del file. Successivamente, lo installo a "pipe viewer (pv)" e gli fornisco una stima della dimensione del file in base alla dimensione di questi file. Questo non è necessario, ma mi piace vedere un indicatore di progresso. Quindi, installo lo stream alla mia connessione ssh. La connessione ssh utilizza -Cper la compressione (per ridurre la larghezza di banda della rete e cercare di accelerarla), -c arcfour,blowfish-cbcper la crittografia meno costosa (di nuovo per accelerare un po 'le cose), il-pè per la mia porta del firewall che sto usando a destinazione e infine ssh esegue il comando dd sulla destinazione per ricreare il file così come lo riceve. Sono felice di dire che questa soluzione funziona alla grande. Posso guardare la partita di hockey mentre il file viene creato e copiato con un breve ritardo.


0

Non sono sicuro che il metodo tail -f funzioni (anche se probabilmente lo fa se il file è di testo). Il motivo è che non so come tail -f e sftp trasferiscano e faccia affidamento su meta-informazioni.

Se sftp trasferisce prima le meta informazioni e tail -f si affida alle meta informazioni per dire che non c'è più file, allora tail potrebbe danneggiare la fine con EOF o null.

Se non ti interessa il percorso di upload, ad es. Caricamenti da computer 1 a computer 2, caricamenti su computer 3, allora potresti provare ad usare bittorent invece di sftp. Sembra che sia quello per cui è stato progettato.


0

Puoi provare a leggere il file dall'inizio ma devi assicurarti di poterlo scrivere almeno alla stessa velocità.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.