¿Es posible redirigir la salida de un comando a más de un comando?

21

Hasta donde sé, puedo usar el comando tee para dividir la salida estándar en la pantalla y otros archivos:

command -option1 -option2 argument | tee file1 file2 file3 

¿Es posible redirigir la salida a comandos en lugar de archivos usando tee, para que teóricamente pueda crear una cadena de comandos?

Abdul Al Hazred
fuente
3
Explique lo que quiere decir con "señal de salida" y describa lo que quiere decir con la creación de una "red de comandos".
Janis
En Linux, cada comando tiene una entrada y dos salidas. están etiquetados con 0 (para entrada), 1 (para salida) y 2 (para salida de error). Estaba pensando en 1 cuando dije "señal de salida" porque leí que el comando tee divide solo la salida etiquetada 1. Cuando dije "red de comandos" no era muy técnico, no estoy seguro de cómo se define correctamente la red un punto de vista matemático, pero simplemente estaba pensando en un árbol de comandos tipológicamente hablando, de modo que algunos comandos pueden ser padres de más de un comando hijo.
Abdul Al Hazred
Gracias por tu aclaración. No utilice la palabra señal, ya que tiene un significado específico en Unix, y el término fue muy engañoso en este contexto. Gracias de nuevo.
Janis
En la línea de comando, ingrese man -k signal para aprender el significado especial de este concepto clave en UNIX y Linux. Man kill sería una buena página para comenzar.
Rob
Además, muchas personas se refieren a stdin stdout y stderr como 'flujos' de entrada o salida. Hay como pequeños ríos de datos, por lo tanto, una corriente. Tenías razón al lidiar con una palabra para describirla colectivamente, pero señal es simplemente la palabra incorrecta.
Rob

Respuestas:

25

Puede usar canalizaciones con nombre ( http://linux.die.net/man/1/mkfifo ) en la línea de teecomandos y hacer que los comandos se lean en las canalizaciones con nombre.

mkfifo /tmp/data0 /tmp/data1 /tmp/data2
cmd0 < /tmp/data0 & cmd1 < /tmp/data1 & cmd2 < /tmp/data2 &
command -option1 -option2 argument | tee /tmp/data0 /tmp/data1 /tmp/data2

Cuando commandfinalice, teecerrará las tuberías con nombre, lo que indicará un EOF (lectura de 0 bytes) en cada uno de los /tmp/dataNque normalmente terminaría los cmdNprocesos. Ejemplo real:

$ mkfifo /tmp/data0 /tmp/data1 /tmp/data2
$ wc -l < /tmp/data0 & wc -w < /tmp/data1 & wc -c < /tmp/data2 &
$ tee /tmp/data0 /tmp/data1 /tmp/data2 < /etc/passwd >/dev/null
$ 61
1974
37

Debido a los procesos en segundo plano, el shell devolvió un mensaje antes de la salida del programa. Las tres instancias de wcterminado normalmente.

Arcege
fuente
1
En bash , puedes guardar mucho a través de la escritura /tmp/data/{0,1,2}. Por otra parte, en bash, podría usar la sustitución de procesos y omitir por mkfifocompleto
Tobias Kienzler el
2
Es posible que desee cambiar / dev / data0 a / tmp / data0. Además, gracias por responder la pregunta de una manera agnóstica. Eso es más útil que asumir que todos están usando bash.
Abonet
15

Si entiendo correctamente, está buscando el equivalente de tee file1 file2 file3, pero en lugar de escribir los mismos datos en tres archivos file1, file2y file3desea canalizar los mismos datos en tres comandos cmd1, cmd2y cmd3, es decir

… | ??? cmd1 cmd2 cmd3

debe ser equivalente a

… | cmd1 &
… | cmd2 &
… | cmd3 &

excepto que solo se ejecutaría una vez.

Hay dos maneras de hacerlo.

Ksh93, bash y zsh admiten la sustitución de procesos . Esta es una generalización de canalizaciones que permite que el argumento de un comando sea un archivo que, cuando se escribe, pasa datos como entrada a un comando (también existe la variante de entrada que, cuando se lee, obtiene la salida de datos mediante un comando) . Es decir,

echo hello | tee >(cmd1)

grabados helloen la salida estándar y, además, se ejecuta cmd1con hellocomo entrada.

Entonces, por ejemplo, si desea duplicar la entrada de somecommandy pasarla a ambos cmd1y cmd2, puede usar

somecommand | tee >(cmd1) | cmd2

Si su shell no admite la sustitución de procesos, puede utilizar canalizaciones con nombre. Vea la respuesta de Arcege para saber cómo funciona. Las canalizaciones con nombre son menos convenientes que la sustitución de procesos porque debe crearlas y eliminarlas, e iniciar y sincronizar procesos manualmente. Tienen la ventaja de ser totalmente portátiles, mientras que no todos los shells admiten sustituciones de procesos. También se pueden usar en escenarios distintos de aquellos para los que es la sustitución de procesos.

Bajo el capó, en algunos sistemas, la sustitución de procesos utiliza tuberías con nombre internamente. Sin embargo, en la mayoría de los sistemas, se basa en archivos con nombre que representan descriptores de archivos .

Gilles 'SO- deja de ser malvado'
fuente
55
Ver también peede moreutils.
Stéphane Chazelas
Tenga en cuenta que la sustitución del proceso fue introducida por ksh88.
Stéphane Chazelas
6

Al menos en puedes saltarte mkfifousando la sustitución de procesos:

command -option1 -option2 argument | tee >(cmd1) >(cmd2) >(cmd3)

o para adoptar el ejemplo de Arcege

tee >(wc -l) >(wc -w) >(wc -c) < /etc/passwd >/dev/null
Tobias Kienzler
fuente