Назад | Перейти на главную страницу

ssh и tar для постепенной передачи (например, rsync)

В среде хостинга, в которой нет клиента rsync, я хотел бы выполнить действие, аналогичное тому, что делает rsync: отправлять только те файлы, которые были изменены.

Я бы выполнил эту однострочную запись в текущем каталоге. Это обновит archive.tar.gz измененными файлами, затем скопирует файл на удаленный сайт и, наконец, распакует его, оставив синхронизированные каталоги. У меня есть видение этого с использованием нескольких каналов, но я полагаю, что мне понадобится архив, чтобы действительно использовать инкрементную функцию.

Я теряюсь в синтаксисе tar при использовании инкрементального.

Это модифицированная версия DigitalRossсценарий:

#!/bin/bash
TarFile=fun.tgz
TheScript=$0
saveIFS="$IFS"
IFS=$'\n'
files=($( find -maxdepth 1 -type f -newer $TheScript -print ))
tmpfile=$(mktemp)
IFS="$saveIFS"
tar cvfz $TarFile "${files[@]}" && touch -r $tmpfile $TheScript
rm $tmpfile

это уменьшает шанс условий гонки за счет сохранения результата find в массив и сразу же создав временный файл. Но это, конечно, не гарантия. Также этот скрипт избегает использования ls. Еще одно преимущество состоит в том, что он обновляет метку времени сценария только в том случае, если tar успешно. Он также будет обрабатывать имена файлов с пробелами.

bozosync.sh

Хм, если вы хотите переместить только измененные файлы, зачем команде tar обновлять архив? Если пересылаются только измененные файлы, разве tar-архив не будет состоять только из них и не обязательно будет создаваться каждый раз с нуля?

Если я правильно понимаю, вы хотите что-то вроде этого, я называю это bozosync.sh:

TarFile=fun.tgz
TheScript=$0
result=
ls -1 . | (
  while read f; do
    if [ -f "$f" -a $f -nt $TheScript ]; then
      result="$result $f"
    fi
  done
  tar cvfz $TarFile $result
  touch $TheScript
)

Это помещает каждый простой файл в текущий каталог в tar-архив для каждого файла, который новее, чем сам скрипт, а затем запускается touch(1) в скрипте, чтобы обновить время его модификации. У этого действительно есть состояние гонки, в котором файл, который был изменен между тестом и касанием, будет проигнорирован в следующий раз. Если это проблема, вы можете обойти ее, скопировав сценарий до цикла, а затем переместив его обратно в себя в конце. (Тогда у вас все еще есть гонка, но ошибка более мягкая, она может просто включать файл, который на самом деле не изменился.)

Я внес несколько изменений после тестирования, но это отлично работает, спасибо.

#!/bin/bash
TarFile=transfer-me.tar.gz
TheScript=$0
saveIFS="$IFS"
IFS=$'\n'
files=($(find . -maxdepth 1 -newer $TheScript -print))
unset files[0]; #remove "."
tmpfile=$(mktemp temp.XXXXXX)
IFS="$saveIFS"
elements=${#files[@]}
if [ "$elements" -gt "0" ]; then
    tar cvfz $TarFile --exclude ".svn" --exclude ".swp" --exclude "Icon?" --exclude ".DS_Store" --exclude "$TarFile" "${files[@]}" && touch -r $tmpfile $TheScript
fi
rm $tmpfile;