这个问题给我很大的启发:并行化 Bash FOR 循环 并行化我编写的一些涉及非常长的 while read 循环的工具(即跨输入文件中给定的路径执行相同的任务/一组任务。输入文件将包含大约 90,000 行,并且还在不断增长)。
我已经完成了将 PSkocik 的“带有基于 FIFO 的信号量的 N 个进程”示例“插入”到我的代码中的所有工作...
# initialize a semaphore with a given number of tokens
open_sem(){
mkfifo /tmp/pipe-$$
exec 3<>/tmp/pipe-$$
rm /tmp/pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
# run the given command asynchronously and pop/push tokens
run_with_lock(){
local x
# this read waits until there is something to read
read -u 3 -n 3 x && ((0==x)) || exit $x
(
( "$@"; )
# push the return code of the command to the semaphore
printf '%.3d' $? >&3
)&
}
N=4
open_sem $N
for thing in {a..g}; do
run_with_lock task $thing
done
然而,我的“旧”代码在读取循环中内置了一个很好的进度计数器(下面的代码是缩写的),是的,我知道有 echo、awk 和 printf 的奇怪组合,我倾向于重用我已经使用过的其他脚本中的代码编写的某些代码可能是基于其他在线示例等...我确信我可以整理它...但它有效,而且我是唯一使用此代码的人!:
## $temp1 is the file with 90,000 lines to read over
## $YELLOW is a global variable exported from my bashrc with the escape code for yellow text
## $GREEN is a global variable exported from my bashrc with the escape code for green text
## $CL is a global variable exported from my bashrc with the escape code for Clear Line
## $NC is a global variable exported from my bashrc with the escape code to revert text colour back to normal
num_lines="$(cat $temp1 | wc -l)"
percent_per_line="$(awk "BEGIN {print 100/$num_lines}")"
progress_percent='0'
current_line='1'
echo -ne "${CL}${YELLOW}PROGRESS: ${progress_percent}% ${NC}\r"
while read line; do
############################################
##commands to process $line data as needed##
############################################
progress_percent="$(awk "BEGIN {print $progress_percent + $percent_per_line }")"
awk -v y=$YELLOW -v nc=$NC -v progress=$progress_percent -v current_line=$current_line -v total_lines=$num_lines 'BEGIN {printf (y"\033[2KPROGRESS: %.3f%% (%d OF %d)\n\033[1A"nc, progress, current_line, total_lines) }'
#I think I mixed my global var escape codes with typed out ones cause I was I forgot / have no need to export \033[2K and \033[1A for anything else?
((current_line++))
done < "$temp1"
echo -e "${CL}${GREEN}PROGRESS: 100.000% (${num_lines} OF ${num_lines})${NC}"
我正在尝试再次找到一种方法,将具有类似输出的东西塞入“新”的 FIFO 信号量代码中......
我就是不知道怎么办!它是否进入run_with_lock函数,如果是的话,在哪里,我需要将percent_per_line和num_lines变量传递到该函数中,但它$@
在其中传递:(我觉得我没有完全理解FIFO信号量是如何工作的,就像我一样我是否会使用另一个信号量消息类型来传递我需要的数据......
任何帮助将不胜感激,因为它可以帮助我学习和提高!
答案1
好吧,所以我觉得很愚蠢......虽然我确信它不是 100% 准确,但在使用简单的测试脚本进行了大量测试后,我觉得我必须掌握一点。
我没有完全“意识到”整个信号量的确切功能方法。我看到的方式是while read
循环会立即执行所有“读取”,将所有行添加到某个队列(我认为是管道),所以我最初的想法是读取循环中的任何其他内容也会“完全”运行(即立即跳转到 100%),然后脚本将移动到wait
读取循环之后以完成队列,给我留下一个显示 100% 完成的终端屏幕,尽管它实际上仍在执行工作。
事实证明,我大错特错了!这run_with_lock
意味着循环一次while read
仅读取行,因此调用后的任何代码仅在锁释放时间歇性运行。N
run_with_lock
因此,为了实现我的目标,我需要做的就是将我的进度代码保持在完全相同的位置,一切都很好......没有我认为需要的特殊处理。
缺点是进度现在显示项目何时开始处理,而不是在它们实际完成后更新,但这相对于所需的内容来说很小