Как скопировать файл, который все еще пишется поверх ssh?

20

Вот ситуация:

  1. Я загружаю большой файл с клиента A на сервер, используя sftp.
  2. Мне также нужно скачать этот файл с сервера на клиент B через SSH.

Я хотел бы начать передачу с сервера на клиент B, когда загрузка все еще происходит с клиента A.

Какой лучший метод / инструмент, чтобы сделать это?

ОБНОВЛЕНИЕ :

Пока ответы интересны - я обязательно прочитаю и протестирую их все. Бонусные баллы за ответы, которые не зависят от того, как клиент загружает файл. (т.е. единственное, что мы знаем от клиента A, это то, что файл записывается с известным именем файла.)

Стивен Д
источник
Ооо, хороший вопрос Это, конечно, возможно, но я ничего не знаю о том, что это реализует
Майкл Мрозек

Ответы:

10

Для одного файла вместо использования SFTP вы можете передать файл через ssh, используя catили pvна стороне отправки и используя teeна промежуточном сервере, чтобы отправить данные в файл и отправить копию по другой ссылке ssh, другая сторона которой просто записывает данные в файл. Точное требуемое вуду я оставлю в качестве упражнения для читателя, поскольку у меня нет времени играть прямо сейчас (извините). Этот метод будет работать только в том случае, если второе назначение является общедоступным через SSH, что может быть не так, как вы описываете его как клиентский компьютер.

Другой подход, который менее «запускай и жди», но в противном случае может быть проще, его можно использовать rsyncмежду сервером и клиентом B. При первом запуске он может получить частичную копию данных, но вы можете просто перезапустить это, чтобы получить больше данных впоследствии (с одним последним запуском, когда передача Client1-> Server завершена). Это будет работать только в том случае, если сервер помещает данные прямо в правильное имя файла во время передачи SFTP (иногда вы увидите, что данные переходят во временный файл, который затем переименовывается после полной передачи файла - это делается для обновление файла более атомное, но сделает идею rsync непригодной для использования). Вы также можете использовать rsync для передачи C1-> S вместо scp (если вы используете--inplaceвозможность избежать проблемы, упомянутой выше) - использование rsync также защитит вас от необходимости повторной отправки всего, если у соединения C1-> Server возникают проблемы во время большой передачи (я обычно использую rsync --inplace -a --progress <source> <dest>вместо scp / sftp, когда rsync доступен, для это поведение "передачи резюме").

Подводя итог вышесказанному, запустим:

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

на client1 потом работает

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

на client2 несколько раз, пока первая передача не будет завершена (затем запустите еще раз, чтобы убедиться, что вы все получили). rsyncочень хорошо передает только абсолютный минимум, необходимый для обновления местоположения, вместо того, чтобы каждый раз передавать весь лот. Для паранойи вы можете добавить --checksumопцию к командам rsync (которая займет гораздо больше процессорного времени для больших файлов, но не приведет к значительному увеличению объема передаваемых данных, если в этом нет необходимости), а для скорости эта --compressопция поможет, если данные Вы передаете не в сжатом формате.

Дэвид Спиллетт
источник
5

Я не могу попробовать это в данный момент, так что это вполне может дать сбой: Моя идея такова: смонтировать каталог, куда файл поступает на клиент B, например, с помощью sshfs в / mnt / server в файловой системе клиента b. потом

