Я переключаю машины и подключил старый жесткий диск (/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'