【问题标题】:Show persistent status message on console在控制台上显示持久状态消息
【发布时间】:2014-02-27 15:32:19
【问题描述】:

我正在开发一个向标准输出发送大量输出的程序,但我希望能够轻松判断程序在做什么。我见过一些程序显示脚本或程序的输出,但控制台上的最后一行是“保留的”,这意味着命令的输出显示在屏幕上,但最后一行(或两行,或多行) ) 保留用于静态或偶尔更改的状态文本(例如Building <xxxxxx>...)。这样,人们可以看到脚本/程序的输出以进行调试/故障排除,而且还可以快速浏览并查看程序的状态。 有什么办法可以用shell脚本来实现吗?我不介意使用内置的系统工具,例如awk,来格式化文本,只要使用的工具是常用的在大多数系统上都可以找到。如果可能的话,我也想避免使用ncurses 和其他库。

如果你还是不明白我在说什么,我会在这里尝试说明:

make -gcc -NOFLAGS -someotherGibberishHere Component1afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component2afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component3afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component4afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component5afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component6afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component7afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component8afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component9afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component10afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component11afdjadfjfadkladfjk . . (等等。) . -------------------------------------------------- ---------------------- 安装组件 11/134...

在这个特定的示例中,即使控制台输出开始滚动,我也希望“正在安装组件 11/134...”这一行保持不变。最好,我也想把那条线也放在它上面。

这样,一旦我们进入程序的最深处并且通常外壳会开始滚动,我们仍然会看到:

. . (这里有更多的输出行) . make -gcc -NOFLAGS -someotherGibberishHere Component58afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component59afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component60afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component61afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component62afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component63afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component64afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component65afdjadfjfadkladfjk make -gcc -NOFLAGS -someotherGibberishHere Component66afdjadfjfadkladfjk -------------------------------------------------- ---------------------- 安装组件 66/134...

【问题讨论】:

  • 最简单、最可靠的解决方案是在分屏模式下自动启动screentmux,并分别运行两个单独的命令。
  • 我已经研究了这些方法,但到目前为止,它们都是由最终用户执行的。有没有办法以编程方式建立它?
  • 可能有一个(可能是可选的)专用状态行。寻找启用它并写入它的方法。
  • @CalebXu 是的,它们都具有以编程方式发送窗口拆分命令等功能。

标签: bash shell output stdout


【解决方案1】:

可能值得看看tput 的功能。

类似以下的内容可以形成始终在屏幕底部打印状态行的解决方案的开始:

numlines=$(tput lines)
numcols=$(tput cols)
numcols=$(expr $numcols - 1)
separator_line=$(for i in $(seq 0 $numcols);do printf "%s" "-";done;printf "\n")
tput cup $numlines
echo $separator_line
echo <your status line>

这个逻辑的目的是:

  • 算出屏幕上有多少行并移到底部

  • 计算出多少列并构建分隔线以跨越那么多列

  • 打印分隔线,然后打印您的状态行

话虽如此,我确信一定有一种更优雅的方式来实现你想做的事情......

【讨论】:

  • tput 看起来像是用于该任务的可能工具。上面提到的解决方案的唯一问题是无法确定运行该代码块的频率。如果我在每个命令之后运行它,它会在输出中显示十亿次——这不是我想要的。如果我只在最后(或开始)运行一次,则输出仅在我完成时显示(或很快隐藏在输出中)。
  • 是的,你是对的。我认为这不是正确的解决方案。回到绘图板。
  • 我想知道ncurses 是否可能是要走的路。我不熟悉它,所以我无法提出解决方案,但可能值得阅读手册页或教程?
  • 我对@9​​87654325@ 非常熟悉,但我试图避免这种情况。我只编写一个 shell 脚本作为一个软件,并且将 ncurses 列为依赖项会有点奇怪(而且我在 OS X 上,但在这里尝试使用 shell 脚本,而 ncurses 的行为有点奇怪有时)。只为这项工作初始化 ncurses 似乎也有点矫枉过正(它涉及将输出初始化为“ncurses 模式”,并且输出格式非常严格)。
【解决方案2】:

虽然它需要客户端依赖,但有一种方法可以使用 screen 来做到这一点。

#!/bin/bash

# Check if script was started in our screen session
if [ -z "$INTERNAL_INIT_SCRIPT" ]; then
  # Create temporary screen config file to avoid conflicts with
  # user's .screenrc
  screencfg=$(mktemp)
  # Show status line at bottom of terminal
  echo hardstatus alwayslastline > "$screencfg"
  # Start script in a new screen session
  INTERNAL_INIT_SCRIPT=1 screen -mq -c "$screencfg" bash -c "$0"
  # Store screen return code
  ret=$?
  # Remove temporary screen config file
  rm "$screencfg"
  # Exit with the same return code that screen exits with
  exit $ret
fi

total=134

function set_status {
  screen -X hardstatus string "[$1/$total] $2"
}

# Prints "[1/134] Installing jq..." to the status line
set_status 1 'Installing jq...'

# Install some component

我在一个脚本中使用它来初始化我在 DigitalOcean 上启动的 Fedora 服务器。下面是它在实践中的样子:

同样,虽然它确实涉及安装 screen,但它是一种常用工具,并且为此目的使用它非常容易。

【讨论】:

    【解决方案3】:

    正如Lindsay Winkler's answer 建议的那样,tput 可能会做你想做的事情如果你的终端(模拟器)支持它。

    tput 可用的功能由terminfo 定义,列在terminfo(5) man page 中。

    这样的事情应该可以工作(如果有的话):

    #!/bin/bash
    
    if tput hs ; then
        tput tsl
        echo -n This is the status line
        tput fsl
    else
        echo Sorry, there is no status line
    fi
    

    (它会为我打印错误消息。)

    您可以使用tput 在底行打印文本,但正常输出只会覆盖它(除非您仔细控制写入屏幕的内容)。

    GNU screen 命令还使用了状态行,如果终端不支持它,可能会模拟一个状态行。 man screen 了解详情。但screen 倾向于将其用于自己的消息(如果可用),而且您似乎不想对用户强加要求。

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 2019-01-12
      • 2020-12-26
      • 2022-01-06
      • 2023-03-13
      • 2017-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多