Bash IO Redirection – Invisible Prompt After Redirecting Stderr to /dev/null

bashdebianio-redirection

Studying TLDP's Advanced Bash-Scripting Guide I am unable to reconstruct the following shell output in bash 4.4.12 in debian 9, both from tty and pts:

bash$ lsof -a -p $$ -d0,1,2
COMMAND PID     USER   FD   TYPE DEVICE SIZE NODE NAME
 bash    363 bozo        0u   CHR  136,1         3 /dev/pts/1
 bash    363 bozo        1u   CHR  136,1         3 /dev/pts/1
 bash    363 bozo        2u   CHR  136,1         3 /dev/pts/1


bash$ exec 2> /dev/null
bash$ lsof -a -p $$ -d0,1,2
COMMAND PID     USER   FD   TYPE DEVICE SIZE NODE NAME
 bash    371 bozo        0u   CHR  136,1         3 /dev/pts/1
 bash    371 bozo        1u   CHR  136,1         3 /dev/pts/1
 bash    371 bozo        2w   CHR    1,3       120 /dev/null

Whenever I run the second command the shell prompt disappears and all keyboard input stops being displayed, though I can still run commands and see their output. Why is that?

Best Answer

It's because you have redirected the shell's standard error.

That's where a POSIX-conformant shell is supposed to write its interactive prompts, according to the standard.

  • The Bourne Again, Heirloom Bourne, (Debian and FreeBSD) 93 Korn, MirBSD Korn, (FreeBSD, OpenBSD, and Debian) PD Korn, (FreeBSD and Debian) Almquist, and Watanabe shells all conform in this regard and write their interactive prompts to standard error. You will see the lack of prompt behaviour with all of them.

    The not echoing input behaviour is however a lot more complex:

    • The Debian PD Korn, Debian Almquist, and Heirloom Bourne shells do not implement their own line editors, but rely upon the one provided by the terminal line discipline in the kernel. You will still see echoed what you type as their standard input.
    • The Watanabe, (FreeBSD 93) Korn, and (Debian 93) Korn shells implement their own line editors which also write to standard error when they (re-)display the input lines as they are being edited. However, they turn terminal echo on before executing the exec command, and (because standard error is no longer a terminal device) fail to turn it off again when invoking the line editor for their next input. Thus you will see further input that you type echoed by the terminal line discipline, even though the input echo from the shell's line editor is going to the now redirected standard error. Their line editors also go wrong in subtle ways, such as not recognizing any further terminal size changes.
    • The MirBSD Korn, (FreeBSD PD) Korn, and (OpenBSD PD) Korn shells implement their own line editors that (re-)display the edited line to standard error, but open another file descriptor to /dev/tty directly in order to control things like terminal echo. They succeed in turning echo off again when invoking the line editor for its next input. Thus you will not see further input that you type echoed by their line editors or the terminal line discipline.
    • The Bourne Again and FreeBSD Almquist shells implement their own line editors that (re-)display the edited line to standard error, but use standard input to control things like terminal echo. They succeed in turning echo off again when invoking the line editor for its next input. Thus you will not see further input that you type echoed by their line editors or the terminal line discipline.
  • The BusyBox Almquist and Z shells do not conform to POSIX in this regard. They both implement their own line editors. With both, you will see the behaviour that that appendix leads you to believe will occur.

    • The BusyBox Almquist shell's line editor uses standard output for input echo, and that is also where it writes its prompts. It is simply unaffected by redirection of standard error. But you can get the effect by redirecting standard output instead. It uses standard input for recognizing terminal size changes.
    • The Z shell goes to some effort to try to find a terminal device to run ZLE against, up to and including explicitly opening /dev/tty. It duplicates a file descriptor to the terminal device at startup and ZLE then uses that for everything; for echoing typed input, for reading typed input, for writing interactive prompts to, and for turning terminal echo on and off. So ZLE is unaffected by subsequent redirection of standard error, output, or indeed even input. You can have all three redirected to /dev/null by exec if you like, and the Z shell will still interactively prompt you for and receive input.

(The Thompson shell does not support the shell exec command mechanism in the first place, because it pre-dates its invention.)

You should complain to author Stéphane Chazelas that that appendix is wrong, so that it might get fixed.

Further reading

Related Question