Wie kopiere ich eine Datei, die noch über ssh geschrieben wird?

20

Hier ist die Situation:

  1. Ich lade eine große Datei mit sftp von Client A auf einen Server hoch.
  2. Ich muss diese Datei auch über ssh vom Server auf Client B herunterladen.

Was ich tun möchte, ist die Übertragung vom Server zum Client B zu starten, während der Upload noch vom Client A erfolgt.

Was ist die beste Methode / das beste Werkzeug, um dies zu erreichen?

UPDATE :

Die bisherigen Antworten sind interessant - ich werde sie alle lesen und testen. Bonuspunkte für Antworten, die nicht davon abhängen, wie Client A die Datei hochlädt. (Das einzige, was wir von Client A wissen, ist, dass die Datei in einen bekannten Dateinamen geschrieben wird.)

Steven D
quelle
Oh, gute Frage. Dies ist sicherlich möglich, aber mir ist nichts bekannt, das dies umsetzt
Michael Mrozek

Antworten:

10

Für eine einzelne Datei anstelle von SFTP können Sie die Datei mit catoder pvauf der sendenden Seite über ssh leiten und teeauf dem mittleren Server die Daten an eine Datei dort senden und eine Kopie über den anderen ssh-Link senden, dessen andere Seite schreibt einfach die Daten in eine Datei. Das genaue Voodoo werde ich als Übung für den Leser hinterlassen, da ich gerade keine Zeit zum Spielen habe (sorry). Diese Methode funktioniert nur, wenn das zweite Ziel über SSH öffentlich zugänglich ist. Dies ist möglicherweise nicht der Fall, da Sie es als Client-Computer bezeichnen.

Bei einem anderen Ansatz, der weniger "Ausführen und Warten" erfordert, ansonsten jedoch einfacher ist, kann er rsynczwischen Server und Client B verwendet werden. Wenn Sie ihn zum ersten Mal ausführen, wird möglicherweise eine teilweise Kopie der Daten abgerufen, Sie können ihn jedoch erneut ausführen um danach mehr Daten zu erhalten (mit einem letzten Lauf, sobald die Client1-> Server-Übertragung abgeschlossen ist). Dies funktioniert nur, wenn der Server die Daten während der SFTP-Übertragung direkt in den richtigen Dateinamen schreibt (manchmal werden die Daten in eine temporäre Datei geschrieben, die dann umbenannt wird, sobald die Datei vollständig übertragen wurde Dateiaktualisierung ist atomarer, macht aber die rsync-Idee unbrauchbar). Sie können anstelle von scp auch rsync für die C1-> S-Übertragung verwenden (wenn Sie das verwenden)--inplaceOption, um das oben erwähnte Problem zu vermeiden) - Die Verwendung von rsync schützt Sie auch davor, alles erneut senden zu müssen, wenn bei der C1-> Server-Verbindung während einer großen Übertragung Probleme auftreten (ich verwende rsync --inplace -a --progress <source> <dest>statt scp / sftp, wenn rsync verfügbar ist, z dieses "Übertragungswiederaufnahme" -Verhalten).

Um das Obige zusammenzufassen:

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

auf client1 läuft dann

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

auf client2 wiederholt, bis die erste Übertragung abgeschlossen ist (und dann erneut ausgeführt wird, um sicherzustellen, dass Sie alles haben). rsyncist sehr gut darin, nur das absolute Minimum zu übertragen, das zum Aktualisieren eines Standorts erforderlich ist, anstatt jedes Mal das gesamte Los zu übertragen. Für Paranoia möchten Sie vielleicht die hinzuzufügen --checksumOption zu den rsync - Befehle (die viel CPU - Zeit für große Dateien dauern wird , aber nicht wesentlich mehr Daten führen zu übertragen, es sei denn es ist erforderlich) für die Geschwindigkeit der --compresswird Option , wenn die Daten helfen Sie übertragen, ist noch nicht in einem komprimierten Format.

David Spillett
quelle
5

Ich kann es im Moment nicht ausprobieren, daher könnte dies fehlschlagen: Meine Idee ist: Hängen Sie das Verzeichnis, in dem die Datei ankommt, in Client B ein, z. B. mit sshfs nach / mnt / server im Dateisystem von Client b. Dann

tail -c +0 -f /mnt/server/thefileinquestion > ~/finalfile
fschmitt
quelle
/ usr / bin / tail: +0 kann nicht zum Lesen geöffnet werden: Keine solche Datei oder kein solches Verzeichnis - coreutils 7.4
maxschlepzig
Entschuldigung, es fehlte ein -c. Ich habe es in der obigen Antwort behoben.
fschmitt
ok, ein problem dabei ist, dass der befehl nicht beendet wird (-f -> follow ...). Man muss ein SIGQUIT oder ähnliches ausgeben, wenn man sicher ist, dass die Datei vollständig geschrieben ist. Übrigens fragt tail, abhängig von Ihrer tail-Version und fs, die Datei intern ab (z. B. jede Sekunde).
Maxschlepzig
Ich hatte einen Fall: Aufzeichnen einer Videodatei auf meine Festplatte, aber ich wollte sie auf einen externen USB-Flash-Speicher kopieren, damit ich sie an eine Person weitergeben kann, sobald die Aufzeichnung gestoppt ist. Ich habe es mehrfach versucht rsync --appendund dann mit überprüft, md5sumaber die Dateien stimmen nie überein. tail -c +0hat den Job für mich gemacht. Ich habe auch verwendet pv -ptera, um den Fortschritt des Schwanzes zu überwachen, damit ich sehen kann, ob es funktioniert. Ich habe die md5s noch nicht überprüft, um zu überprüfen, ob sie funktioniert haben, aber sie sehen toll aus.
unfa
@unfa Bitte aktualisiere deinen Kommentar, indem du unten eine Antwort hinzufügst (dh keinen Kommentar).
Xofo
1

