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

iezvtpos  于 2023-08-07  发布在  Shell
关注(0)|答案(4)|浏览(145)

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

字符串
在这个特定的例子中,我希望“Installing component 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...

yeotifhr

yeotifhr1#

也许有必要了解一下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>

字符串
这一逻辑的意图是:

  • 计算出屏幕上有多少行,然后移到底部
  • 计算出有多少列,并构建分隔线以跨越那么多列
  • 打印分隔线,然后打印状态行

话虽如此,我觉得肯定有一个更优雅的方式来实现你想做的事情...

vsdwdz23

vsdwdz232#

虽然它需要有一个客户端依赖项,但有一种方法可以用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,但它是一个常用的工具,使用它来实现这一目的非常容易。

iyr7buue

iyr7buue3#

正如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

字符串
(It为我打印错误消息。)
您可以使用tput在最下面一行打印文本,但正常输出将覆盖它(除非您仔细控制写入屏幕的内容)。
GNU screen命令还使用了状态行,如果终端不支持,可能会模拟状态行。man screen详细信息。但是screen倾向于在它可用的情况下将其用于自己的消息,并且您似乎不想将要求强加给用户。

uxhixvfz

uxhixvfz4#

您可以通过向终端仿真器发送特殊的控制台代码来实现这一点。这些都是相当标准的,应该希望在任何地方都能得到支持,并在console_codes(4)和其他地方进行了描述。
手册页告诉你使用像ncurses或tput这样的实用程序,但是对于像这样的小程序,我不想麻烦。

#!/bin/bash

numlines=$(tput lines)

# reset screen and limit scrolling
echo -e "\ec\e[2;$((numlines-1))r" 

# go to first line and output a header
echo -e "\e[0HWelcome to this little demo"

for x in $(seq 100); do
    # save position, go to last line, write status and restore position
    echo -ne "\e7\e[$((numlines))Hnow doing $x\e8"

    sleep 0.5
    echo $x
done

字符串
如果stdout不是tty,那么您可能应该恢复到简单的哑输出,并通过捕获SIGWINCH来更新$numlines和滚动区域来处理窗口大小调整。

相关问题