bash 等待所有进程完成(不起作用)
bash wait for all processes to finish (doesn't work)
我有一个目录,其中包含几个名称为
的子目录
1
2
3
4
backup_1
backup_2
我写了一个并行化的 bash 代码来处理这些文件夹中的文件,最小工作示例如下:
#!/bin/bash
P=`pwd`
task(){
dirname=$(basename $dir)
echo $dirname running >> output.out
if [[ $dirname != "backup"* ]]; then
sed -i "s/$dirname running/$dirname is good/" $P/output.out
else
sed -i "s/$dirname running/$dirname ignored/" $P/output.out
fi
}
for dir in */; do
((i=i%8)); ((i++==0)) && wait
task "$dir" &
done
wait
echo all done
脚本末尾的“等待”应该等待所有进程完成,然后再继续回显“全部完成”。 output.out 文件,所有进程完成后应该显示
1 is good
2 is good
3 is good
4 is good
backup_1 ignored
backup_2 ignored
如果我将脚本设置为 运行 与 ((i=i%1)); ((i++==0)) && wait
串行,我就能获得此输出。但是,如果我 运行 它与 ((i=i%2)); ((i++==0)) && wait
并行,我会得到类似
的东西
2 is good
1 running
3 running
4 is good
backup_1 running
backup_2 ignored
谁能告诉我为什么 wait 在这种情况下不起作用?
我也知道 GNU parallel 可以在并行化任务中做同样的事情。但是,我不知道如何在父目录中的所有子目录上并行命令 运行 此任务。如果有人可以生成我可以遵循的示例脚本,那就太好了。
非常感谢
亚采克
GNU Parallel 的文字移植看起来像这样:
task(){
dir=""
P=`pwd`
dirname=$(basename $dir)
echo $dirname running >> output.out
if [[ $dirname != "backup"* ]]; then
sed -i "s/$dirname running/$dirname is good/" $P/output.out
else
sed -i "s/$dirname running/$dirname ignored/" $P/output.out
fi
}
export -f task
parallel -j8 task ::: */
echo all done
正如其他人指出的那样,当您 运行 sed
并行处理同一个文件时,您会遇到竞争条件。
要避免竞争条件,您可以这样做:
task(){
dir=""
P=`pwd`
dirname=$(basename $dir)
echo $dirname running
if [[ $dirname != "backup"* ]]; then
echo "$dirname is good" >&2
else
echo "$dirname ignored" >&2
fi
}
export -f task
parallel -j8 task ::: */ >running.out 2>done.out
echo all done
您最终会得到两个文件 running.out 和 done.out。
如果你真的只想忽略名为 backup*
的目录:
task(){
dir=""
P=`pwd`
dirname=$(basename $dir)
echo $dirname running
echo "$dirname is good" >&2
}
export -f task
parallel -j8 task '{=/backup/ and skip()=}' ::: */ >running.out 2>done.out
echo all done
考虑花 20 分钟阅读 https://doi.org/10.5281/zenodo.1146014 的第 1+2 章,您的命令行会因此而爱上您。
我有一个目录,其中包含几个名称为
的子目录1
2
3
4
backup_1
backup_2
我写了一个并行化的 bash 代码来处理这些文件夹中的文件,最小工作示例如下:
#!/bin/bash
P=`pwd`
task(){
dirname=$(basename $dir)
echo $dirname running >> output.out
if [[ $dirname != "backup"* ]]; then
sed -i "s/$dirname running/$dirname is good/" $P/output.out
else
sed -i "s/$dirname running/$dirname ignored/" $P/output.out
fi
}
for dir in */; do
((i=i%8)); ((i++==0)) && wait
task "$dir" &
done
wait
echo all done
脚本末尾的“等待”应该等待所有进程完成,然后再继续回显“全部完成”。 output.out 文件,所有进程完成后应该显示
1 is good
2 is good
3 is good
4 is good
backup_1 ignored
backup_2 ignored
如果我将脚本设置为 运行 与 ((i=i%1)); ((i++==0)) && wait
串行,我就能获得此输出。但是,如果我 运行 它与 ((i=i%2)); ((i++==0)) && wait
并行,我会得到类似
2 is good
1 running
3 running
4 is good
backup_1 running
backup_2 ignored
谁能告诉我为什么 wait 在这种情况下不起作用?
我也知道 GNU parallel 可以在并行化任务中做同样的事情。但是,我不知道如何在父目录中的所有子目录上并行命令 运行 此任务。如果有人可以生成我可以遵循的示例脚本,那就太好了。
非常感谢 亚采克
GNU Parallel 的文字移植看起来像这样:
task(){
dir=""
P=`pwd`
dirname=$(basename $dir)
echo $dirname running >> output.out
if [[ $dirname != "backup"* ]]; then
sed -i "s/$dirname running/$dirname is good/" $P/output.out
else
sed -i "s/$dirname running/$dirname ignored/" $P/output.out
fi
}
export -f task
parallel -j8 task ::: */
echo all done
正如其他人指出的那样,当您 运行 sed
并行处理同一个文件时,您会遇到竞争条件。
要避免竞争条件,您可以这样做:
task(){
dir=""
P=`pwd`
dirname=$(basename $dir)
echo $dirname running
if [[ $dirname != "backup"* ]]; then
echo "$dirname is good" >&2
else
echo "$dirname ignored" >&2
fi
}
export -f task
parallel -j8 task ::: */ >running.out 2>done.out
echo all done
您最终会得到两个文件 running.out 和 done.out。
如果你真的只想忽略名为 backup*
的目录:
task(){
dir=""
P=`pwd`
dirname=$(basename $dir)
echo $dirname running
echo "$dirname is good" >&2
}
export -f task
parallel -j8 task '{=/backup/ and skip()=}' ::: */ >running.out 2>done.out
echo all done
考虑花 20 分钟阅读 https://doi.org/10.5281/zenodo.1146014 的第 1+2 章,您的命令行会因此而爱上您。