du дає два різні результати для одного файлу


23

Я аспірант обчислювальної хімії з доступом до кластеру Linux. Кластер складається з дуже великого (25 ТБ) файлового сервера, до якого підключено кілька десятків обчислювальних вузлів. Кожен обчислювальний вузол складається з 8 до 24 ядер Intel Xeon. Кожен обчислювальний вузол також містить локальний диск близько 365 ТБ.

Оскільки до сервера файлових файлів регулярно звертаються десяток користувачів в дослідницькій групі, файлсервер використовується в основному для довготривалого зберігання файлів (він створюється резервна копія вночі, тоді як локальні диски обчислювальних вузлів ніколи не створюються резервними копіями). Таким чином, системний адміністратор доручив нам запустити моделювання на локальних дисках - які мають швидший введення-виведення, ніж сервер файлів, - щоб не уповільнити файловий сервер для інших користувачів.

Отже, я запускаю симуляції на локальних дисках, а потім, після їх закінчення, копіюю файли траєкторії - я виконую моделювання молекулярної динаміки (MD) - у файл-сервер для зберігання. Припустимо , у мене є файл з ім'ям траєкторії traj.trrв директорії на локальному диску вузла, /home/myusername/mysimulation1/traj.trr. Для тривалого зберігання, я завжди скопіювати traj.trrв каталог у файловому, ~/mysimulation1/traj.trrде ~представляє свій каталог в файловому, /export/home/myusername. Після копіювання я звично використовую, du -hщоб перевірити, чи /home/myusername/mysimulation1/traj.trrмає той самий розмір файлу, що і ~/mysimulation1/traj.trr. Таким чином, я можу бути принаймні обґрунтовано впевнений, що передача на сервер файлів пройшла успішно. Наприклад:

cd /home/myusername/mysimulation1/
cp -v traj.trr ~/mysimulation1/
du /home/myusername/mysimulation1/traj.trr -h
du ~/mysimulation1/traj.trr -h

Якщо два дзвінки du -hнадати однаковий розмір файлу, прочитаного людиною, я можу бути впевненим, що передача / копія була успішною. (Мої типові traj.trrфайли мають розмір приблизно від 15 до 20 Гб, залежно від точного моделювання, яке я запустив.) Якщо я запускаю du(тобто без -hкомутатора) на два traj.trrфайли, їх розміри в байтах зазвичай дуже-дуже схожі - - як правило, всього в декількох байтах. Я використовую цей загальний метод останні півтора року, без проблем.

Однак останнім часом у мене виникла така проблема: інодіdu -hповідомляється, що дваtraj.trrфайли відрізняються за розміром на кілька ГБ. Ось приклад:

cd /home/myusername/mysimulation1/            # this is the local disk
cp -v traj.trr ~/mysimulation1/
du traj.trr -h
cd ~/mysimulation1/                           # this is the fileserver
du traj.trr -h

Вихід із двох дзвінків до du -hнаступного:

20G     traj.trr
28G     traj.trr

Я вважаю, що колишній (тобто, на traj.trrлокальному диску /home/myusername/mysimulation1/), - це правильний розмір файлу, оскільки очікується, що мої траєкторії моделювання становитимуть приблизно 15-20 ГБ кожна. Але як тоді файл на сервері файлів насправді може бути більшим ? Я міг бачити, як він може бути меншим, якби якось cpпередача не вдалася. Але я не бачу, як це насправді може бути більшим .

Я отримую аналогічний вихід, коли виконую ті ж команди, що і вище, але без -hперемикача, заданого для du:

20717480        traj.trr
28666688        traj.trr

Чи можете ви придумати якусь причину різниці?

Якщо якимось випадковим випадком duякимось чином не працює, я можу з цим все гаразд. Але мені просто потрібно переконатися, що копія traj.trrфайлового сервера є повною та ідентичною його вихідній версії на локальному диску. Мені потрібно видалити локальний файл, щоб у мене було достатньо місцевого дискового простору для запуску нових симуляцій, але я не можу дозволити собі traj.trrпошкодити версію файлового сервера.

Формат .trr файлу (з пакета молекулярної динаміки Gromacs) являє собою бінарний формат, а не текст. Таким чином, я не впевнений, чи можна надійно порівняти файли такою програмою, як diff.


5
Спробуйте запустити md5sumабо sha1sumна файлах. Вони відповідають?
cjm

2
@cjm Я щойно побіг md5sumна два файли. Дві контрольні суми відповідають. Я думаю, це означає, що два файли однакові?
Андрій

3
Про які розміри повідомляється ls -l? Команда duповідомляє, скільки місця на диску використовується для вашого файлу, а не наскільки великий ваш файл. На розмір диска може впливати ваша файлова система та її стратегія розподілу.
Кейсі

2
@casey ls -l -hговорить, що обидва файли мають 20 Гб. Так само ls -lговорить, що обидва файли мають 21214683940 байт. Тому я здогадуюсь, що файли однакового розміру, але не використовують однакову кількість дискового простору (згідно du).
Андрій

2
@Andrew з огляду на розміри, про які повідомляє ls, однакові, а хеші - однакові, ви можете зробити висновок, що файли однакові. Ці інструменти - це те, що дає вам впевненість, яка вам потрібна, і показує, що du не є інструментом для задоволення ваших потреб.
Кейсі

Відповіді:


32

Ви дійсно повинні використовувати щось на кшталт md5sumабо sha1sumперевірити цілісність.

Якщо ви дійсно хочете використовувати розмір, використовуйте ls -lабо du -b.

