¿Cómo salen los programas a otro lugar que STDOUT / STDERR? ¿Cómo evitarlo?

15

Aparentemente no conozco todos los destinos de salida que están disponibles para su uso. Sé sobre stdout( &1) y stderr( &2). Sin embargo, después de redirigir ambos descriptores, a veces aún obtengo algo de salida en mi consola.

El ejemplo más fácil que se me ocurre es GNU Parallel; Cada vez que lo uso, veo un aviso de cita. Incluso cuando lo hago &2>1 > file, todavía veo el aviso.

Y lo mismo se aplica a emerge: cuando ejecuto emerge y hay algunos problemas, algunas informaciones no se imprimen en stdoutni stdin, ya que las redirijo y aún así pasan.

Principalmente resuelvo estos problemas usando script, pero todavía me pregunto qué está causando este problema.

MatthewRock
fuente
1
Por favor proporcione un ejemplo completo .
Kusalananda
cual caparazón? eche un vistazo a mywiki.wooledge.org/BashFAQ/055 y stackoverflow.com/questions/876239/…
Sundeep
8
No los conseguirás a todos . Un guión siempre puede escribir /dev/tty.
Satō Katsura
1
En cuanto a GNU parallel: mkdir ~/.parallel; touch ~/.parallel/will-citedeshabilitará el mensaje molesto. Alternativamente, busque otras implementaciones de parallel.
Satō Katsura
2
@OleTange Debido a que no es un problema, estoy preguntando por qué sucede algo y lo estoy usando parallelcomo ejemplo.
MatthewRock

Respuestas:

40

La sintaxis que usó es incorrecta.

cmd &2>1 >file

se dividirá como

cmd &
2>1 >file

Esta voluntad:

  1. Ejecutar cmdcomo un trabajo en segundo plano sin redireccionamientos
  2. En un proceso separado (¡sin un comando!) Redirigirá stderra un archivo literalmente llamado 1y redirigirá stdoutafile

La sintaxis que desea es:

cmd >file 2>&1

El orden de las operaciones es importante. Esta voluntad:

  1. Redirigir stdoutafile
  2. Redirigir stderra &1- es decir, el mismo identificador de archivo questdout

El resultado es que ambos stderry stdoutserán redirigidos a file.

En bash, una sintaxis más simple no estándar (y, por lo tanto, no la recomiendo, por razones de portabilidad) cmd &> filehace lo mismo.

Stephen Harris
fuente
Genial gracias. El otro problema podría ser /dev/tty, pero espero que esto no suceda con demasiada frecuencia (si es que lo hace).
MatthewRock
55
Si tiene el atcomando en su máquina y tiene privilegios para usarlo, puede ejecutar el comando a través de at now. Vea la página de manual para más detalles. Esto ejecutará el comando a través de un mecanismo de proceso por lotes y el proceso nunca tendrá un tty para escribir. Pero, en general, no me preocuparía por este caso límite. Por lo general, solo los procesos que requieren interacción y deliberadamente necesitan mostrar cosas a los usuarios a pesar de la redirección /dev/tty.
Stephen Harris
estado allí, hecho eso
davidbak
10

Hay dos problemas

El primero es que el orden importa, el segundo es /dev/tty.

Usemos este script como un script de ejemplo del que queremos capturar resultados:

test.sh:

#!/bin/bash

echo dada
echo edada 1>&2
echo ttdada >/dev/tty

Ahora veamos las salidas de los comandos:

./testmyscript.sh 2>&1 >/dev/null:

edada
ttdada

Debido a que el orden de evaluación es de izquierda a derecha, primero obtenemos "redirigir stderra donde stdoutsea ​​que salga (por lo tanto, salida de consola)". Luego tenemos "redirigir stdouta /dev/null. Terminamos con una situación como esta:

stdout-> /dev/null stderr-> consola

Entonces lo hacemos bien:

./testmyscript.sh >/dev/null 2>&1

Y obtenemos:

ttdada.

Ahora hacemos "Redirigir stdouta /dev/null" y luego "Redirigir stderr a donde apunta stdout" (entonces, /dev/null). ¡Hurra!

Sin embargo, todavía tenemos un problema; programa imprime a /dev/tty. Ahora no sé cómo solucionar este tipo de comportamiento, por lo que es muy probable que lo necesites script, pero espero que este comportamiento no ocurra con demasiada frecuencia.

MatthewRock
fuente