Jak skopiować plik, który wciąż jest zapisywany przez ssh?


20

Oto sytuacja:

  1. Przesyłam duży plik z klienta A na serwer za pomocą sftp.
  2. Muszę również pobrać ten plik z serwera do klienta B przez ssh.

Chciałbym rozpocząć transfer z serwera do klienta B, gdy przesyłanie nadal trwa od klienta A.

Jaka jest najlepsza metoda / narzędzie, aby to zrobić?

AKTUALIZACJA :

Odpowiedzi do tej pory są interesujące - na pewno je wszystkie przeczytam i przetestuję. Punkty premiowe za odpowiedzi, które nie zależą od kontrolowania sposobu przesyłania pliku przez klienta A. (tj. jedyną rzeczą, którą wiemy od klienta A, jest to, że plik jest zapisywany pod znaną nazwą pliku).


Ooo, dobre pytanie. Jest to z pewnością możliwe, ale nie jestem świadomy niczego, co by to zaimplementowało
Michael Mrozek

Odpowiedzi:


10

W przypadku pojedynczego pliku zamiast SFTP można przesyłać plik przez ssh za pomocą catlub pvpo stronie wysyłającej i za pomocą teena środkowym serwerze, aby zarówno wysłać dane do pliku tam, jak i wysłać kopię przez inny link ssh, po drugiej stronie po prostu zapisuje dane do pliku. Dokładne wymagane voodoo pozostawię jako ćwiczenie dla czytelnika, ponieważ nie mam teraz czasu na zabawę (przepraszam). Ta metoda działałaby tylko wtedy, gdy drugie miejsce docelowe jest publicznie dostępne za pośrednictwem protokołu SSH, co może nie być prawdą, ponieważ opisuje się je jako maszynę klienta.

Innym podejściem, które jest mniej „uruchom i czekaj”, ale może być łatwiejsze, jest użycie rsyncmiędzy serwerem a klientem B. Przy pierwszym uruchomieniu może on otrzymać częściową kopię danych, ale możesz po prostu ponownie uruchomić aby później uzyskać więcej danych (z jednym końcowym uruchomieniem po zakończeniu transferu Klient1-> Serwer). Będzie to działać tylko wtedy, gdy serwer umieści dane bezpośrednio we właściwej nazwie pliku podczas przesyłania SFTP (czasami zobaczysz, że dane przechodzą do pliku tymczasowego, którego nazwa zostaje zmieniona po całkowitym przesłaniu pliku - odbywa się to w celu aktualizacja pliku bardziej atomowa, ale sprawi, że pomysł rsync będzie bezużyteczny). Możesz także użyć rsync do transferu C1-> S zamiast scp (jeśli używasz--inplaceopcja uniknięcia wyżej wspomnianego problemu) - użycie rsync zapewniłoby również ochronę przed koniecznością ponownego wysyłania wszystkiego, jeśli połączenie C1-> Serwer napotka problemy podczas dużego transferu (zwykle używam rsync --inplace -a --progress <source> <dest>zamiast scp / sftp, gdy rsync jest dostępny, dla takie zachowanie „wznawianie przesyłania”).

Podsumowując powyższe, uruchom:

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

na kliencie1, a następnie uruchomiony

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

na kliencie2 wielokrotnie, aż pierwszy transfer zostanie zakończony (następnie uruchom ponownie, aby upewnić się, że masz wszystko). rsyncjest bardzo dobry w przenoszeniu tylko absolutnego minimum, musi zaktualizować lokalizację zamiast przesyłać całą partię za każdym razem. W przypadku paranoi możesz chcieć dodać tę --checksumopcję do poleceń rsync (co zajmie znacznie więcej czasu procesora w przypadku dużych plików, ale nie spowoduje przeniesienia znacznie większej ilości danych, chyba że jest to potrzebne), a dla szybkości --compressopcja pomoże, jeśli dane przesyłane dane nie są już w formacie skompresowanym.


5

W tej chwili nie mogę go wypróbować, więc może się to nie powieść: mam pomysł: Zamontuj katalog, w którym plik dociera do klienta B, np. Sshfs do / mnt / server w systemie plików klienta b. Następnie

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

