Як з'єднати дві названі труби в один вхідний потік в Linux


64

Використовуючи функцію pipe ( |) в Linux, я можу переслати ланцюг стандартного вводу на один або кілька вихідних потоків.

Я можу використовувати, teeщоб розділити вихід на окремі підпроцеси.

Чи є команда з'єднати два вхідні потоки?

Як би я пішов про це? Як працює диференція?

Відповіді:


105

Особисто мій улюблений (вимагає 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одночасно надіслати висновок однієї команди, наприклад, 4 іншим командам.


приголомшливий! Я багато разів читав довідник компанії Bash, але не вибрав цього
Хав'єр

2
Довідку можна знайти в [розширеному посібнику з сценаріїв по bash] ( tldp.org/LDP/abs/html/process-sub.html ) у проекті з документацією на Linux
брик

3
я був в змозі запобігти чергуються лінії по конвеєру через grep --line-buffered- зручно для одночасно grep«т tailз декількох файлів журналів. см stackoverflow.com/questions/10443704/line-buffered-cat
RubyTuesdayDONO

16

Можна додати дві пари до іншої cat, як показує горила.

Ви також можете створити FIFO, направити висновок команд на це, а потім прочитати з FIFO будь-яку іншу програму:

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

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


2
Цей працює на pfSense (FreeBSD), тоді як прийнята відповідь не відповідає. Дякую!
Натан

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

/tmp/p1і /tmp/p2ваші вхідні труби, а /tmp/outputвихідний.


6
Примітка: Якщо обидві команди поруч не ()вмикають свої результати у кожному рядку (та деякі інші незрозумілі правила POSIX щодо атомності), у вас може
виникнути

Якщо ви не використовуєте крапку з комою замість символів "амперсанд"?
Самір

це епічні речі
Mobigital

5

Я створив для цього спеціальну програму: fdlinecombine

Він зчитує декілька труб (зазвичай програмні виходи) і записує їх у stdout лінійно (ви також можете переокремити роздільник)


Працює як реклама. Дякуємо, що зробили це загальнодоступним.
Алексей

3

Дійсно класна команда, яку я використав для цього tpipe, вам може знадобитися компілювати, оскільки це не так часто. Це дійсно чудово для того, щоб робити саме те, про що ви говорите, і це так чисто, що зазвичай я його встановлюю. Сторінка man розміщена тут 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

Будьте обережні тут; просто їх котирування призведе до змішування результатів способами, які ви можете не захотіти: наприклад, якщо вони є файлами журналів, ви, мабуть, не хочете, щоб рядок з однієї, вставленої на півдорозі через лінію від іншого. Якщо це нормально, значить

хвіст -f / tmp / p1 / tmp / p2> / tmp / вихід

буду працювати. Якщо це не нормально, то вам доведеться знайти щось, що дозволить зробити буферизацію ліній та вивести лише повні рядки. Syslog це робить, але я не впевнений, що ще може.

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

розглядаючи / tmp / p1, / ​​tmp / p2, / tmp / p3 як названі труби, створені "mkfifo / tmp / p N "

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

тепер цим способом ми можемо читати вихідну назву труби "/ tmp / p3", нерозподілену :

хвіст -f / tmp / p3

є невелика помилка сортування, вам потрібно "ініціалізувати" 1-у вхідну трубу / tmp / p1:

echo -n> / tmp / p1

для того, щоб хвіст першим прийняв вхід з 2-ї труби / tmp / p2 і не чекати, поки щось прийде в / tmp / p1. це може бути не так, якщо ви впевнені, що / tmp / p1 спочатку отримає вхід.

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


більш корисним буде: "хвіст -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 = рядок за рядком , однак, є невелика помилка сортування. 1-й файл / названа труба потрібно ініціалізувати першою, щоб хвіст прийняв вихід з другого. тож вам знадобиться echo -n > /tmp/p1і тоді все буде працювати безперебійно.
readyblue

1

Найкраща програма для цього lmerge. На відміну від відповіді freihart, він орієнтований на лінійку, тому вихід двох команд не буде чіпляти один одного. На відміну від інших рішень, він досить об'єднує вхід, тому жодна команда не може домінувати над результатами. Наприклад:

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

Дає вихід:

foo
bar
foo
bar
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.