Diferencia entre 2> & 1> output.log y 2> & 1 | tee output.log

35

Quería saber la diferencia entre los siguientes dos comandos

2>&1 > output.log 

y

2>&1 | tee output.log

Vi a uno de mis colegas usar la segunda opción para redirigir. Sé lo que hace 2> & 1, mi única pregunta es ¿cuál es el propósito de usar tee donde se puede usar un simple operador de redirección ">"?

Chander Shivdasani
fuente

Respuestas:

11

Mirando los dos comandos por separado:

utility 2>&1 >output.log 

Aquí, dado que las redirecciones se procesan de izquierda a derecha, el flujo de error estándar primero se redirigirá a donde quiera que vaya el flujo de salida estándar (posiblemente a la consola), y luego el flujo de salida estándar se redirigirá a un archivo. La secuencia de error estándar no se redirigiría a ese archivo.

El efecto visible de esto sería que obtienes lo que se produce en un error estándar en la pantalla y lo que se produce en la salida estándar en el archivo.

utility 2>&1 | tee output.log

Aquí, redirige el error estándar al mismo lugar que la secuencia de salida estándar. Esto significa que ambas secuencias se canalizarán a la teeutilidad como una única secuencia de salida entremezclada y que estos datos de salida estándar se guardarán en el archivo dado tee. Los datos también se reproducirían teeen la consola (esto es lo que teehace, duplica los flujos de datos).

Cualquiera de estos que se use depende de lo que le gustaría lograr.

Tenga en cuenta que no podrá reproducir el efecto de la segunda tubería con solo >(como en utility >output.log 2>&1, lo que ahorraría tanto la salida estándar como el error en el archivo). Debería usarlo teepara obtener los datos en la consola, así como en el archivo de salida.


Notas adicionales:

El efecto visible del primer comando,

utility 2>&1 >output.log 

sería lo mismo que

utility >output.log

Es decir, la salida estándar va al archivo y el error estándar va a la consola.

Sin embargo, si se agrega un paso de procesamiento adicional al final de cada uno de los comandos anteriores, habría una gran diferencia:

utility 2>&1 >output.log | more_stuff

utility >output.log      | more_stuff

En la primera tubería, more_stuffobtendría lo que originalmente era el flujo de error estándar de utilitysus datos de entrada estándar, mientras que en la segunda tubería, dado que es solo el flujo de salida estándar resultante que se envía a través de una tubería, la more_stuffparte de la tubería no obtendría nada para leer en su entrada estándar.