/ usr / bin / tail: nie można otworzyć `+0 'do odczytu: Brak takiego pliku lub katalogu - coreutils 7.4
maxschlepzig

Przepraszamy, brakowało -c. Naprawiłem to w powyższej odpowiedzi.
fschmitt

ok, widzę problem z tym, że polecenie się nie kończy (-f -> wykonaj ...). Trzeba wydać sIGQUIT lub coś takiego, gdy masz pewność, że zapytanie o plik jest całkowicie napisane. Btw, w zależności od wersji tail i fs, tail wewnętrznie wykonuje odpytywanie pliku (np. Co sekundę).
maxschlepzig

Miałem przypadek: nagrywanie pliku wideo na mój dysk twardy, ale chciałem skopiować go do zewnętrznej pamięci flash USB, aby móc przekazać go osobie, gdy tylko nagrywanie zostanie zatrzymane. Próbowałem wiele, rsync --appenda następnie sprawdziłem, md5sumale pliki nigdy nie pasowały. tail -c +0wykonał dla mnie pracę. Użyłem również pv -pterado monitorowania postępu ogona, pozwala mi zobaczyć, czy działa. Nie skończyłem jeszcze sprawdzać md5s, aby sprawdzić, czy działa, ale wygląda świetnie.
unfa,

@unfa Zaktualizuj swój komentarz, dodając odpowiedź poniżej (tj. nie komentarz).
Xofo

1

Myślę, że to powinno działać:

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

i wtedy

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

Dodaj komendę pv, jeśli chcesz zobaczyć swoją przepustowość.


Miałeś na myśli pisać tail -c +0?
deser

1

Możesz do tego użyć fifo. Dla uproszczenia najpierw bez ssh obejmującego tylko dwa xtermy:

W Xterm A:

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

W 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

W przypadku ssh powinno to być coś w tym stylu - być może trzeba wyłączyć znak zmiany znaczenia w ssh (-e brak):

klient A:

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

klient B:

 $ ssh server cat fif > dest.tar.gz

1

Mam sytuację, która wymaga rozwiązania takiego jak pierwotny plakat. Nagrywam grę hokejową na komputerze w jednym miejscu i chciałbym oglądać ją na telewizorze w innym miejscu. Połączenie między dwiema lokalizacjami pozwala na kopiowanie z prędkością około 1,3 Mb / s, a nagrywanie wideo wynosi około 1,5 Mb / s. Chcę więc skopiować plik, gdy zacznie się nagrywać. W ten sposób moja 3-godzinna gra zostanie skopiowana za około 3,5 godziny. Tak więc, kopiuję go, gdy zaczyna się nagrywanie i mogę zacząć oglądać go 30 minut po uruchomieniu. Następnie mogę oglądać bez żadnych zakłóceń, prawie w czasie rzeczywistym. To znaczy, o ile mogę go skopiować, tak jak zapisuje nowy plik. Problem z narzędziami takimi jak rsync i scp polega na tym, że patrzą na rozmiar pliku podczas inicjowania kopiowania, a gdy kopiuje taką ilość danych, kończy pracę; nawet jeśli plik powiększył się ponad dwukrotnie podczas tej kopii. A jeśli po prostu używam rsync w pętli, aby go skopiować po zatrzymaniu, to kiedy następny rsync zakończy, odbudowuje plik docelowy, co zabija mój odtwarzacz wideo i muszę ponownie go obejrzeć i szybko przejść do miejsca, w którym byłem w programie, gdy nagle go zabił. Chciałem lepszego rozwiązania i nie byłem w stanie go znaleźć, więc poskładałem to razem:

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'

Co to robi?

Najpierw używam dd do kopiowania pliku w miarę jego wzrostu. Ponieważ plik rośnie szybciej niż dd może wysłać go przez sieć, dd nigdy nie dogania do końca pliku. Następnie przesyłam potokiem do „podglądu rur (pv)” i podam szacunkową wielkość pliku na podstawie tego, jak duże są zwykle te pliki. Nie jest to konieczne, ale lubię widzieć wskaźnik postępu. Następnie potokuję strumień do mojego połączenia ssh. Połączenie ssh używa -Cdo kompresji (w celu zmniejszenia przepustowości sieci i próby jej przyspieszenia), -c arcfour,blowfish-cbcdo najtańszego szyfrowania (ponownie w celu nieco przyspieszenia),-pjest dla mojego portu zapory sieciowej, którego używam w miejscu docelowym, a ssh w końcu uruchamia polecenie dd na celu, aby odtworzyć plik po jego otrzymaniu. Z przyjemnością mogę powiedzieć, że to rozwiązanie działa świetnie. Mogę oglądać grę w hokeja podczas tworzenia i kopiowania pliku z niewielkim opóźnieniem.


0

Nie jestem pewien, czy metoda tail -f działa (choć prawdopodobnie działa, jeśli plik jest tekstem). Powodem jest to, że nie wiem, jak tail -f i sftp przesyłają i polegają na meta informacjach.

Jeśli sftp przesyła najpierw meta informacje, a tail -f polega na meta informacjach, aby powiedzieć, że nie ma już pliku, wtedy tail może źle uszkodzić koniec z EOF lub zerami.

Jeśli nie zależy ci na ścieżce przesyłania, tj. Przesyłanie komputera 1 na komputer 2 przesyłanie na komputer 3, możesz spróbować użyć bittorent zamiast sftp. Wydaje się, że po to został zaprojektowany.


0

Możesz spróbować odczytać plik od samego początku, ale musisz mieć pewność, że możesz go zapisać przynajmniej z tą samą prędkością.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.