18

I am trying to execute the following:

exec &>filename

After this I am not able to see anything including what I typed, alright.

I frantically try , exec 1>&1 and exec 2>&2 , but nothing happens.

Now , without killing the shell , how do I get back the output redirected to the stdout and error redirected to stderr respectively? Are the file descriptors the only way to refer standard [in|out]put and stderr?

Mat
  • 52,586
  • 1
    Hmm... why do you redirect the stderr/stdout of your interactive shell then? This exec construct is usually used in scripts that run in a subshell, to redirect their output e.g. to a file. I don't see a use for it in an interactive session. – Martin von Wittich Sep 20 '13 at 15:59
  • 4
    @MartinvonWittich I agree with the statement on exec. I agree. I am just a kid playing around :) – user917279 Sep 23 '13 at 15:44

2 Answers2

28

After you run exec &>filename, the standard output and standard error of the shell go to filename. Standard input is file descriptor 0 by definition, and standard output is fd 1 and standard error is fd 2.

A file descriptor isn't either redirected or non-redirected: it always go somewhere (assuming that the process has this descriptor open). To redirect a file descriptor means to change where it goes. When you ran exec &>filename, stdout and stderr were formerly connected to the terminal, and became connected to filename.

There is always a way to refer to the current terminal: /dev/tty. When a process opens this file, it always means the process's controlling terminal, whichever it is. So if you want to get back that shell's original stdout and stderr, you can do it because the file they were connected to is still around.

exec &>/dev/tty
  • 1
    as @Joseph R. answered $(tty) shows me /dev/pty0 , but your command too works, which one is more portable across Unix flavors? thank yo u for the more clear answer. – user917279 Sep 23 '13 at 11:58
  • 2
    @user917279 They're equally portable in the sense of working on different unix flavors. /dev/tty works in cases where $(tty) doesn't: /dev/tty works as long as the process has a controlling terminal (which is the best you can hope, as there has to be something still connecting the process with the terminal), whereas $(tty) requires that the terminal still be opened on standard input. – Gilles 'SO- stop being evil' Sep 23 '13 at 22:38
  • Why exec &>/dev/tty and not exec >/dev/tty? – Anthony Rutledge Mar 10 '20 at 02:46
  • @AnthonyRutledge Because the question is what to do after exec &>filename, not what to do after exec >filename. – Gilles 'SO- stop being evil' Mar 10 '20 at 08:40
13

You want

exec &>$(tty)

What you're doing in your question is replicating in stdout and stderr the original stdout and stderr which have already been redirected to the file.

As Gilles' answer explains, tty will return the terminal device of the current terminal. This is where the three standard file descriptors are coming from/going to by default in a login shell. So the above statement makes use of tty to redirect stdout and stderr back to the terminal device as they were before.

If you're concerned about portability (as per your comment on Gilles' answer), both methods (the tty utility and the /dev/tty file) are in the POSIX standard.

Copied verbatim from Gilles' comment:

There's an advantage to /dev/tty: it works even after exec <somefile, 
whereas $(tty) would complain “not a tty”
Joseph R.
  • 39,549
  • it works! Thank you. echo $(tty) gives /dev/pty0 ( in cygwin) ,how is it related to stdin,stdout and what happens with the above statement? please do let me know if I need to ask this as a seperate question. – user917279 Sep 23 '13 at 11:54
  • @user917279 Answer updated. – Joseph R. Sep 23 '13 at 13:49
  • Thank you Joseph. I posted this question before looking at Giles' answer. Thank you very much. Please allow me to mark Giles answer as accepted, for it made even dumb minds like mine to understand properly. – user917279 Sep 23 '13 at 15:43
  • 3
    There's an advantage to /dev/tty: it works even after exec <somefile, whereas $(tty) would complain “not a tty”. – Gilles 'SO- stop being evil' Sep 23 '13 at 22:38
  • @Gilles Thanks for the characteristically enlightening comment :) – Joseph R. Sep 23 '13 at 23:55