78 votes

Comment joindre deux tuyaux nommés en un seul flux d'entrée sous linux

En utilisant les |, fonctionnalité de Linux, je peux transférer en chaîne l'entrée standard vers un ou plusieurs flux de sortie.

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

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

Comment puis-je procéder ? Comment fonctionne diff ?

125voto

freiheit Points 14144

Personnellement, mon favori (nécessite bash et d'autres choses qui sont standard sur la plupart des distributions Linux)

Les détails peuvent beaucoup dépendre de ce que les deux choses produisent et de la façon dont vous souhaitez les fusionner ...

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

cat <(command1) <(command2) > fichier_de_sortie

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

paste <(command1) <(command2) > fichier_de_sortie

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

diff <(command1) <(command2) > fichier_de_sortie

Ou s'ils sont des sorties ordonnées d'une certaine manière, fusionnez-les :

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

Ou exécutez les deux commandes en même temps (cela pourrait mélanger un peu les choses, cependant) :

cat <(command1 & command2) > fichier_de_sortie

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

0 votes

Génial! J'ai lu la page de manuel de Bash de nombreuses fois mais je n'avais pas choisi celle-là

2 votes

Vous pouvez trouver la référence dans le [guide avancé de script Bash] (tldp.org/LDP/abs/html/process-sub.html) sur le projet de documentation Linux

3 votes

J'ai pu empêcher les lignes imbriquées en passant par grep --line-buffered - pratique pour rechercher simultanément le grep de la tail de plusieurs fichiers journaux. voir stackoverflow.com/questions/10443704/line-buffered-cat

18voto

frameworkninja Points 628

Vous pouvez ajouter deux flux à un autre avec cat, comme le montre gorilla.

Vous pouvez également créer un FIFO, diriger la sortie des commandes vers celui-ci, 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 sortent que stdout/fichier avec ceux qui ne supportent que l'autre.

2 votes

Ce code fonctionne sur pfSense (FreeBSD) tandis que la réponse acceptée ne fonctionne pas. Merci!

0 votes

Comment cela fonctionne-t-il en termes d'empêcher les fichiers d'écraser les données de l'autre ? Je cherche quelque chose qui respecte la mise en tampon des lignes

13voto

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

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

6 votes

Note : À moins que les deux commandes à l'intérieur des () ne vident leur sortie sur chaque ligne (et certaines autres règles obscures POSIX pour l'atomicité), vous pourriez vous retrouver avec un mélange bizarre dans l'entrée de cat ...

0 votes

Ne devriez-vous pas utiliser un point-virgule à la place du caractère d'esperluette ?

0 votes

C'est un contenu épique

7voto

Vi. Points 821

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

Il lit plusieurs tuyaux (généralement des sorties de programme) et les écrit sur stdout ligne par ligne (vous pouvez également remplacer le séparateur)

0 votes

Fonctionne comme annoncé. Merci de l'avoir rendu public.

4voto

mreggen Points 2940

Faites attention ici ; les concaténer les fichiers finiront par mélanger les résultats de manières que vous ne voulez peut-être pas : par exemple, s'il s'agit de fichiers journaux, vous ne voulez probablement pas vraiment qu'une ligne d'un soit insérée à mi-chemin à travers une ligne de l'autre. Si c'est le cas, alors

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

fonctionnera. Si ce n'est pas ok, alors vous devrez trouver quelque chose qui fera du buffer des lignes et n'affichera que des lignes complètes. Syslog le fait, mais je ne suis pas sûr de ce qui d'autre pourrait.

ÉDIT : optimisé pour une lecture non bufferisée et les tubes nommés :

en considérant /tmp/p1, /tmp/p2, /tmp/p3 comme des tubes nommés, créés par "mkfifo /tmp/pN"

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

maintenant nous pouvons lire le tube nommé de sortie "/tmp/p3" non bufferisé par :

tail -f /tmp/p3

il y a un petit bug de genre, vous devez "initialiser" le 1er tube d'entrée /tmp/p1 en faisant :

echo -n > /tmp/p1

afin que tail accepte l'entrée du 2ème tube /tmp/p2 en premier et n'attende pas qu'il y ait quelque chose dans /tmp/p1. Cela peut ne pas être le cas à moins que vous soyez sûr que /tmp/p1 recevra d'abord l'entrée.

Aussi l'option -q est nécessaire pour que tail n'imprime pas d'informations inutiles sur les noms de fichiers.

0 votes

Plus utile sera: "tail -q -f /tmp/p1 /tmp/p2 | another_command" car il sera exécuté ligne par ligne et avec l'option -q, il n'imprimera aucun autre déchet

0 votes

Pour un fichier/non accroché/pipe nommé, utilisez : tail -q -f /tmp/p1 /tmp/p2 | awk '{print $0 > "/tmp/p3"; close("/tmp/p3"); fflush();}' & maintenant le /tmp/p3 peut même être un pipe nommé et vous pouvez le lire simplement avec tail -f /tmp/p3 tout cela est NON MIS EN TAMBOUR = ligne par ligne il y a cependant un petit bug de tri. le 1er fichier/pipe nommé doit être initialisé d'abord pour que tail accepte la sortie du 2ème. donc vous devrez echo -n > /tmp/p1 et ensuite tout fonctionnera correctement.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X