web-dev-qa-db-fra.com

Comment joindre deux canaux nommés en un seul flux d'entrée sous Linux

Utilisation des tuyaux (|) dans Linux, je peux transmettre en chaîne l'entrée standard à un ou plusieurs flux de sortie.

Je peux utiliser tee pour diviser la sortie en sous-processus séparés.

Existe-t-il une commande pour joindre deux flux d'entrée?

Comment pourrais-je m'y prendre? Comment fonctionne diff?

66
Brad

Personnellement, mon préféré (nécessite bash et d'autres choses standard sur la plupart des distributions Linux)

Les détails peuvent dépendre en grande partie de la sortie des deux éléments et de la manière dont vous souhaitez les fusionner ...

Contenu de command1 et command2 l'un après l'autre dans la sortie:

cat <(command1) <(command2) > outputfile

Ou si les deux commandes produisent des versions alternatives des mêmes données que vous souhaitez voir côte à côte (je l'ai utilisé avec snmpwalk; les nombres d'un côté et les noms MIB de l'autre):

paste <(command1) <(command2) > outputfile

Ou si vous voulez comparer la sortie de deux commandes similaires (dites une recherche sur deux répertoires différents)

diff <(command1) <(command2) > outputfile

Ou s'il s'agit de sorties ordonnées, fusionnez-les:

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

Ou exécutez les deux commandes à la fois (pourrait brouiller un peu les choses, cependant):

cat <(command1 & command2) > outputfile

L'opérateur <() configure un canal nommé (ou/dev/fd) pour chaque commande, en canalisant la sortie de cette commande dans le canal nommé (ou/dev/fd référence de descripteur de fichier) et transmet le nom sur la ligne de commande. Il y a un équivalent avec> (). Vous pouvez faire: command0 | tee >(command1) >(command2) >(command3) | command4 pour envoyer simultanément la sortie d'une commande à 4 autres commandes, par exemple.

109
freiheit

Vous pouvez ajouter deux vapeurs à l'autre avec cat, comme le montre le gorille.

Vous pouvez également créer un FIFO, diriger la sortie des commandes vers cela, puis lire à partir du FIFO avec n'importe quel autre programme:

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

Particulièrement utile pour les programmes qui n'écriront ou ne liront qu'un fichier, ou pour mélanger des programmes qui ne produisent que stdout/file avec un qui ne prend en charge que l'autre.

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

/tmp/p1 et /tmp/p2 sont vos canaux d'entrée, tandis que /tmp/output est la sortie.

9
gorilla

J'ai créé un programme spécial pour cela: fdlinecombine

Il lit plusieurs canaux (généralement des sorties de programme) et les écrit dans la sortie standard de la ligne (vous pouvez également remplacer le séparateur)

5
Vi.

Faites attention ici; le simple fait de les attacher finira par mélanger les résultats comme vous ne le souhaitez peut-être pas: par exemple, s'il s'agit de fichiers journaux, vous ne voulez probablement pas vraiment qu'une ligne de l'un soit insérée à mi-chemin à travers une ligne de l'autre. Si ça va, alors

tail -f/tmp/p1/tmp/p2>/tmp/sortie

marchera. Si c'est pas d'accord, alors vous devrez trouver quelque chose qui fera la mise en mémoire tampon des lignes et ne produira que des lignes complètes. Syslog fait cela, mais je ne sais pas quoi d'autre pourrait le faire.

EDIT: optimisation pour la lecture sans tampon et les canaux nommés:

considérant/tmp/p1,/​​tmp/p2,/tmp/p3 comme des canaux nommés, créés par "mkfifo/tmp/p [~ # ~] n [~ # ~] "

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

maintenant de cette façon, nous pouvons lire la sortie nommée pipe "/ tmp/p3" sans tampon par:

queue -f/tmp/p3

il y a un petit bug en quelque sorte, il faut "initialiser" le 1er pipe d'entrée/tmp/p1 en:

echo -n>/tmp/p1

afin de tail acceptera d'abord l'entrée du 2ème tube/tmp/p2 et n'attendra pas que quelque chose arrive à/tmp/p1. ce n'est peut-être pas le cas, si vous êtes sûr, le/tmp/p1 recevra d'abord l'entrée.

L'option -q est également nécessaire pour que tail n'imprime pas les ordures sur les noms de fichiers.

3
pjz

Une commande vraiment cool que j'ai utilisée pour cela est tpipe, vous pourriez avoir besoin de compiler car ce n'est pas si courant. C'est vraiment génial pour faire exactement ce dont vous parlez, et c'est tellement propre que je l'installe habituellement. La page de manuel se trouve ici http://linux.die.net/man/1/tpipe . Le téléchargement actuellement répertorié se trouve dans cette archive http://www.eurogaran.com/downloads/tpipe/ .

Il est utilisé comme ça,

## Reinject sub-pipeline stdout into standard output:
$ pipeline1 | tpipe "pipeline2" | pipeline3
3
J. M. Becker

Le meilleur programme pour ce faire est lmerge . Contrairement à la réponse de freihart, elle est orientée ligne, de sorte que la sortie des deux commandes ne s'encombrera pas. Contrairement à d'autres solutions, il fusionne assez bien l'entrée afin qu'aucune commande ne puisse dominer la sortie. Par exemple:

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

Donne la sortie de:

foo
bar
foo
bar
1
Rian Hunter