控制bash中启动程序的数量

控制bash中启动程序的数量

作为我的研究项目的一部分,我正在处理分成许多文件的大量数据。

文件夹中的所有文件都foo必须由myScript涉及文件夹所有元素的脚本处理bar

这是myScript

for f in bar/*
do
    awk 'NR==FNR{a[$0]=$0;next}!a[$0]' $f $1 > tmp
    cp tmp $1
done

用 for 循环处理所有文件的第一个想法是有效的:

for f in foo/*
do
    ./myScript $f
done

然而,这需要很长时间。简单地通过附加方式在后台启动每个 myScript&会创建数千个并行执行的 和 实例awk,并cp具有巨大的输入,这显然是不好的。

我想限制使用以下命令创建的“线程”的数量

for f in foo/*
do
    THREAD_COUNT=$(ps | wc -f)
    while [ $THREAD_COUNT -ge 12 ]
    do
        sleep 1
        THREAD_COUNT=$(ps | wc -f)
    done
    ./myScript $f &
done

附带说明:我正在与 12 进行比较,因为我的节点上有 8 个核心,并且显然总是有bash,正在运行pswc并且在调用 时的标题行也在运行ps | wc -l

不幸的是, 的调用myScript会导致 中出现多个附加条目ps,因此我的脚本的行为并不符合预期。

所以这是我的问题:有没有更简单的方法?哪种方式更稳定?

我没有在节点上做任何其他事情,所以发生的一切都是由脚本引起的。

答案1

虽然您可以使用 shell 脚本来完成此操作,但这却很困难。 Shell 脚本不太擅长操作多个后台作业。

我的建议是使用GNU 使或者其他版本的 make 可以-j选择并行执行多个作业。将每个子任务编写为 makefile 规则。

我认为下面的 makefile 片段实现了您的规则,但您的代码很难遵循,所以我现在可能已经得到了正确的结果。第一行枚举输入文件的输出文件(注意:永远不要覆盖任何输入文件!如果作业由于任何原因在中间停止,您最终将得到不知道是否已处理的数据) 。缩进行是要运行的命令。使用制表符缩进每个命令,而不是 8 个空格。在这些命令中,$<代表源文件(.in文件),$@代表目标文件(.out文件),并且$*是不带扩展名的目标。 shell 命令中的所有$符号都必须加倍,并且每个命令行都在单独的子 shell 中执行,除非您\在末尾添加 a 来取消换行符(因此 shell 会看到以 开头set -e和结尾的一长行done)。

all: $(patsubst %.in,%.out,$(wildcard foo/*.in))
%.out: %.in
        cp $< $*.tmp.in
        set -e; \
        for f in bar/*; do \
          awk 'NR==FNR{a[$$0]=$$0;next}!a[$$0]' $$f $*.tmp.in >$*.tmp.out; \
          mv $*.tmp.out $*.tmp.in; \
        done
        mv $*.tmp.in $@

Makefile将其放入名为并调用 的文件中make -j12

答案2

使用 GNU Parallel (http://www.gnu.org/software/parallel/),它看起来像这样:

parallel awk \'NR==FNR\{a\[\$0\]=\$0\;next\}\!a\[\$0\]\' {1} {2} '>{2}.tmp; mv {2}.tmp {2}' ::: bar/* ::: foo/*

这将为每个核心运行一项作业。用于-j150%每个核心运行 1.5 个作业。

如果您只想并行运行多个,myScript请执行以下操作:

parallel ./myScript ::: foo/*

观看介绍视频以了解更多信息:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

答案3

您可以尝试使用ulimit.来自 bash 手册页:

ulimit [-HSTabcdefilmnpqrstuvx [limit]]
Provides control over the resources available to the shell and to processes started  by  it, 
on systems  that  allow  such control.
[...]
-u     The maximum number of processes available to a single user

因此,如果您将其置于ulimit -u 8脚本内的适当位置,则会将该 shell 可用的进程限制为 8 个。

不过没有测试过。

相关内容