Эффективное объединение / сортировка / уникальное большое количество текстовых файлов

У нас была эта ошибка у пары клиентов, DRDY ERR. Воспринимаемая ситуация заключалась в снижении скорости / производительности с большим количеством (очень большим числом) Raw_Read_Error_Rate.

К сожалению, эти ошибки обычно не являются доброкачественными, ожидаемая скорость при копировании файлов составляла 42–100 МБ / с и упала до менее 2 МБ / с за 60–90 секунд при копировании только 2 ГБ данных с последующим отказом. На самом деле это была проблема с контроллером SATA.

После проверки журналов мы сделали все необходимое для отказа оборудования. Была заменена материнская плата, заменены рейд-контроллеры, а также старые внебиржевые жесткие диски снова были заменены заводскими сертифицированными устройствами. Все идеально, хорошо и быстро после надлежащего ухода. Хотя дороговизна.

Dec 17 12:24:15 JoaoLuiz (ada0:ata3:0:0:0): WRITE_DMA. ACB: ca 00 00 00 00 40 00 00 00 00 00 00
Dec 17 12:24:15 JoaoLuiz (ada0:ata3:0:0:0): CAM status: ATA Status Error
Dec 17 12:24:15 JoaoLuiz (ada0:ata3:0:0:0): ATA status: 51 (DRDY SERV ERR),  error: 84 (ICRC ABRT )
Dec 17 12:24:15 JoaoLuiz (ada0:ata3:0:0:0): RES: 51 84 10 00 00 00 00 00 00 f0 00
Dec 17 12:24:15 JoaoLuiz (ada0:ata3:0:0:0): Retrying command
<about 10.000 DRDY SERV ERRs were enough to command maitenance>

Салют!

8
07.11.2019, 10:16
5 ответов

С GNU sort и оболочкой, в которую встроен printf (в настоящее время все POSIX-подобные, за исключением некоторых вариантов pdksh ):

printf '%s\0' * | sort -u --files0-from=- > output

Теперь проблема заключается в том, что, поскольку два компонента этого конвейера выполняются одновременно и независимо, к тому времени, когда левый расширяет глобус *, правый может уже создали файл output, который может вызвать проблемы (возможно, не с -u здесь), поскольку output будет и входным, и выходным файлом, так что вы можете хотите, чтобы вывод перешел в другой каталог (например, > ../output), или убедитесь, что glob не соответствует выходному файлу.

Другой способ обратиться к этому экземпляру — написать его:

printf '%s\0' * | sort -u --files0-from=- -o output

Таким образом, он сортирует открывает выход для записи и (в моих тестах) Не делайте этого до того, как он получит полный список файлов (так долго после того, как глобус был расширен). Это также позволит избежать затирания вывода , если ни один из входных файлов не читается.

Другой способ записать это с помощью zsh или bash

sort -u --files0-from=<(printf '%s\0' *) -o output

Это использование подстановки процесса (где <(...) заменяется путем к файлу, который ссылается к считывающему концу канала printf для записи). Эта функция происходит от ksh, но ksh настаивает на том, чтобы сделать расширение <(...) отдельным аргументом команды, поэтому вы не можете использовать это с опцией --option=<(...) синтаксис. Это будет работать с этим синтаксисом:

sort -u --files0-from <(printf '%s\0' *) -o output

Обратите внимание, что вы увидите разницу с подходами, которые передают вывод cat в файлы в случаях, когда есть файлы, которые не заканчиваются новой строкой. символ:

$ printf a > a
$ printf b > b
$ printf '%s\0' a b | sort -u --files0-from=-
a
b
$ printf '%s\0' a b | xargs -r0 cat | sort -u
ab

Также обратите внимание, что sort сортирует с использованием алгоритма сопоставления в локали (strcollate()), а sort -u сообщает об одном из каждого набора строк, которые сортируются одинаково по этому алгоритму, а не уникальные строки на уровне байтов. Если вы заботитесь только об уникальности строк на уровне байтов и не слишком заботитесь о порядке их сортировки, вы можете захотеть исправить языковой стандарт на C, где сортировка основана на байтовых значениях (memcmp( ); это, вероятно, значительно ускорит процесс):

printf '%s\0' * | LC_ALL=C sort -u --files0-from=- -o output
9
27.01.2020, 20:08

Эффективность — понятие относительное, поэтому вам действительно нужно указать, какой фактор вы хотите свести к минимуму; процессор, память, диск, время и т. д. В качестве аргумента я собираюсь предположить, что вы хотели минимизировать использование памяти и готовы потратить больше циклов процессора для достижения этого. Решения, подобные предложенному Stéphane Chazelas, работают хорошо

sort -u --files0-from <(printf '%s\0' *) > ../output

, но они исходят из того, что отдельные текстовые файлы изначально обладают высокой степенью уникальности. Если это не так, то есть если после

sort -u < sample.txt > sample.srt

файл sample.srt более чем на 10% меньше, чем файл sample.txt, вы сэкономите значительную часть памяти, удалив дубликаты в файлах перед слиянием. Вы также сэкономите еще больше памяти, не связывая команды, что означает, что результаты разных процессов не должны находиться в памяти одновременно.

find /somedir -maxdepth 1 type f -exec sort -u -o {} {} \;
sort -u --files0-from <(printf '%s\0' *) > ../output
1
27.01.2020, 20:08

Простое исправление, работает по крайней мере в Bash, так как printf встроен, и к нему не применяются ограничения аргументов командной строки:

printf "%s\0" * | xargs -0 cat | sort -u > /tmp/bla.txt

(echo * | xargs также будет работать, за исключением обработки имен файлов с пробелами и т. д.)

11
27.01.2020, 20:08
find . -maxdepth 1 -type f ! -name ".*" -exec cat {} + | sort -u -o /path/to/sorted.txt

Это объединит все не скрытые обычные файлы в текущем каталоге и отсортирует их объединенное содержимое (при удалении повторяющихся строк) в файл /путь/к/sorted.txt.

9
27.01.2020, 20:08

Вроде @ilkkachu, но кот (1 )лишний:

printf "%s\0" * | xargs -0 sort -u

Кроме того, если данные такие длинные, возможно, вы захотите использовать сорт (1 )вариант--параллельный = N

Когда N — это количество процессоров вашего компьютера

0
27.01.2020, 20:08

Теги

Похожие вопросы