Vraag Hoe kan ik twee named pipes samenvoegen in single input stream in linux


De leidingen gebruiken (|) in Linux Ik kan de standaardinvoer doorsturen naar een of meerdere uitvoerstromen.

ik kan gebruiken tee om de uitvoer te splitsen naar afzonderlijke subprocessen.

Is er een opdracht om twee invoerstromen samen te voegen?

Hoe zou ik dit aanpakken? Hoe werkt diff?


59
2017-08-16 17:29


oorsprong




antwoorden:


Persoonlijk mijn favoriet (vereist bash en andere dingen die standaard zijn op de meeste Linux-distributies)

De details kunnen sterk afhangen van wat de twee dingen uitvoeren en hoe u ze wilt samenvoegen ...

Inhoud van opdracht1 en opdracht2 na elkaar in de uitvoer:

cat <(command1) <(command2) > outputfile

Of als beide opdrachten alternatieve versies van dezelfde gegevens uitvoeren die u naast elkaar wilt weergeven (ik heb dit met snmpwalk gebruikt: nummers aan de ene kant en MIB-namen aan de andere kant):

paste <(command1) <(command2) > outputfile

Of als u de uitvoer van twee vergelijkbare opdrachten wilt vergelijken (bijvoorbeeld een zoekopdracht in twee verschillende mappen)

diff <(command1) <(command2) > outputfile

Of als ze een of andere soort van volgorde hebben besteld, voeg ze dan samen:

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

Of voer beide commando's tegelijk uit (kan echter een beetje scramble):

cat <(command1 & command2) > outputfile

De operator <() stelt een named pipe (of / dev / fd) in voor elke opdracht, piping de uitvoer van die opdracht in de named pipe (of / dev / fd filehandle reference) en geeft de naam door op de commandoregel. Er is een equivalent met> (). Je zou kunnen doen: command0 | tee >(command1) >(command2) >(command3) | command4 om tegelijkertijd de uitvoer van één commando naar 4 andere commando's te sturen, bijvoorbeeld.


94
2017-08-16 18:28



geweldig! ik heb de manpage van bash veel tijd gelezen, maar had die niet gekozen - Javier
U kunt de referentie vinden in de [geavanceerde bash scriptinggids] (tldp.org/LDP/abs/html/process-sub.html) bij het Linux-documentatieproject - brice
Jij rockt. Bedankt. - Steve Kehlet
ik was in staat om doorschoten lijnen te voorkomen door er doorheen te sluipen grep --line-buffered - handig voor gelijktijdig grephet tail van meerdere logbestanden. zien stackoverflow.com/questions/10443704/line-buffered-cat - RubyTuesdayDONO


Je kunt twee stomen toevoegen aan een andere met cat, zoals gorilla laat zien.

Je kunt ook een FIFO maken, de uitvoer van de commando's daarheen sturen en dan met elk ander programma van de FIFO lezen:

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

Vooral handig voor programma's die alleen een bestand schrijven of lezen, of voor het mixen van programma's die alleen stdout / file uitvoeren met een programma dat alleen het andere ondersteunt.


12
2017-08-16 17:43



Deze werkt op pfSense (FreeBSD) terwijl het geaccepteerde antwoord dat niet doet. Dank je! - Nathan


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

/tmp/p1 en /tmp/p2 zijn je invoerpijpen, terwijl /tmp/output is de uitvoer.


8
2017-08-16 17:36



Opmerking: Tenzij beide opdrachten in de zijkant staan () spoel hun uitvoer op elke regel (en een paar andere obscure POSIX-regels voor atomiciteit), je zou kunnen eindigen met een of ander raar klauteren op de invoer naar kat ... - freiheit
Zou u geen puntkomma moeten gebruiken in plaats van een ampersand-teken? - Samir


Ik heb hiervoor een speciaal programma gemaakt: fdlinecombine

Het leest meerdere buizen (meestal programma-uitgangen) en schrijft ze naar stdout linewise (je kunt ook het scheidingsteken overschrijven)


4
2017-07-26 00:09



Werkt zoals geadverteerd. Bedankt voor het openbaar maken. - alexei


Een echt coole opdracht die ik hiervoor heb gebruikt is tpipe, misschien moet je compileren omdat het niet zo gebruikelijk is. Het is echt geweldig om precies datgene te doen waar je het over hebt, en het is zo schoon dat ik het meestal installeer. De man-pagina bevindt zich hier http://linux.die.net/man/1/tpipe . De momenteel weergegeven download bevindt zich in dit archief http://www.eurogaran.com/downloads/tpipe/ .

Het is zo gebruikt,

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

3
2018-01-24 07:34





Wees hier voorzichtig; door ze gewoon in elkaar te zetten vermenigvuldig je de resultaten op manieren die je misschien niet wilt: bijvoorbeeld, als het logbestanden zijn, wil je waarschijnlijk niet echt een regel van de ene die halverwege de regel wordt ingevoegd van de andere. Als dat goed is, dan

staart -f / tmp / p1 / tmp / p2>   / Tmp / output

zal werken. Als dat zo is niet oke, dan zul je iets moeten doen dat lijnbuffering zal doen en alleen complete regels zal uitvoeren. Syslog doet dit, maar ik weet niet zeker wat anders.

EDIT: optimalisatie voor ongebufferd lezen en named pipes:

overweegt / tmp / p1, / ​​tmp / p2, / tmp / p3 als named pipes, gemaakt door "mkfifo / tmp / pN"

tail -q-f / tmp / p1 / tmp / p2 | awk '{print $ 0> "/ tmp / p3"; close ( "/ tmp / p3"); fflush ();} '&

nu kunnen we op deze manier de Output named pipe "/ tmp / p3" lezen gebufferd door :

staart - f / tmp / p3

er is een kleine bug van soort, je moet de 1e ingangspijp / tmp / p1 "initialiseren" door:

echo -n> / tmp / p1

om te staart accepteert eerst de invoer van 2nd pipe / tmp / p2 en wacht niet tot er iets op / tmp / p1 komt. dit is misschien niet het geval, als u zeker bent, ontvangt de / tmp / p1 als eerste invoer.

Ook is de -q optie nodig om staart print geen rommel over bestandsnamen.


3
2017-08-16 17:45



hoe nuttiger het zal zijn: "tail -q-f / tmp / p1 / tmp / p2 | another_command" omdat het regel voor regel wordt gedaan en met de optie -q wordt geen ander afval afgedrukt - readyblue
voor ongebufferd bestand / named pipe gebruik: tail -q -f /tmp/p1 /tmp/p2 | awk '{print $0 > "/tmp/p3"; close("/tmp/p3"); fflush();}' &   nu kan / tmp / p3 zelfs pipe genoemd worden en kun je het eenvoudig lezen tail -f /tmp/p3 dit is alles ONBUFFERD = regel voor regel  er is echter een kleine fout van soort. het eerste bestand / named pipe moet eerst worden geïnitialiseerd om de uitvoer van de tweede te accepteren. dus je moet het doen echo -n > /tmp/p1 en dan zal alles soepel werken. - readyblue


Het beste programma om dit te doen is lmerge. In tegenstelling tot het antwoord van Freihart is het lijngeoriënteerd zodat de uitvoer van de twee commando's elkaar niet overlapt. In tegenstelling tot andere oplossingen, wordt de invoer redelijk samengevoegd, zodat geen enkele opdracht de uitvoer kan domineren. Bijvoorbeeld:

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

Geeft de output van:

foo
bar
foo
bar

0
2018-05-11 22:16