Как вызвать несколько функций одновременно в bash [duplicate]

У меня есть другая перспектива ответить на это.

При работе на разных уровнях, например, в приложении MVC, контроллеру нужны службы для вызова бизнес-операций. В таких сценариях контейнер инжекции зависимостей может использоваться для инициализации служб, чтобы исключить исключение NullReferenceException. Это означает, что вам не нужно беспокоиться о проверке нулевого значения и просто вызвать службы с контроллера, как будто они всегда будут доступны (и инициализированы) как одиночный или прототип.

public class MyController
{
    private ServiceA serviceA;
    private ServiceB serviceB;

    public MyController(ServiceA serviceA, ServiceB serviceB)
    {
        this.serviceA = serviceA;
        this.serviceB = serviceB;
    }

    public void MyMethod()
    {
        // We don't need to check null because the dependency injection container 
        // injects it, provided you took care of bootstrapping it.
        var someObject = serviceA.DoThis();
    }
}
42
задан mark 15 July 2009 в 14:44
поделиться

3 ответа

Это мое грубое решение:

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
}

Идея состоит в том, чтобы использовать «задания», чтобы узнать, сколько детей активно в фоновом режиме и ждать, пока это число не упадет (ребенок выйдет). После того, как ребенок существует, можно запустить следующую задачу.

Как вы можете видеть, существует также немного дополнительной логики, чтобы избежать одновременного запуска одних и тех же экспериментов / команд. Он выполняет эту работу для меня. Однако эта логика может быть либо пропущена, либо улучшена (например, отметьте отметки времени создания файла, параметры ввода и т. Д.).

69
ответ дан muru 3 September 2018 в 14:33
поделиться
  • 1
    Это было быстро и решило мою проблему, хорошо заработанную, спасибо! – mark 15 July 2009 в 15:03
  • 2
    подскажите использовать wait $(jobs -p) для ожидания новых созданных заданий. – lambacck 27 April 2016 в 14:31
  • 3
    спасибо @lambacck – pabloa98 19 October 2016 в 23:11
  • 4
    @lambacck не wait без эквивалента аргументов? – Olivier Lalonde 4 May 2017 в 06:25
  • 5
    Или используйте wait $(jobs -rp), если у вас есть другие заданные задания (например, когда вы приостановили vim с помощью Ctrl + Z): дополнительный флаг -r отфильтровывает задания running . – Luc 5 May 2018 в 22:33

Использование GNU Parallel сделает ваш скрипт еще короче и, возможно, более эффективным:

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

Это запустит одно задание на ядро ​​процессора и продолжит это делать до тех пор, пока все файлы не будут обработаны.

Ваше решение будет в основном разделять задания на группы перед запуском. Здесь 32 задания в 4 группах:

Simple scheduling [/g1]

GNU Parallel вместо этого запускает новый процесс, когда заканчивается - сохранение активных CPU и, следовательно, экономия времени:

GNU Parallel scheduling [/g2]

Чтобы узнать больше:

21
ответ дан Cœur 3 September 2018 в 14:33
поделиться

Я должен был сделать это недавно и получил следующее решение:

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

Вот как это работает:

wait -n завершается, как только один из ( потенциально много) фоновые задания завершаются. Он всегда оценивает значение true, и цикл продолжается до:

  1. Код выхода 127: последнее фоновое задание успешно завершено. В этом случае мы игнорируем код выхода и выходим из под-оболочки с кодом 0.
  2. Любое из фоновых заданий не удалось. Мы просто выходим из под-оболочки с этим кодом выхода.

С помощью set -e это гарантирует, что сценарий закончится раньше и пройдет через код выхода любого неудачного фонового задания.

2
ответ дан Olivier Lalonde 3 September 2018 в 14:33
поделиться