我在 Linux 机器上有一个脚本,其中一个奇特的 pv 通过管道传输到第二个 pv,该 pv 计算输出行的子集。
这是脚本:
max=1000
for (( i=0; i<max; i++ )); do
[[ $(shuf -i 1-100 -n 1) -lt 20 ]] && echo REMOVE || echo LEAVE
done | pv -F "%N %b / $(numfmt --to=si $max) %t %p %e" -c -N 'Lookups' -l -s $max \
| grep --line-buffered '^REMOVE' \
| pv -F "%N %b / $(numfmt --to=si $max)" -c -N 'Deletes' -l -s $max \
>/dev/null
stty sane
我期望的是第一个 pv 总是首先显示,第二个总是第二个。
就像这个例子的输出:
$ ./fancy_pv.sh
Lookups: 1.00k / 1.0K 0:00:03 [===============================================================================================================================================================================================================================================================================================================================================================>] 100%
Deletes: 189 / 1.0K
但事实并非如此,有时他们交换位置,我看到这样的事情:
$ ./fancy_pv.sh
Deletes: 199 / 1.0K
Lookups: 1.00k / 1.0K 0:00:03 [===============================================================================================================================================================================================================================================================================================================================================================>] 100%
有时我也会看到这样的事情:
$ ./fancy_pv.sh
Lookups: 321 / 1.0K 0:00:01 [===============================================================================================================> ] 32% ETA 0:00:02
Deletes: 198 / 1.0K
Lookups: 1.00k / 1.0K 0:00:03 [===============================================================================================================================================================================================================================================================================================================================================================>] 100%
我知道这一定是因为 pv 删除该行并重新绘制它的方式,但是我可以做些什么来防止它扰乱顺序吗?
stty sane
是否可以清理提示符,因为有时 pv 会使终端无法使用。
谢谢
答案1
pv
管道中的两个进程可以按任意顺序启动。最新的输出pv
将在底线。
延迟pv
你想要的底线。而不是使用子 shell pv …
(其中表示其所有参数):…
( </dev/null sleep 1; exec pv … )
理论上,另一个pv
可能仍然在延迟的之后启动,但在不完全过载的系统中,几乎可以肯定延迟的pv
将最后启动。
sleep
无论如何都不应该从它的标准输入中读取;</dev/null
以防万一你sleep
很奇怪。
我不确定某些竞争条件是否会导致出现额外的(陈旧)行。如果是这样,推迟pv
(几乎肯定)应该会有所帮助。在我的测试中,当终端需要“额外”更新时,输出会被破坏。所以:
pv
运行时请勿调整终端大小。- 避免滚动:
- 在运行脚本之前,调用
clear
(或按Ctrl+ L)。这将清除屏幕,将提示放在顶部并在下面提供空间,而无需稍后滚动。 pv
s 运行时请勿打字;特别是应避免使用多个Enters (最终可能滚动文本)。- 一般来说,在 s 完成之前,不要让除
pv
s 以外的任何内容打印到终端pv
。这适用于管道的其他部分(例如 via/dev/tty
)、脚本中的异步进程(例如仅通过其 stdout)、脚本外部的进程(例如 via/dev/tty*
或/dev/pts/*
)。
- 在运行脚本之前,调用