Почему существует большое несоответствие между размерами файлов, сообщаемыми du и ls?

На сервере у меня есть каталог /opt/kafka/data/topics,

$ du -hs /opt/kafka/data/topics
52M     /opt/kafka/data/topics

Когда я tar этот каталог, как

$ tar czfv /tmp/topics.tar.gz /opt/kafka/data/topics

Я получаю размер файла, который имеет смысл

$ ls -alh /tmp/topics.tar.gz
-rw-r--r-- 1 user user  11M Jan 12 15:15 kafka

Тем не менее, когда я скачиваю topics.tar.gz на мой локальный компьютер OS X и распакуйте его, он занимает 10 ГБ!


После изучения содержания /opt/kafka/data/topics на сервере более внимательно, я заметил, что в соответствии с ls он содержит много 10 МБ файлов:

$ find /opt/kafka/data -type f -exec ls -alh {} \;
... [output]
-rw-r--r-- 1 user user 10M Jan 12 02:45 /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index
-rw-r--r-- 1 user user 10M Jan 12 02:45 /opt/kafka/data/topics/user-entities-KSTREAM-KEY-SELECT-0000000123-repartition-2/00000000000000000012.index
... [and many more]

du сообщает, что каждый из этих файлов размером 10 МБ составляет 0 байтов:

$ du -h /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index
0       /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index

Так, что происходит? Очевидно, я что-то здесь упускаю:

  • du сообщает 52M всего. Это имеет смысл, потому что устройство, которое /opt/kafka/data установлен только на 5 ГБ, df сообщает, что он заполнен только на 2% и все еще работает.
  • tar GZIPS содержимое до 10M. Это тоже имеет смысл.
  • ls сообщает, что многие файлы имеют размер 10 МБ на диске, и когда я извлекаю архив, я получаю 10 ГБ.
  • du сообщает, что каждый из этих файлов имеет размер 0 байт.
  • mount сообщает, что /dev/sdc on /opt/kafka/data type ext4 (rw,relatime,data=ordered)

Ничего не складывается. Есть ли какое-то прозрачное сжатие на диске, о котором я не знаю?

1 ответ

Судя по обсуждению в комментариях, все файлы редки. Подобные вещи на самом деле смущают многих людей, когда они впервые сталкиваются с этим, так что не расстраивайтесь.

Что на самом деле происходит здесь со значениями, сообщенными ls а также du?

Это легче всего объяснить на примере.

Допустим, вы создали пустой файл, а затем записали в него 1 МБ данных, начиная с самого начала. Результирующий файл будет иметь размер 1 МБ и занимать 1 МБ на диске. И то и другое ls а также du сообщит тот же размер 1 МБ для файла.

Теперь скажите, что вместо этого вы создаете пустой файл, а затем вызываете seek() переместить 1MB в файл, а затем записать один байт. Результирующий файл будет иметь размер 1 МБ + 1 байт, но на самом деле он содержит только 1 байт данных.

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

Эта неэффективность (как с точки зрения времени создания файла, так и пространства, используемого на диске) приводит к появлению разреженных файлов. Вместо записи 1 МБ нулевых байтов ОС, поддерживающая разреженные файлы (как и все современные системы UNIX), будет в метаданных этой файловой системы укажите, что область размером 0-1 МБ пуста, а затем сохраните только тот единственный записанный вами байт. В результате файл будет иметь размер 1 МБ + 1 байт, но на диске он займет всего 1 байт. Кроме того, когда что-то идет на чтение этого файла, любые регионы, аннотированные ОС как пустые, будут просто считываться как нулевые байты (таким образом, это не похоже на программы пользователя из первого файла).

Это где расхождение между значениями, сообщенными ls а также du происходит от. По умолчанию, ls сообщает о видимом размере файлов (то есть о том, сколько данных вы прочитали бы, если бы начали читать файл с первого байта и читать до конца), а du сообщает фактическое пространство, используемое файлом на диске (обычно не включая другие приемы экономии пространства, выполняемые ОС, такие как прозрачное сжатие). du согласен с df в этом случае, потому что df только сообщает объем пространства, который фактически физически используется на диске.

Изменяя это ls -l командовать ls -ls, вы получите дополнительный столбец, показывающий фактический размер файлов на диске, который должен соответствовать du,

Другие вопросы по тегам