我正在寻找一种并行运行函数并准确知道所有函数实例何时完成的方法。 我添加了一个微调器(函数的实例运行不同的时间,取决于变量,所以我需要在屏幕上看到一些东西)并按以下方式尝试:
for a in "${ARRAY[@]}"; do
spin='/-\|'
while true; do
i=$(( (i+1) %4 )); printf "\r[ ${spin:$i:1} ] "; sleep .3;
done & someFunction &
kill $!; trap 'kill $!' SIGTERM
done
但是
someFunction
不起作用。我认为是因为如果它被触发为 someFunction &
它会立即被下一个代码行杀死。而且脚本结束后,旋转器将在 CLI 上永远工作。
如何同时运行
someFunction
,等到最后一个实例完成,并保持旋转直到那时?
您需要跟踪您已分叉的进程,然后为它们进行
wait
。 wait
命令非常灵活,还可以一次等待所有后台作业(而不是一个接一个)或仅等待特定作业。请参阅 man bash
,第 SHELL BUILTIN COMMANDS
部分。以下脚本启动一个旋转器,每秒打印一些内容,然后分叉出 5 个睡眠不同时间的进程。
spinner() { for ((;;)); do sleep 1; printf '<spin>'; done; }
someFunction() { sleep "$1"; }
spinner &
spinner_pid="$!"
for ((i = 2; i < 12; i += 2)); do
someFunction "$i"&
function_pids["$!"]="$i"
done
while ((${#function_pids[@]})); do
wait -n -p pid && echo -n 'finished: ' || echo -n 'failed: '
echo "${function_pids[pid]}"
unset 'function_pids[pid]'
done
kill -TERM "$spinner_pid"
wait -n "$spinner_pid" || :
由于 Bash 管理后台进程的方式,通过 PID 杀死进程通常有很小的可能性会杀死错误的进程。如果您使用的是 Bash 4.3(2014 年发布)或更高版本,请尝试此免杀代码:
#! /bin/bash -p
# FIXME: Define the 'args' array and the 'someFunction' function
# Run a spinner as a coprocess
coproc spinner \
{
declare -r spin='/-\|'
declare i=0
while read -r -t 0.3 _; (( $? > 128 )); do
printf '\r[ %s ] ' "${spin:i++%4:1}" >&2
done
}
# Disown the spinner coprocess so 'wait' will not wait for it to exit
disown %%
for a in "${args[@]}"; do
someFunction "$a" &
done
# Wait for all background processes (except the disowned spinner) to exit
wait
# Close the pipe to the spinner. It will read EOF and close.
exec {spinner[1]}>&-
read -r -t 0.3 _
在0.3秒内未能读取输入行,则会返回大于128的状态。使用 read
而不是 sleep
来表示微调器中的延迟,可以避免每次延迟都运行子进程,从而节省资源。ARRAY
替换为 args
。我觉得大家有点想多了...
(
for a in "${ARRAY[@]}"; do
someFunction &
done
wait
) &
GRP=$!
spin='/-\|'
while true
do
i=$(( (i+1) %4 )); printf "\r[ ${spin:$i:1} ] "
done &
SPINNER=$!
wait $GRP
kill $SPINNER