У меня есть три вида данных в разных форматах; для каждого типа данных существует скрипт Python, который преобразует его в единый унифицированный формат.
Этот сценарий Python является медленным и привязанным к процессору (к одному ядру на многоядерном компьютере), поэтому я хочу запустить три его экземпляра - по одному для каждого типа данных - и объединить их вывод для передачи в него sort
. В основном эквивалентно этому:
{ ./handle_1.py; ./handle_2.py; ./handle_3.py } | sort -n
Но три сценария работают параллельно.
Я нашел этот вопрос, где GNU split
использовался для циклического перебора некоторого потока stdout между n экземплярами скрипта, который обрабатывает поток.
Из разделенной страницы руководства:
-n, --number=CHUNKS
generate CHUNKS output files. See below
CHUNKS may be:
N split into N files based on size of input
K/N output Kth of N to stdout
l/N split into N files without splitting lines
l/K/N output Kth of N to stdout without splitting lines
r/N like 'l' but use round robin distributio
Таким образом, r/N
команда подразумевает « без разделения строк ».
Исходя из этого, представляется целесообразным следующее решение:
split -n r/3 -u --filter="./choose_script" << EOF
> 1
> 2
> 3
> EOF
Где choose_script
это:
#!/bin/bash
{ read x; ./handle_$x.py; }
К сожалению, я вижу некоторое смешивание строк - и много новых строк, которых там быть не должно.
Например, если я заменю свои скрипты Python на несколько простых скриптов bash, которые делают это:
#!/bin/bash
# ./handle_1.sh
while true; echo "1-$RANDOM"; done;
,
#!/bin/bash
# ./handle_2.sh
while true; echo "2-$RANDOM"; done;
,
#!/bin/bash
# ./handle_3.sh
while true; echo "3-$RANDOM"; done;
Я вижу этот вывод:
1-8394
2-11238
2-22757
1-723
2-6669
3-3690
2-892
2-312511-24152
2-9317
3-5981
Это раздражает - основываясь на извлечении man-страницы, которое я вставил выше, оно должно поддерживать целостность строки.
Очевидно, это работает, если я удаляю -u
аргумент, но затем он буферизуется, и у меня заканчивается память, поскольку он буферизует вывод всех скриптов, кроме одного.
Если у кого-то есть понимание, это будет с благодарностью. Я здесь из моей глубины.
coproc
встроенную в bash, хотя я не очень понимаю, как это применимо.job1.py > file1 & job2.py > file 2 & job3.py > file3 ; wait ; sort -n file1 file2 file3
?Ответы:
Попробуйте использовать параметр -u в GNU параллельно.
Это запускает их параллельно, без буферизации всего процесса.
источник
X
вIX
говорить ,-I
что X будет флаг для замены, или его применения-X
флаг, который , казалось бы , также имеет соответствующее значение?parallel -u -X ./handle_{}.sh ::: "1" "2" "3"
и, к сожалению, я все еще вижу некоторые искажения вывода.parallel -u ./handle_{}.sh
, но я предпочитаю изменить его, поскольку скобки также имеют смысл объединения команд (как в вашем вопросе).Пытаться:
Если
handle_1.py
берет имя файла:Вы не хотите смешивать вывод, поэтому не используйте -u.
Если вы хотите сохранить порядок (поэтому все выходные данные handle_1 предшествуют handle_2 и, таким образом, вы можете избежать сортировки):
Если вы все еще хотите отсортировать, вы можете распараллелить сортировку и использовать
sort -m
:Установите $ TMPDIR в каталог, достаточно большой для хранения вывода.
источник
Может быть, я что-то упустил, но вы не можете просто сделать:
Если вы хотите, чтобы строки каждого процесса не чередовались, возможно, проще будет убедиться, что процесс сам запишет их полностью и, возможно, отключит буферизацию вывода, поскольку
write
s в канал гарантированно будут атомарными, если они не больше, чемPIPE_BUF
, Например, вы можете убедиться , что он делает использование буферизации ляstdio
и вызоваfflush
или любой другой эквивалент вpython
после того, как один или нескольких строк были написаны.Если вы не можете изменить скрипты Python, вы можете сделать:
(с GNU grep) или:
(См. Примечания в комментариях ниже, если вывод команды не является текстом)
И делать:
Другой вариант, позволяющий избежать этих трех
lb
процессов, состоит в том, чтобы иметь три канала для одной команды, которая используетselect
/,poll
чтобы увидеть, откуда поступает какой-то вывод, и передать его на основеsort
строк, но это требует небольшого программирования.источник
wait
там, я думаю.sort -n
будет оставаться до тех пор, пока все программы, у которых открыт fd, не завершены.Ответ Flowbok был правильным решением. Странно, но вывод GNU
parallel
искажается, если он выводится непосредственно в файл, но не если он идет в tty.К счастью,
script -c
имеется возможность имитировать tty.Есть еще три сценария:
,
,
Тогда есть файл, который инкапсулирует вызов параллели:
И тогда я называю это так:
Строки в выходных данных смешиваются построчно между выходными данными различных сценариев, но они не искажаются и не чередуются в данной строке.
Странное поведение от
parallel
- я могу подать отчет об ошибке.источник