【问题标题】:Curious tput behavior, with stderr redirection奇怪的 tput 行为,带有 stderr 重定向
【发布时间】:2014-03-12 20:55:33
【问题描述】:

我正在尝试在 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 和 OS X 上都对此进行了测试,结果是一样的。

这里发生了什么?实际上,让tput 工作同时抑制stderr spew 的最佳方法是什么?

注意:我知道$COLUMNS。我对使用tput 特别感兴趣。

【问题讨论】:

  • zshdashksh 中的行为相同,因此这似乎与用于运行 tput 的 shell 无关。

标签: bash io-redirection


【解决方案1】:

快速运行strace 表明tput 首先尝试确定stdout 上的终端宽度,如果失败,它会退回到stderr。因此,在失败的情况下,两者都被重定向,tput(显然)假定默认为 80 列。

【讨论】:

    【解决方案2】:

    Google 将我带到这里,因为我遇到了类似的问题。事实上,虽然接受的答案确实回答了这个问题,但它并没有真正提供有关如何解决原始问题中提到的错误喷射的任何建议。以为我会提出可能的解决方法。

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

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

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

    【讨论】:

      【解决方案3】:

      显然他们此后更改了tput。它在 Ubuntu 18.04 (ncurses 6.2.20200212) 中运行得更好。即使在tput 命令之前运行eval $(resize) 的旧软件可能会有所帮助,但您必须为此安装xterm。有关tput 方法的替代方法,请参阅here

      【讨论】:

        猜你喜欢
        • 2011-01-12
        • 1970-01-01
        • 2014-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-30
        相关资源
        最近更新 更多