Kusalananda
fuente
Con el comando " utility 2>&1 | tee output.log, ¿quiere decir que dado que 1 se dirige a tee, también lo es 2. Como tee duplica la transmisión, la salida se muestra en la consola y se escribe en el archivo? De ahí la diferencia entre utility 2>&1 > output.logy utility 2>&1 | tee output.loges teeque duplica la transmisión. ¿Sería correcto?
Motivado el
Con los ejemplos de utility 2>&1 > output.log | more_stuffy utility >ouput.log| more_stuff , is the difference that more_stuff` tiene la salida de error estándar a la consola como entrada more_stuff? Dado que en el segundo ejemplo, no hay salida para la consola, esencialmente no hay entrada para more_stuff? En caso afirmativo, eso no está claro ya que en el párrafo anterior observa que la salida estándar va al archivo y el error estándar va a la consola.
Motivado el
@ Motivado Tu primer comentario me parece correcto, sí. En cuanto al segundo comentario: en el primer comando, more_stuffrecibiría lo que utilityoriginalmente se envió a su flujo de error (pero que se redirigió a la salida estándar). No porque terminaría en la consola si more_stuffno estuviera allí, sino porque va a la transmisión de salida estándar . En el segundo comando, nomore_stuff recibe nada, ya que no hay salida estándar desde el lado izquierdo de la tubería. El flujo de error de utilitytodavía terminaría en la consola en el segundo comando.
Kusalananda
Gracias. ¿Quiere decir eso porque el comando utility > output.log | more_stuffno produce una salida en la secuencia de salida estándar desde un punto de vista de error estándar?
Motivado el
@ Motivado Dado que el lado izquierdo no produce nada en la salida estándar (se redirige), no se enviarán datos por la tubería.
Kusalananda
24

Nota editorial

Asegúrese de leer los comentarios sobre esta respuesta : derobert .


Respuesta original

2>&1 >output.logsignifica primero comenzar a enviar todas las cosas del identificador de archivo 2 (error estándar) al identificador de archivo 1 (salida estándar) y luego enviarlo al archivo output.log. En otras palabras, envíe un error estándar y una salida estándar al archivo de registro.

2>&1 | tee output.loges lo mismo con el 2>&1bit, combina la salida estándar y el error estándar en la secuencia de salida estándar. Luego lo canaliza a través del teeprograma que enviará su entrada estándar a su salida estándar (como cat) y también al archivo. Por lo tanto, combina las dos secuencias (error y salida), luego las envía al terminal y al archivo.

La conclusión es que el primero envía stderr/ stdoutal archivo, mientras que el segundo lo envía tanto al archivo como a la salida estándar (que probablemente sea el terminal a menos que esté dentro de otra construcción que haya redirigido la salida estándar).

Menciono esa última posibilidad porque puedes tener cosas como:

(echo hello | tee xyzzy.txt) >plugh.txt

donde nada termina en la terminal.

derobert
fuente
13
-1 Tienes la sintaxis correcta, pero no la semántica. Ejecutar cat /doesnotexist 2>&1 >output.txt: verá que se cat: /doesnotexist: No such file or directorymuestra en el terminal y output.txt es un archivo vacío. El orden de precedencia y el cierre están en juego: 2>&1(dup fd2 del fd1 actual ), luego >output.txt(redirige fd1 a output.txt, sin cambiar nada más). La razón que 2>&1 |es diferente es por el orden de precedencia: |antes >.
Arcege
55
Esta respuesta es fundamentalmente incorrecta esencialmente en todos los aspectos . Muchas de las respuestas a continuación son mejores, pero creo que esta de Kusalananda es la más clara.
Michael Homer
2
@ user14408: Si alguna vez crea una cuenta en Unix y Linux y solicita esta respuesta, no dude en eliminar mi nota editorial una vez que haya abordado los comentarios.
derobert
8

El primer comando hará la otra tarea:

Después

2>&1 > output.log 

el STDOUT anterior se guardará (copiará) en STDERR y luego STDOUT se redirigirá al archivo.

Entonces, stdout irá al archivo y stderr irá a la consola.

Y en

 2>&1 | tee output.log

ambas transmisiones serán redirigidas a tee. Tee duplicará cualquier entrada a su stdout (la consola en su caso) y al archivo ( output.log).

Y hay otra forma de primero:

    > output.log  2>&1

esto redirigirá tanto STDOUT como STDERR al archivo.

osgx
fuente
4

El primero solo se envía al archivo. El segundo sale tanto al archivo como a la pantalla.


fuente
4

La razón 2>&1 | teees poder capturar stdout y stderr en un archivo de registro y verlo en la pantalla al mismo tiempo. Esto también podría hacerse >output.txt 2>&1 & tail -f, pero no sabría cuándo finalizó el comando de fondo: si el programa finalizó o si se ejecuta sin salida. El 2>&1 | teeera un idioma común para los programadores.

Arcege
fuente
¿Quiere decir que 2> & 1> file.txt, por ejemplo, no capturaría tanto stdout como stderr en file.txt?
Motivado el
0

Veamos primero un código de muestra:

#include <stdio.h>
main() 
{
// message 1, on stdout (using  printf)
printf("%s",          "message 1, on stdout (using  printf)\n");

// message 2, on stdout (using fprintf)
fprintf(stdout, "%s", "message 2, on stdout (using fprintf)\n");

// message 3, on stderr (using fprintf)
fprintf(stderr, "%s", "message 3, on stderr (using fprintf)\n");
}

Vamos a comparar los resultados:
./helloerror
+ archivo: sin mensaje; consola: mensaje 1,2,3;

./helloerror >error.txt
+ archivo: mensaje 1,2; consola: mensaje 3;

./helloerror 2>&1 >error.txt
+ archivo: mensaje 1,2; consola: mensaje 3;
+ igual que ./helloerror> error.txt

./helloerror >error.txt 2>&1
+ archivo: mensaje 3,1,2; consola: sin mensaje;
+ tenga en cuenta que el orden 3 es primero, luego 1, luego 2

./helloerror | tee error.txt 2>&1
+ archivo: mensaje 1,2; consola: mensaje 3,1,2;
+ tenga en cuenta que el orden 3 es primero, luego 1, luego 2

./helloerror 2>&1 | tee error.txt
+ archivo: mensaje 3,1,2; consola: mensaje 3,1,2;

Para usar:
./helloerror >error.txt 2>&1
-> si uno quiere todos los mensajes (stdout + stderr) en el archivo, pero no anclado en la consola

./helloerror 2>&1 | tee error.txt
-> si uno quiere todos los mensajes (stdout + stderr) en el archivo e impresos en la consola

Hari Perev
fuente
-1

Aquí hay una publicación que resume las secuencias de salida de Unix: http://www.devcodenote.com/2015/04/unix-output-streams.html

Un fragmento de la publicación:

Hay 3 flujos de salida estándar:

STDIN - Standard Input - Writes from an input device to the program
STDOUT - Standard Output - Writes program output to screen unless specified otherwise.
STDERR - Standard Error Output - Writes error messages. Also printed to the screen unless specified otherwise.
Abhishek Jain
fuente