Bash并发作业被卡住了

时间:2017-03-02 18:20:50

标签: linux bash shell concurrency

我已经实现了一种在bash中拥有并发作业的方法,如here所示。

我正在遍历大约13000行的文件。我只是测试和打印每一行,如下:

#!/bin/bash
max_bg_procs(){
    if [[ $# -eq 0 ]] ; then
        echo "Usage: max_bg_procs NUM_PROCS.  Will wait until the number of background (&)"
        echo "           bash processes (as determined by 'jobs -pr') falls below NUM_PROCS"
        return
    fi
    local max_number=$((0 + ${1:-0}))
    while true; do
        local current_number=$(jobs -pr | wc -l)
        if [[ $current_number -lt $max_number ]]; then
                echo "success in if"
                break
        fi
        echo "has to wait"
        sleep 4
    done
}

download_data(){
    echo "link #" $2 "["$1"]"
}

mapfile -t myArray < $1

i=1
for url in "${myArray[@]}"
do
    max_bg_procs 6
    download_data $url $i &
    ((i++))
done
echo "finito!"

我也尝试了其他解决方案,例如thisthis,但我的问题仍然存在:

在“随机”给定步骤,通常在第2000次和第5000次迭代之间,它只是卡住了。我已将各种echo放在代码中间以查看它会被卡住的位置,但它打印的最后一件事是$url $i

我已经完成了简单的测试以删除任何并行性并只是循环文件内容:一切都很顺利,它循环到最后。

所以这让我觉得我错过了对并行性的一些限制,我想知道是否有人可以帮助我搞清楚。

非常感谢!

2 个答案:

答案 0 :(得分:3)

在这里,我们最多有6个并行bash进程调用download_data,每个进程最多传递16个URL。根据您自己的调整进行调整。

请注意,这需要bash(用于导出的函数支持)和GNU xargs。

#!/usr/bin/env bash
#              ^^^^- not /bin/sh

download_data() {
  echo "link #$2 [$1]" # TODO: replace this with a job that actually takes some time
}
export -f download_data
<input.txt xargs -d $'\n' -P 6 -n 16 -- bash -c 'for arg; do download_data "$arg"; done' _

答案 1 :(得分:2)

使用GNU Parallel看起来像这样

cat input.txt | parallel echo link '\#{#} [{}]' 

{#} =工作号码
{} =参数

它将为每个CPU生成一个进程。如果你想要并行使用6 -j:

cat input.txt | parallel -j6 echo link '\#{#} [{}]' 

如果您更喜欢运行功能:

download_data(){
    echo "link #" $2 "["$1"]"
}
export -f download_data
cat input.txt | parallel -j6 download_data {} {#}