Вопрос или проблема
Учитывая следующий скрипт:
if [[ -z "$DOWNLOAD_ONLY" || "$DOWNLOAD_ONLY" = *conditions* ]]; then
function get_condition {
curl -s "https://conditions.com" | jq '.included[].attributes | select(retracted)' | jq --arg item $2 '. + {item: $item}' > "$1_$2.json"
}
function conditions {
for item in `cat items.json | jq -r '.data[].id'`
do
get_condition $1 $item
done
jq -s '.' $1_*.json | jq 'reduce .[] as $item (retracted)' > "$1.json"
rm $1_*.json
}
curl "https://items.com" | jq '.' > "items.json"
for language in cs da de en es fr it nl pl pt sv zh
do
conditions $language &
done
wait
fi
Могу ли я добавить &
к get_condition $1 $item
, а затем вызвать wait
позже?
Я предполагаю, что проблема может заключаться в том, что ожидание в b
будет ждать все процессы, запущенные из сценария оболочки, что приведет к взаимной блокировке. Это не проблема, wait
ожидает детей текущей (под)оболочки; запуск b
в фоновом режиме заставляет его иметь свою собственную под-оболочку с собственным списком задач и дочерних процессов.
Так что
function b {
for n in `cat ok.txt`
do
a $1 $n &
done
wait
}
будет работать хорошо с этой точки зрения — b
будет ждать a
, которые он запустил, и только их.
.
Ответ или решение
Конечно, можно выполнить функцию в фоновом режиме из функции, которая уже выполняется в фоновом режиме. Ваша основная забота заключается в том, как управлять этими процессами, чтобы избежать возможных проблем, таких как блокировки.
Основные моменты:
-
Фоновое выполнение функций:
- Использование символа
&
для выполнения функций в фоновом режиме позволяет запускать несколько процессов одновременно, что является полезным для задач, требующих сетевых запросов или длительных операций ввода-вывода.
- Использование символа
-
Использование
wait
:- Команда
wait
используется для того, чтобы дождаться завершения процессов, запущенных в фоновом режиме. Важно понимать, что эта команда будет ожидать завершения дочерних процессов текущей оболочки или подосновы. Это значит, что вы можете безопасно запускать процессы в фоновом режиме из функции, и потом вызватьwait
для ожидания только этих дочерних процессов, избегая потенциальных блокировок.
- Команда
Ваш сценарий:
В приведённом вами коде, функция conditions
вызывает функцию get_condition
, и если добавить символ &
после вызова get_condition
, вы запустите этот процесс в фоновом режиме. Пример:
get_condition $1 $item &
Это позволит вашей функции conditions
продолжать выполнение и запускать несколько экземпляров get_condition
параллельно для различных элементов item
.
Последующий вызов wait
:
Каждая выполнение get_condition
будет происходить в своем дочернем процессе, и вызов wait
в функции conditions
будет ожидать завершения всех фоновых процессов, которые были инициированы этой функцией.
Таким образом, ваш код может выглядеть следующим образом:
function conditions {
for item in `cat items.json | jq -r '.data[].id'`
do
get_condition $1 $item &
done
wait
jq -s '.' $1_*.json | jq 'reduce .[] as $item (retracted)' > "$1.json"
rm $1_*.json
}
Что учесть:
-
Конкуренция за ресурсы: Если функции
get_condition
делают множество сетевых запросов одновременно, это может привести к превышению лимитов API или к сильной нагрузке на сеть. Применение задержек (например,sleep
) между запусками может помочь смягчить эту проблему. -
Ошибки и обработка исключений: Учтите, что даже в фоновом режиме ошибки могут произойти в запущенных функциях. Убедитесь, что вы обрабатываете возможные ошибки или добавляете механизмы повторного запуска по мере необходимости.
Заключение:
С добавлением &
к вызову get_condition
и использованием wait
для ожидания этих фоновый процессов, вы сможете добиться требуемого поведения без угрозы блокировок. Это подход, который позволяет эффективно управлять многопоточными операциями в Bash-скрипте, повышая производительность и отзывчивость вашего приложения.