Restaurando la salida al terminal después de haber emitido "exec &> filename"

15

Estoy tratando de ejecutar lo siguiente:

exec &>filename

Después de esto, no puedo ver nada, incluido lo que escribí, está bien.

Lo intento frenéticamente, exec 1>&1y exec 2>&2, pero no pasa nada.

Ahora, sin matar el shell, ¿cómo recupero la salida redirigida a stdout y el error redirigido a stderr respectivamente? ¿Son los descriptores de archivo la única forma de referir estándar [in | out] put y stderr?

usuario917279
fuente
1
Hmm ... ¿por qué redirige el stderr / stdout de su shell interactivo entonces? Esta execconstrucción se usa generalmente en scripts que se ejecutan en una subshell, para redirigir su salida, por ejemplo, a un archivo. No veo su uso en una sesión interactiva.
Martin von Wittich
3
@MartinvonWittich Estoy de acuerdo con la declaración sobre el ejecutivo. Estoy de acuerdo. Solo soy un niño jugando :)
user917279

Respuestas:

23

Después de ejecutar exec &>filename, la salida estándar y el error estándar del shell van a filename. La entrada estándar es el descriptor de archivo 0 por definición, y la salida estándar es fd 1 y el error estándar es fd 2.

Un descriptor de archivo no se redirige o no se redirige: siempre va a alguna parte (suponiendo que el proceso tenga este descriptor abierto). Redirigir un descriptor de archivo significa cambiar a dónde va. Cuando exec &>filenamecorriste, stdout y stderr se conectaban anteriormente a la terminal y se conectaban a filename.

Siempre hay una manera de referirse a la terminal actual: /dev/tty. Cuando un proceso abre este archivo, siempre significa el terminal de control del proceso , cualquiera que sea. Entonces, si desea recuperar el stdout y stderr original de ese shell, puede hacerlo porque el archivo al que estaban conectados todavía está presente.

exec &>/dev/tty
Gilles 'SO- deja de ser malvado'
fuente
1
como @Joseph R. respondió $ (tty) me muestra / dev / pty0, pero su comando también funciona, ¿cuál es más portátil en los sabores de Unix? Gracias por la respuesta más clara.
user917279
2
@ user917279 Son igualmente portátiles en el sentido de trabajar en diferentes sabores de Unix. /dev/ttyfunciona en casos donde $(tty)no /dev/ttyfunciona : funciona siempre que el proceso tenga un terminal de control (que es lo mejor que puede esperar, ya que debe haber algo que todavía conecte el proceso con el terminal), mientras $(tty)que requiere que el terminal todavía esté abierto en entrada estándar.
Gilles 'SO- deja de ser malvado'
11

Usted quiere

exec &>$(tty)

Lo que está haciendo en su pregunta es replicar en stdout y stderr el stdout y stderr original que ya se han redirigido al archivo.

Como explica la respuesta de Gilles, ttydevolverá el dispositivo terminal del terminal actual. Aquí es donde los tres descriptores de archivo estándar provienen / van por defecto en un shell de inicio de sesión. Por lo tanto, la declaración anterior se utiliza ttypara redirigir stdout y stderr nuevamente al dispositivo terminal como lo eran antes.

Si le preocupa la portabilidad (según su comentario sobre la respuesta de Gilles), ambos métodos (la utilidad tty y el /dev/ttyarchivo ) están en el estándar POSIX.

Copiado literalmente del comentario de Gilles:

There's an advantage to /dev/tty: it works even after exec <somefile, 
whereas $(tty) would complain “not a tty”
Joseph R.
fuente
¡funciona! Gracias. echo $ (tty) da / dev / pty0 (en cygwin), ¿cómo se relaciona con stdin, stdout y qué sucede con la declaración anterior? por favor, avíseme si necesito hacer esto como una pregunta separada.
user917279
@ user917279 Respuesta actualizada.
Joseph R.
Gracias Joseph Publiqué esta pregunta antes de mirar la respuesta de Giles. Muchas gracias. Permítame marcar la respuesta de Giles como aceptada, ya que incluso mentes tontas como la mía entienden correctamente.
user917279
2
Hay una ventaja /dev/tty: funciona incluso después exec <somefile, mientras que $(tty)se quejaría "no es un tty".
Gilles 'SO- deja de ser malvado'
@Gilles Gracias por el comentario característicamente esclarecedor :)
Joseph R.