tail -c +0 -f /mnt/server/thefileinquestion > ~/finalfile
fschmitt
источник
/ usr / bin / tail: невозможно открыть `+0 'для чтения: нет такого файла или каталога - coreutils 7.4
maxschlepzig
Извините, пропал -c. Я исправил это в ответе выше.
fschmitt
Хорошо, проблема с этим заключается в том, что команда не завершается (-f -> follow ...). Нужно выдать sigQUIT или что-то в этом роде, когда вы уверены, что запрос файла полностью написан. Кстати, в зависимости от вашей версии tail и fs, tail внутренне выполняет опрос файла (например, каждую секунду).
maxschlepzig
У меня был случай: запись видеофайла на мой жесткий диск, но я хотел скопировать его на внешнюю флэш-память USB, чтобы я мог передать его человеку, как только запись будет остановлена. Я попробовал несколько, rsync --appendа затем проверил, md5sumно файлы никогда не совпадали. tail -c +0сделал работу за меня. Я также использовал, pv -pteraчтобы следить за прогрессом хвоста, это позволяет мне видеть, работает ли он. Я еще не закончил проверять md5s, чтобы убедиться, что он работает, но выглядит великолепно.
unfa
@unfa Пожалуйста, обновите свой комментарий, добавив ответ ниже (т.е. не комментарий).
Xofo
1

Я думаю, что это должно работать:

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

а потом

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

Добавьте команду pv, если вы хотите увидеть свою пропускную способность.

прослушивались
источник
Ты хотел написать tail -c +0?
десерт
1

Вы можете использовать FIFO для этого. Для простоты сначала без ssh, включающего только два xterms:

На этапе А:

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

В конце Б:

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

С ssh это должно быть примерно так: возможно, вам нужно отключить escape-символ в ssh (-e none):

клиент А:

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

клиент Б:

 $ ssh server cat fif > dest.tar.gz
maxschlepzig
источник
1

У меня есть ситуация, которая требует решения, как в оригинальном плакате. Я записываю хоккейную игру на своем компьютере в одном месте, и я хотел бы посмотреть ее по телевизору в другом месте. Связь между этими двумя местоположениями позволяет копировать со скоростью около 1,3 Мбит / с, а запись видео - около 1,5 Мбит / с. Итак, я хочу скопировать файл, когда он начинает запись. Таким образом, моя 3-часовая игра будет скопирована примерно за 3,5 часа. Итак, я копирую его, когда он начинает запись, и я могу начать смотреть его через 30 минут после его начала. Тогда я могу смотреть это без перерывов, почти в режиме реального времени. То есть до тех пор, пока я могу получить его для копирования, как при записи нового файла. Проблема с такими инструментами, как rsync и scp, заключается в том, что они смотрят на размер файла, когда вы инициируете копирование, и как только он копирует этот объем данных, он закрывается; даже если файл увеличился более чем вдвое за эту копию. И, если я просто использую rsync в цикле, чтобы скопировать его после его остановки, когда следующий rsync заканчивает, он восстанавливает целевой файл, и это убивает мой видеопроигрыватель, и я должен возобновить просмотр и перемотать туда, где я был в программе, когда он внезапно убил его. Я хотел лучшее решение, и я не смог найти его, поэтому я собрал это:

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'

Так, что это делает?

Во-первых, я использую dd для копирования файла по мере его роста. Поскольку файл растет быстрее, чем dd может отправить его по сети, dd никогда не доходит до конца файла. Затем я передаю его «pipe viewer (pv)» и оцениваю, насколько большим будет файл, исходя из размера этих файлов. Это не обязательно, но мне нравится видеть индикатор прогресса. Затем я передаю поток в мое соединение ssh. Соединение ssh использует -Cдля сжатия (чтобы уменьшить пропускную способность сети и попытаться ускорить его), -c arcfour,blowfish-cbcдля наименее дорогого шифрования (опять же, чтобы немного ускорить процесс),-pдля моего порта брандмауэра, который я использую в месте назначения, и ssh наконец запускает команду dd на цели, чтобы воссоздать файл, когда он его получает. Я рад сказать, что это решение прекрасно работает. Я могу наблюдать за игрой в хоккей, пока файл создается и копируется с небольшой задержкой.

Neophraz
источник
0

Я не уверен, что метод tail -f работает (хотя он, вероятно, работает, если файл текстовый). Причина в том, что я не знаю, как tail -f и sftp переносят и полагаются на метаинформацию.

Если sftp сначала передает метаинформацию, а tail -f использует метаинформацию, чтобы сообщить ей, что файла больше нет, то tail может испортить конец EOF или пустыми значениями.

Если вам не важен путь загрузки, то есть загрузка с компьютера 1 на компьютер 2, выгрузка на компьютер 3, тогда вы можете попробовать использовать битторент вместо sftp. Кажется, именно для этого он и был разработан.

HandyGandy
источник
0

Вы можете попробовать прочитать файл с самого начала, но вам нужно быть уверенным, что вы можете записать его как минимум с той же скоростью.

Тим Коннор
источник