Curious tput behavior, with stderr redirection

ε祈祈猫儿з 提交于 2021-02-08 13:50:59

问题


I'm trying to use tput in a Bash script, and doing my best to avoid random error spew. To that end, I wrote the following line:

COLS="$(tput cols 2> /dev/null)"

To my surprise, when I run this, COLS is consistently set to 80, no matter what the width of my terminal window happens to be. (For the sake of demonstration, my terminal happens to be 115 columns wide.) To figure out what was going on, I tried a few things on the command-line:

$ tput cols
115
$ tput cols | cat
115
$ echo "$(tput cols)"
115
$ tput cols 2> /dev/null
115
$ echo "$(tput cols 2> /dev/null)"
80

So, tput seems to be succeeding in figuring out the terminal characteristics when its stderr is redirected, or when it is embedded in a process substitution, but not both. How odd!

I tested this on both Linux and OS X, and the behavior is the same.

What is going on here? And as a practical matter, what's the best way to get tput to work while suppressing stderr spew?

Note: I know about $COLUMNS. I'm specifically interested in using tput.


回答1:


A quick strace run suggests that tput tries to determine the terminal width on stdout first, and if that fails, it falls back to stderr. So, in the failing case both are redirected, and tput (apparently) assumes a default of 80 columns.




回答2:


Google led me here as I was having a similar issue. While the accepted answer does, in fact, answer the question, it doesn't really offer any suggestions on how to work around the error spew mentioned in the original question. Thought I'd chime in with a possible work around.

My specific situation is writing scripts that can be called from the command line or from cron. When running from cron, Solaris sets the TERM variable to "dumb", which tput doesn't know anything about, and it spews errors (which get mailed to the owner of the cron job). Since you can't catch the errors and the stdout to get the number of columns, I first tried to figure out a way to determine if tput knows about a particular terminal, before running tput cols. To that end, this code seems to serve my purpose:

declare TPUT C
TPUT="$(tput longname 2>/dev/null)"
[[ "$TPUT" ]] && C="$(tput cols)"
C=${C:-80}

I realize this won't catch all errors, but it at least sidesteps the errors possible if tput doesn't know about a specific terminal.



来源:https://stackoverflow.com/questions/21763397/curious-tput-behavior-with-stderr-redirection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!