Поведінка rsync з файлом, який ще пишеться?


13

Якщо Apache знаходиться в середині запису великого файлу і на цьому файлі виконується завдання cron rsync, чи rsync намагається скопіювати файл?

Приклад

  • Apache-1: в файл записується великий файл /var/www.
  • Apache-2: Клон Apache-1. Кожні п'ять хвилин запускається rsync за допомогою крон, щоб /var/wwwсинхронізуватися.

Відповіді:


21

Якщо Apache пише якийсь файл в одне місце і не закінчив його писати, а потім rsync запускає, rsyncскопіює все, що там сидить.

Значить, якщо Apache має справу з файлом 5 МБ, записано лише 2 МБ і rsyncзапускається, частковий файл 2 МБ буде скопійовано. Отже, цей файл здається, що він "пошкоджений" на сервері призначення.

Залежно від розміру файлів, які ви використовуєте, ви можете скористатися --inplaceопцією, rsyncщоб зробити наступне:

Цей параметр змінює, як rsync передає файл, коли дані файлу потребують оновлення: замість методу за замовчуванням створити нову копію файлу та перемістити її на місце, коли вона завершена, rsync замість цього записує оновлені дані безпосередньо до місця призначення файл.

Перевага від цього полягає в тому, що якщо у файлі 5 МБ було скопійовано лише 2 МБ при першому запуску, наступний запуск набереться на рівні 2 МБ і продовжить копіювати файл до повного 5 МБ.

Негативним є те, що це може створити ситуацію, коли хтось звертається до веб-сервера під час копіювання файлу, і тоді вони побачать частковий файл. На мою думку, rsyncнайкраще працює в тому, що поведінка за замовчуванням кешується «невидимим» файлом, а потім відразу переміщується на місце. Але --inplaceце добре для сценаріїв, коли великі файли та обмеження пропускної здатності можуть стояти на шляху, коли великий файл легко копіюється з квадратного.

Це сказало, що ви констатуєте це; акцент мій:

Кожні п’ять хвилин rsync виконує крон…

Тож я припускаю, що у вас є якийсь баш сценарій для управління цією роботою cron? Що ж, річ rsyncрозумна, щоб лише копіювати файли, які потрібно скопіювати. І якщо у вас є сценарій, який працює кожні 5 хвилин, то, здається, ви намагаєтеся уникати rsyncкроку один на одного, якщо він пройде швидше. Це означає, що якщо ви запускаєте його щохвилини, є ризик того, що один або кілька rsyncпроцесів все одно будуть працювати через розмір файлу або швидкість мережі, і наступний процес буде просто конкурувати з ним; стан перегонів.

Один із способів уникнути цього - загортати всю свою rsyncкоманду в скрипт bash, який перевіряє блокування файлу; нижче - рамка сценарію bash script 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оновлення, що не усуне проблему передачі часткових файлів, але це допоможе прискорити загальний процес, тому повний файл можна буде належним чином скопіювати в якийсь момент.


2
Дякую, що вказали на можливість запуску декількох rsyncs, не думали про це. Сценарій звучить чудово. Я просто намагався зрозуміти проблеми синхронізації завантаженого сайту з rsync, і це, здається, полегшує їх. Чудовий бонус. Все ще відчуваю, що, можливо, це неправильний підхід ... але подивимось :)
Луї Ваверу

@Louis Ласкаво просимо! Також, якщо ви хочете тримати синхронізацію папок на основі негайних змін файлів, я б дуже рекомендував вивчити використання та адаптацію lsyncd. Це дозволяє мати "гарячі папки", які по-справжньому звертають увагу на активність у них, а потім діють на ці файли, коли вносяться зміни. Я rsyncдуже багато використовую, як було зазначено у моїй відповіді, але я використовую lsyncdу випадках, коли потрібна некронова / більш негайна форма дії.
JakeGould

3

Так - і файл може бути пошкоджений, якщо rsync одночасно читає файл, у який записується файл.

Ви можете спробувати це: /unix//a/2558

Ви також можете скопіювати його за допомогою lsof:

lsof /path/to file

Код виходу 0 означає, що файл використовується, а вихідний код 1 означає, що в цьому файлі немає жодної активності.


Я не бачу, чому файл стане пошкодженим, якщо rsync просто читає його
orestisf
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.