我有一个bash脚本,其功能需要与不同的参数并行运行。 我需要知道是否至少有一个执行失败(返回非零)-多少失败都没有关系。
该命令接受用于执行的参数数组。 由于高负载,我需要将并发限制为4个并发运行。 我还需要在父进程(运行bash脚本的父进程)中打印日志
这是我正在运行的功能:
function run_and_retry {
EXIT_STATUS=0
$COMMAND || EXIT_STATUS=$?
if [ $EXIT_STATUS -ne 0 ]; then
EXIT_STATUS=0
$COMMAND || EXIT_STATUS=$?
fi
return $EXIT_STATUS
}
我尝试使用GNU parallel和xargs并遇到了问题。
使用xargs :(无法获得退出状态,并且当我在TravisCI中运行它时也无法正常工作)
PARAMETERS=(first-parameter second-parameter third-parameter)
export -f run_and_retry
echo "${PARAMETERS[@]}" | xargs -P 4 -n 1 -I {} bash -c "run_and_retry {}"
与GNU并行:
PARAMETERS=(first-parameter second-parameter third-parameter)
export -f run_and_retry
parallel -j 4 -k --lb 2 run_and_retry {} ::: echo "${PARAMETERS[@]}"
答案 0 :(得分:6)
如此您接近使GNU Parallel的语法正确:
COMMAND=echo
PARAMETERS=(first-parameter second-parameter third-parameter)
parallel -j 4 -k --retries 2 "$COMMAND" {} ::: "${PARAMETERS[@]}" ||
echo $? commands failed. More than 99 if $? = 100
或者,如果您真的坚持要自己重试:
PARAMETERS=(first-parameter second-parameter third-parameter)
export -f run_and_retry
parallel -j 4 -k run_and_retry {} ::: "${PARAMETERS[@]}" ||
echo One or more commands failed
答案 1 :(得分:2)
我需要知道至少有一个执行失败(返回非零)
来自posix xargs:
退出状态
1-125
不能满足要求的命令行进行汇编,一个或多个实用程序调用返回非零退出状态,或发生其他错误。
man xargs似乎有点不同:
退出状态
123,如果以状态1-125退出命令的任何调用
但是我会检查命令的返回状态,并从函数中返回预定义的数字(例如1)来处理该数字。
parameters=(1 2 3 fail)
func() {
COMMAND=sleep
# I guess OP intends to try running COMMAND twice
if ! "$COMMAND" 0."$1" && ! "$COMMAND" 0."$1"; then
return 1
fi
}
export -f func
if printf "%s\0" "${parameters[@]}" | xargs -0 -P4 -n1 -t -- bash -c 'func $1' -- ; then
echo "Success!"
else
echo "Error!"
fi
可通过tutorialspoint获得实时版本。
好吧,我们甚至可以手动计算孩子的数量,而使用wait -n
则非常简单。来自stackoverflow - WAIT for “1 of many process” to finish:
bash 4.3在内置的wait命令中添加了-n标志,该标志使脚本等待下一个孩子完成。
所以我们可以:
cnt=0
failed=false
for i in "${parameters[@]}"; do
( func "$i" ) &
if (( cnt < 4 )); then
cnt=$((cnt+1))
else
# handle more then 4 processes
if ! wait -n; then
failed=true
fi
fi
done
# handle still running processes after all have been forked
for i in $(seq $cnt); do
if ! wait -n; then
failed=true
fi
done
if "$failed"; then
echo "One of the jobs failed!"
fi