如何将`pv`的输出发送到python脚本,并一次一行输出进度?

如何将`pv`的输出发送到python脚本,并一次一行输出进度?

我用来tar快速复制数千个小文件,通过管道pv显示复制的进度和速度。

$ sudo tar c --files-from /tmp/camfilenames | 
  pv --width 40 | 
  sudo tar x -C /home/pi/test

...这工作得很好。输出示例:

191MiB 0:00:03 [58.1MiB/s] [<=>       ]

...在航站楼。但我想用这个输出做更多的事情,我有简单的 python 脚本/home/pi/screentest.py

import sys
print "start"
for line in sys.stdin:
    print "line: " + line
print "end"

测试运行:

$ (   sudo tar c --files-from /tmp/camfilenames | 
      pv --width 40 | 
      sudo tar x -C /home/pi/test   ) | 
   python /home/pi/screentest.py

输出:

start
191MiB 0:00:03 [55.1MiB/s] [<=>       ]
end

我知道pv返回一个缓冲区中的所有内容,那么如何强制它逐行返回并每次刷新缓冲区以输出类似以下内容:

start
line: 0MiB 0:00:00 ...
line: 60MiB 0:00:01 ...
line: 120MiB 0:00:02 ...
line: 191MiB 0:00:03 ...
end

答案1

pv将进度输出到 stderr,因此管道到 python 脚本没有从pv.它在输出停止end后打印,可能是因为那时最后一个输出已经退出,因此脚本的标准输入已经关闭。pvtar

您可能需要类似的东西:

( sudo tar c --files-from /tmp/camfilenames | 
  pv --width 40 -f | 
  sudo tar x -C /home/pi/test ) 2>&1 >/dev/null | python /home/pi/screentest.py

我们丢弃 tar 管道的 stdout,而是将 stderr 发送到 pythons 脚本。请注意,我们需要强制pvwith输出进度-f,因为pv如果 stderr 不是终端,则不会进度。

但您可能想查看 topv--format选项。你可以使用类似的东西:

sudo tar c --files-from /tmp/camfilenames | 
  pv --width 40 --format $'%b %t\n' | 
  sudo tar x -C /home/pi/test

以获得类似的输出。

答案2

谢谢@muru,我尝试了你的解决方案,但与此同时,我发现主要问题是强制 PV 输出新行,而不是不断更新一行。

所以我写了这个:

$ tail -f /home/pi/log | pv -f |& stdbuf -oL tr '\r' '\n'

它起作用了,所以现在的问题是 - 如何调用我的 python 脚本来对每一行执行某些操作 - 我发现我可以使用 do-while 循环来实现这一点:

$ tail -f /home/pi/log | pv -f |& stdbuf -oL tr '\r' '\n' | (while read -r LINE; do echo $LINE; done;)

因此,有了这个,我只需使用我的 python 脚本(小 LCD 处理程序)在 LCD 上显示 PV 状态:

tail -f /home/pi/log | pv -f --width 20 -i 2 |& stdbuf -oL tr '\r' '\n' | (while read -r LINE; do python /home/pi/screen.py $LINE; done;)

我重新引入了我的 TAR 脚本,将许多小文件复制到其中:

$ (sudo tar c --files-from /tmp/camfilenames | pv -f --width 20 -i 1 | sudo tar x -C /home/pi/test) |& stdbuf -oL tr '\r' '\n' | (while read -r LINE; do python /home/pi/screen.py $LINE; done;)

所以最后,当我向 PV 添加更多参数,并且在将 PV 输出发送到 LCD 之前我做了一些字符串替换,并且添加了一些断行时,我有以下内容:

cd /home/pi/cam \ && ( \ sudo tar c --files-from /tmp/camfilenames \ | pv -f -s $( \ du -sb /home/pi/cam \ | awk '{print $1}' \ ) --width 64 -i 5 \ | sudo tar x -C /mnt/usb \ ) \ |& stdbuf -oL tr '\r' '\n' \ | ( \ while read -r LINE; \ do LINE="${LINE// /_}"; \ LINE="${LINE//_\[/ [}"; \ LINE="${LINE//\]_/] }"; \ lcd $LINE; \ done; \ ) \ && cd /home/pi

这是 PV 输出在 LCD 上的显示方式: 这就是 PV 输出在 LCD 上的显示效果

相关内容