Ich denke das sollte funktionieren:

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

und dann

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

Fügen Sie den Befehl pv hinzu, wenn Sie Ihren Durchsatz anzeigen möchten.

abgehört
quelle
Wolltest du schreiben tail -c +0?
Dessert
1

Sie könnten ein FIFO dafür verwenden. Der Einfachheit halber zunächst ohne ssh mit nur zwei xterms:

Bei xterm A:

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

Bei 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

Mit ssh sollte es ungefähr so ​​aussehen - vielleicht müssen Sie das Escape-Zeichen in ssh deaktivieren (-e none):

Kunde A:

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

Kunde B:

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

Ich habe eine Situation, die eine Lösung wie das Originalplakat benötigt. Ich nehme an einem Ort ein Hockeyspiel auf meinem Computer auf und möchte es an einem anderen Ort auf meinem Fernseher sehen. Die Verbindung zwischen den beiden Speicherorten ermöglicht eine Kopiergeschwindigkeit von ca. 1,3 MB / s und eine Videoaufzeichnungsgeschwindigkeit von ca. 1,5 MB / s. Daher möchte ich die Datei beim Beginn der Aufnahme kopieren. Auf diese Weise wird mein 3-Stunden-Spiel in ungefähr 3,5 Stunden kopiert. Ich kopiere es also zu Beginn der Aufnahme und kann es 30 Minuten nach dem Start wiedergeben. Dann kann ich es fast in Echtzeit ohne Unterbrechungen ansehen. Das heißt, solange ich es zum Kopieren bringen kann, während es die neue Datei schreibt. Das Problem bei Tools wie rsync und scp besteht darin, dass sie die Größe der Datei prüfen, wenn Sie den Kopiervorgang starten. Sobald diese Datenmenge kopiert wurde, wird sie beendet. auch wenn die Datei während dieser Kopie um mehr als das Doppelte gewachsen ist. Und wenn ich nur rsync in einer Schleife verwende, um es zu kopieren, sobald es anhält, erstellt es nach Abschluss der nächsten rsync-Operation die Zieldatei neu. Dadurch wird mein Videoplayer beendet, und ich muss ihn erneut ansehen und schnell vorspulen, wo immer ich war im Programm, als es plötzlich tötete. Ich wollte eine bessere Lösung und konnte keine finden, also habe ich stattdessen Folgendes zusammengesetzt:

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'

Also, was macht das?

Zuerst benutze ich dd, um die Datei zu kopieren, während sie wächst. Da die Datei schneller wächst, als dd sie über das Netzwerk senden kann, holt dd niemals das Ende der Datei ein. Als nächstes leite ich es an "pipe viewer (pv)" weiter und gebe eine Schätzung, wie groß die Datei sein wird, basierend darauf, wie groß diese Dateien normalerweise sind. Dies ist nicht notwendig, aber ich möchte eine Fortschrittsanzeige sehen. Dann leite ich den Stream zu meiner SSH-Verbindung. Die SSH-Verbindung verwendet -Cfür die Komprimierung (um die Netzwerkbandbreite zu reduzieren und sie zu beschleunigen), -c arcfour,blowfish-cbcfür die kostengünstigste Verschlüsselung (um die Dinge wieder etwas zu beschleunigen) die-pist für meinen Firewall-Port, den ich am Ziel verwende, und der ssh führt schließlich den Befehl dd auf dem Ziel aus, um die Datei neu zu erstellen, sobald sie empfangen wird. Ich bin froh zu sagen, dass diese Lösung großartig funktioniert. Ich kann mir das Hockeyspiel ansehen, während die Datei mit einer kurzen Verzögerung erstellt und kopiert wird.

Neophraz
quelle
0

Ich bin nicht sicher, ob die tail -f-Methode funktioniert (obwohl es wahrscheinlich funktioniert, wenn die Datei Text ist). Der Grund ist, dass ich nicht weiß, wie Tail -f und SFTP übertragen und sich auf Metainformationen verlassen.

Wenn sftp zuerst die Metainformationen überträgt und tail -f sich auf die Metainformationen stützt, um darauf hinzuweisen, dass keine weiteren Dateien vorhanden sind, kann tail das Ende mit EOFs oder Nullen beschädigen.

Wenn Sie sich nicht für den Pfad des Uploads interessieren, dh Computer 1 lädt auf Computer 2 lädt auf Computer 3 hoch, können Sie versuchen, bittorent anstelle von sftp zu verwenden. Es sieht so aus, als wäre es genau dafür gedacht.

HandyGandy
quelle
0

Sie können versuchen, die Datei von Anfang an zu lesen, müssen jedoch sicherstellen, dass Sie sie mindestens mit derselben Geschwindigkeit schreiben können.

Tim Connor
quelle