在控制台上显示持久状态消息

时间:2014-02-03 22:41:48

标签: bash shell output stdout

我正在开发一个向stdout发送大量输出的程序,但我希望能够轻松地告诉程序正在做什么。我已经看到一些程序显示脚本或程序的输出,但控制台上的最后一行是“保留”,这意味着命令的输出显示在屏幕上,但是最后一行(或两行,或者很多) )保留用于静态或偶尔更改的状态文本(例如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

.
. (etc.)
.

------------------------------------------------------------------------
Installing component 11/134...

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

这样,一旦我们深入了解程序,通常shell会开始滚动,我们仍然会看到:

.
. (more lines of output here)
.
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
------------------------------------------------------------------------
Installing component 66/134...

3 个答案:

答案 0 :(得分:3)

可能值得研究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>

这种逻辑的目的是:

  • 计算屏幕上有多少行并移至底部

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

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

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

答案 1 :(得分:3)

虽然它需要具有客户端依赖关系,但有一种方法可以使用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

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

Screenshot

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

答案 2 :(得分:0)

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

tput可用的功能由terminfo中定义的#!/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

(它为我打印错误信息。)

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

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