Когда `ls -s` выводит« 0 »

13

Конечно, стандартным способом проверки, если файл пуст, является test -s FILEодин, но один из наших клиентов получил скрипт, содержащий такие тесты:

RETVAL=`ls -s ./log/cr_trig.log | awk '{print $1}'`
if test $RETVAL -ne 0
then
    echo "Badness: Log not empty"
    exit 25
fi

с заявлениями поставщика о том, что он работает в двух средах, в которых они его тестировали. Само собой разумеется, что он потерпел неудачу в обоих двух местах, где я его тестировал.

Итак, мне стало любопытно. Когда ls -sпечатать 0для пустых файлов?

Это мои выводы до сих пор:

  • GFS в Linux: 4
  • ext4 в Linux: 0
  • ZFS на Солярисе: 1
  • UFS на Солярисе: 0
  • JFS в AIX: 0
  • VxFS в HP-UX: 0
  • HFS на HP-UX: 0
  • HFS в Mac OS X: 0

Я еще не исследовал сетевые файловые системы.

Вопрос: Как я могу элегантно объяснить другим, что их сценарии неверны ?

На мой взгляд, «правильной» версией будет:

if test ! -s ./log/cr_trig.log
then
    echo "Badness: Log not empty"
    exit 25
fi
MattBianco
источник
5
Просто покажи им свои тесты. У вас есть достоверные данные, которые доказывают, что их тест не является переносимым, что еще вам нужно?
Мат
Один из самых интересных вопросов, которые я когда-либо видел на этом сервере. Жаль, что можно потратить только одно очко.
KTF
@ktf Вы всегда можете назначить награду.
Джо

Ответы:

6

Очень интересная находка. Хотя я никогда не ls -sпроверял, является ли файл пустым или нет, я бы предположил, что он также сообщает 0о пустых файлах.

На ваш вопрос: Как уже прокомментировал Мат , покажите им свои результаты теста. Чтобы объяснить им результаты, укажите, что в ls -sотчете указано количество выделенных блоков в файловой системе, а не фактический размер в байтах. Очевидно, что некоторые реализации файловой системы выделяют блоки, даже если им не нужно хранить какие-либо данные, вместо того, чтобы хранить только нулевой указатель в inode.

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

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

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

РЕДАКТИРОВАТЬ:

На ум пришла еще одна причина: файловыми системами, в которых вы нашли значения> 0, являются ZFS , реализация RAID + LVM + FS и GFS , кластерная файловая система. Оба могут хранить метаданные для сохранения целостности файлов, которые не хранятся в inode. Это может быть то, что ls -sсчитается в блоках данных, выделенных для этих метаданных.

КТФ
источник
4

В отличие от большинства (если не всех) других файловых систем, ZFS не выделяет статический массив inode заранее. При создании пустого файла в ZFS будет использоваться новый блок данных, о котором сообщает ls -s.

Я подозреваю, что GFS должен хранить данные синхронизации / блокировки, приводящие к другому ненулевому результату.

jlliagre
источник
2

ls -s сообщает о количестве блоков, выделенных для файла, не считая того, что хранится непосредственно в записи каталога.

В большинстве случаев количество блоков - это количество байтов, деленное на размер блока в байтах, округленное в большую сторону.

Количество блоков может быть меньше, чем для разреженного файла . Например, в большинстве файловых систем это создаст 8192-байтовый файл, охватывающий 0 блоков:

$ perl -e 'truncate STDOUT, 8192' >a
$ ls -l a
-rw-r--r-- 1 gilles gilles 8192 Nov  1 21:32 a
$ ls -s a
0 a

И наоборот, количество блоков может быть больше, если файловая система предварительно выделяет блоки для файлов или использует блоки для хранения метаданных. Я не удивлен, что Zfs имеет неочевидное соответствие между размером файла и количеством блоков, учитывая большое количество функций, которые он предлагает, и его ориентацию на большие файловые системы; Я не знаю деталей, но количество блоков зависит не только от размера файлов, но и от его истории (вы можете иметь более одного блока в пустом файле, если это результат усечения файла большего размера).

Чтобы объяснить, почему ls -sэто неправильно: он не учитывает размер файла, а зависит от файловой системы. Это очень косвенный способ определить, является ли файл пустым, во-первых, требующий внешнего инструмента ( ls) и некоторого анализа; вместо этого они должны использовать test -s, что не требует анализа и выполняет именно то, что запрашивается. Если они считают, что ls -sэто хороший способ проверить, является ли файл пустым, ответственность за него должна быть возложена на него.

Жиль "ТАК - прекрати быть злым"
источник