En el shell, ¿qué significa "2> & 1"?


En un shell Unix, si quiero combinar stderr y stdout en el flujo stdout para una mayor manipulación, puedo añadir lo siguiente al final de mi comando:

2>&1

Entonces, si quiero usar head en la salida de g++, puedo hacer algo como esto:

g++ lots_of_errors 2>&1 | head

Así que solo puedo ver los primeros errores.

Siempre tengo problemas para recordar esto, y constantemente tengo que ir a buscarlo, y es principalmente porque no entiendo completamente la sintaxis de este particular truco.

¿Puede alguien romper esto y explicar carácter por carácter lo que 2>&1 significa?

Author: Ricardo, 2009-05-04

15 answers

El descriptor de fichero 1 es la salida estándar (stdout).
El descriptor de archivo 2 es el error estándar (stderr).

Aquí hay una manera de recordar esta construcción (aunque no es del todo precisa): al principio, 2>1 puede parecer una buena manera de redirigir stderr a stdout. Sin embargo, en realidad se interpretará como "redireccionar stderr a un archivo llamado 1". & indica que lo que sigue es un descriptor de archivo y no un nombre de archivo. Así que la construcción se convierte en: 2>&1.

 2000
Author: Ayman Hourieh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-09 20:18:47
echo test > afile.txt

Redirige stdout a afile.txt. Esto es lo mismo que hacer

echo test 1> afile.txt

Para redirigir stderr, lo haces:

echo test 2> afile.txt

>& es la sintaxis para redirigir un flujo a otro descriptor de archivo - 0 es stdin, 1 es stdout, y 2 es stderr.

Puede redirigir stdout a stderr haciendo:

echo test 1>&2 # or echo test >&2

O viceversa:

echo test 2>&1

Así que, en resumen... 2> redirige stderr a un archivo (no especificado), añadiendo &1 redirige stderr a stdout.

 495
Author: dbr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-04 20:36:11

Algunos trucos sobre la redirección

Alguna particularidad de sintaxis sobre esto puede tener comportamientos importantes. Hay algunas pequeñas muestras sobre las redirecciones, STDERR, STDOUT, y argumentos ordenando.

1-Sobrescribir o anexar?

Símbolo >significa redirección.

  • > mean send to as a whole completed file , overwriting target if exist (see noclobber bash feature at #3 tarde).
  • >>mean send in addition to would append to target if exist.

En cualquier caso, el archivo sería creado si no existen.

2-La línea de comandos shell depende del orden!!

Para probar esto, necesitamos un comando simple que enviará algo en ambas salidas:

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(Esperando que no tengas un directorio llamado /tnt, por supuesto ;). Bueno, lo tenemos!!

Así que, vamos a véase:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

La última línea de comandos vuelca STDERR a la consola, y parece que no es el comportamiento esperado... Pero...

Si quieres hacer algún post filtering sobre una salida, la otra o ambas:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

Observe que la última línea de comandos en este párrafo es exactamente la misma que en el párrafo anterior, donde escribí parece no ser el comportamiento esperado (por lo tanto, esto incluso podría ser un comportamiento esperado).

Bueno, hay un poco trucos sobre redirecciones, para haciendo una operación diferente en ambas salidas :

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

Nota: &9 descriptor ocurriría espontáneamente debido a ) 9>&2.

Anexo: nota! Con la nueva versión de bash (>4.0) hay una nueva característica y una sintaxis más sexy para hacer este tipo de cosas:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

Y finalmente para tal formato de salida en cascada:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Anexo: nota! Misma nueva sintaxis, en ambos formas:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Donde STDOUT pasan por un filtro específico, STDERR a otro y finalmente ambas salidas fusionadas pasan por un tercer filtro de comandos.

3-Una palabra sobre la opción noclobber y la sintaxis >|

Se trata de sobrescribir :

Mientras que set -o noclobber indica a bash que no sobrescriba ningún archivo existente, la sintaxis >| le permite pasar por esta limitación:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

El archivo se sobrescribe cada vez, bien ahora:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

Pasar a través de >|:

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

