Можно ли распространять STDIN по параллельным процессам? - PullRequest
8 голосов
/ 11 января 2011

Учитывая следующий пример ввода на STDIN:

foo
bar bar
baz
===
qux
bla
===
def
zzz yyy

Можно ли разделить его на разделитель (в данном случае '===') и передать его через stdin команде, выполняющейся параллельно?

Таким образом, приведенный выше пример ввода приведет к 3 параллельным процессам (например, команде с именем do.sh), где каждый экземпляр получит часть данных в STDIN, например:

do.sh (экземпляр 1) получает это через STDIN:

foo
bar bar
baz

do.sh (экземпляр 2) получает это через STDIN:

qux
bla

do.sh (экземпляр 3) получает это через STDIN:

def
zzz yyy

Полагаю, что-то подобное возможно с использованием параллельных xargs или GNU, но я не знаю как.

Ответы [ 3 ]

12 голосов
/ 11 января 2011

GNU Parallel может делать это с версии 20110205.

cat | parallel --pipe --recend '===\n' --rrs do_stuff
2 голосов
/ 11 января 2011

В общем, нет. Одной из причин такой оценки является то, что стандартное чтение ввода-вывода из файлов, а не из терминала, считывает блоки данных - байты BUFSIZ за раз, где обычно BUFSIZ имеет степень 2, например 512 или больше. Если данные находятся в файле, один процесс будет читать весь показанный файл - другие не увидят ничего, если они будут использовать одно и то же описание открытого файла (аналогично дескриптору файла, но несколько файловых дескрипторов могут совместно использовать одно и то же описание открытого файла, и может быть в разных процессах) или будет читать весь тот же файл, если они не будут использовать одно и то же описание открытого файла.

Итак, вам нужен процесс для чтения файла, который знает, что ему нужно разделить информацию между тремя процессами - и ему нужно знать, как он должен соединиться с этими тремя процессами. Возможно, ваша дистрибьюторская программа запускает три процесса и записывает их на отдельные входные каналы. Или же это может быть связано с тем, что распределитель подключается к трем сокетам и записывает в разные сокеты.

Ваш пример не показывает / не описывает, что произошло бы, если бы маркер разделял 37 секций.

У меня есть программа домашнего пивоварения под названием tpipe, которая похожа на команду Unix tee, но она записывает копию (все) своего стандартного ввода в каждый из процессов и в стандартный вывод тоже по умолчанию , Это может быть подходящей основой для того, что вам нужно (по крайней мере, она охватывает часть управления процессами). Свяжитесь со мной, если хотите получить копию - смотрите мой профиль.


Если вы используете Bash, вы можете использовать обычный tee с подстановкой процесса для имитации tpipe. См. статью для иллюстрации того, как.

См. Также SF 96245 для другой версии той же информации - плюс ссылка на программу под названием pee, которая очень похожа на tpipe (та же основная идея, немного отличающаяся реализация в разных отношениях ).

1 голос
/ 11 января 2011

Вы можете сделать это, используя именованные каналы . Именованные каналы позволяют рассматривать стандартные трубопроводы как файлы. У вас может быть несколько именованных каналов, и ваши другие программы могут их обрабатывать.

Я не так уж хорошо знаком с именованными каналами, но время от времени использую их в подобных ситуациях.

...