Чому з'являється tar, щоб пропустити вміст файлу, коли вихідний файл / dev / null?


21

У мене є каталог із понад 400 ГБ даних. Я хотів переконатися, що всі файли можна читати без помилок, тому простий спосіб, який я придумав, був у tarньому /dev/null. Але замість цього я бачу таку поведінку:

$ time tar cf /dev/null .

real    0m4.387s
user    0m3.462s
sys     0m0.185s
$ time tar cf - . > /dev/null

real    0m3.130s
user    0m3.091s
sys     0m0.035s
$ time tar cf - . | cat > /dev/null
^C

real    10m32.985s
user    0m1.942s
sys     0m33.764s

Третю команду вище було насильно зупинено Ctrl+ Cпісля того, як вона вже досить довго бігла. Більше того, в той час, як перші дві команди працювали, індикатор активності пристрою зберігання даних .майже завжди не працював. Третьою командою індикатор постійно горить, що означає надзвичайну зайнятість.

Отже, здається, що, коли tarзможе дізнатись, що його вихідний файл є /dev/null, тобто коли /dev/nullвін відкритий безпосередньо, щоб мати обробку файлу, на яку tarзаписується, тіло файлу з'являється пропущеним. (Додавання vопції для tarдруку всіх файлів у каталозі є tarчервоними.)

Тож мені цікаво, чому це так? Це якась оптимізація? Якщо так, то навіщо tarвзагалі хотіти робити таку сумнівну оптимізацію для такого особливого випадку?

Я використовую GNU tar 1.26 з glibc 2.27 в Linux 4.14.105 amd64.


7
Як практичну альтернативу розглянемо щось подібне find . -type f -exec shasum -a256 -b '{}' +. Мало того, що він на самому справі читати і контрольну суму всіх даних, але якщо ви зберігаєте на вихід, ви можете повторно запустити його пізніше , щоб перевірити , що вміст файлів не змінилися.
Ільмарі Каронен

Для вимірювання речей , які ви можете використовувати pv: tar -cf - | pv >/dev/null. Це вирішує проблему і надає інформацію про хід (різні pvваріанти)
ксеноїд

Ви потрапили на добре відому функцію пропуску смоли GNU. Використовуйте gtar -cf /dev/zero ...для отримання того, що вам подобається.
schily

Відповіді:


25

Це є документованої оптимізація :

Коли архів створюється для /dev/null, GNU tar намагається мінімізувати операції введення та виводу. Система резервного копіювання Amanda при використанні з GNU tar має початковий пропускний розмір, який використовує цю функцію.


4
Ах, це не було описано на чоловіковій сторінці, яку я встановив. Потрібно info tarнатомість спробувати ...
Руслан

9
Вони справді повинні синхронізувати сторінки man & info, це практично помилка, якої вони не є
Xen2050

9
@Ruslan У більшості утиліт GNU, довідкова сторінка містить лише короткий підсумок, в основному достатньо хороший лише тоді, коли ви пам’ятаєте, що на ньому є можливість щось робити, але не пам’ятайте імені цього варіанта. Повна документація складається у форматі, який не добре перекладається на підручні сторінки та доступний із infoабо як HTML у браузері.
Жиль "ТАК - перестань бути злим"


8

Це може статися з різними програмами, наприклад, я мав таку поведінку один раз, коли просто користувався cp file /dev/null; замість того, щоб отримати оцінку швидкості читання мого диска, команда повернулася через кілька мілісекунд.

Наскільки я пам’ятаю, це було на Solaris або AIX, але принцип стосується всіх видів unix-y систем.

У старі часи, коли програма копіювала файл кудись, вона чергувала readдзвінки, які отримують деякі дані з диска (або те, що дескриптор файлу посилається) на пам'ять (з гарантією, що все є, коли readповертається) та writeдзвінки (які забирають шматок пам'яті та надсилають вміст до пункту призначення).

Однак є як мінімум два новіші способи досягти того ж:

  • У Linux є системні виклики copy_file_range(зовсім не портативні для інших Unix) та sendfile(дещо портативні; спочатку призначені для надсилання файлу в мережу, але зараз можуть використовувати будь-яке призначення). Вони призначені для оптимізації передач; якщо програма використовує один із них, ядро ​​легко визнати цільовим /dev/nullі перетворює системний виклик у неоперативний

  • Програми можуть використовуватись mmapдля отримання вмісту файлу замість цього read, це в основному означає "переконайтесь, що дані є, коли я намагаюся отримати доступ до цього фрагменту пам'яті", а не "переконайтеся, що дані є там, коли системний виклик повертається". Таким чином, програма може mmapвихідний файл, а потім зателефонувати writeна цю частину картографічної пам'яті. Однак, оскільки для запису /dev/nullне потрібно отримувати доступ до письмових даних, умова "переконайтеся, що це там" ніколи не спрацьовує, в результаті чого файл також не читається.

Не впевнений , що якщо гну дьоготь використовує будь-який, і які з цих двох механізмів , коли він виявляє , що це пише /dev/null, але вони чомусь будь-яка програма, коли використовується для перевірки читання , швидкості , повинна працювати з | cat > /dev/nullзамість > /dev/null- і чому | cat > /dev/nullповинен слід уникати у всіх інших випадках.


Думаю, що на tarінформаційній сторінці GNU (див. Іншу відповідь) значення має те, що для цього є спеціальний режим, який, імовірно, просто зафіксує файли, не відкриваючи їх. Насправді я просто перевірив tar cf /dev/null foo*кілька файлів, і так, лише newfstatat(..., AT_SYMLINK_NOFOLLOW)системні дзвінки, навіть не той, open()який може оновлювати час. Але +1 для опису механізмів, де це може статися без особливого виявлення.
Пітер Кордес

Чи має пояснення mmap зазначати "доступ до прочитаних даних", а не "доступ до письмових даних?"
Уейн Конрад

Дивіться також splice(2)на Linux. Насправді, заміна cat > /dev/nullна pv -q > /dev/null(що використовується splice()на Linux), швидше за все, зменшить накладні витрати. Або dd bs=65536 skip=9999999999 2> /dev/null, або wc -c > /dev/nullабо tail -c1 > /dev/null...
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.