Назад | Перейти на главную страницу

Как мне объединить два именованных канала в один входной поток в Linux

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

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

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

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

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

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

Содержимое command1 и command2 друг за другом в выводе:

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 для одновременной отправки вывода одной команды, например, четырем другим командам.

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

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

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

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

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

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

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

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

По-настоящему крутая команда, которую я использовал для этого, - 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

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

хвост -f / tmp / p1 / tmp / p2> / tmp / output

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

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

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

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

теперь таким образом мы можем прочитать выходной именованный канал "/ tmp / p3" небуферизованный по :

хвост -f / tmp / p3

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

эхо -n> / tmp / p1

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

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

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

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

Дает результат:

foo
bar
foo
bar