2

Running some shell functions and ctrl-c-ing them leads to my stderr being suppressed, such that echo hi >&2 and echo hi > /dev/stderr print nothing. I want to debug this, but I have no idea how to start. How can I check where stderr is redirected to? Doing a exec zsh doesn't solve this problem in an affected shell, which indicates the problem is indeed with a rogue redirection.

I'm on macOS.

I tried:

ll /dev/fd
crw--w---- 0,11 evar 12 May 18:32 0
crw--w---- 0,11 evar 12 May 18:32 1
crw-rw-rw-  0,2 root 12 May 18:32 2

Perhaps the issue is that /dev/fd/2 is somehow owned by root?

Update:

lsof -p $$
COMMAND   PID USER   FD   TYPE DEVICE  SIZE/OFF                NODE NAME
zsh     69568 evar  cwd    DIR    1,6      1472          8624004142 /Users/evar/Base/Lectures
zsh     69568 evar  txt    REG    1,6    618652          8678375637 /usr/local/Cellar/zsh/5.8/bin/zsh
zsh     69568 evar  txt    REG    1,6    452676          8677805768 /usr/local/Cellar/pcre/8.44/lib/libpcre.1.dylib
zsh     69568 evar  txt    REG    1,6    312924          8678370072 /usr/local/Cellar/ncurses/6.2/lib/libncursesw.6.dylib
zsh     69568 evar  txt    REG    1,6    251160          8678375669 /usr/local/Cellar/zsh/5.8/lib/zsh/zle.bundle
zsh     69568 evar  txt    REG    1,6    123012          8678375645 /usr/local/Cellar/zsh/5.8/lib/zsh/complete.bundle
zsh     69568 evar  txt    REG    1,6     65188          8678375676 /usr/local/Cellar/zsh/5.8/lib/zsh/compctl.bundle
zsh     69568 evar  txt    REG    1,6     18220          8678375661 /usr/local/Cellar/zsh/5.8/lib/zsh/terminfo.bundle
zsh     69568 evar  txt    REG    1,6     27888          8678375680 /usr/local/Cellar/zsh/5.8/lib/zsh/system.bundle
zsh     69568 evar  txt    REG    1,6     17240          8678375681 /usr/local/Cellar/zsh/5.8/lib/zsh/langinfo.bundle
zsh     69568 evar  txt    REG    1,6     38064          8678375656 /usr/local/Cellar/zsh/5.8/lib/zsh/parameter.bundle
zsh     69568 evar  txt    REG    1,6     22864          8678375674 /usr/local/Cellar/zsh/5.8/lib/zsh/pcre.bundle
zsh     69568 evar  txt    REG    1,6     37588          8678375667 /usr/local/Cellar/zsh/5.8/lib/zsh/zutil.bundle
zsh     69568 evar  txt    REG    1,6     62316          8678375647 /usr/local/Cellar/zsh/5.8/lib/zsh/complist.bundle
zsh     69568 evar  txt    REG    1,6     22620          8678375675 /usr/local/Cellar/zsh/5.8/lib/zsh/stat.bundle
zsh     69568 evar  txt    REG    1,6     29076          8678375649 /usr/local/Cellar/zsh/5.8/lib/zsh/zpty.bundle
zsh     69568 evar  txt    REG    1,6     18736          8678375668 /usr/local/Cellar/zsh/5.8/lib/zsh/datetime.bundle
zsh     69568 evar  txt    REG    1,6     17628          8678375660 /usr/local/Cellar/zsh/5.8/lib/zsh/zleparameter.bundle
zsh     69568 evar  txt    REG    1,6     18208          8678375654 /usr/local/Cellar/zsh/5.8/lib/zsh/termcap.bundle
zsh     69568 evar  txt    REG    1,6     63728          8678375662 /usr/local/Cellar/zsh/5.8/lib/zsh/computil.bundle
zsh     69568 evar  txt    REG    1,6     22440          8678375673 /usr/local/Cellar/zsh/5.8/lib/zsh/sched.bundle
zsh     69568 evar  txt    REG    1,6   1534352 1152921500311885154 /usr/lib/dyld
zsh     69568 evar    0u   CHR  16,11   0t56261                3469 /dev/ttys011
zsh     69568 evar    1u   CHR  16,11   0t56261                3469 /dev/ttys011
zsh     69568 evar    2w   CHR    3,2 0t1314232                 314 /dev/null
zsh     69568 evar   10u   CHR  16,11   0t21049                3469 /dev/ttys011
zsh     69568 evar   11u   CHR   15,9    0t9086                 583 /dev/ptmx
  • Try lsof. macOS may have some macOS-specific way to do it as well. – Stéphane Chazelas May 12 at 14:07
  • @StéphaneChazelas I posted the result of lsof. I guess zsh 69568 evar 2w CHR 3,2 0t1314232 314 /dev/null means that 2 is now null. Any idea on how I can debug what sets it off? A hook or sth? – HappyFace May 12 at 14:21
  • Doing set -x or running zsh -x might help. You won't see the exec 2> /dev/null, as xtrace output goes to stderr, but you'll see the last messages before that which may give you a clue as to what does the exec 2> /dev/null. – Stéphane Chazelas May 12 at 15:06
  • So did you figure out what was redirecting stderr? Somebody just reported the same issue in a duplicate question – Stéphane Chazelas May 18 at 11:58
  • @StéphaneChazelas I did, though not by setting set -x. I hate that beast. :D I reported the issue here. It seems to be fixed in the new version. – HappyFace May 18 at 12:10
3

The usual way of obtaining the information is the normal BSD command

fstat -p $$
but your listing of /dev/fd already has enough to tell you that file descriptor 2 is not connected to the terminal character device that file descriptors 0 and 1 are. The major and minor numbers of files under /dev/fd are somewhat complex to grasp, but they do tell you, in conjunction with the permissions and owners, that there is a difference here.

Sans explicit redirection, processes running in a terminal login session will have all three descriptors referencing the same (terminal) character device. File descriptors 0 and 1 are clearly still referencing your terminal character device, owned by you and only readable and writable by you, as is common for terminal devices in login sessions.

Standard error has not been "suppressed". Writes to it are still happening, and are being sent to a character device of some kind, which you do not own but to which you have write access. Almost certainly that character device that file descriptor 2 references is /dev/null, and you've sourced a script that redirected standard error to /dev/null with something like

exec 2>/dev/null

So, after checking to see what fstat tells you just to expand your knowledge, redirect it back again.

exec 2>&1

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.