Учитывая каталог с несколькими миллионами файлов в нем, мы хотим извлечь некоторые данные из этих файлов.Командный вывод, управляемый при перенаправлении
find /dir/ -type f | awk -F"|" '$2 ~ /string/{ print $3"|"$7 }' > the_good_stuff.txt
Это никогда не будет масштабироваться так мы вводим xargs.
find /dir/ -type f -print0 | xargs -0 -n1 -P6 awk -F"|" '$2 ~ /string/{ print $3"|"$7 }'
Это дает правильный выход независимо от того, сколько времени мы проводим его. Sweet, поэтому давайте напишем его в файл, добавив > the_good_stuff_from_xargs.txt
к этой команде. Кроме того, файл содержит искаженные строки.
Что меня поразило, так это то, что при просмотре вывода шести подпроцессов, которые xargs открывают как STDOUT в моем терминале, данные выглядят нормально. В момент, когда данные перенаправляются на файловую систему, возникает коррупция.
Я попытался добавить команду со следующим.
> myfile.txt
>> myfile.txt
| mawk '{print $0}' > myfile.txt
И другие различные концепции перенаправлять или иначе «объединение» выход из xargs перед записью на диск с данными, которые повреждены в каждой версии.
Я уверен, что исходные файлы не искажены. Я уверен, что при просмотре в терминале в качестве stdout команда с xargs производит допустимый выход в течение 10 минут, глядя на него текст с запятой ...
Локальный диск - это SSD ... Я читаю и пишу из той же файловой системы.
Почему перенаправление вывода find /dir/ -type f -print0 | xargs -0 -n1 -P6 awk -F"|" '$2 ~ /string/{ print $3"|"$7 }'
приводит к искажению данных?
EDIT
Я не могу в настоящее время установить unbuffer но stdbuf -oL -eL
изменяет выход команды будет строка в буфер и поэтому, теоретически, должен сделать то же самое.
Я пробовал оба: stdbuf xargs cmd
и xargs stdbuf cmd
оба привели к чрезвычайно ломающимся линиям.
-P6
требуется для выполнения этой команды в любое разумное время.
EDIT 2
Для уточнения ... xargs
и это -P6
флаг требования, чтобы решить эту проблему, так как каталог мы работаем в миллионы файлов, которые необходимо проверить.
Очевидно, что мы могли бы удалить -P6
или каким-либо другим способом остановить запуск нескольких рабочих мест сразу, но это на самом деле не отвечая на вопрос почему выход становится все подогнаны и не является реалистичным подходом к как выход может быть восстанавливается до состояния «правильное», но при этом выполняет задачу по шкале.
Решение
Принятый ответ упоминал об использовании parallel
, который работал лучший из всех ответов.
Последняя команда, с которой я работал, выглядела. time find -L /dir/ -type f -mtime -30 -print0 | parallel -0 -X awk -f manual.awk > the_good_stuff.txt
Awk было трудно, поэтому я переместил -F"|"
в саму команду. По умолчанию параллельная развертка задания на ядро на коробке, вы можете использовать -j
, чтобы установить количество заданий ниже, если это необходимо.
В действительно научных терминах это было массовое увеличение скорости. То, что заняло неизмеримое количество часов (вероятно, 6+), составляет 10%, завершено через 6-6 минут, поэтому, скорее всего, закончится в течение часа.
Один из них заключается в том, что вы должны убедиться, что команда, запущенная в parallel
, не пытается записать в файл ..., что эффективно обходит обработку вывода, выполняемую параллельно при выполнении заданий!
Истекает без -X
Параллельные действия аналогичны xargs -n1
.
Стандартный вывод буферизируется по строке при записи на терминал, но он полностью буферизуется при записи в канал или файл. – Barmar
Используйте команду 'unbuffer', которая поставляется с' Expect'. – Barmar
Удалите '-P6'; что приводит к тому, что 6 асинхронных процессов записывают в произвольном порядке на ваш вывод, и они пишут частичные строки по мере заполнения буфера, а разные процессы пишут разные частичные линии в разных точках и т. д. Если вы должны использовать '-P6', вам нужно иметь 6 процессов, записывающих разные файлы, чтобы они не топтались друг от друга. Это, в свою очередь, может означать запуск сценария оболочки, который запускает 'awk' и перенаправляет I/O в отдельный файл (возможно, используйте' mktemp', чтобы указать имя в PID скрипта). –