显示命令输出的最后 n 行

显示命令输出的最后 n 行

我正在尝试运行docker build命令。我只想连续查看输出的最后“n”行。例如,通常的 docker build 命令给我类似的东西:

Building myimage
Step 1/15 : FROM python:3.6.9
 ---> 5bf410ee7bb2
Step 2/15 : WORKDIR /
 ---> Running in 201dd686c5d9
Removing intermediate container 201dd686c5d9
 ---> 298d3c728059
Step 3/15 : COPY . .
 ---> a47754a932c3
Step 4/15 : RUN chmod 755 /launch/start-script.sh
 ---> Running in ef27984abecf
Removing intermediate container ef27984abecf
 ---> ae13426f44e9
Step 5/15 : RUN pip install --upgrade pip
...
...
...

所需的输出n=3

Removing intermediate container ef27984abecf
 ---> ae13426f44e9
Step 5/15 : RUN pip install --upgrade pip

我试着把它管到尾巴上,

docker build | tail -3

但是一旦构建完成,就会显示最后 3 行。进程运行时是否可以连续显示最后“n”行?

答案1

#!/bin/sh
i=0
[ "$#" = 1 ] || { >&2 echo "The number of lines should be provided"; exit 9; }
nlines=$1
while IFS= read -r line; do
    clear
    all="$all
$line"
    i=$((i+1))
    if [ "$i" -ge "$nlines" ]; then
        all="${all#*
}"
    fi
    printf '%s\n' "$all"
done

使其可执行 ( chmod +x nlines.sh),然后仅连续打印 3 行,

docker build | ./nlines.sh 3

  • clear清除屏幕。每当一行来自标准输入时就会执行此操作。

  • 这会将新读取的行添加到变量中all

all="$all
$line"
  • [ "$i" -ge "$nlines" ]测试是否达到要显示的最大行数。如果是,

    • 这将从变量中删除最旧的行。
all="${all#*
}"

答案2

我开发了一个用于观看程序输出的实用程序,称为pw(管表)

它的基本要点与接受的答案中的 shell 脚本没有太大不同:程序连续读取标准输入中的所有内容,并通过重新定位光标(ANSI 序列)和重新绘制线条来更新显示。

pw通过一个小的 FIFO 缓冲区泵送线路,该缓冲区根据其所处的模式根据几个不同的规则进行采样。因为它不保留通过它的所有数据,所以程序以少量固定量运行内存。

pw与 POSIX 作业控制集成。当您将其放在后台并告诉它执行(或在后台启动作业)时,它仍然读取其输入,但不会更新终端显示(这样做会产生信号SIGTTOU)。在后台操作中,触发器仍在运行,并且会拍摄 FIFO 的快照。当您将其置于前台时,显示内容将被重新绘制。因此,在一个 shell 会话中,您可以同时处理许多可以监视的工作pw。在后台,它们不会阻塞,因为有东西正在读取它们的输出。

pw为您提供一堆 grep 模式,您可以即时编辑它们,以便在输入到达 FIFO 之前对其进行过滤。

您可以设置触发器来捕获 FIFO 的快照以供显示。有 19 深的快照历史记录。触发器由与 FIFO 的特定行相匹配的模式组成。如果您使用触发器来锁定重复模式,触发器可以使显示看起来“冻结”,就像示波器的触发如何使周期性波形看起来静止一样。

该视图可以分为两个或三个不同大小和位置的垂直窗格。左窗格显示行的前缀,中间窗格显示任意中间部分,右窗格显示可水平滚动的前缀之后的行的其余部分。

答案3

在此输入图像描述

您可以使用 轻松完成此操作tput。我创建了一个 zsh 函数,可以在不清除屏幕的情况下跟踪命令的最后 n 行。我仅在运行 MacOS 12.6 Monterey 的 m1 mac 上对此进行了测试。

function tail_lines () {
  # save cursor position
  tput sc
  tput ed

  # if is a number
  # `<->' is a special zsh pattern to match any number, an extension of forms like `<1-100>' which matches any number in the range 1 to 100 inclusive
  # https://zsh.sourceforge.io/Guide/zshguide03.html
  if [[ "$1" = <-> ]]; then
    nlines=$1
  else
    nlines=5
  fi

  YELLOW=$(tput setaf 3)
  NORMAL_COLOR=$(tput sgr0)
  while IFS= read -r line; do
    # restore cursor position
    tput rc
    if [ -z "$output" ]; then
      output="  $line"
    else
      output=`echo "$output\n  $line" | tail -n $nlines`
    fi
    printf -- "${YELLOW}$output${NORMAL_COLOR}\n"
  done < /dev/stdin
  tput rc
  tput ed || tput 'cd'
}

用法

brew update | tail_lines

或者 brew update | tail_line 10

答案4

尝试

docker build > logfile &
tail -3 -f logfile

-f 可以执行您想要的操作,但它不适用于管道,因此需要中间文件。

相关内容