Я пытаюсь обрабатывать входные данные разными способами параллельно, записывая полученные строки по мере их поступления. Мой текущий подход таков:
# process_parallel.sh
read input
parallel --colsep ' ' --linebuffer 'echo $input | {}' \
::: 'python process1.py' ./process2.sh ./process3
Контекст сводится к чему-то вроде этого:
(sleep 1; echo "short input arriving late") | ./process_parallel.sh | ./collate_results.sh
Вышеуказанное работает, но имеет один важный недостаток: процессы не запускаются, пока не будет прочитан ввод. Я хочу запустить их немедленно, так как это может занять некоторое время, а затем параллельно передать полный stdin каждому из них.
Как этого добиться?
решение1
В GNU Parallel было вложено немало усилий, чтобы он не начинал новую работу, если нет данных для выполнения. Это связано с тем, что некоторые программы резко падают, если не получают никаких входных данных. Так что вы будете работать против дизайна GNU Parallel.
Чтобы продублировать входные данные, можно использовать tee
и обработать замену:
cat namedpipe_or_file | tee >(process1) >(process2) >(process3) >/dev/null
Он запустится process1
, process2
, и process3
немедленно. Однако вывод может быть смешанным, поэтому, если вывод необходимо использовать, следует перенаправить его в разные файлы:
cat namedpipe_or_file | tee >(process1 > out1) >(process2 > out2) >(process3 > out3) >/dev/null
решение2
Создайте два сценария-оболочки: во-первых, измените process_parallel.sh так, чтобы каждый из процессов получил указание считывать свои входные данные из трех файлов, скажем, file1, file2, file3.
Теперь напишите второй скрипт-оболочку, который параллельно отправляет свой стандартный ввод в три файла, что-то вроде:
#!/bins/bash
#parallelise input
# let's call this file parallelise
parallel -j 3 -- "echo $1 > file1" "echo $1 > file2" "echo $1 file3"
Теперь вы начинаете с:
./process_parallel_sh; cat InputFile | parallelise;
решение3
У Parallel есть --tee
опция, которую можно использовать следующим образом:
(sleep 1; echo "short input arriving late") |\
parallel --colsep ' ' --linebuffer --pipe --tee ::: 'python process1.py' ./process2.sh ./process3 |\
./collate_results.sh