Gio*_*ano 6 bash jobs background-process
我写了一个 bash 脚本,它执行一个 Java jar n次。
在实践中,我定义了 e foo()函数,包含对jar的调用,然后我运行这个脚本:
for RUN in $(seq 1 $RUNS)
do
foo &
done
Run Code Online (Sandbox Code Playgroud)
现在,我不想在jar中并行执行运行时间。等待限制并行执行的数量(例如每 10 个进程)?wait
小智 5
bash
4.4 版引入了一个有用的新习语,称为参数转换,可以在这种情况下为您提供帮助。在下面的代码片段中,请注意${num_jobs@P}
. 的@P
是一种类型的参数变换使得就好像它是一个变量被扩展bash
提示字符串。有关man bash
其他参数转换选项,请参阅。
#!/bin/bash
num_procs=$1
num_iters=$2
num_jobs="\j" # The prompt escape for number of jobs currently running
for ((i=0; i<num_iters; i++)); do
while (( ${num_jobs@P} >= num_procs )); do
wait -n
done
foo &
done
Run Code Online (Sandbox Code Playgroud)
在/sf/answers/2714305961/ 上感谢 chepner 。
按照 Kusalananda 的评论,如果需要,为了使这组进程独立于会影响计数的任何其他后台作业,您可以用它们自己的 shell 包装它们。为此,需要进行一些更改。
#!/bin/bash
# start a wrapper shell for the group of jobs
cat<<EOS | bash &
num_procs="$1"
num_iters="$2"
for ((i=0; i<num_iters; i++)); do
# escape what's not supposed to be expanded
# at the time of here-doc redirection
while (( \${num_jobs@P} >= num_procs )); do
wait -n
done
foo &
done
EOS
# now you can do other things
Run Code Online (Sandbox Code Playgroud)
for RUN in $(seq 1 $RUNS); do
foo &
if (( (RUN % 10) == 0 )); then
wait
fi
done
Run Code Online (Sandbox Code Playgroud)
或者,使用替代循环构造(恕我直言,看起来更好):
for (( r = 1; r <= RUNS; ++i )); do
foo &
if (( (r % 10) == 0 )); then
wait
fi
done
Run Code Online (Sandbox Code Playgroud)
如果不是 10 的倍数,您可能还需要wait
在循环后添加一个 lone 。$RUNS
除了RUNS
运行总数之外,我们还可以想象有n
10 个作业的批次:
for (( i = 0; i < n; ++i )); do
printf 'starting batch %d...\n' "$i"
for (( j = 0; j < 10; ++j )); do
foo &
done
echo 'waiting...'
wait
done
Run Code Online (Sandbox Code Playgroud)
使用xargs
并且没有显式的替代解决方案wait
:
seq 1 "$RUNS" | xargs -n 1 -P 10 foo
Run Code Online (Sandbox Code Playgroud)
然而,这会给进程一个可能不需要的foo
命令行参数(由 生成的整数之一)。seq
这消除了这个问题:
seq 1 "$RUNS" | xargs -n 1 -P 10 sh -c 'foo'
Run Code Online (Sandbox Code Playgroud)