如何在并行处理的Bash脚本中用pv显示管道数据进度?
解决pv在GNU Parallel并行任务中无法显示进度的问题
问题根源
GNU Parallel默认会捕获子进程的标准输出与错误输出,多个pv实例的进度信息会被混在一起,且无法正确输出到终端,导致看不到预期的管道数据进度。
可行解决方案
方案1:让单个任务的pv进度独立输出到终端
修改脚本,将pv的错误输出直接指向终端设备,同时保证并行任务的标准输出正常传递给后续的pigz:
#!/bin/bash doit() { pv "$1" 2>/dev/tty | pigz -dc | awk -F, '$1>0.5 && $2<1.5' } export -f doit find "$1" -name '*.csv.gz' | parallel doit | pigz > output.csv.gz
这种方式下每个pv的进度会直接打印到终端,适合待处理文件数量不多的场景,缺点是多文件并行时进度条会交替刷新。
方案2:显示全局总数据处理进度
先统计所有待处理压缩文件的总字节数,再在并行输出的管道后添加pv并指定总大小,实现全局进度可视化:
#!/bin/bash # 计算目标目录下所有csv.gz文件的总字节数 total_size=$(find "$1" -name '*.csv.gz' -exec du -sb {} + | awk '{sum+=$1} END {print sum}') doit() { pigz -dc "$1" | awk -F, '$1>0.5 && $2<1.5' } export -f doit find "$1" -name '*.csv.gz' | parallel doit | pv -s "$total_size" | pigz > output.csv.gz
该方案能避免多进度条混乱的问题,适合需要直观了解整体处理进度的场景。
方案3:借助parallel的--ungroup参数
使用parallel --ungroup参数关闭子进程输出捕获,让pv的错误输出直接传递到终端:
#!/bin/bash doit() { pv "$1" | pigz -dc | awk -F, '$1>0.5 && $2<1.5' } export -f doit find "$1" -name '*.csv.gz' | parallel --ungroup doit | pigz > output.csv.gz
此方式会保留子进程的输出顺序,每个pv的进度条会正常显示,但同样存在多进度条交替刷新的情况。
内容的提问来源于stack exchange,提问作者kiasari
相关产品推荐
相关产品推荐

