如何限制在bash脚本中运行的命令数量?

时间:2012-01-04 22:25:58

标签: bash

让我们假设我有一个执行代码的bash脚本:

for i in $LIST; do
 /path/to/my/script.sh $i &
done

正如您所看到的,我正在将这些脚本推送到后台,并允许父脚本尽可能快地执行尽可能多的命令。问题是我的系统最终会耗尽内存,因为这些命令需要大约15或20秒才能运行每个实例。

我正在运行一个静态script.sh文件,并将一个简单的变量(即客户编号)传递给脚本。我在任何特定的时间都有大约20,000到40,000条记录。

我的问题是,如何告诉系统只能同时运行X个script.sh实例。如果运行的太多,我想暂停脚本,直到脚本数低于阈值,然后继续。

有什么想法吗?

7 个答案:

答案 0 :(得分:5)

两个工具可以做到这一点

(注意我已更改了您的文件选择,因为我认为您应该准备处理奇怪的文件名,例如使用空格)

GNU xargs

find -iname '*.txt' -print0 | xargs -0 -r -n1 -P4 /path/to/my/script.sh

在4个处理器上并行运行

Xjobs

find -iname '*.txt' -print0 | xjobs -0 /path/to/my/script.sh

运行尽可能多的处理器。 Xjobs在分离各种作业的输出方面比xargs做得更好。

添加-j4以并行运行4个作业

答案 1 :(得分:3)

一个简单的hack就是创建一个Makefile来执行每个脚本并运行make -jX

all : $(LIST)

% : /path/to/my/script.sh
    $^ $*

一个不错的副作用是make会在脚本发生更改时自动检测,但为了使用它,你必须用一个模板替换%以获取任何输出文件的名称您的脚本为给定的输入参数生成(假设它是它的作用)。 E.g:

out.%.txt: /path…

答案 2 :(得分:2)

您应该将xargs与-P一起使用。像这样构建你的脚本:


echo "$LIST" | xargs -n1 -P $SIMULTANEOUS_JOBS /path/to/my/script.sh

SIMULTANEOUS_JOBS当然是您想要同时运行多少个命令。

答案 3 :(得分:1)

您可能对Joey Hess'moreutils包中的parallel命令感兴趣。[*]用法将是

parallel -j MAXJOBS /path/to/my/script.sh -- $LIST

[*]不要与更强大但更难用的混淆,GNU parallel

答案 4 :(得分:1)

仅限bash的解决方案:

MAXJOBS=<your-requested-max + 3>
for i in $LIST; do
 /path/to/my/script.sh $i &
 while true; do
   NUMJOBS=`ps --ppid $$ -o pid= | wc | awk -F ' ' '{ print $1;}'`
   test $NUMJOBS -lt $MAXJOBS && break
done

答案 5 :(得分:0)

GNU Parallel专为此类任务而设计:

parallel /path/to/my/script.sh ::: $LIST

这将在每个核心上运行一个script.sh。

观看介绍视频以了解更多信息:

http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

答案 6 :(得分:-2)

我总是喜欢为此做一点递归:

#!/bin/bash

max=3
procname="journal"

calltask()
{
    if [ "$(ps -ef | grep ${procname} | grep -v grep | wc -l)" -le "${max}" ]; then
       echo " starting new proc "
       calltask
    else
       echo "too many processes... going to sleep"
       sleep 5
       calltask
    fi
}

calltask