如果仅预先知道命令输入的大小,如何跟踪管道中命令的进度?

如果仅预先知道命令输入的大小,如何跟踪管道中命令的进度?

我想使用 来跟踪缓慢操作的进度pv。该操作的输入的大小是预先已知的,但其输出的大小却不是。这迫使我将pv操作放在管道的左侧。

问题在于,由于缓冲,长时间运行的命令会立即消耗其全部输入。这有点类似于关闭管道中的缓冲问题,但就我而言,消耗操作很慢,而不是生产操作,并且另一个问题的答案似乎在这种情况下不起作用。

这是一个演示该问题的简单示例:

seq 20 | pv -l -s 20 | while read line; do sleep 1; done
  20 0:00:00 [13.8k/s] [=====================================>] 100%

进度条不是每秒更新一次,而是立即跳至 100%,并在处理输入所需的整个 20 秒内保持该状态。pv如果一行一行地处理,则只能测量进度,但最后一个命令的整个输入似乎都被读入缓冲区。

一个更长的示例也演示了未知数量的输出行:

#! /bin/bash
limit=10
seq 20 | \
  pv -l -s 20 | \
  while read num
do
  sleep 1
  if [ $num -gt $limit ]
  then
    echo $num
  fi
done

对于解决方法有什么建议吗?谢谢!

答案1

在您的设置中,数据已通过pv,但仍在右侧进行处理。您可以尝试像这样移动pv到最右侧:

seq 20 | while read line; do sleep 1; echo ${line}; done | pv -l -s 20 > /dev/null

更新: 关于您的更新,也许最简单的解决方案是使用命名管道和子 shell 来监视进度:

#! /bin/bash
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
(rm /tmp/progress.pipe; mkfifo /tmp/progress.pipe; tail -f /tmp/progress.pipe | pv -l -s 20 > /dev/null)&
limit=10
seq 20 | \
  while read num
do
  sleep 1
  if [ $num -gt $limit ]
  then
    echo $num
  fi
  echo $num > /tmp/progress.pipe
done

相关内容