cp/rsync асинхронные?

Вопрос или проблема

Мы запускаем скрипт резервного копирования, который сначала копирует файл в назначение, а затем выполняет tar.

DIR2BCK='/foo/bar'
TMPDIR=$(mktemp -d)
rsync -a ${DIR2BCK} ${TMPDIR}/ > /dev/null 2>&1
tar czf /tmp/foo.backup.tar ${TMPDIR}

После выполнения этой последней команды иногда появляется следующее предупреждение:

/tmp/tmp.blqspkA136: файл изменился, пока мы его читали

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

Если я вставлю команду sleep между строками rsync/cp и tar, предупреждение не отображается, но я считаю это не совсем чистым решением.

Некоторые факты:

  • Я пытался добавить команду sync между командами rsync и tar с тем же результатом.
  • Как предложил @jcbermu, я также попытался изменить скрипт так, чтобы две строки выглядели следующим образом:

    rsync -a ${DIR2BCK} ${TMPDIR}/ > /dev/null 2>&1 &
    wait
    

    Я запускал скрипт несколько раз, и некоторые из них показали то же самое поведение, заявляя, что файл изменился во время копирования.

  • Используемая файловая система – EXT4 как для ${TMPDIR}, так и для ${DIR2BCK}.

  • ${DIR2BCK} находится на удаленной файловой системе, фактически это точка монтирования samba удаленной машины. ${TMPDIR} находится на локальной файловой системе. Тем не менее, изменение ${DIR2BCK} на локальную файловую систему не дает никаких результатов.
  • Все файловые системы основаны на аппаратном RAID-5.

Эти команды действительно синхронные? Если нет, есть ли способ сделать их таковыми или альтернативная команда?

Одно решение – переписать его следующим образом:

rsync -a ${DIR2BCK} ${TMPDIR}/ > /dev/null 2>&1 ; tar czf foo.backup.tar ${TMPDIR}

Таким образом, tar не начнется, пока не завершится rsync.


Другое решение – отправить cp/rsync в фон и подождать, пока он завершится с помощью команды wait.

Например:

rsync -a ${DIR2BCK} ${TMPDIR}/ > /dev/null 2>&1 &
wait
tar czf foo.backup.tar ${TMPDIR}

Последний & в строке rsync отправляет выполнение в фон (он становится дочерним текущей сессии), а затем wait заставляет эту сессию оболочки ждать, пока все дочерние процессы не завершатся, чтобы продолжить.

Я поставил команду sleep между строками rsync/cp и tar, предупреждение не появляется, но я считаю это не совсем чистым решением.

Хорошо для вас или для соблюдения стандартов. Что будет, если, вместо sleep, вы используете:

sudo sync; echo 3 | sudo tee /proc/sys/vm/drop_caches

Считаете ли вы это хорошим решением?

Примечание: /proc/sys/vm/drop_caches, похоже, используется в Ubuntu и не ожидается, что это будет подход, который работает на всех Unix-системах (хотя, возможно, на всех Linux-системах). Я упоминаю это после того, как прочитал https://ubuntuforums.org/showthread.php?t=589975 и, после того как прочитал первоначальный отчет, который ставил под сомнение безопасность этого, прочитал еще сообщения на форуме, которые подтверждают его безопасность.

Ответ или решение

Являются ли команды cp/rsync асинхронными?

При выполнении скрипта резервного копирования, который сначала копирует файл в назначенную директорию, а затем создает архив tar, можно столкнуться с предупреждениями о том, что файл изменился в процессе его чтения. Давайте рассмотрим, как это связано с синхронностью работы команд cp и rsync.

Основные моменты

  1. Синхронное выполнение: По умолчанию команды cp и rsync работают синхронно, что означает, что выполнение следующей команды начнется только после завершения предыдущей. Однако это правило имеет прецеденты, например, если вы добавите амперсанд (&), команда начнет выполняться в фоновом режиме, что делает её асинхронной.

  2. Проблема с "файл изменился": В вашем случае предупреждение о том, что файл изменился при его чтении, может возникать из-за нескольких факторов:

    • Сетевые задержки: Так как DIR2BCK находится на удаленной файловой системе Samba, возможны задержки в синхронизации данных, которые могут приводить к тому, что файл может измениться между моментом копирования и созданием архива tar.
    • Кеширование: Операционная система или файловая система может кешировать изменения, что также приводит к этому предупреждению.
  3. Методы устранения проблемы:

    • Жесткая синхронизация: Использование конструкции типа rsync ... ; tar ... гарантирует, что команда tar запустится только после завершения rsync, тем самым предотвращая любые изменения в файле после его копирования.
    • Команда wait: Если использовать rsync ... & wait, то, после отправки rsync в фоновый режим, последующий вызов wait заставит основную оболочку ждать завершения всех фоновых процессов, прежде чем продолжить.

Потенциальные улучшения

Ваша идея с sleep может временно устранить проблему, но это не чистое решение, так как оно лишь добавляет паузу в выполнение. Использование sync между командами также не всегда гарантирует нужный эффект, особенно при работе с удаленными файловыми системами.

Оптимальным решением было бы следующее:

rsync -a ${DIR2BCK} ${TMPDIR}/ > /dev/null 2>&1; tar czf /tmp/foo.backup.tar ${TMPDIR}

или с использованием фонового процесса:

rsync -a ${DIR2BCK} ${TMPDIR}/ > /dev/null 2>&1 & wait; tar czf /tmp/foo.backup.tar ${TMPDIR}

Оба подхода обеспечивают, что команда tar не начнет выполняться, пока rsync не завершит свою работу.

Заключение

Команды cp и rsync, по своей природе, являются синхронными, но при использовании конструкции с & они могут работать асинхронно. Для избежания предупреждений и проблем с целостностью данных лучше использовать подходы, обеспечивающие завершение одной команды перед началом другой. Это также минимизирует риски, связанные с сетевыми задержками и кешированием, и повышает надежность процесса резервного копирования.

Оцените материал
Добавить комментарий

Капча загружается...