Como eu uno dois pipes nomeados em um único fluxo de entrada no linux

60

Usando o recurso pipes ( | ) no Linux, posso encaminhar a cadeia de entrada padrão para um ou vários fluxos de saída.

Eu posso usar tee para dividir a saída para separar subprocessos.

Existe um comando para juntar dois fluxos de entrada?

Como eu faria isso? Como funciona o diff?

    
por Cristian Ciupitu 16.08.2010 / 19:29

7 respostas

95

Pessoalmente, meu favorito (requer bash e outras coisas que são padrão na maioria das distribuições Linux)

Os detalhes podem depender muito do que as duas coisas produzem e como você deseja mesclá-las ...

Conteúdo do comando1 e comando2 após o outro na saída:

cat <(command1) <(command2) > outputfile

Ou se ambos os comandos geram versões alternativas dos mesmos dados que você deseja ver lado a lado (usei isso com snmpwalk; números em um lado e nomes MIB no outro):

paste <(command1) <(command2) > outputfile

Ou se você quiser comparar a saída de dois comandos semelhantes (digamos, um encontro em dois diretórios diferentes)

diff <(command1) <(command2) > outputfile

Ou, se eles tiverem saídas ordenadas de algum tipo, mescle-as:

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

Ou execute os dois comandos ao mesmo tempo (pode embaralhar um pouco as coisas):

cat <(command1 & command2) > outputfile

O operador < () configura um canal nomeado (ou / dev / fd) para cada comando, canalizando a saída desse comando para o canal nomeado (ou / dev / fd filehandle reference) e passa o nome no linha de comando. Existe um equivalente com > (). Você poderia fazer: command0 | tee >(command1) >(command2) >(command3) | command4 para enviar simultaneamente a saída de um comando para 4 outros comandos, por exemplo.

    
por 16.08.2010 / 20:28
13

Você pode acrescentar dois fluxos a outro com cat , como mostra o gorila.

Você também pode criar um FIFO, direcionar a saída dos comandos para aquele, então ler o FIFO com qualquer outro programa:

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

Particularmente útil para programas que apenas escrevem ou lêem um arquivo, ou misturam programas que apenas produzem stdout / file com um que suporta somente o outro.

    
por 16.08.2010 / 19:43
8
(tail -f /tmp/p1 & tail -f /tmp/p2 ) | cat > /tmp/output

/tmp/p1 e /tmp/p2 são seus pipes de entrada, enquanto /tmp/output é a saída.

    
por 16.08.2010 / 19:36
5

Eu criei um programa especial para isso: fdlinecombine

Ele lê vários canais (geralmente saídas de programa) e os grava em stdout linewise (você também pode substituir o separador)

    
por 26.07.2012 / 02:09
3

Um comando muito legal que eu usei para isso é tpipe , você pode precisar compilar porque não é tão comum. É realmente ótimo para fazer exatamente o que você está falando, e é tão limpo que eu geralmente o instalo. A página man está localizada aqui link . O download atualmente listado é neste link do arquivo.

É usado assim,

## Reinject sub-pipeline stdout into standard output:
$ pipeline1 | tpipe "pipeline2" | pipeline3
    
por 24.01.2012 / 08:34
3

Tenha cuidado aqui; apenas catalogá-los acabará misturando os resultados de maneiras que você pode não querer: por exemplo, se eles são arquivos de log, você provavelmente não quer realmente uma linha de um inserido na metade de uma linha do outro. Se estiver tudo bem, então

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

funcionará. Se não estiver bem, então você terá que encontrar algo que faça o buffer de linha e apenas exiba linhas completas. O syslog faz isso, mas não sei o que mais poderia fazer.

EDIT: otimização para leitura sem buffer e pipes nomeados:

considerando / tmp / p1, / tmp / p2, / tmp / p3 como pipes nomeados, criados por "mkfifo / tmp / p N "

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

agora, desta forma, podemos ler o canal nomeado de saída "/ tmp / p3" sem buffer por:

tail -f /tmp/p3

há um pequeno bug de tipo, você precisa "inicializar" o primeiro canal de entrada / tmp / p1 por:

echo -n > /tmp/p1

para que tail aceite a entrada do segundo pipe / tmp / p2 primeiro e não espere até que algo chegue a / tmp / p1. isso pode não ser o caso, se você tiver certeza, o / tmp / p1 receberá a entrada primeiro.

Além disso, a opção -q é necessária para que tail não imprima lixo sobre nomes de arquivos.

    
por 16.08.2010 / 19:45
1

O melhor programa para fazer isso é lmerge . Ao contrário da resposta do freihart, ele é orientado para a linha, de modo que a saída dos dois comandos não vai atrapalhar um ao outro. Ao contrário de outras soluções, ela funde bastante a entrada, de modo que nenhum comando pode dominar a saída. Por exemplo:

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

Fornece saída de:

foo
bar
foo
bar
    
por 12.05.2017 / 00:16