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

Копирование данных с помощью rsync вызывает расхождения в размерах

Я переключаю машины и подключил старый жесткий диск (/dev/sda4) к новой машине.

У старой машины был жесткий диск немного меньшего размера (720G), по сравнению с новым (736G), поэтому я также создал раздел немного большего размера.

Итак, я побежал rsync чтобы скопировать все данные в новый раздел, как показано ниже:

linux-70e2:/ # time rsync -azprvl /mnt/external-disk/foo /media/sda4/

...
sent 169,237,139,987 bytes  received 24,529 bytes  24,419,185.41 bytes/sec
total size is 190,542,953,489  speedup is 1.13

real    115m30.297s
user    112m13.068s
sys     3m59.996s

Данные копируются без ошибок.

Однако когда я это сделаю:

du -h -m -s /mnt/external-disk/foo /media/sda4/foo

Я получил:

162414  /mnt/external-disk/foo
181721  /media/sda4/foo

Не мог бы кто-нибудь объяснить эту огромную разницу? Почему я не получаю таких же результатов? Это уже несколько дней сводит меня с ума. Есть еще несколько разделов, и у меня тоже есть похожие расхождения.

Обе перегородки ext4.

linux-70e2:/ # mount | grep sda4
/dev/nvme0n1p5 on /media/sda4 type ext4 (rw,relatime,data=ordered)
/dev/sda4 on /mnt/external-disk type ext4 (rw,nosuid,nodev,relatime,data=ordered,uhelper=udisks2)

Насколько мне известно, с обоими твердотельными накопителями все в порядке. Один из них совершенно новый. Я бегал e2fsck на них обоих.

Кроме того, я запустил:

find -L /mnt/external-disk type/foo -type l

и это не перечисляет никаких символических ссылок ниже исходного каталога.

Я не впервые использую rsync для такого рода вещей, но у меня никогда раньше не было такой проблемы. Пожалуйста, порекомендуйте!

Несоответствие, скорее всего, вызвано более редким файлом на старом диске.

В любом случае, давайте сначала проверим, что номера файла и inode совпадают:

  • выпуск find <path> | wc -l на обеих точках монтирования. Одинаково ли количество файлов / каталогов?
  • выпуск df -i. Количество индексов одинаковое?

Если ответ на оба вопроса утвердительный, то разницу можно объяснить меньшим количеством файлов на новом диске. Но что такое разреженные файлы? Короче говоря, разреженные файлы - это обычные файлы, размер которых меньше, чем кажется. Это возможно благодаря функции (относительно) современных файловых систем, которые вместо записи всех нулей в файл просто устанавливают флаг, сообщающий системе: «этот файл (или его часть) заполнен нулями, не позволяйте мне писать торговый центр".

По умолчанию, du сообщает реальное пространство, занятое файлом, а не его видимый размер. Чтобы показать видимый размер, используйте du --apparent-size (другие варианты см. Du Manpage)

В качестве практического примера вы можете создать разреженный файл с помощью команды truncate test.img -s 1G. Как сообщает ls, размер вновь созданного файла составляет 1 ГБ, но если вы попробуете du -hs test.img, вы увидите очень и очень маленький размер файла (возможно, даже ноль!). Как это возможно? Как указано выше, современная файловая система иногда «лжет» приложениям, сообщая о выделенном размере, которого в действительности не существует. С другой стороны du -hs --apparent-size test.img напечатает тот же размер, что и ls.

Когда вы начнете писать в разреженный файл, файловая система будет динамически выделять необходимое пространство. Например, выдавая dd if=/etc/services of=test.img conv=notrunc,nocreat запишет некоторые данные в ранее разреженный файл test.img. Теперь бегу du -hs test.img сообщит о ~ 600 КБ, выделенных для хранения данных.

Очевидным, но очень важным следствием является то, что поддержка разреженных файлов может быть оптимизирована только для файлов с нулевым заполнением (или их части). В тот же момент, когда вы пишете в файл, его выделенное пространство начинает расти. Это истинное событие, если вы записываете в файл другие нули, если только приложение не знает, как обрабатывать разреженные файлы (в этом случае приложение сообщит файловой системе, что она собирается записать все нули, и файловая система оптимизируется соответственно).

Что, если ты хочешь действительно предварительно выделить место? Тогда вы можете использовать fallocate test.img -l 1G. Если вы выполните ls; du -hs test.img; du -hs --apparent-size test.img, вы увидите, что все инструменты сообщают один и тот же размер, потому что файл действительно был полностью выделен fallocate вызов.

Короче говоря, возможно, что во время копирования какой-то файл был воссоздан менее разреженным образом, заменив разреженные разделы «настоящими» нулями. Чтобы использовать разреженный файл с rsync вам пришлось использовать -S вариант.

Ваши параметры rsync не будут копировать жесткие ссылки, попробуйте добавить -H

-H, --hard-links. Это указывает rsync искать жестко связанные файлы при передаче и связывать вместе соответствующие файлы на принимающей стороне. Без этой опции жестко связанные файлы при передаче обрабатываются как отдельные файлы. Когда вы обновляете непустое место назначения, этот параметр только гарантирует, что файлы, жестко связанные между собой в источнике, жестко связаны вместе в месте назначения. В настоящее время он НЕ пытается разорвать уже существующие жесткие ссылки в месте назначения, которые не существуют между исходными файлами. Обратите внимание, однако, что если один или несколько дополнительных связанных файлов имеют изменения содержимого, они станут несвязанными при обновлении (при условии, что вы не используете параметр --inplace).

Редкие файлы, такие как образы виртуальных машин, также могут увеличивать использование, заменяя пустоты реальными блоками. Попробуйте использовать --sparse вариант с rsync.

Вы также можете попробовать использовать diff для сравнения деревьев каталогов. Видеть https://stackoverflow.com/questions/4997693/given-two-directory-trees-how-can-i-find-out-which-files-differ

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

tune2fs -l /dev/sdXX | grep -i 'block size'