我在一堆帐户上运行 Offlineimap,并希望检查每次运行的退出代码并相应地执行一些操作。
我有 6 个独立的电子邮件帐户,我在这些帐户上运行了大量代码重复。原来的命令结构是:
$ $(which offlineimap) -c offlineimaprc -o -a yahoo & declare yahoo_pid=$!
wait $yahoo_pid
yahoo_st=$?
if [[ $yahoo_st -ne 0 ]];then <do some stuff>
$ $(which offlineimap) -c offlineimaprc -o -a gmail & declare gmail_pid=$!
wait $gmail_pid
gmail_st=$?
if [[ $gmail_st -ne 0 ]];then <do some stuff>
现在我想删除重复项并从for in
循环和wait
命令中运行它。 ${account-name}_pid(例如 yahoo_pid)替换工作正常,但我被该wait
命令卡住了。
$ for app in yahoo gmail
do
$(which offlineimap) -c offlineimaprc -o -a ${app} & declare ${app/%/_pid}=$!
wait ${app}_pid
done
[1] 73443
-bash: wait: `$yahoo_pid': not a pid or valid job spec
[2] 73444
-bash: wait: `$gmail_pid': not a pid or valid job spec
答案1
app=(yahoo gmail)
# ...
declare ${app/%/_pid}=$!
上面的这个看起来很奇怪。虽然app
是一个数组,但仅引用$app
就会获取数组中的第一个元素,与 相同${arr[0]}
。所以总是会分配给yahoo_pid
.
$(eval echo \$${app}_st)=$?
这根本行不通。等号左侧的扩展使其成为无效赋值,shell 会将其作为命令处理。如果$yahoo_st
未设置,并且$?
是例如0
,它将尝试运行名为 的命令=0
。
无论如何,就你的情况而言。
Bash 有关联数组,即按字符串索引的数组,它们几乎正是您所需要的。它们需要用 声明declare -A
,常规数组可以像上面那样分配。
imap=$(which offlineimap)
apps=(yahoo gmail)
declare -A pids=()
declare -A st=()
for app in "${apps[@]}"; do
"$imap" -c offlineimaprc -o -a "$app" &
pids[$app]=$!
wait "${pids[$app]}"
st[$app]=$?
done
# and to check on them later:
for app in "${apps[@]}"; do
printf "app '%s' ran pid %s returning status %s\n" "$app" "${pids[$app]}" "${st[$app]}"
done
或者可能:
for app in "${apps[@]}"; do
"$imap" -c offlineimaprc -o -a "$app" &
pids[$app]=$!
done
for app in "${apps[@]}"; do
wait "${pids[$app]}"
st[$app]=$?
done
# ...
或者,您可以使用 namerefs 来引用另一个变量中命名的变量。这将设置pid_yahoo
和st_yahoo
:
app=yahoo
declare -n pid="pid_$app"
declare -n st="st_$app"
something... & pid=$!
wait "$pid"
st=$?
但实际上只是使用关联数组。
另请参见例如
答案2
从问题转移到答案
经过大量的搜索和示例才最终在这个上投入了资金,但最终对我有用的是:
app=(yahoo gmail)
$(which offlineimap) -c offlineimaprc -o -a ${app} & declare ${app/%/_pid}=$!
wait $(eval echo \$${app}_pid) <<== THIS IS THE MAGIC SYNTAX
$(eval echo \$${app}_st)=$? && if [[ $(eval echo \$${app}_st) -ne 0 ]];then error_msg ${app}; fi