Desactivar esta opción y/o preguntar si ya está establecida.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 - Último truco y más...

Para redireccionar ambos salida de un comando dado, vemos que una sintaxis correcta podría ser:

$ ls -ld /tmp /tnt >/dev/null 2>&1

Para este caso especial, hay una sintaxis abreviada: &> ... o >&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

Nota: si 2>&1 existen, 1>&2 es una sintaxis correcta también:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b-Ahora, te dejaré pensar en: {[45]]}
$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c-Si estás interesado en más información

Puedes leer el manual fino pulsando: {[43]]}

man -Len -Pless\ +/^REDIRECTION bash

En una consolabash ; -)

 264
Author: F. Hauri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-04 20:41:51

Los números se refieren a los descriptores de fichero (fd).

  • Cero es stdin
  • Uno es stdout
  • Dos es stderr

2>&1 redirige fd 2 a 1.

Esto funciona para cualquier número de descriptores de archivo si el programa los usa.

Puedes mirar /usr/include/unistd.h si los olvidas:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

Dicho esto, he escrito herramientas de C que utilizan descriptores de archivo no estándar para el registro personalizado para que no lo vea a menos que lo redirija a un archivo o algo.

 71
Author: Colin Burnett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-06 01:25:12

Encontré este brillante post en redirección: Todo sobre redirecciones

Redirigir tanto la salida estándar como el error estándar a un archivo

Command comando & > archivo

Este one-liner utiliza el operador &> para redirigir ambos flujos de salida - stdout y stderr - from al comando file. Este es el atajo de Bash para redirigir rápidamente ambas transmisiones al mismo destino.

Así es como se ve la tabla de descriptores de archivo después de Bash ha redirigido ambas corrientes:

Introduzca la descripción de la imagen aquí

Como puede ver, tanto stdout como stderr ahora apuntan a file. Así que cualquier cosa escrita en stdout y stderr se escribe en file.

Hay varias maneras de redirigir ambos flujos al mismo destino. Puedes redirigir cada flujo uno tras otro:

Command comando > archivo 2> & 1

Esta es una forma mucho más común de redirigir ambas secuencias a un archivo. Primera salida estándar se redirige a archivo, y luego stderr se duplica para ser el mismo que stdout. Así que ambas corrientes terminan apuntando a file.

Cuando Bash ve varias redirecciones, las procesa de izquierda a derecha. Repasemos los pasos y veamos cómo sucede. Antes de ejecutar cualquier comando, la tabla de descriptores de archivo de Bash se ve así:

Introduzca la descripción de la imagen aquí

Ahora Bash procesa la primera redirección >archivo. Hemos visto esto antes y hace que stdout apunte a archivo:

Introduzca la descripción de la imagen aquí

Siguiente Bash ve la segunda redirección 2>&1. No hemos visto esta redirección antes. Este duplica el descriptor de archivo 2 para ser una copia del descriptor de archivo 1 y obtenemos:

Introduzca la descripción de la imagen aquí

Ambas secuencias han sido redirigidas a file.

Sin embargo, tenga cuidado aquí! Escritura

Comando > archivo 2> & 1

No Es lo mismo que escribir:

Command comando 2> & 1 > archivo

El orden de redirecciones importa en Bash! Este comando redirige solo la salida estándar al archivo. El stderr seguirá imprimiéndose en el terminal. Para entender por qué sucede eso, repasemos los pasos de nuevo. Así que antes de ejecutar el comando, la tabla descriptor de archivo se ve así:

Introduzca la descripción de la imagen aquí

Ahora Bash procesa redirecciones de izquierda a derecha. Primero ve 2> & 1 por lo que duplica stderr a stdout. La tabla descriptor de archivo se convierte en:

Introduzca la descripción de la imagen aquí

Ahora Bash ve la segunda redirección, >file, y redirige stdout a file:

Introduzca la descripción de la imagen aquí

¿Ves lo que sucede aquí? Stdout ahora apunta al archivo, pero el stderr todavía apunta a la terminal! Todo lo que se escribe en stderr todavía se imprime en la pantalla! Así que ser muy, muy cuidadoso con el orden de redirecciones!

