Если Apache записывает какой-то файл в одно место и не завершил его запись, а затем включается rsync
, rsync
скопирует все, что там находится.
Это означает, что если Apache имеет дело с 5-мегабайтным файлом, записывается только 2 мегабайта и rsync
, то частичный 2-мегабайтный файл будет скопирован. Таким образом, этот файл может показаться «поврежденным» на конечном сервере.
В зависимости от размера файлов, которые вы используете, вы можете использовать опцию --inplace
в rsync
чтобы сделать следующее:
Этот параметр изменяет способ, которым rsync передает файл, когда необходимо обновить данные файла: вместо метода по умолчанию создания новой копии файла и перемещения его на место после завершения, rsync вместо этого записывает обновленные данные непосредственно в место назначения. файл.
Преимущество этого состоит в том, что если в файле объемом 5 МБ копируется только 2 МБ при первом запуске, то при следующем запуске будет загружено 2 МБ и будет продолжаться копирование файла до тех пор, пока не будут заполнены все 5 МБ.
Недостатком является то, что это может создать ситуацию, когда кто-то обращается к веб-серверу во время копирования файла, и тогда он увидит частичный файл. На мой взгляд, rsync
лучше всего работает по умолчанию, кэшируя «невидимый» файл, а затем сразу же перемещая его на место. Но --inplace
подходит для сценариев, когда большие файлы и ограничения пропускной способности могут помешать тому, чтобы большой файл легко копировался из квадратного.
Тем не менее, вы утверждаете это; Акцент мой:
Каждые пять минут cron run rsync…
Итак, я предполагаю, что у вас есть некоторый bash-скрипт для управления этой работой cron? Дело в том, что rsync
достаточно умен, чтобы копировать только те файлы, которые нужно скопировать. И если у вас есть скрипт, который запускается каждые 5 минут, похоже, вы пытаетесь избежать rsync
друг на друга, если она идет быстрее. Это означает, что если вы запускаете его каждую минуту, существует риск того, что один или несколько процессов rsync
будут по-прежнему работать из-за размера файла или скорости сети, и следующий процесс будет просто конкурировать с ним; гоночное состояние.
Один из способов избежать этого - обернуть всю команду rsync
в скрипт bash, который проверяет блокировку файла; ниже приведен шаблонный сценарий bash, который я использую для подобных случаев.
Обратите внимание, что некоторые люди порекомендуют использовать flock
но поскольку flock
не установлен на некоторых системах, которые я использую - и я часто переключаюсь между Ubuntu (у которого он есть) и Mac OS X (без него) - я использую эту простую среду без каких-либо реальных вопрос:
LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'
if mkdir ${LOCK_DIR} 2>/dev/null; then
# If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
echo $$ > ${PID_FILE}
echo "Hello world!"
rm -rf ${LOCK_DIR}
exit
else
if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
# Confirm that the process file exists & a process
# with that PID is truly running.
echo "Running [PID "$(cat ${PID_FILE})"]" >&2
exit
else
# If the process is not running, yet there is a PID file--like in the case
# of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
rm -rf ${LOCK_DIR}
exit
fi
fi
Идея состоит в том, что общее ядро - где у меня есть echo "Hello world!"
- где сердце вашего сценария. В остальном это механизм блокировки / логика на основе mkdir
. Хорошее объяснение концепции в этом ответе:
mkdir создает каталог, если он еще не существует, и если он существует, он устанавливает код выхода. Что еще более важно, он делает все это в одном атомном действии, что делает его идеальным для этого сценария.
Так что в случае вашего процесса rsync
я бы порекомендовал использовать этот скрипт, просто изменив команду echo
на вашу команду rsync
. Кроме того, измените LOCK_NAME
на что-то вроде RSYNC_PROCESS
и тогда все готово .
Теперь, когда ваш rsync
обернут в этот скрипт, вы можете настроить выполнение задания cron каждую минуту без риска возникновения состояния гонки, когда два или более процесса rsync
борются за одно и то же. Это позволит вам увеличить скорость или обновления rsync
что не устранит проблему частичной передачи файлов, но поможет ускорить весь процесс, чтобы в какой-то момент весь файл можно было правильно скопировать.