![子 shell 中的 stderr 重定向更改了 tput 的输出](https://linux22.com/image/1509948/%E5%AD%90%20shell%20%E4%B8%AD%E7%9A%84%20stderr%20%E9%87%8D%E5%AE%9A%E5%90%91%E6%9B%B4%E6%94%B9%E4%BA%86%20tput%20%E7%9A%84%E8%BE%93%E5%87%BA.png)
我正在编写一个脚本,发现了一些奇怪的行为。我确信第 4行和第 6行命令行的输出与其他情况不同是有逻辑解释的,但我找不到它。
1 $ tput cols
128
2 $ tput cols 2>/dev/null
128
3 $ echo $(tput cols)
128
4 $ echo $(tput cols 2>/dev/null)
80
5 $ (tput cols >/tmp/cols.txt); cat /tmp/cols.txt
128
6 $ (tput cols &>/tmp/cols.txt); cat /tmp/cols.txt
80
7 $ echo $(tput cols 2>/dev/null; echo $COLUMNS; tput cols)
80 128 128
为什么 stderr 重定向会改变子 shell 中 tput 的输出?
最终,我想在我的脚本中做这样的事情,以使其在没有 tput/ncurses 的系统上工作:
cols=$(tput cols 2>/dev/null || echo $COLUMNS)
上述示例是使用 Bash 4.3.46(1)-release 和 ncurses 6.0.20150627 创建的
答案1
根据strace
,发生这种情况是因为tput
仅尝试从其 stdout 和 stderr (fd 1 & 2) 读取 tty 设置。由于您已明确重定向 stderr,并且$( )
也重定向 stdout,因此 tput 放弃。
最好的解决办法是修补 tput 以检查标准输入是否存在 tty;但是,您也可以删除2>/dev/null
重定向,因为它tput cols
无论如何都不会输出任何错误消息。(如果它确实输出了一些错误消息,最好注意它们。)