Есть ли способ узнать, завершен ли копирование файла?

7145
Mike Cooper

Сценарий таков: на машине A есть файлы, которые я хочу скопировать на машину C. Машина A не может получить доступ к C напрямую, но может получить доступ к машине B, которая может получить доступ к машине C. Я использую scp для копирования с машины A на B, и затем от B до C.

Машина B имеет ограниченное пространство для хранения, поэтому, когда файлы приходят, мне нужно скопировать их в C и удалить их из B. Вторая копия гораздо быстрее, так что это не проблема с пропускной способностью.

Я мог бы сделать это вручную, но я ленив. Я хотел бы запустить скрипт на B или C, который будет копировать каждый файл в C по окончании каждого . Задание scp запускается из A.

Так что мне нужен способ спросить (желательно из bash-скрипта), если файл X.avi «готов» копировать. Каждый из этих файлов имеет разный размер, и я не могу предсказать размер или время завершения.

Изменить: кстати, время передачи файла составляет около 1 часа от A до B и около 10 минут от B до C, если масштаб времени имеет значение вообще.

2

6 ответов на вопрос

4
bmb

Обычный способ сделать это - сначала скопировать его во временное имя файла, предпочтительно в скрытый файл. Когда копирование заканчивается, скрипт, который делает копию, переименовывает его в не скрытое имя файла.

Затем сценарий на машине B может отслеживать не скрытые файлы.

Сценарий на машине A будет выглядеть примерно так:

for file in `ls *` ; do scp $file user@host:~/.$.tmp ssh user@host "mv ~/.$.tmp $file" done 

Хотя это не удовлетворяет желание ОП использовать одну строку

scp * user@host:~/ 

он выполняет то же самое, а также позволяет машине B передавать каждый файл по завершении, не дожидаясь следующего файла.

Проблема в том, что на компьютере AI нужно выполнить `scp * user @ host: ~ /`, а копируемые файлы будут больше, чем заполнять машину B, поэтому я не могу перемещать / переименовывать файлы после их копирования из A. Mike Cooper 15 лет назад 0
Ах, так что, если я правильно понимаю, вы копируете более одного файла одновременно? Вот откуда проблема? Josh 15 лет назад 0
Да, это проблема. Я не могу сохранить все файлы на B, но эта копия займет достаточно много времени, поэтому я не хочу сидеть и присматривать за ней, наблюдая за завершением каждого файла, а затем копируя его. Может быть, я пойду с вашей расширенной версией. Mike Cooper 15 лет назад 0
2
Josh

Есть ли lsofна машине B показывают, что УПП открыть файл? если это так, вы можете посмотреть lsofи увидеть, когда scp закроет файл. Если нет, вы можете посмотреть размер файла и после того, как он не изменился в течение заданного периода времени (например, 5 минут), скопируйте его из B в C.

Третий вариант - скопировать файлы из A в каталог «in_progress» на C. После завершения копирования на A выполните mvкоманду, чтобы выйти из каталога «in_progress».

К сожалению, `lsof`, по-видимому, не существует на компьютере B. Что касается вашего третьего варианта, он не сработает, потому что, если я позволю копии закончить, прежде чем что-то делать, я значительно перегружу свое разрешенное пространство на B (что-то вроде 10: 1). Поэтому любое решение, которое у меня есть, должно работать во время копирования. Mike Cooper 15 лет назад 0
Идея подождать 5 минут хороша (я подумал о чем-то похожем), но я не совсем уверен, как это будет сделано. Есть идеи? Mike Cooper 15 лет назад 0
Да, я мог бы написать для вас быстрый и грязный скрипт ruby ​​- есть ли на машине B рубин? Josh 15 лет назад 0
Нету. Это не под моим контролем и, кажется, не имеет ничего из того, что я пытаюсь использовать. Я надеялся, что в bash для этого есть что-то встроенное. Хотя я мог бы запустить скрипт со своего локального компьютера ... Я поэкспериментирую с этим. Mike Cooper 15 лет назад 0
Я посмотрю, смогу ли я написать что-то подобное только в bash. Однако мое мастерство в рубине превосходит мое мастерство в Bash. stackoverflow.com может помочь с таким сценарием. Josh 15 лет назад 0
На самом деле я думаю, что я понял это, см. Мой ответ. Mike Cooper 15 лет назад 0
2
Josh

