最大限度地占用(I的运行上的东西Debian Lenny t2)我有一个简单的脚本来启动的工作平行:

#!/bin/bash

for i in apache-200901*.log; do echo "Processing $i ..."; do_something_important; done &
for i in apache-200902*.log; do echo "Processing $i ..."; do_something_important; done &
for i in apache-200903*.log; do echo "Processing $i ..."; do_something_important; done &
for i in apache-200904*.log; do echo "Processing $i ..."; do_something_important; done &
...

我很满意这个工作方案,但是我不知道如何写进一步的代码,其中只有执行一旦所有的循环已经完成。

有没有办法得到控制这个吗?

有帮助吗?

解决方案

有一个bash内建命令为该。

wait [n ...]
      Wait for each specified process and return its termination  sta‐
      tus.   Each  n  may be a process ID or a job specification; if a
      job spec is given, all processes  in  that  job’s  pipeline  are
      waited  for.  If n is not given, all currently active child pro‐
      cesses are waited for, and the return  status  is  zero.   If  n
      specifies  a  non-existent  process or job, the return status is
      127.  Otherwise, the return status is the  exit  status  of  the
      last process or job waited for.

其他提示

使用GNU平行会让你的脚本中甚至更短的和可能更加有效:

parallel 'echo "Processing "{}" ..."; do_something_important {}' ::: apache-*.log

这将运行一个工作每CPU核心,并继续做,直到所有文件的处理。

你的解决方案将基本上是分裂该工作组成之前在运行。这里32工作4小组:

Simple scheduling

GNU平行,而不是产生一个新的进程时,一个完成保留的Cpu活性,从而节省时间:

GNU Parallel scheduling

要了解更多信息:

我不得不这样做,最近结束了与以下方案:

while true; do
  wait -n || {
    code="$?"
    ([[ $code = "127" ]] && exit 0 || exit "$code")
    break
  }
done;

在这里,它是如何工作:

wait -n 退出后尽快之一(可能多的)背景的工作退出。它始终的计算结果为真正的和循环下去,直至发生下述任何一种情形:

  1. 出口码 127:最后一背景工作成功退出。在 这种情况下,我们忽略的出口码和出口子壳的代码 0.
  2. 任何背景的工作失败。我们只是退出子壳,退出的代码。

set -e, 这将保证该脚本将终止早期,并通过出口码的任何失败的背景工作。

这是我的粗溶液:

function run_task {
        cmd=$1
        output=$2
        concurency=$3
        if [ -f ${output}.done ]; then
                # experiment already run
                echo "Command already run: $cmd. Found output $output"
                return
        fi
        count=`jobs -p | wc -l`
        echo "New active task #$count:  $cmd > $output"
        $cmd > $output && touch $output.done &
        stop=$(($count >= $concurency))
        while [ $stop -eq 1 ]; do
                echo "Waiting for $count worker threads..."
                sleep 1
                count=`jobs -p | wc -l`
                stop=$(($count > $concurency))
        done
}

我们的想法是用“工作”,看看有多少孩子都在后台继续运行,等到这个数字下降(孩子退出)。一旦发现孩子存在,接下来的工作就可以开始。

可以看到,还存在一些额外的逻辑,以避免运行相同的实验/命令多次。它确实对我来说工作。然而,这样的逻辑可以是任一跳过或进一步改进(例如,检查文件创建时间戳,输入参数,等)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top