Десь прямо зараз завдання резервного копіювання «зелене», але мовчки пропускає файли. Інша команда відправляє реліз, зібраний із папки, яка «має відповідати продакшену». А хтось збирається скопіювати терабайт двічі, бо не довіряє першій копії.
Порівняння двох папок звучить як базове завдання. У виробництві це пастка. Правильний метод залежить від того, що саме ви доводите: присутність, ідентичність по байтах чи «достатньо схоже» для деплою. Помилковий вибір дає або хибну впевненість, або дорогий повільний результат, що прийде після інциденту.
Що саме ви доводите (і чому це важливо)
«Порівняти дві папки» — це не одне завдання. Це щонайменше п’ять різних речей. Якщо ви не скажете, що саме маєте на увазі, за замовчуванням оберете або повільний шлях (захешувати все), або такий, що вводить в оману (довіряти розмірам файлів). Ось таксономія, якою я керуюся під час викликів.
1) Існування: чи всі очікувані файли присутні?
Це проблема «відсутніх файлів»: часткова копія, невдале резервне копіювання, неповна синхронізація артефактів. Вас хвилюють імена файлів і, можливо, структура директорій. Зазвичай вас ще не цікавить вміст файлів.
Добрі інструменти: rsync --dry-run, comm на відсортованих списках файлів, манифести від find.
2) Рівність метаданих: чи співпадають часи, права та власники?
Це важливо при відновленні систем, міграції домашніх директорій або переміщенні даних між NFS-серверами, де режими й власники — це «справжні дані». Якщо права відрізняються, ваш застосунок падає з помилками, що виглядають як «випадкові збої». Вони не випадкові.
Добрі інструменти: rsync -a --dry-run, stat, getfacl, якщо ACL мають значення.
3) Рівність вмісту: чи байти ідентичні?
Це перевірка цілісності. Ви доводите, що два файли однакові, навіть якщо часи або імена файлів підводять. Це повільніший підхід, але єдиний, що закриває суперечки після відновлення.
Добрі інструменти: контрольні суми (SHA-256), rsync --checksum (з обережністю), вибіркове хешування, коли обмежений час.
4) Логічна рівність: чи дають вони однаковий результат?
Для збірок, контейнерів і наборів даних вам може бути байдуже до ідентичності по байтах. Вас цікавить, чи поводиться застосунок однаково. Це інший доказ. Порівняння папок усе ще допоможе, але не плутайте «виглядає однаково» з «справді однаково».
5) Стабільність під час змін: чи порівнюєте рухливу ціль?
Порівнювати папку під час запису файлів — це як вимірювати рибу, поки вона тікає. Іноді це можна (снапшоти, зупинка записів, іммутебл-зборки). Іноді ні, і правильна відповідь — «зупиніть світ, а потім порівнюйте».
Одна оперативна цитата для запам’ятовування:
Парафразована ідея — Gene Kim: високоефективні операції скорочують цикли зворотного зв’язку та роблять роботу видимою, щоб проблеми проявлялися до того, як стануть інцидентами.
Порівняння папок — це видимість. Не гламурно. Але це різниця між «ми думаємо, що скопіювали» і «ми можемо довести, що скопіювали».
Спершу швидкі методи: як вибрати інструмент
Правило №1: не хешуйте петабайт через невпевненість
Контрольні суми — золотий стандарт, але це також «податок читання кожного байта». Якщо єдине питання «чи ми нічого не пропустили?», хешування — самошкода. Почніть з манифесту відносних шляхів і розмірів; потім ескалюйте.
Правило №2: rsync --dry-run — найкорисніший інструмент порівняння папок на Землі
Він говорить мовою операцій: «Що змінилося б, якби я синхронізував це?» Це diff з наслідками. Використовуйте локально, через SSH, через точку монтування. Коли напруга зростає, він дає список дій.
Правило №3: часові позначки часто брешуть
Інструменти копіювання іноді зберігають mtime, іноді ні. Файлові системи по-різному округлюють mtime. Зміни часових поясів і дрейф годинника трапляються. Якщо ви порівнюєте mtimes, трактуйте результати як підказку, а не вердикт.
Правило №4: права та ACL — це дані
Якщо ви відновлюєте сервіс, неправильний власник — це «втрата даних» з кращим маркетингом. Якщо порівняння ігнорує ACL, ви відправите проблему під виглядом успішного відновлення.
Правило №5: якщо набір даних «живий», використовуйте снапшоти (або прийміть невизначеність)
На ZFS снапшоти роблять це просто. На LVM — теж можна. В об’єктному сховищі в хмарі потрібні версіоновані манифести. Без стабільного погляду в точку часу ваше порівняння показуватиме лише сьогоднішні записи.
Жарт №1: Хешувати все «просто щоб бути в безпеці» — це як щодня зважувати машину, щоб перевірити рівень палива. Точно, так. Потрібно — ні.
Практичні завдання (команди, вивід, рішення)
Нижче наведені завдання промислового рівня. Кожне містить команду, реалістичний фрагмент виводу та рішення, яке з нього випливає. Виконуйте їх з чіткою метою: знайти відсутні файли, змінені файли, дрейф метаданих або проблеми цілісності.
Завдання 1: Швидке виявлення відсутніх файлів за допомогою rsync (локально)
cr0x@server:~$ rsync -a --dry-run --itemize-changes /data/src/ /data/dst/
sending incremental file list
*deleting old/unused.log
>f+++++++++ reports/2026-01.csv
>f..t...... images/logo.png
sent 1,204 bytes received 88 bytes 2,584.00 bytes/sec
total size is 9,812,441,102 speedup is 7,589,904.72 (DRY RUN)
Що це означає: >f+++++++++ — файл, який було б створено в destination (відсутній там). >f..t...... означає, що часові позначки відрізняються (вміст може бути або не бути відмінним). *deleting вказує, що в destination є зайві файли, яких немає в source (показується лише якщо додати прапори видалення; див. наступне завдання).
Рішення: Якщо ви перевіряєте копію, відсутні файли (+++++++++) — це підстава зупинити процес. Різниця лише в часових позначках вимагає додаткових перевірок (розмір/хеш) залежно від вашої толерантності до ризику.
Завдання 2: Виявити зайві файли в destination (безпечно) за допомогою rsync
cr0x@server:~$ rsync -a --dry-run --delete --itemize-changes /data/src/ /data/dst/
sending incremental file list
*deleting tmp/debug.dump
*deleting cache/.DS_Store
sent 1,112 bytes received 64 bytes 2,352.00 bytes/sec
total size is 9,812,441,102 speedup is 8,342,119.31 (DRY RUN)
Що це означає: З --delete rsync запропонує видалити файли в destination, яких немає в source. У dry-run він лише повідомляє.
Рішення: Якщо destination має бути дзеркалом (бекапи, репліки), ці зайві файли — дрейф. Якщо destination — архів, ймовірно, ви не захочете застосовувати видалення.
Завдання 3: Швидко порівняти дві директорії за допомогою diff -rq
cr0x@server:~$ diff -rq /data/src /data/dst | head
Only in /data/src/reports: 2026-01.csv
Files /data/src/images/logo.png and /data/dst/images/logo.png differ
Only in /data/dst/tmp: debug.dump
Що це означає: Відсутні файли та рядки «differ». diff порівнює вміст і читає файли; на великих деревах він може бути повільнішим за rsync, який використовує метадані для виявлення змін.
Рішення: Використовуйте, коли потрібен простий звіт «однаково/різно» і набір даних помірний. Якщо це кілька терабайт — віддайте перевагу манифестам rsync та вибірковому хешуванню.
Завдання 4: Побудувати стабільний манифест шляхів і розмірів (дешево, зазвичай достатньо)
cr0x@server:~$ cd /data/src
cr0x@server:~$ find . -type f -printf '%P\t%s\n' | sort > /tmp/src.pathsizes
cr0x@server:~$ wc -l /tmp/src.pathsizes
84217 /tmp/src.pathsizes
Що це означає: Одна строка на файл: відносний шлях і розмір. Сортування робить порівняння можливим.
Рішення: Якщо манифести src і dst збігаються точно, ви довели «ті самі файли, ті самі розміри». Не байт-ідентичність, але сильний доказ для копій, де корупція малоймовірна і час обмежений.
Завдання 5: Порівняти манифести за допомогою comm, щоб знайти відсутні файли
cr0x@server:~$ cd /data/dst
cr0x@server:~$ find . -type f -printf '%P\t%s\n' | sort > /tmp/dst.pathsizes
cr0x@server:~$ comm -3 /tmp/src.pathsizes /tmp/dst.pathsizes | head
reports/2026-01.csv 12044
tmp/debug.dump 4096
Що це означає: Рядки з префіксом табуляції існують лише у другому файлі; рядки без табуляції — лише в першому. Тут: report відсутній у dst; debug.dump — зайвий у dst.
Рішення: Відсутні файли: перекопіюйте або пересинхронізуйте. Зайві файли: виріште, чи dst має бути точним дзеркалом; якщо так — видаліть або відтворіть dst із джерела істини.
Завдання 6: Швидко визначити «той самий шлях, інший розмір»
cr0x@server:~$ join -t $'\t' -j 1 \
<(cut -f1,2 /tmp/src.pathsizes) \
<(cut -f1,2 /tmp/dst.pathsizes) | awk -F'\t' '$2 != $3 {print $1, $2, $3}' | head
images/logo.png 18432 18312
db/seed.sql 901122 901114
Що це означає: Той самий відносний шлях існує в обох, але розміри файлів відрізняються.
Рішення: Трактуйте як змінений вміст. Якщо має бути ідентичним, пересинхронізуйте ці шляхи й потім захешуйте їх для підтвердження.
Завдання 7: Цільове хешування лише підозрілих файлів (швидка ескалація)
cr0x@server:~$ sha256sum /data/src/images/logo.png /data/dst/images/logo.png
a1c3d2d19c9f7f0c2a2a0ddc7f6d4b2e9f1b2d3c4a5b6c7d8e9f001122334455 /data/src/images/logo.png
b88f2bd42a9e0f1c9d8e7f6a5b4c3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c /data/dst/images/logo.png
Що це означає: Різні хеші: різні байти, крапка.
Рішення: Якщо dst — бекап/репліка, розслідуйте помилку передачі/зберігання або несинхронізоване оновлення. Якщо це артефакт деплою, зупиніться і перебудуйте з єдиного джерела істини.
Завдання 8: Повний манифест контрольних сум дерева (повільно, остаточно)
cr0x@server:~$ cd /data/src
cr0x@server:~$ find . -type f -print0 | sort -z | xargs -0 sha256sum > /tmp/src.sha256
cr0x@server:~$ head -3 /tmp/src.sha256
9f2a... ./bin/app
44c1... ./conf/app.yaml
e11b... ./images/logo.png
Що це означає: Стабільний відсортований манифест контрольних сум для всього дерева. Сортування з null-роздільниками уникає проблем з шляхами і дрейфом порядку.
Рішення: Використовуйте, коли потрібен доказ «судового» рівня (відновлення, відповідність, промоція артефактів). Прийміть, що це I/O-інтенсивно; плануйте його, не дивуйте прод.
Завдання 9: Перевірити, чи destination відповідає манифесту контрольних сум
cr0x@server:~$ cd /data/dst
cr0x@server:~$ sha256sum -c /tmp/src.sha256 | head
./bin/app: OK
./conf/app.yaml: OK
./images/logo.png: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
Що це означає: OK — точна відповідність. FAILED — вміст відрізняється. Якщо з’явиться «No such file», файл відсутній.
Рішення: Будь-який FAILED або відсутній файл — жорстка помилка для верифікації бекапу. Перекопіюйте ці файли; якщо помилки повторюються, підозрюйте проблеми зі зберіганням/носієм або тиху корупцію.
Завдання 10: Порівняти папки через SSH за допомогою rsync (dry-run)
cr0x@server:~$ rsync -a --dry-run --itemize-changes -e ssh /data/src/ backup01:/data/dst/
sending incremental file list
>f+++++++++ reports/2026-01.csv
>f..t...... images/logo.png
sent 1,882 bytes received 112 bytes 3,988.00 bytes/sec
total size is 9,812,441,102 speedup is 4,920,184.83 (DRY RUN)
Що це означає: Ті самі семантики, але тепер ви верифікуєте віддалений стан. Зауважте: rsync порівнює метадані за замовчуванням, а не контрольні суми.
Рішення: Використовуйте як первинний віддалений аудит. Якщо з’являються підозрілі результати — виконайте цільове хешування через SSH для підозрілих файлів (або згенеруйте манифести на кожній стороні).
Завдання 11: Впіймати дрейф прав (клас «файли є, але не працюють»)
cr0x@server:~$ stat -c '%a %U:%G %n' /data/src/conf/app.yaml /data/dst/conf/app.yaml
640 app:app /data/src/conf/app.yaml
600 app:app /data/dst/conf/app.yaml
Що це означає: Той самий власник, різні режими. Це може зламати читання, запис або очікування керування конфігурацією.
Рішення: Якщо права мають співпадати — виправте метод копіювання: rsync -a (і запускайте як root, коли власність важлива), або зберігайте ACL/xattr, якщо середовище їх використовує.
Завдання 12: Порівняти розширені атрибути (xattrs), коли вони важливі
cr0x@server:~$ getfattr -d -m - /data/src/bin/app 2>/dev/null
# file: data/src/bin/app
security.capability=0sAQAAAgAgAAAAAAAAAAAAAAAAAAA=
cr0x@server:~$ getfattr -d -m - /data/dst/bin/app 2>/dev/null
# file: data/dst/bin/app
Що це означає: У джерелі є Linux capability xattr; у destination його немає. Бінарний файл може не змогти прив’язатися до низьких портів або поводитися інакше.
Рішення: Використовуйте rsync -aX (xattrs) і, можливо, -A (ACL). Якщо ви на файлових системах, що втрачають xattr, припиніть зображувати це як достовірну копію.
Завдання 13: Знайти файли, що змінилися нещодавно (тріаж під час інциденту)
cr0x@server:~$ find /data/src -type f -mmin -60 -printf '%TY-%Tm-%Td %TH:%TM %p\n' | head
2026-02-05 09:12 /data/src/reports/2026-02.csv
2026-02-05 09:21 /data/src/tmp/run.log
Що це означає: Файли змінені за останню годину. Чудово підходить для «чому порівняння постійно змінюється?»
Рішення: Якщо дерево активно змінюється — перестаньте порівнювати його в реальному часі. Використовуйте снапшоти, зупиніть записи або порівнюйте лише іммутебл-піддерева (наприклад артефакти релізів).
Завдання 14: Швидка перевірка «чи ці директорії на різних ФС з різною семантикою?»
cr0x@server:~$ df -T /data/src /data/dst
Filesystem Type 1K-blocks Used Available Use% Mounted on
tank/data zfs 9767548928 512334112 9255214816 6% /data/src
backup:/data nfs4 9767548928 515220480 9252328448 6% /data/dst
Що це означає: Source — ZFS; destination — NFS. Очікуйте різну точність таймстемпів, дивності з відображенням власників і кешування атрибутів.
Рішення: Якщо результати порівняння «шумні», верифікуйте критичні файли контрольними сумами і налаштуйте опції монтовання NFS за потреби. Також: не припускайте, що POSIX-особливості поводяться однаково.
Завдання 15: Оцініть вартість вашого методу порівняння (не гадати)
cr0x@server:~$ /usr/bin/time -v rsync -a --dry-run /data/src/ /data/dst/ >/dev/null
Command being timed: "rsync -a --dry-run /data/src/ /data/dst/"
User time (seconds): 0.82
System time (seconds): 4.11
Percent of CPU this job got: 62%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:07.96
File system inputs: 126544
File system outputs: 0
Що це означає: Багато файлових введень навіть для dry-run. Це метадані I/O. На холодних кешах це може навантажити ваше сховище.
Рішення: Якщо сканування метаданих заштовхує прод, плануйте порівняння в непіковий час, прогрівайте кеші або підтримуйте ролінговий манифест, що оновлюється інкрементально.
Завдання 16: Коли потрібне байт-рівне порівняння для одного великого файлу
cr0x@server:~$ cmp -n 1048576 /data/src/big.img /data/dst/big.img && echo "first 1MiB matches"
first 1MiB matches
Що це означає: Перший 1 МіБ збігається. Це не повна верифікація, але швидка перевірка при тріажі.
Рішення: Використовуйте як швидкий смоук-тест, потім зробіть повні контрольні суми, якщо файл критичний.
Жарт №2: Нічого так не згуртовує команду, як відсутній файл, виявлений за п’ять хвилин до демонстрації.
План швидкої діагностики
Коли «порівняння папок повільне» або «результати незрозумілі», не метушіться. Діагностуйте як SRE: ізолюйте вузьке місце, потім оберіть найменш інвазивне виправлення.
По-перше: підтвердіть тип проблеми
- Відсутні файли? Використовуйте
rsync -a --dry-runабо манифести шляхів. Ще не хешуйте. - Змінений вміст? Перевірте різниці розмірів/mtime, потім хешуйте лише дельту.
- Проблеми з правами/ACL? Порівнюйте метадані; хешування не допоможе.
- Живий дрейф? Перестаньте порівнювати рухливі цілі: снапшоти або зупинка записів.
По-друге: визначте, що саме повільне (CPU, метадані I/O, мережа чи диск)
cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0 (server) 02/05/2026 _x86_64_ (16 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
3.11 0.00 9.44 41.02 0.00 46.43
Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s w_await aqu-sz %util
nvme0n1 821.0 66240.0 0.0 0.00 47.20 80.70 2.0 64.0 1.50 38.80 99.20
Інтерпретація: Високий %iowait і %util близько 100%: вузьке місце — сховище. Сканування директорій навантажує диски.
Дія: Перестаньте робити повні сканування дерева в піковий час. Використовуйте снапшоти/манифести або запускайте порівняння на репліці/вторинному вузлі.
cr0x@server:~$ sar -n DEV 1 3 | tail -n +4
Average: IFACE rxpck/s txpck/s rxkB/s txkB/s %ifutil
Average: eth0 120.11 115.88 9821.33 9012.47 82.50
Інтерпретація: Мережа завантажена; віддалені порівняння можуть обмежуватись використанням каналу або затримкою.
Дія: Віддавайте перевагу генерації манифестів на віддаленій стороні та порівнянню невеликих текстових результатів. Уникайте читання всіх файлів по мережі, якщо це не потрібно.
По-третє: перевірте семантику файлової системи та монтовання
- Кешування атрибутів NFS може тимчасово «спотворювати» mtime.
- SMB/CIFS може нормалізувати регістр; копії з macOS можуть створювати файли AppleDouble.
- Різна точність часових позначок може давати постійні «зміни».
cr0x@server:~$ mount | grep -E ' /data/dst | /data/src '
tank/data on /data/src type zfs (rw,xattr,noacl)
backup:/data on /data/dst type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2)
Інтерпретація: Різні платформи. Очікуйте метадані крані випадки.
Дія: Якщо мета — цілісність, не сперечайтеся з mtime. Використовуйте манифести контрольних сум для критичних піднаборів.
По-четверте: розумно зменшіть область
- Порівнюйте лише іммутебл-директорії (релізи, снапшоти, денні партиції).
- Виключайте кеші та тимчасові папки; вони створюють ентропію.
- Починайте з «лише список» порівнянь і ескалюйте.
cr0x@server:~$ rsync -a --dry-run --itemize-changes --exclude='tmp/' --exclude='cache/' /data/src/ /data/dst/ | head
sending incremental file list
>f+++++++++ reports/2026-01.csv
Інтерпретація: Сигнал-шум покращується миттєво.
Дія: Включіть виключення в стандартні скрипти порівняння, але документуйте їх, щоб не приховати реальні проблеми.
Три корпоративні міні-історії (з болем)
Інцидент через хибне припущення: «збіг розмірів означає збіг вмісту»
Команда мігрувала великий архів звітів між двома NAS. Вони виконали швидку перевірку: кількість файлів і загальна кількість байтів. Все збіглося. Вони оголосили перемогу і вивели стару систему з експлуатації.
Через тижні аудитори попросили конкретний набір щомісячних звітів. Невелика кількість файлів відкривалася з помилками: PDF були пошкоджені. Імена файлів існували, розміри збігалися. Саме це зробило випадок болючим; ніхто не підозрював корупцію.
Корінь проблеми — ненадійний мережевий шлях під час початкового копіювання. Інструмент копіювання повторював спроби і «завершив» роботу, але кілька файлів були тихо обрізані і потім доповнені процесом додатка, що торкав метадані. Ті самі розміри. Різні байти. Перевірка кількості файлів не спрацювала; перевірка розмірів не спрацювала; перевірка таймстемпів не спрацювала.
Виправлення було нудним: згенерувати SHA-256 манифест на джерелі, перевірити його на destination і лише потім видаляти старий набір даних. Вони відновили пошкоджені файли з більш ранніх бекапів і впровадили верифікацію контрольних сум для майбутніх міграцій.
Урок: якщо ви виводите джерело істини з експлуатації, зробіть хоча б один перевірочний прохід за вмістом. Не обов’язково для всього щодня — але для міграцій завжди.
Оптимізація, що обернулася проти: «давайте використаємо --checksum скрізь»
Група платформи втомилася сперечатися, чи дві директорії «справді» однакові. Вони обгорнули rsync у скрипт і за замовчуванням додали --checksum. На папері це вирішило проблему довіри: rsync хешував кожен файл і порівнював хеші.
У реальності це перемістило вартість від «інколи ми пересилаємо зайве» до «ми читаємо весь набір даних кожного запуску». На кластері зі значним навантаженням на метадані і зайнятими дисками це означало, що завдання порівняння стало відмовою в обслуговуванні для власної інфраструктури. Затримки зросли. Вікна бекапів зсунулися. Декілька сервісів почали таймаути при зверненні до спільного сховища.
Найнеприємніше: скрипт працював як cron job. Отже, удар був періодичним і збивав з пантелику, як будинок з привидами, але з графіками. Спочатку звинувачували мережу. Потім — вендора сховища. Зрештою хтось запустив iostat під час події і побачив насичення читаннями.
Вирішення було багаторівневе: використати метадані rsync для щоденних перевірок і запускати манифест контрольних сум щотижня (або при інцидентах). Також додали контроль області: хешувати лише іммутебл-артефакти релізів і критичні для відповідності директорії.
Урок: «правильно» може бути операційно неправильним, якщо застосовувати безрозбірливо. Детермінований доказ — чудово; детерміновані відмови — ні.
Нудна, але правильна практика, що врятувала день: снапшот + манифест
Команда інженерії даних щодня реплікувала великий набір даних до сайту відновлення після катастрофи. Набір даних був великим і постійно змінювався в робочий час. Ранні спроби порівнювати «живі» директорії давали нестабільні результати: файли з’являлися й зникали під час сканування, і diff був шумним.
Вони впровадили просту практику: о 01:00 робити снапшот джерела, реплікувати цей снапшот, а потім порівнювати вміст снапшоту з реплікованим снапшотом. Ніяких «живих» порівнянь. Ніяких суперечок про дрейф.
В один випадковий вівторок реплікація «успішно» завершилася, але downstream job-и в DR почали падати. Їхній конвеєр порівняння позначив невелику кількість відсутніх файлів у партиції. Оскільки порівняння було щодо снапшоту, воно було однозначним: файли відсутні в реплікованому вигляді, а не «ще записуються».
Вони швидко знайшли причину: неправильно налаштований exclude у задачі реплікації, що фільтрував директорію, яка використовувалася лише одним клієнтом. Вона була введена під час прибирання. Конвеєр порівняння виявив це відразу, до того як довелося б покладатися на DR під час справжньої катастрофи.
Урок: снапшоти перетворюють порівняння з думки на математику. Практика нудна. Саме тому вона працює.
Цікаві факти та історія, що може стати в пригоді
- Ідея «дельти передачі» rsync походить із середини 1990-х і зробила віддалену синхронізацію практичною по повільних лінках, не відправляючи повторно незмінні блоки.
- Unix
diffпередує більшості сучасних файлових систем. Він створювався для тексту, але його рекурсивний режим став грубим інструментом для дерев директорій. - MD5 колись був поширеним для перевірки цілісності, але атаки на колізії зробили його поганим вибором у ворожих контекстах. Для операційної валідації SHA-256 — розумний стандарт.
- Точність часових позначок файлових систем відрізняється: ext4 підтримує наносекунди; деякі мережеві ФС округлюють до 1 секунди (або гірше). Ваш «сигнал зміни» може бути шумом округлення.
- Різна чутливість до регістру: файлові системи Linux зазвичай чутливі до регістру; багато Windows і стандартні macOS — нечутливі. Два різні файли можуть зруйнуватися в одному під час копіювання.
- Жорсткі посилання ускладнюють метрики «кількість файлів»: один індексний вузол може мати кілька записів у директоріях. Деякі методи копіювання дублюють дані замість збереження посилань, якщо не налаштовані.
- Розширені атрибути та ACL стали широко використовуватися в міру зростання уваги до безпеки; їхня втрата може змінити виконання і доступ без зміни вмісту файлу.
- Тиха корупція даних реальна: сучасні системи покладаються на перевірки на всіх етапах (файлові системи як ZFS, прикладні хеші або верифікація манифестів), бо диски, контролери та ОЗП можуть іноді помилятися.
- «Бекап пройшов» рідко означає «відновлення верифіковано»: оперативна зрілість часто проявляється у рутинній верифікації, а не в гарніших дашбордах.
Поширені помилки: симптом → корінь → виправлення
1) Симптом: порівняння показує тисячі «змінених» файлів кожен раз
Корінь: невідповідність точності часового штампа (локальний ext4 проти NFS/SMB), дрейф часу або інструмент копіювання, що не зберігає mtime.
Виправлення: Перестаньте довіряти mtime як основному сигналу. Спочатку використовуйте манифести розмірів; потім хешуйте дельту. Якщо потрібна точність метаданих — використовуйте rsync -a і впевніться, що обидві сторони її підтримують.
2) Симптом: файли є в destination, але застосунок падає з «permission denied»
Корінь: власність/режим/ACL/xattr не збережено; відновлення виконано не від root; ACL втрачені файловою системою.
Виправлення: Використовуйте rsync -aAX де потрібно. Перевірте за допомогою stat, getfacl, getfattr. Якщо destination не може зберігати ACL/xattr — змініть destination або свідомо адаптуйте модель безпеки.
3) Симптом: «Only in source» файли з’являються і зникають під час сканування
Корінь: порівнюється жива директорія, що записується, ротується або очищується.
Виправлення: Порівнюйте снапшоти або зупиніть записи під час порівняння. Для логів і тимчасових шляхів виключайте їх із області порівняння.
4) Симптом: rsync показує відмінності, але хешування показує файли ідентичні
Корінь: відмінності в метаданих (mtime, perms) або округлення часових позначок; rsync говорить правду про метадані, а не про вміст.
Виправлення: Визначте, що означає «однаково» для вашого робочого процесу. Для цілісності бекапів важливий вміст; для відновлення систем — метадані також важливі. Налаштуйте порівняння відповідно.
5) Симптом: перевірка контрольних сум неймовірно повільна і впливає на прод
Корінь: повне читання великих наборів даних, холодні кеші, конкуренція з користувацьким I/O; виконання в піковий час.
Виправлення: Плануйте сканування контрольних сум в непіковий час. Хешуйте лише іммутебл або високоцінні піднабори. Підтримуйте ролінгові манифести за партицією/днем замість сканування всього дерева.
6) Симптом: у destination є зайві dotfiles і «дивні» метадані файли
Корінь: копіювання з macOS (AppleDouble ._ файли), метадані Windows або артефакти програм резервного копіювання.
Виправлення: Намагайтеся виключати відомі шаблони сміття свідомо, але задокументуйте виключення. Краще: відокремте «дані» від «артефактів клієнтської ОС» на джерелі.
7) Симптом: результати порівняння залежать від того, хто їх запускає
Корінь: відмінності в правах впливають на те, що find може бачити; деякі файли недоступні не-root. Також NFS root-squash може приховувати реалії власності.
Виправлення: Запускайте порівняння з однаковими привілеями. Для відновлень на рівні системи виконуйте як root на обох кінцях (обережно). Захоплюйте помилки від find і трактуйте їх як помилки, а не як шум.
8) Симптом: файл з тим самим ім’ям перезаписав інший під час копіювання
Корінь: файловa система destination нечутлива до регістру; Readme і README колізують.
Виправлення: Не копіюйте case-sensitive дерева на case-insensitive томи без політики іменування та валідації. Виявляйте колізії, нормалізуючи регістр у манифестах перед міграцією.
Чеклісти / покроковий план
Чекліст A: «Мені потрібно лише знати, що відсутнє» (швидко, низький ризик)
- Підтвердьте область: оберіть кореневі директорії і впевніться, що слеші в кінці правильні для rsync (
/src/vs/src). - Запустіть rsync у dry-run з itemize:
cr0x@server:~$ rsync -a --dry-run --itemize-changes /data/src/ /data/dst/ | head -50 sending incremental file list >f+++++++++ reports/2026-01.csv - Якщо потрібно виявити зайві файли в destination — додайте
--delete(ще в dry-run) і перегляньте рядки*deleting. - Вирішіть: якщо мета — дзеркало, синхронізуйте; якщо мета — зберегти додаткові версії в бекапі, — не видаляйте.
Чекліст B: «Потрібно довести цілісність» (повільніше, оборонно)
- Затвердіть датасет: зробіть снапшот або призупиніть запис. Якщо не можете — будьте чесні щодо невизначеності.
- Згенеруйте відсортований SHA-256 манифест на джерелі:
cr0x@server:~$ cd /data/src cr0x@server:~$ find . -type f -print0 | sort -z | xargs -0 sha256sum > /tmp/src.sha256 cr0x@server:~$ tail -1 /tmp/src.sha256 3d4c... ./reports/2026-01.csv - Скопіюйте манифест на destination (або згенеруйте його там) і верифікуйте:
cr0x@server:~$ cd /data/dst cr0x@server:~$ sha256sum -c /tmp/src.sha256 | tail -3 ./images/logo.png: OK ./reports/2026-01.csv: OK - Будь-який
FAILEDабо «No such file» — жорстка помилка. Пересинхронізуйте і перевірте повторно. - Вирішіть: якщо помилки повторюються, зупиніться і розслідуйте корупцію сховища/мережі, брак ОЗП, проблеми контролера або програму, що модифікує файли після копіювання.
Чекліст C: «Відновлення має працювати» (права, ACL та xattr)
- Оберіть репрезентативну вибірку файлів: конфіги, виконувані файли, секрети та директорії з правами.
- Порівняйте метадані:
cr0x@server:~$ stat -c '%a %U:%G %n' /data/src/bin/app /data/dst/bin/app 755 root:root /data/src/bin/app 755 root:root /data/dst/bin/app - Якщо середовище використовує ACL/xattr — перевірте їх явно (
getfacl,getfattr). - Виправте метод копіювання (
rsync -aAX) і повторіть валідацію.
Чекліст D: «Великий набір даних, обмежений час» (тріаж)
- Запустіть порівняння манифестів шляхів+розмірів (дешево), щоб знайти відсутні й файли з різними розмірами.
- Хешуйте лише файли з різними розмірами та випадкову вибірку «однакового розміру».
- Якщо випадкова вибірка провалилася — розширте область хешування. Якщо пройшла — дійте з обережною впевненістю й задокументуйте кроки.
Поширені запитання
1) Який найшвидший спосіб порівняти дві папки на Linux?
Для операційного використання rsync -a --dry-run --itemize-changes зазвичай найшвидший і дає дієвий результат. Він переважно читає метадані, а не повний вміст файлів, тому масштабується краще за хешування.
2) Чи diff -rq верифікує вміст файлів?
Так, він може читати і порівнювати вміст файлів, що робить його більш остаточним, ніж порівняння за mtime/size. Але на великих деревах і бінарно-насичених наборах даних він може бути набагато повільнішим і шумнішим.
3) Коли варто використовувати контрольні суми?
Використовуйте контрольні суми, коли потрібен доказ: міграції, де видаляють джерело; верифікація відповідності; тестування відновлення; або коли підозрюєте корупцію. Для щоденного виявлення дрейфу — використовуйте манифести і rsync.
4) Чи rsync --checksum те саме, що манифест контрольних сум?
Не зовсім. --checksum змушує rsync обчислювати контрольні суми, щоб вирішити, чи передавати файл. Він все одно читає весь вміст файлів і не є довготривалим артефактом, якщо ви не зберігаєте результати окремо. Манифест — це автономний запис, який можна перевірити пізніше.
5) Чому я бачу зміни, хоч ніхто файли не чіпав?
Типові причини: різна точність часових позначок, дрейф годинника, оновлення метаданих антивірусом/індексатором, кешування атрибутів NFS або інструменти, що переписують файли на місці (навіть якщо вміст логічно такий самий).
6) Як порівнювати папки через SSH, не передаючи всю інформацію по мережі?
Згенеруйте невеликі манифести на кожній стороні (шляхи+розміри або контрольні суми за потреби) і порівняйте текстові результати. Або використовуйте rsync dry-run через SSH — він передає лише метадані і списки файлів.
7) Що з символічними та жорсткими посиланнями?
Символічні посилання можна порівнювати як лінки або як їхні цілі, залежно від інструмента й прапорів. Жорсткі посилання потребують спеціальної обробки, якщо ви хочете зберегти зв’язки; інакше копії можуть дублювати дані і все одно «виглядати правильно» за вмістом.
8) Як працювати з іменами файлів, що містять пробіли та дивні символи у манифестах?
Використовуйте null-роздільні конвеєри: find ... -print0 з sort -z і xargs -0. Уникайте наївного рядкового парсингу, коли шляхи можуть містити табуляції або переводи рядка.
9) Чи можна довіряти порівнянням за розміром файлів для валідації цілісності?
Збіг розміру файлів корисний для швидкого тріажу і виявлення очевидної усіченості, але не доводить ідентичність вмісту. Якщо ставки високі — розмір лише підказка, не доказ.
10) Як порівнювати лише піднабір (винятити кеші, тимчасові файли, логи)?
Використовуйте виключення rsync (або обрізки find) явно і послідовно. Тримайте список виключень під контролем версій, бо «тимчасові виключення» мають звичку ставати постійними сліпими зонами.
Наступні кроки, які можна зробити сьогодні
- Визначте стандарт для вашої організації: rsync dry-run для щоденних перевірок, манифести контрольних сум для міграцій і верифікації відновлення.
- Запишіть, що означає «однаково» для кожного робочого процесу: лише існування, вірність метаданих або байт-ідентичність. Покладіть це в руnbook, щоб о 3:00 ви не імпровізували.
- Зробіть один багаторазовий скрипт для манифестів, що безпечно працює з null-розділювачами і сортуванням, і зберігайте манифести поруч з бекапами/снапшотами.
- Заплануйте важкі перевірки (хешування всього дерева) в непіковий час і вимірюйте вплив за допомогою
iostatта таймінгів. Не гадйте. - Практикуйте верифікацію відновлення на невеликій, але репрезентативній вибірці щотижня. Не тому, що ви любите папери. Тому, що інциденти люблять сюрпризи.
Якщо взяти одне з цього всього: починайте дешево, ескалюйте лише коли докази вказують на необхідність, і ніколи не порівнюйте рухливу ціль, якщо вам не подобається філософська дискусія зі своїм масивом зберігання.