duУтиліта зазвичай показує тільки використання дискового файлу, тобто скільки з файлової системи в її користуванні. Це значення повністю залежить від резервної файлової системи та інших факторів, таких як розріджені файли.

Приклад:

$ truncate -s 512M foo
$ cat foo >bar
$ ls -l foo bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:06 bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:03 foo
$ du foo bar
0       foo
524288  bar
$ du -b foo bar
536870912       foo
536870912       bar

У нас є два файли, що містять нулі 512 Мб. Перший зберігається рідко і не використовує місця на диску, а другий явно зберігає кожен байт на диску. - Той самий файл, але зовсім інше використання диска.

Можливий -bваріант:

   -b, --bytes
          equivalent to '--apparent-size --block-size=1'

   --apparent-size
          print apparent sizes, rather than disk usage; although the apparent
          size is  usually  smaller,  it  may  be  larger  due  to  holes  in
          ('sparse')  files, internal fragmentation, indirect blocks, and the
          like

8

Це поширена проблема, коли ви ставите однакові дані на 2 різні жорсткі диски. Ви хочете запустити duкоманду за допомогою та додатковий комутатор, припускаючи, що вона має її - що їй слід дати, це Linux-вузли.

Перемикач?

   --apparent-size
          print  apparent  sizes,  rather  than  disk  usage;  although the 
          apparent size is usually smaller, it may be larger due to holes in
          ('sparse') files, internal fragmentation, indirect blocks, and the 
          like

Приклад

$ du -sh --apparent-size /home/sam/scsconfig.log ~/scsconfig.log 
93K /home/sam/scsconfig.log
93K /root/scsconfig.log

Вищезазначені файлові системи - це локальний диск ( /root), а інша /home/sam- це поділка NFS від мого NAS.

$ df -h . /home/sam
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
                      222G  118G   92G  57% /
mulder:/export/raid1/home/sam
                      917G  566G  305G  65% /home/sam

Отже, що сталося?

Це бентежить багато людей, але пам’ятайте, що, коли файли зберігаються на диску, вони споживають блоки простору, навіть якщо вони використовують лише частину цих блоків. Якщо ви запускаєтесь duбез отримання, --apparent-sizeви отримуєте розмір залежно від кількості використовуваного блоку дискового простору, а не фактичного місця, що споживається файлами.

використовуючи контрольну суму замість цього?

Це, мабуть, кращий варіант, якщо ви стурбовані порівнянням двох дерев файлів. Ви можете використовувати цю команду для обчислення контрольної суми для всіх файлів, а потім обчислити остаточну контрольну суму контрольних сум. Цей приклад використовує, sha1sumале ви можете так само легко використовувати його md5sum.

$ cd /some/dir
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum

Приклад

$ cd ~/dir1
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

$ cd ~/dir2
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

Тож ми можемо бачити, що 2 дерева однакові.

(Примітка. Команда find перелічить файли так, як вони з'явилися у файловій системі. Отже, якщо ви порівнюєте два каталоги з різної файлової системи (наприклад, Ext3 проти APFS), вам потрібно впорядкувати спочатку до остаточного ша1суму. (Додано Сяньцзюнь Донг)


5

Коротка відповідь: не перевіряйте розмір файлу, не перевіряйте стан повернення команди. Статус повернення - єдиний достовірний показник того, чи вдалося копіювати (окрім порівняння двох байтів за байтом, безпосередньо побічно - що зайве, якщо копія вдалася).

Перевірка розміру файлу - не дуже корисний спосіб перевірити, чи вдалася копія. У деяких випадках це може бути корисною обстеженням, наприклад, коли ви завантажуєте файл з Інтернету. Але тут є кращий спосіб.

Усі команди Unix повертають статус, щоб вказати, чи вдалося їм: 0 за успіх, 1 або більше для помилок. Тому перевірте стан виходу cp. cpзазвичай буде надруковано повідомлення про помилку, якщо воно не вдалося, із зазначенням, що таке помилка. У сценарії статус виходу останньої команди знаходиться в магічній змінній $?.

cp -v traj.trr ~/mysimulation1/
if [ $? -ne 0 ]; then
  echo 1>&2 "cp failed due to the error above"
  exit 2
 fi

Замість того, щоб перевіряти, чи $?дорівнює нулю, ви можете використовувати булі оператори.

cp -v traj.trr ~/mysimulation1/ || exit 2

Якщо ви запускаєте сценарій і хочете, щоб він припинився, якщо будь-яка команда не вдалася, запустіть set -e. Якщо будь-яка команда виходить з ладу (тобто повертає ненульовий статус), сценарій негайно вийде з того ж статусу, що і команда.

set -e
…
cp -v traj.trr ~/mysimulation1/

Що стосується причини, коли ваш скопійований файл був більшим, він повинен бути, тому що це був розріджений файл . Рідкий файл - це сира форма стиснення, де блоки, що містять лише нульові байти, не зберігаються. Коли ви копіюєте файл, cpкоманда зчитує та записує нульові байти, тож там, де в оригіналі були відсутні блоки, у копії є блоки, наповнені нульовими байтами. У Linux cpкоманда намагається виявити розріджені файли, але це не завжди вдається; cp --sparse=alwaysзмушує постаратися більше за рахунок дуже незначного збільшення часу процесора.

Більш загально, duможна повернути різні результати завдяки іншим формам стиснення. Хоча стислі файлові системи рідкісні. Якщо ви хочете знати розмір файлу як кількість байтів у файлі, на відміну від кількості блоків дисків, які він використовує, використовуйте ls -lзамість du.


Дуже дякую! Чи знаєте ви, чи існує (окрема) утиліта, яка може сказати мені, чи мій файл розріджений чи ні?
Андрій

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.