Bash 奇怪的tput行为,带有stderr重定向

Bash 奇怪的tput行为,带有stderr重定向,bash,io-redirection,Bash,Io Redirection,我正在尝试在Bash脚本中使用tput,并尽最大努力避免随机错误喷出。为此,我写了以下几行: COLS="$(tput cols 2> /dev/null)" 令我惊讶的是,当我运行此命令时,COLS始终设置为80,而不管终端窗口的宽度是多少。(为了演示,我的终端恰好有115列宽。)为了弄清楚发生了什么,我在命令行上尝试了一些方法: $ tput cols 115 $ tput cols | cat 115 $ echo "$(tput cols)" 115 $ tput cols 2&

我正在尝试在Bash脚本中使用
tput
,并尽最大努力避免随机错误喷出。为此,我写了以下几行:

COLS="$(tput cols 2> /dev/null)"
令我惊讶的是,当我运行此命令时,
COLS
始终设置为
80
,而不管终端窗口的宽度是多少。(为了演示,我的终端恰好有115列宽。)为了弄清楚发生了什么,我在命令行上尝试了一些方法:

$ tput cols
115
$ tput cols | cat
115
$ echo "$(tput cols)"
115
$ tput cols 2> /dev/null
115
$ echo "$(tput cols 2> /dev/null)"
80
因此,
tput
似乎成功地计算出了当其stderr被重定向时,或者当它被嵌入到一个进程替换中时,终端的特征,但不是两者都是如此。真奇怪

我在Linux和OSX上都测试了这个,行为是一样的

这是怎么回事?实际上,在抑制stderr喷出的同时,让
tput
工作的最佳方法是什么


注意:我知道
$COLUMNS
。我特别感兴趣的是使用
tput
快速运行
strace
建议
tput
首先尝试确定
stdout
上的终端宽度,如果失败,则返回到
stderr
。因此,在失败的情况下,两者都被重定向,并且
tput
(显然)假定默认值为80列。

当我遇到类似问题时,谷歌将我带到了这里。虽然被接受的答案确实回答了这个问题,但它并没有就如何解决原始问题中提到的错误提供任何建议。我想我会加入一个可能的解决方案

我的具体情况是编写可以从命令行或cron调用的脚本。从cron运行时,Solaris会将
TERM
变量设置为“dumb”,而
tput
对此一无所知,并且会抛出错误(这些错误会被邮寄给cron作业的所有者)。由于无法捕获错误和stdout来获取列数,因此在运行
tput cols
之前,我首先尝试找出一种方法来确定tput是否知道某个特定的终端。为此,本准则似乎符合我的目的:

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

我意识到这不会捕获所有错误,但如果
tput
不知道某个特定终端,它至少可以避免可能的错误。

zsh
dash
ksh
中的相同行为,因此这看起来与运行
tput
的shell无关。