Bash: несколько для циклов в фоновом режиме

8

Это правильный способ запустить несколько последовательных обработок в фоновом режиме?

for i in {1..10}; do
    for j in {1..10}; do
        run_command $i $j;
    done &
done;

Все jдолжны быть обработаны после друг друга для данного i, но все iдолжны быть обработаны одновременно.

Контролируется радио
источник
Что вы подразумеваете под «правильным путем»?
Эран Бен-Натан
Главным образом это работает. Я пропустил это на stackoverflow.
Радиоуправление
1
:-) Я спрашиваю, потому что ваш код работает нормально для меня. Если под «правильным способом» вы подразумеваете лучшую практику, то я бы поместил внутренний цикл в функцию или даже в другой файл, чтобы он был более понятным
Эран Бен-Натан

Ответы:

8

Внешний цикл, который у вас есть, в основном

for i in {1..10}; do
    some_compound_command &
done

Это запустит десять одновременных экземпляров some_compound_commandв фоновом режиме. Они будут запущены настолько быстро, насколько это возможно, но не совсем «все одновременно» (то есть, если это some_compound_commandзанимает очень мало времени, первое может закончиться раньше, чем начнется последнее).

Тот факт, что some_compound_commandэто цикл, не важен. Это означает, что код, который вы показываете, верен в том jсмысле, что итерации внутреннего цикла будут выполняться последовательно, но все экземпляры внутреннего цикла (по одному на итерацию внешнего iцикла) будут запускаться одновременно.

Единственное, что нужно иметь в виду, это то, что каждое фоновое задание будет выполняться в подоболочке. Это означает, что изменения, внесенные в среду (например, изменения значений переменных оболочки, изменения текущего рабочего каталога с помощью cdи т. Д.) В одном экземпляре внутреннего цикла, не будут видны за пределами этого конкретного фонового задания.

Возможно, вы захотите добавить waitоператор после цикла, просто чтобы дождаться завершения всех фоновых заданий, по крайней мере, до завершения сценария:

for i in {1..10}; do
    for j in {1..10}; do
        run_command "$i" "$j"
    done &
done

wait
Кусалананда
источник
3

Если у вас есть GNU Parallel, вы бы сделали:

parallel -j0 'for j in {1..10}; do run_command {} $j; done' ::: {1..10}

Одним из преимуществ является то, что выход от параллельной работы run_commandsне будет смешиваться.

Оле Танге
источник