También tenga en cuenta que en Bash, escribiendo

Command comando &>archivo

Es exactamente lo mismo que:

Command orden > & archivo

 53
Author: Deen John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-05 03:43:35

Esa construcción envía el flujo de error estándar (stderr) a la ubicación actual de la salida estándar (stdout) - este problema de moneda parece haber sido descuidado por las otras respuestas.

Puede redirigir cualquier controlador de salida a otro utilizando este método, pero se usa con mayor frecuencia para canalizar flujos stdout y stderr en un solo flujo para su procesamiento.

Algunos ejemplos son:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

Tenga en cuenta que este último no dirigirá stderr a outfile2 - lo redirige a lo que stdout era cuando se encontró el argumento (outfile1) y luego redirige stdout a outfile2.

Esto permite algunos trucos bastante sofisticados.

 50
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-26 08:39:06

2>&1 es una construcción POSIX shell. Aquí hay un desglose, token por token:


2: "Error estándar" descriptor de archivo de salida.

>&: Duplicar un Descriptor de Archivo de Salida operador (una variante de Redirección de Salida operator >). Dado [x]>&[y], el descriptor de fichero denotado por x se hace para ser una copia del descriptor de fichero de salida y.

1 "Salida estándar" archivo de salida descriptor.

La expresión 2>&1 copia el descriptor de archivo 1 a la ubicación 2, por lo que cualquier salida escrita en 2 ("error estándar") en el entorno de ejecución va al mismo archivo descrito originalmente por 1 ("salida estándar").


Explicación adicional:

Descriptor de Archivo: "Un entero único por proceso, no negativo utilizado para identificar un archivo abierto con el propósito de acceder al archivo."

Salida estándar / error: Refiérase a la siguiente nota en la sección Redirección de la documentación del shell:

Los archivos abiertos están representados por números decimales que comienzan con cero. El mayor valor posible está definido por la implementación; sin embargo, todas las implementaciones deberán admitir al menos de 0 a 9, inclusive, para su uso por la aplicación. Estos números se llaman "descriptores de archivo". Los valores 0, 1 y 2 tienen un significado especial y usos convencionales y están implícitos en ciertas operaciones de redirección; son conocido como entrada estándar, salida estándar y error estándar, respectivamente. Los programas generalmente toman su entrada de la entrada estándar y escriben la salida en la salida estándar. Los mensajes de error generalmente se escriben en error estándar. Los operadores de redirección pueden ir precedidos de uno o más dígitos (sin caracteres intermedios permitidos) para designar el número del descriptor de archivo.

 14
Author: wjordan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-25 06:43:43

Para responder a su pregunta: Toma cualquier salida de error (normalmente enviada a stderr) y la escribe en la salida estándar (stdout).

Esto es útil con, por ejemplo, 'más' cuando necesita paginación para toda la salida. A algunos programas les gusta imprimir información de uso en stderr.

Para ayudarte a recordar

  • 1 = salida estándar (donde los programas imprimen salida normal)
  • 2 = error estándar (donde los programas imprimen errores)

"2>&1" simplemente apunta todo lo enviado a stderr, a stdout en su lugar.

También recomiendo leer este post sobre la redirección de errores donde este tema se cubre con todo detalle.

 12
Author: Andrioid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-03 23:24:58

2 es el error estándar de la consola.

1 es la salida estándar de la consola.

Este es el Unix estándar, y Windows también sigue el POSIX.

Por ejemplo, cuando se ejecuta

perl test.pl 2>&1

El error estándar se redirige a la salida estándar, por lo que puede ver ambas salidas juntas:

perl test.pl > debug.log 2>&1

Después de la ejecución, puede ver toda la salida, incluidos los errores, en la depuración.registro.

perl test.pl 1>out.log 2>err.log

Entonces la salida estándar va a salir.log, y error estándar para errar.registro.

I sugiero que trates de entender esto.

 12
Author: Marcus Thornton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-05 03:14:53

Desde el punto de vista de un programador, significa precisamente esto:

dup2(1, 2);

Vea la página de manual .