Я просто подумал о другом, совершенно не связанном варианте. Не использует scp вообще. Пожалуйста, дайте мне знать, если это будет работать:

  1. на B создайте где-нибудь трубу fifo: mkfifo / tmp / xfer

  2. на A, не используйте scp, вместо этого, tar -cz files | ssh B 'cat > /tmp/xfer

  3. на С, беги ssh B 'cat /tmp/xfer' | tar -xz

Таким образом, данные не хранятся на B, они просто проходят через канал. Недостатком является то, что вы можете иметь только одну копию за раз ...

Вам нужно будет убедиться, что процесс на C возрождается при каждом его завершении.

То, как вы это объясняете, кажется, работает ... но мне кажется, что это немного "темная магия". Я думаю, что нашел другое решение, которое работает оригинальным способом, но я обязательно оставлю этот фрагмент для дальнейшего использования. Mike Cooper 15 лет назад 0
Этот способ на самом деле не «темная магия», он просто использует каналы, которые являются стандартным средством ОС. Но мне больше нравится ваше другое решение, оно меньше кода и, вероятно, проще в обслуживании. Josh 15 лет назад 0
О, я не просто имею в виду, что это волшебство, потому что я никогда не играл с любопытными трубками, и это не то, что используется так часто, как другие вещи. Хоть чему-то научиться сейчас. Кроме того, обслуживание не является большой проблемой. Это будет настроено примерно на день, и все. Mike Cooper 15 лет назад 0
2
Mike Cooper

Подумав об опубликованных ответах (в частности, об идее @ Джоша по просмотру измененного времени), я пытался запустить манипуляции с файлами B на C. Понимаете, B является анемичным, насколько доступны инструменты, поэтому ничто, казалось, не могло выполнить эту работу был здесь. Я пришел к этому решению. Эта идея не моя, я нашел ее в поиске Google перед этим вопросом. Я отказался от этого ранее, так как машина B не имела findутилиты.

Сначала смонтируйте соответствующий каталог на B на C, чтобы он отображался как локальная файловая система. Я использовал sshfsдля этого (кстати, замечательный инструмент). Это позволит мне использовать утилиты C вместо B.

Во-вторых, команда find /the/folder/* -mmin +5будет соответствовать всем файлам, измененным более 5 минут назад. Таким образом, команда find /the/folder/* -mmin +5 -exec {} /the/other/folder \;переместит все файлы, которые были изменены более 5 минут назад, в другую папку (которая на самом деле находится на C, вместо sshfs, смонтированного из B.

Наконец, я настроил скрипт cron для запуска вышеуказанного скрипта каждые 10 минут сегодня и завтра. Строка в моем crontab выглядит следующим образом.

*/5 * 22,23 9 * find /the/folder/* -mmin +5 -exec mv {} /the/other/folder \; 

Надеюсь, это сработает. Следующий файл еще не закончен, так что я не могу комментировать, действительно ли он работает в сочетании со скриптом cron, но я сделал несколько файлов вручную и посеял их, и они переместились нормально. скрестить пальцы

Изменить: это работает, хотя, как это было изначально, были некоторые ошибки, теперь они исправлены.

Это звучит как отличное решение Josh 15 лет назад 0
1
tuomassalo

Нет необходимости в mkfifo. На машине B запустите это:

ssh A 'tar -cz files' | ssh C 'tar -xz' 

Вы можете найти опцию tar -C полезной.

Если вам нужно начать копирование на машине A, просто выполните:

tar -cz files' | ssh B "ssh C 'tar -xz'" 

Остерегайтесь правильного цитирования, хотя.

0
gbarry

Копия будет запущена как другой процесс, или вы можете принудительно запустить его, используя подоболочку. Затем вы можете использовать ps, чтобы «наблюдать» за процессом и видеть, когда он исчезает.

Также я считаю, что в * nix вы можете удалить файл во время его копирования. Система не удалит его, пока программа копирования не закроет его. Конечно, если копия не удалась, вы потеряете файл, так что не лучшая идея.

Мне не нужно копировать, как только вся копия сделана, потому что я копирую много файлов. Мне нужно знать, когда каждый отдельный файл готов. Mike Cooper 15 лет назад 0

Похожие вопросы