Вопрос: Как объединить два именованных канала в один поток ввода в Linux


Использование труб (|) в Linux Я могу переслать цепочку стандартного ввода в один или несколько выходных потоков.

я могу использовать tee для разделения вывода на отдельные подпроцессы.

Есть ли команда присоединиться к двум входным потокам?

Как я могу это сделать? Как работает diff?


56
2017-08-16 17:29


Источник




Ответы:


Лично, мой любимый (требуется bash и другие вещи, которые являются стандартными для большинства дистрибутивов Linux)

Детали могут сильно зависеть от того, что выводит две вещи и как вы хотите их объединить ...

Содержание команды 1 и команды2 друг на друга в выводе:

cat <(command1) <(command2) > outputfile

Или, если обе команды выдают альтернативные версии тех же данных, которые вы хотите видеть бок о бок (я использовал это с snmpwalk, номерами с одной стороны и именами MIB на другом):

paste <(command1) <(command2) > outputfile

Или если вы хотите сравнить вывод двух похожих команд (скажем, найти в двух разных каталогах)

diff <(command1) <(command2) > outputfile

Или, если они заказаны какие-то выходы, объедините их:

sort -m <(command1) <(command2) > outputfile

Или запустите обе команды сразу (может немного скрестить вещи):

cat <(command1 & command2) > outputfile

Оператор <() устанавливает именованный канал (или / dev / fd) для каждой команды, передает вывод этой команды в именованный канал (или ссылку на ссылку на файл / dev / fd) и передает имя в командной строке. Существует эквивалент с> (). Вы можете сделать: command0 | tee >(command1) >(command2) >(command3) | command4 например, для одновременной отправки вывода одной команды на 4 других команды.


90
2017-08-16 18:28



здорово! Я много раз читал справочную страницу Баша, но не выбрал этот - Javier
Вы можете найти ссылку в [расширенном руководстве по сценарию bash] (tldp.org/LDP/abs/html/process-sub.html) в проекте документации linux - brice
Ты жжешь. Благодарю. - Steve Kehlet
я смог предотвратить чередующиеся линии путем прохождения через grep --line-buffered - Удобно для одновременного grepв tail из нескольких файлов журнала. видеть stackoverflow.com/questions/10443704/line-buffered-cat - RubyTuesdayDONO


Вы можете добавить два пара в другое с помощью cat, как показывает горилла.

Вы также можете создать FIFO, направлять вывод команд на это, а затем читать из FIFO с помощью любой другой программы:

mkfifo ~/my_fifo
command1 > ~/my_fifo &
command2 > ~/my_fifo &
command3 < ~/my_fifo

Особенно полезно для программ, которые будут только писать или читать файл, или смешивать программы, которые выводят только файл stdout / file с тем, который поддерживает только другой.


12
2017-08-16 17:43



Это работает на pfSense (FreeBSD), а принятый ответ - нет. Спасибо! - Nathan


(tail -f /tmp/p1 & tail -f /tmp/p2 ) | cat > /tmp/output

/tmp/p1 а также /tmp/p2 ваши входные трубы, в то время как /tmp/output это выход.


8
2017-08-16 17:36



Примечание. Если обе команды в стороне () очистить их вывод на каждой строке (и некоторые другие неясные правила POSIX для атомарности), вы можете в конечном итоге с некоторым странным скремблированием на входе в cat ... - freiheit
Если вы не используете точку с запятой вместо символа амперсанда? - Samir


Для этого я создал специальную программу: fdlinecombine

Он считывает несколько каналов (обычно программные выходы) и записывает их в стандартный вывод (вы также можете переопределить разделитель)


4
2017-07-26 00:09



Работает как рекламируется. Спасибо, что сделали это публично. - alexei


Действительно классная команда, которую я использовал для этого, - это tpipe, вам может понадобиться компиляция, потому что это не так часто. Это действительно здорово для того, чтобы делать то, о чем вы говорите, и это так чисто, что я обычно устанавливаю его. Страница руководства находится здесь http://linux.die.net/man/1/tpipe , Текущая в списке загрузка находится в этом архиве http://www.eurogaran.com/downloads/tpipe/ ,

Он используется так,

## Reinject sub-pipeline stdout into standard output:
$ pipeline1 | tpipe "pipeline2" | pipeline3

3
2018-01-24 07:34





Будьте осторожны; просто котировка их приведет к смешению результатов способами, которые вам могут не понадобиться: например, если они являются файлами журналов, вы, вероятно, действительно не хотите, чтобы строка из одной вставлена ​​на полпути через другую. Если все в порядке, то

tail -f / tmp / p1 / tmp / p2>   / TMP / вывода

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

EDIT: оптимизация для небуферизованного чтения и названных каналов:

учитывая / tmp / p1, / ​​tmp / p2, / tmp / p3 как именованные каналы, созданные «mkfifo / tmp / pN"

tail -q -f / tmp / p1 / tmp / p2 | awk '{print $ 0> "/ tmp / p3"; закрыть ( "/ TMP / р3"); fflush ();} '&

теперь, таким образом, мы можем прочитать Output named pipe "/ tmp / p3" небуферизован от :

tail -f / tmp / p3

есть небольшая ошибка, вам нужно «инициализировать» первый входной канал / tmp / p1:

echo -n> / tmp / p1

чтобы хвост сначала будет принимать входной сигнал от второго канала / tmp / p2, а не ждать, пока что-то не поступит в / tmp / p1. это может быть не так, если вы уверены, что / tmp / p1 сначала получит вход.

Также необходима опция -q, чтобы хвост не печатает мусор о именах файлов.


3
2017-08-16 17:45



тем полезнее будет: "tail -q -f / tmp / p1 / tmp / p2 | another_command" так как это будет выполняться по строкам и с опцией -q, он не будет печатать какой-либо другой мусор - readyblue
для использования небуферизованного файла / именованного канала: tail -q -f /tmp/p1 /tmp/p2 | awk '{print $0 > "/tmp/p3"; close("/tmp/p3"); fflush();}' &   теперь / tmp / p3 может быть даже именованным каналом, и вы можете прочитать его просто tail -f /tmp/p3 все это UNBUFFERED = строка за строкой  есть, однако, небольшая ошибка. первый файл / именованный канал должен быть инициализирован первым, так как хвост будет принимать результат со второго. так что вам нужно будет echo -n > /tmp/p1 и все будет работать гладко. - readyblue


Лучшая программа для этого - lmerge, В отличие от ответа Freihart, он ориентирован на линию, поэтому вывод двух команд не будет сжиматься друг с другом. В отличие от других решений, он довольно сглаживает вход, поэтому никакая команда не может доминировать над выходом. Например:

$ lmerge <(yes foo) <(yes bar) | head -n 4

Дает вывод:

foo
bar
foo
bar

0
2018-05-11 22:16