¿Por qué redirigir la salida a 2> & 1 y 1> & 2?

36

Me he encontrado con varios comandos que usan 2>&1y 1>&2, pero no puedo entender el propósito de usarlo y cuándo debería usarlo.

lo que yo entiendo

Sé que 1representa la salida estándar y 2representa el error estándar. Entiendo que 2>&1combina la salida de 2to 1y viceversa.

Lo que no entiendo

  1. ¿Cuándo debería usarlo?
  2. ¿Para qué sirve?
CacahuetesMonkey
fuente

Respuestas:

39

A veces desea redirigir tanto stdout como stderr a la misma ubicación. Esto es cuando >&se usa: señala un descriptor de archivo a otro.


Por ejemplo, si desea escribir stdout y stderr en el mismo archivo (ya sea /dev/nullo output.txt), puede redirigirlos por separado, con

app 1>/dev/null 2>/dev/null

o puede redirigir un descriptor de archivo al archivo y el otro descriptor de archivo al primero:

app 1>/dev/null 2>&1

app 2>/dev/null 1>&2

En el primer ejemplo, 2>&1señala el descriptor de archivo # 2 a donde # 1 ya está apuntando. El segundo ejemplo logra lo mismo, solo comienza con stderr.

Como otro ejemplo, hay casos en que stdout (descriptor de archivo # 1) ya está apuntando a la ubicación deseada, pero no puede referirse a él por su nombre (puede estar asociado con una tubería, un zócalo o tal). Esto sucede a menudo cuando se utiliza la expansión del proceso (los operadores ` `o $( )), que normalmente solo captura stdout, pero es posible que desee incluir stderr en él. En este caso, también >&usarías para señalar stderr a stdout:

out=$(app 2>&1)

Otro ejemplo común es un buscapersonas, o grepuna utilidad similar, ya que la tubería |normalmente solo funciona en stdout, redirigiría stderr a stdout antes de usar la tubería:

app 2>&1 | grep hello

¿Cómo saber cuál de 2>&1o 1>&2es correcta? El descriptor de archivo ya configurado va a la derecha de >&, y el descriptor de archivo que desea redirigir va a la izquierda. ( 2>&1significa "señalar el descriptor de archivo # 2 al descriptor de archivo # 1")


Algunos proyectiles tienen accesos directos para redireccionamientos comunes; Aquí hay ejemplos de Bash:

  • 1> se puede acortar a solo >

  • 1>foo 2>&1a >&fooo&>foo

  • 2>&1 | program a |& program

Gravedad
fuente
No tenía idea de que hacerlo app 1>/dev/null 2>&1significaría que 2> & 1 apuntaría al archivo al que 1 ya estaba redirigiendo. ¿Supongo que podría hacerlo con la misma facilidad app > /dev/null &>?
PeanutsMonkey
Me está costando entenderlo the already set up fd goes to the right of >&, and the fd you want to redirect goes to the left. ¿Qué quiere decir con el descriptor de archivo ya configurado? ¿Qué significa el derecho de?
PeanutsMonkey
Lo siento, a menos que tuviera la intención de enseñarme instrucciones, no sigo la declaración que hizo como se señaló anteriormente.
PeanutsMonkey
1
Tome la redirección de cada descriptor de archivo de uno en uno, de izquierda a derecha, y aplique esas reglas en ese orden. Si primero dirige stdout a un archivo, luego redirija stderr a donde stdout ahora estamos apuntando, luego stderr y stdout irán al mismo archivo. Si intercambiaste esos dos redireccionamientos, obtendrías resultados diferentes (redirige stderr a donde va stdout ahora , luego mueve stdout para apuntar a otro archivo, mientras stderr continúa donde se señaló).
Jason
2

Una situación cuando la necesita es cuando desea mostrar la stracesalida en un buscapersonas. straceimprime su salida a error estándar y las tuberías generalmente conectan la salida estándar a la entrada estándar, por lo que debe usar la redirección

strace -p $pid 2>&1 | less
jpalecek
fuente
¿Qué quieres decir con pipes generally connect standard output to standard input?
PeanutsMonkey
2
Quiero decir que pipe ( |) toma la salida estándar del primer comando y la conecta a la entrada estándar del segundo comando.
jpalecek
2

A veces desea redirigir ambos stdout( 1) y stderr( 2) a la misma ubicación ( /dev/nullpor ejemplo). Una forma de lograr esto sería:

$ program 1>/dev/null 2>/dev/null

Pero la mayoría de la gente se acortan esta redirigiendo stderra stdoutcon 2>&1:

$ program 1>/dev/null 2>&1

Una versión aún más corta es:

$ program >&- 2>&-
Zaz
fuente
1

2: es para cuando tendrá salida proveniente tanto de error estándar como de salida estándar, y desea que se compongan en una sola cadena.

1: Cuando desea manipular la salida de error estándar y salida estándar.

soandos
fuente
¿Qué quieres decir con manipular? Tengo entendido que todo lo que se redirige a >2se envía a / dev / null. ¿O me he equivocado completamente?
PeanutsMonkey
Eso no es correcto. Por manipular me refiero a canalizarlo a grep o algo similar. Ver aquí para un ejemplo.
soandos
0

Lo uso para comenzar un trabajo separado:

someProgram 2>&1 >& my.log &

entonces puedo cerrar sesión y someProgram todavía se estará ejecutando. La funcionalidad es proporcionada por GNU Screen, tmux y algunos otros programas, pero aquí se logra sin ninguna dependencia externa.

Adobe
fuente
1
Eso solo funciona mientras no se envíe SIGHUP al programa. Mejor uso nohupo disownen tales casos.
slhck
@slhck: ok. Pero si no enviaría SIGHUP al programa, nadie lo hará, ¿verdad?
Adobe
No, el terminal de control avisará a los procesos de un cierre de sesión con SIGHUP. En la práctica, si ejecuta un shell remoto a través de SSH y sale, su proceso también morirá, por ejemplo.
slhck
@slhck: No puede ser cierto: lo uso durante un par de años, salgo de ssh y el proceso aún se está ejecutando.
Adobe
Tendré que buscar esto con más detalle, pero poner programas en segundo plano no me ha funcionado en todos los casos, y definitivamente ni siquiera funciona en mi máquina local. Zsh y Bash se comportan de manera diferente aquí también, parece.
slhck
0

Imagine que hay un directorio llamado tryque tiene estos tres archivos:file file1 and file2.

Ahora ejecuta este comando:

cat file file1 file2 file3

Los primeros tres archivos se abren pero catarrojan un error al abrir el cuarto, ya que no existe.

Ahora ejecuta:

cat file file1 file2 file3 1>outfile 2>&1

No verá ninguna salida en la pantalla: En primer lugar 1>outfilese redirigir la salida de la orden para outfiley luego volverá a dirigir ( 2>&1) lanza el error al intentar abrir file3a outfile.

1>&2 funciona de manera similar y redirige el flujo de error a la salida estándar.

¡Espero que esto ayude!

Faiz
fuente
0

Escenario alternativo: los comandos del terminal muestran la salida en otro terminal

Use el ttycomando en cada terminal para identificarlos:

$ tty
/dev/pts/0

$ tty
/dev/pts/1

Suponiendo estos TTY, para redirigir el stdout del primero al segundo, ejecute esto en el primer terminal:

exec 1>/dev/pts/1

Nota: Ahora cada salida de comando se mostrará en pts / 1

Para restaurar el comportamiento predeterminado stdout de pts / 0:

exec 1>/dev/pts/0

Vea este video para una demostración.

Vitalie Ghelbert
fuente
0

El caso al redirigir stderr a stdout ya se ha cubierto aquí (por ejemplo, úselo para filtrar mensajes de error (grep)).

El otro caso es redirigir stdout a stderr. Un caso de uso común (al menos para mí) es enviar advertencias / mensajes de error impresos con "echo" (en mis shellscripts) al stderr (para que puedan llamar la atención del usuario más fácilmente).

Por ejemplo,

echo "file \"${file\" does not exist..." 1>&2
umläute
fuente