Entender que 2>&1es una copia también explica por qué ...

command >file 2>&1

... no es lo mismo que ...

command 2>&1 >file

El primero enviará ambos flujos a file, mientras que el segundo enviará los errores a stdout, y la salida ordinaria a file.

 10
Author: ams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-03 10:20:34

Gente, siempre recuerden la sugerencia de paxdiablo sobre la ubicación actual del destino de redirección... es importante.

Mi mnemotécnica personal para el operador 2>&1 es esta:

  • Piense en & como 'and' o 'add' (el carácter es un amperios-y, ¿no lo es?)
  • Así que se convierte en: ' redirigir 2 (stderr) a donde 1 (stdout) ya/actualmente está y agregar ambos streams ' .

El mismo mnemotécnico funciona también para la otra redirección de uso frecuente, 1>&2:

  • Piensa en & que significa and o add... (usted consigue la idea sobre el ampersand, sí?)
  • Así que se convierte en: 'redirigir 1 (stdout) a donde 2 (stderr) ya/actualmente está y agregar ambos flujos'.

Y recuerda siempre: tienes que leer cadenas de redirecciones 'desde el final', de derecha a izquierda (no de izquierda a derecha).

 4
Author: Kurt Pfeifle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-01 10:47:27

Siempre que /foo no exista en su sistema y /tmp no exist

$ ls -l /tmp /foo

Imprimirá el contenido de /tmp e imprimirá un mensaje de error para /foo

$ ls -l /tmp /foo > /dev/null

Enviará el contenido de /tmp a /dev/null e imprimirá un mensaje de error para /foo

$ ls -l /tmp /foo 1> /dev/null

Hará exactamente lo mismo (tenga en cuenta la 1)

$ ls -l /tmp /foo 2> /dev/null

Imprimirá el contenido de /tmp y enviará el mensaje de error a /dev/null

$ ls -l /tmp /foo 1> /dev/null 2> /dev/null

Enviará tanto el listado como el mensaje de error a /dev/null

$ ls -l /tmp /foo > /dev/null 2> &1

Es abreviatura

 4
Author: Matijs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-01 20:58:04

Esto es como pasar el error al stdout o al terminal.

Es decir, cmd no es una orden:

$cmd 2>filename
cat filename

command not found

El error se envía al archivo de la siguiente manera:

2>&1

Se envía un error estándar al terminal.

 4
Author: Kalanidhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-05 03:17:17

Redireccionando la entrada

La redirección de entrada causa el archivo cuyo nombre resultados de la expansión de word que se abrirá para su lectura en el archivo descriptor n, o la entrada estándar (descriptor de fichero 0) si n es no especificado.

El formato general para redirigir la entrada es:

[n]<word

Redirigiendo la salida

La redirección de la salida hace que el archivo cuyo nombre resulta de la expansión de la palabra que se abrirá para escribir en file descriptor n, o la salida estándar (descriptor de fichero 1) si n no se especifica. Si el archivo no existe, se crea; si existe se trunca a tamaño cero.

El formato general para redirigir la salida es:

[n]>word

Mover Descriptores de archivo

El operador de redirección,

[n]<&digit-

Mueve el dígito del descriptor de fichero al descriptor de fichero n, o entrada estándar (descriptor de archivo 0) si no se especifica n. el dígito está cerrado después de ser duplicado a n.

Del mismo modo, el operador de redirección

[n]>&digit-

Mueve el dígito del descriptor de fichero al descriptor de fichero n, o salida estándar (descriptor de fichero 1) si no se especifica n.

Ref:

man bash

Escriba /^REDIRECT para localizar la sección redirection y obtener más información...

Una versión en línea está aquí: 3.6 Redirecciones

PS:

Muchas veces, man fue la poderosa herramienta para aprender Linux.

 2
Author: yurenchen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-05 03:25:15

0 para input, 1 para stdout y 2 para stderr.

Un consejo : {[0] } es correcto, mientras que somecmd 2>&1 >1.txtes totalmente incorrecto sin ningún efecto!

 0
Author: fzyzcjy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-25 09:46:19