Можно ли распространять STDIN по параллельным процессам?

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

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

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

Таким образом, приведенный выше пример ввода приведет к 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 parallel, но я не знаю, как это сделать.


person Erik    schedule 11.01.2011    source источник


Ответы (3)


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

cat | parallel --pipe --recend '===\n' --rrs do_stuff
person Ole Tange    schedule 11.01.2011
comment
Этот ответ может потребовать дополнительного объяснения: pipe вызывает параллельную запись в стандартный ввод вместо передачи параметров, recend — это конец записи, то есть разделенная строка, а rrs означает удаление начала записи, то есть удаление '===\n'. Помимо этого, --keep-order полезен. - person Caesar; 15.11.2018

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

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

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

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


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

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

person Jonathan Leffler    schedule 11.01.2011
comment
Чем tpipe отличается от pee? - person Ole Tange; 12.01.2011
comment
Я написал tpipe и раньше не слышал о pee. Но меня не удивляет, что у кого-то еще было такое же основное требование и он его реализовал. Я не уверен, догадываетесь ли вы, насколько сложно искать «pee» в Google (даже «site:gnu.org pee» оказывается спамом)! Таким образом, без URL-адреса программного обеспечения я не могу сравнивать и сопоставлять для вас. - person Jonathan Leffler; 12.01.2011
comment
serverfault.com/ Questions/96245/ показывает pee в использовании и показывает, что вам не нужно pee в bash: cat file | tee >(command1 >out1) >(command2 >out2) - person Ole Tange; 17.01.2011
comment
@Ole: спасибо за URL. Я отмечаю, что pee имеет семантику, отличную от tpipe по нескольким параметрам: в первую очередь, tpipe продолжает писать в доступные каналы до тех пор, пока они все не будут закрыты, а не останавливается при первой ошибке, как это делает pee. Возможности bash хороши, если bash надежно доступен на всех интересующих платформах, что избавляет меня от работы. (URL-адрес в конце моего ответа указывает на то же обозначение, но не на ту же статью), что и у вас. - person Jonathan Leffler; 17.01.2011

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

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

person David W.    schedule 11.01.2011