让我们假设我有一个执行代码的bash脚本:
for i in $LIST; do
/path/to/my/script.sh $i &
done
正如您所看到的,我正在将这些脚本推送到后台,并允许父脚本尽可能快地执行尽可能多的命令。问题是我的系统最终会耗尽内存,因为这些命令需要大约15或20秒才能运行每个实例。
我正在运行一个静态script.sh文件,并将一个简单的变量(即客户编号)传递给脚本。我在任何特定的时间都有大约20,000到40,000条记录。
我的问题是,如何告诉系统只能同时运行X个script.sh实例。如果运行的太多,我想暂停脚本,直到脚本数低于阈值,然后继续。
有什么想法吗?
答案 0 :(得分:5)
两个工具可以做到这一点
(注意我已更改了您的文件选择,因为我认为您应该准备处理奇怪的文件名,例如使用空格)
find -iname '*.txt' -print0 | xargs -0 -r -n1 -P4 /path/to/my/script.sh
在4个处理器上并行运行
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。
观看介绍视频以了解更多信息:
答案 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