如何在bash脚本中等待从该脚本生成的几个子进程完成并返回退出代码!= 0当任何子进程以代码结束时!= 0?
简单的脚本:
#!/bin/bash
for i in `seq 0 9`; do
doCalculations $i &
done
wait
上面的脚本将等待所有10个生成的子进程,但它总是会给出退出状态0(参见help wait
)。如何修改此脚本,以便它发现生成的子进程的退出状态,并在任何子进程以代码结束时返回退出代码1!= 0?
有没有更好的解决方案,而不是收集子流程的PID,按顺序等待它们并汇总退出状态?
答案 0 :(得分:429)
wait
也(可选)使进程的PID等待,并使用$!你得到在后台启动的最后一个命令的PID。
修改循环以将每个生成的子进程的PID存储到一个数组中,然后再次循环等待每个PID。
# run processes and store pids in array
for i in $n_procs; do
./procs[${i}] &
pids[${i}]=$!
done
# wait for all pids
for pid in ${pids[*]}; do
wait $pid
done
答案 1 :(得分:268)
http://jeremy.zawodny.com/blog/archives/010717.html:
#!/bin/bash
FAIL=0
echo "starting"
./sleeper 2 0 &
./sleeper 2 1 &
./sleeper 3 0 &
./sleeper 2 0 &
for job in `jobs -p`
do
echo $job
wait $job || let "FAIL+=1"
done
echo $FAIL
if [ "$FAIL" == "0" ];
then
echo "YAY!"
else
echo "FAIL! ($FAIL)"
fi
答案 2 :(得分:45)
如果你安装了GNU Parallel,你可以这样做:
# If doCalculations is a function
export -f doCalculations
seq 0 9 | parallel doCalculations {}
GNU Parallel将为您提供退出代码:
0 - 所有作业都运行正常。
1-253 - 部分工作失败。退出状态提供失败作业的数量
254 - 超过253个职位失败。
255 - 其他错误。
观看介绍视频以了解详情:http://pi.dk/1
答案 3 :(得分:39)
这是我到目前为止所提出的。如果孩子终止,我想看看如何中断sleep命令,这样就不必将WAITALL_DELAY
调整为一个人的使用。
waitall() { # PID...
## Wait for children to exit and indicate whether all exited with 0 status.
local errors=0
while :; do
debug "Processes remaining: $*"
for pid in "$@"; do
shift
if kill -0 "$pid" 2>/dev/null; then
debug "$pid is still alive."
set -- "$@" "$pid"
elif wait "$pid"; then
debug "$pid exited with zero exit status."
else
debug "$pid exited with non-zero exit status."
((++errors))
fi
done
(("$#" > 0)) || break
# TODO: how to interrupt this sleep when a child terminates?
sleep ${WAITALL_DELAY:-1}
done
((errors == 0))
}
debug() { echo "DEBUG: $*" >&2; }
pids=""
for t in 3 5 4; do
sleep "$t" &
pids="$pids $!"
done
waitall $pids
答案 4 :(得分:37)
简单地说:
#!/bin/bash
pids=""
for i in `seq 0 9`; do
doCalculations $i &
pids="$pids $!"
done
wait $pids
...code continued here ...
<强>更新强>
正如多个评论者指出的那样,上面等待所有进程在继续之前完成,但如果其中一个失败则不会退出和失败,可以使用@Bryan,@ SamBrightman建议的以下修改来完成和其他人:
#!/bin/bash
pids=""
RESULT=0
for i in `seq 0 9`; do
doCalculations $i &
pids="$pids $!"
done
for pid in $pids; do
wait $pid || let "RESULT=1"
done
if [ "$RESULT" == "1" ];
then
exit 1
fi
...code continued here ...
答案 5 :(得分:30)
以下是使用wait
的简单示例。
运行一些流程:
$ sleep 10 &
$ sleep 10 &
$ sleep 20 &
$ sleep 20 &
然后使用wait
命令等待它们:
$ wait < <(jobs -p)
或只是wait
(没有参数)。
这将等待后台的所有工作完成。
如果提供了-n
选项,则等待下一个作业终止并返回其退出状态。
请参阅:help wait
和help jobs
了解语法。
然而,缺点是这只会返回最后一个ID的状态,因此您需要检查每个子流程的状态并将其存储在变量中。
或者让你的计算函数在失败时创建一些文件(空或失败日志),然后检查该文件是否存在,例如
$ sleep 20 && true || tee fail &
$ sleep 20 && false || tee fail &
$ wait < <(jobs -p)
$ test -f fail && echo Calculation failed.
答案 6 :(得分:17)
要并行化......
for i in $(whatever_list) ; do
do_something $i
done
将其翻译为此...
for i in $(whatever_list) ; do echo $i ; done | ## execute in parallel...
(
export -f do_something ## export functions (if needed)
export PATH ## export any variables that are required
xargs -I{} --max-procs 0 bash -c ' ## process in batches...
{
echo "processing {}" ## optional
do_something {}
}'
)
--max-procs
(0
表示“一次性”)。xargs
时提供了一些其他功能 - 但默认情况下并不总是安装。for
循环不是必需的,因为echo $i
基本上只是重新生成$(whatever_list
的输出。我只是认为使用for
关键字可以让您更容易看到发生了什么。这是一个简化的工作示例......
for i in {0..5} ; do echo $i ; done |xargs -I{} --max-procs 2 bash -c '
{
echo sleep {}
sleep 2s
}'
答案 7 :(得分:7)
我认为Bash的内置功能无法实现。
您可以在孩子退出时收到通知:
#!/bin/sh
set -o monitor # enable script job control
trap 'echo "child died"' CHLD
然而,没有明显的方法可以让孩子在信号处理程序中退出状态。
获取子级状态通常是较低级别POSIX API中wait
系列函数的作用。不幸的是,Bash对此的支持是有限的 - 您可以等待一个特定的子进程(并获得其退出状态),或者您可以等待所有,并始终获得0结果。
看起来不可能做的是等同于waitpid(-1)
,它会阻止任何子进程返回。
答案 8 :(得分:7)
我看到很多很好的例子列在这里,也想把我的东西扔进去。
#! /bin/bash
items="1 2 3 4 5 6"
pids=""
for item in $items; do
sleep $item &
pids+="$! "
done
for pid in $pids; do
wait $pid
if [ $? -eq 0 ]; then
echo "SUCCESS - Job $pid exited with a status of $?"
else
echo "FAILED - Job $pid exited with a status of $?"
fi
done
我使用与启动/停止服务器/服务非常类似的东西并检查每个退出状态。对我来说很棒。希望这可以帮助别人!
答案 9 :(得分:5)
这是我的版本适用于多个pid,如果执行时间太长则记录警告,如果执行时间超过给定值,则停止子进程。
function WaitForTaskCompletion {
local pids="${1}" # pids to wait for, separated by semi-colon
local soft_max_time="${2}" # If execution takes longer than $soft_max_time seconds, will log a warning, unless $soft_max_time equals 0.
local hard_max_time="${3}" # If execution takes longer than $hard_max_time seconds, will stop execution, unless $hard_max_time equals 0.
local caller_name="${4}" # Who called this function
local exit_on_error="${5:-false}" # Should the function exit program on subprocess errors
Logger "${FUNCNAME[0]} called by [$caller_name]."
local soft_alert=0 # Does a soft alert need to be triggered, if yes, send an alert once
local log_ttime=0 # local time instance for comparaison
local seconds_begin=$SECONDS # Seconds since the beginning of the script
local exec_time=0 # Seconds since the beginning of this function
local retval=0 # return value of monitored pid process
local errorcount=0 # Number of pids that finished with errors
local pidCount # number of given pids
IFS=';' read -a pidsArray <<< "$pids"
pidCount=${#pidsArray[@]}
while [ ${#pidsArray[@]} -gt 0 ]; do
newPidsArray=()
for pid in "${pidsArray[@]}"; do
if kill -0 $pid > /dev/null 2>&1; then
newPidsArray+=($pid)
else
wait $pid
result=$?
if [ $result -ne 0 ]; then
errorcount=$((errorcount+1))
Logger "${FUNCNAME[0]} called by [$caller_name] finished monitoring [$pid] with exitcode [$result]."
fi
fi
done
## Log a standby message every hour
exec_time=$(($SECONDS - $seconds_begin))
if [ $((($exec_time + 1) % 3600)) -eq 0 ]; then
if [ $log_ttime -ne $exec_time ]; then
log_ttime=$exec_time
Logger "Current tasks still running with pids [${pidsArray[@]}]."
fi
fi
if [ $exec_time -gt $soft_max_time ]; then
if [ $soft_alert -eq 0 ] && [ $soft_max_time -ne 0 ]; then
Logger "Max soft execution time exceeded for task [$caller_name] with pids [${pidsArray[@]}]."
soft_alert=1
SendAlert
fi
if [ $exec_time -gt $hard_max_time ] && [ $hard_max_time -ne 0 ]; then
Logger "Max hard execution time exceeded for task [$caller_name] with pids [${pidsArray[@]}]. Stopping task execution."
kill -SIGTERM $pid
if [ $? == 0 ]; then
Logger "Task stopped successfully"
else
errrorcount=$((errorcount+1))
fi
fi
fi
pidsArray=("${newPidsArray[@]}")
sleep 1
done
Logger "${FUNCNAME[0]} ended for [$caller_name] using [$pidCount] subprocesses with [$errorcount] errors."
if [ $exit_on_error == true ] && [ $errorcount -gt 0 ]; then
Logger "Stopping execution."
exit 1337
else
return $errorcount
fi
}
# Just a plain stupid logging function to replace with yours
function Logger {
local value="${1}"
echo $value
}
示例,等待所有三个进程完成,如果执行时间超过5秒则记录警告,如果执行时间超过120秒则停止所有进程。不要在失败时退出程序。
function something {
sleep 10 &
pids="$!"
sleep 12 &
pids="$pids;$!"
sleep 9 &
pids="$pids;$!"
WaitForTaskCompletion $pids 5 120 ${FUNCNAME[0]} false
}
# Launch the function
someting
答案 10 :(得分:5)
如果任何 doCalculations 失败,以下代码将等待所有计算完成并返回退出状态1。
#!/bin/bash
for i in $(seq 0 9); do
(doCalculations $i >&2 & wait %1; echo $?) &
done | grep -qv 0 && exit 1
答案 11 :(得分:5)
只需将结果存储在shell中,例如在文件中。
#!/bin/bash
tmp=/tmp/results
: > $tmp #clean the file
for i in `seq 0 9`; do
(doCalculations $i; echo $i:$?>>$tmp)&
done #iterate
wait #wait until all ready
sort $tmp | grep -v ':0' #... handle as required
答案 12 :(得分:4)
如果您有bash 4.2或更高版本,则以下内容可能对您有用。它使用关联数组来存储任务名称及其“代码”以及任务名称及其pid。我还内置了一个简单的速率限制方法,如果你的任务消耗大量的CPU或I / O时间并且你想要限制并发任务的数量,那么它可能会派上用场。
脚本在第一个循环中启动所有任务,并在第二个循环中使用结果。
对于简单的情况,这有点过分,但它允许非常整洁的东西。例如,可以将每个任务的错误消息存储在另一个关联数组中,并在一切安定下来后打印它们。
#! /bin/bash
main () {
local -A pids=()
local -A tasks=([task1]="echo 1"
[task2]="echo 2"
[task3]="echo 3"
[task4]="false"
[task5]="echo 5"
[task6]="false")
local max_concurrent_tasks=2
for key in "${!tasks[@]}"; do
while [ $(jobs 2>&1 | grep -c Running) -ge "$max_concurrent_tasks" ]; do
sleep 1 # gnu sleep allows floating point here...
done
${tasks[$key]} &
pids+=(["$key"]="$!")
done
errors=0
for key in "${!tasks[@]}"; do
pid=${pids[$key]}
local cur_ret=0
if [ -z "$pid" ]; then
echo "No Job ID known for the $key process" # should never happen
cur_ret=1
else
wait $pid
cur_ret=$?
fi
if [ "$cur_ret" -ne 0 ]; then
errors=$(($errors + 1))
echo "$key (${tasks[$key]}) failed."
fi
done
return $errors
}
main
答案 13 :(得分:4)
我刚刚将脚本修改为后台并将进程并行化。
我做了一些实验(在Solaris上同时使用bash和ksh)并发现'wait'输出退出状态(如果它不为零),或者在没有提供PID参数时返回非零退出的作业列表。 E.g。
击:
$ sleep 20 && exit 1 &
$ sleep 10 && exit 2 &
$ wait
[1]- Exit 2 sleep 20 && exit 2
[2]+ Exit 1 sleep 10 && exit 1
KSH:
$ sleep 20 && exit 1 &
$ sleep 10 && exit 2 &
$ wait
[1]+ Done(2) sleep 20 && exit 2
[2]+ Done(1) sleep 10 && exit 1
此输出写入stderr,因此OPs示例的简单解决方案可能是:
#!/bin/bash
trap "rm -f /tmp/x.$$" EXIT
for i in `seq 0 9`; do
doCalculations $i &
done
wait 2> /tmp/x.$$
if [ `wc -l /tmp/x.$$` -gt 0 ] ; then
exit 1
fi
虽然这个:
wait 2> >(wc -l)
也将返回一个计数但没有tmp文件。这也可以这种方式使用,例如:
wait 2> >(if [ `wc -l` -gt 0 ] ; then echo "ERROR"; fi)
但这并不比tmp文件IMO更有用。我找不到避免tmp文件的有用方法,同时也避免在子shell中运行“等待”,这根本不起作用。
答案 14 :(得分:3)
这项工作,应该是一个好的,如果不是比@HoverHell的答案更好!
#!/usr/bin/env bash
set -m # allow for job control
EXIT_CODE=0; # exit code of overall script
function foo() {
echo "CHLD exit code is $1"
echo "CHLD pid is $2"
echo $(jobs -l)
for job in `jobs -p`; do
echo "PID => ${job}"
wait ${job} || echo "At least one test failed with exit code => $?" ; EXIT_CODE=1
done
}
trap 'foo $? $$' CHLD
DIRN=$(dirname "$0");
commands=(
"{ echo "foo" && exit 4; }"
"{ echo "bar" && exit 3; }"
"{ echo "baz" && exit 5; }"
)
clen=`expr "${#commands[@]}" - 1` # get length of commands - 1
for i in `seq 0 "$clen"`; do
(echo "${commands[$i]}" | bash) & # run the command via bash in subshell
echo "$i ith command has been issued as a background job"
done
# wait for all to finish
wait;
echo "EXIT_CODE => $EXIT_CODE"
exit "$EXIT_CODE"
# end
当然,我已经在NPM项目中永久化了这个脚本,它允许你并行运行bash命令,对于测试非常有用:
答案 15 :(得分:3)
我已经完成了这项工作,并结合了其他示例中的所有最佳部分。当任何后台进程退出时,此脚本将执行checkpids
函数,并输出退出状态而不依赖于轮询。
#!/bin/bash
set -o monitor
sleep 2 &
sleep 4 && exit 1 &
sleep 6 &
pids=`jobs -p`
checkpids() {
for pid in $pids; do
if kill -0 $pid 2>/dev/null; then
echo $pid is still alive.
elif wait $pid; then
echo $pid exited with zero exit status.
else
echo $pid exited with non-zero exit status.
fi
done
echo
}
trap checkpids CHLD
wait
答案 16 :(得分:3)
#!/bin/bash
set -m
for i in `seq 0 9`; do
doCalculations $i &
done
while fg; do true; done
set -m
允许您使用fg&amp;脚本中的bg fg
,除了将最后一个进程放在前台之外,还具有与前景进程相同的退出状态while fg
以非零退出状态退出时,fg
将停止循环不幸的是,当后台进程以非零退出状态退出时,这将无法处理。 (循环不会立即终止。它将等待先前的进程完成。)
答案 17 :(得分:2)
除了所有标准信号之外。
答案 18 :(得分:2)
set -e
fail () {
touch .failure
}
expect () {
wait
if [ -f .failure ]; then
rm -f .failure
exit 1
fi
}
sleep 2 || fail &
sleep 2 && false || fail &
sleep 2 || fail
expect
顶部的set -e
会使您的脚本失败。
expect
将返回1
。
答案 19 :(得分:2)
等待所有作业,并返回上一个失败的作业的退出代码。与上述解决方案不同,这不需要pid保存。刚走开,然后等待。
function wait_ex {
# this waits for all jobs and returns the exit code of the last failing job
ecode=0
while true; do
wait -n
err="$?"
[ "$err" == "127" ] && break
[ "$err" != "0" ] && ecode="$err"
done
return $ecode
}
答案 20 :(得分:2)
这里已经有很多答案,但我很惊讶似乎没有人建议使用数组......所以这就是我所做的 - 这可能对将来有些人有用。
n=10 # run 10 jobs
c=0
PIDS=()
while true
my_function_or_command &
PID=$!
echo "Launched job as PID=$PID"
PIDS+=($PID)
(( c+=1 ))
# required to prevent any exit due to error
# caused by additional commands run which you
# may add when modifying this example
true
do
if (( c < n ))
then
continue
else
break
fi
done
# collect launched jobs
for pid in "${PIDS[@]}"
do
wait $pid || echo "failed job PID=$pid"
done
答案 21 :(得分:1)
等待几个子进程并在其中任何一个以非零状态代码退出时退出的解决方案是使用'wait -n'
~/.bash_history
状态代码“ 127”用于不存在的进程,这意味着孩子可能已经退出。
答案 22 :(得分:1)
正是出于这个目的,我编写了一个名为bash
的{{1}}函数。
注意::for
不仅保留并返回失败函数的退出代码,而且终止所有并行运行的实例。在这种情况下可能不需要。
:for
#!/usr/bin/env bash
# Wait for pids to terminate. If one pid exits with
# a non zero exit code, send the TERM signal to all
# processes and retain that exit code
#
# usage:
# :wait 123 32
function :wait(){
local pids=("$@")
[ ${#pids} -eq 0 ] && return $?
trap 'kill -INT "${pids[@]}" &>/dev/null || true; trap - INT' INT
trap 'kill -TERM "${pids[@]}" &>/dev/null || true; trap - RETURN TERM' RETURN TERM
for pid in "${pids[@]}"; do
wait "${pid}" || return $?
done
trap - INT RETURN TERM
}
# Run a function in parallel for each argument.
# Stop all instances if one exits with a non zero
# exit code
#
# usage:
# :for func 1 2 3
#
# env:
# FOR_PARALLEL: Max functions running in parallel
function :for(){
local f="${1}" && shift
local i=0
local pids=()
for arg in "$@"; do
( ${f} "${arg}" ) &
pids+=("$!")
if [ ! -z ${FOR_PARALLEL+x} ]; then
(( i=(i+1)%${FOR_PARALLEL} ))
if (( i==0 )) ;then
:wait "${pids[@]}" || return $?
pids=()
fi
fi
done && [ ${#pids} -eq 0 ] || :wait "${pids[@]}" || return $?
}
:
for.sh
#!/usr/bin/env bash
set -e
# import :for from gist: https://gist.github.com/Enteee/c8c11d46a95568be4d331ba58a702b62#file-for
# if you don't like curl imports, source the actual file here.
source <(curl -Ls https://gist.githubusercontent.com/Enteee/c8c11d46a95568be4d331ba58a702b62/raw/)
msg="You should see this three times"
:(){
i="${1}" && shift
echo "${msg}"
sleep 1
if [ "$i" == "1" ]; then sleep 1
elif [ "$i" == "2" ]; then false
elif [ "$i" == "3" ]; then
sleep 3
echo "You should never see this"
fi
} && :for : 1 2 3 || exit $?
echo "You should never see this"
答案 23 :(得分:1)
诱捕CHLD信号可能无效,因为如果它们同时到达,您可能会丢失一些信号。
#!/bin/bash
trap 'rm -f $tmpfile' EXIT
tmpfile=$(mktemp)
doCalculations() {
echo start job $i...
sleep $((RANDOM % 5))
echo ...end job $i
exit $((RANDOM % 10))
}
number_of_jobs=10
for i in $( seq 1 $number_of_jobs )
do
( trap "echo job$i : exit value : \$? >> $tmpfile" EXIT; doCalculations ) &
done
wait
i=0
while read res; do
echo "$res"
let i++
done < "$tmpfile"
echo $i jobs done !!!
答案 24 :(得分:1)
我需要这个,但目标进程不是当前shell的子进程,在这种情况下wait $PID
不起作用。我找到了以下替代方案:
while [ -e /proc/$PID ]; do sleep 0.1 ; done
这取决于 procfs 的存在,这可能不可用(例如,Mac不提供它)。因此,为了便于携带,您可以使用它:
while ps -p $PID >/dev/null ; do sleep 0.1 ; done
答案 25 :(得分:1)
我最近用过这个(感谢Alnitak):
#!/bin/bash
# activate child monitoring
set -o monitor
# locking subprocess
(while true; do sleep 0.001; done) &
pid=$!
# count, and kill when all done
c=0
function kill_on_count() {
# you could kill on whatever criterion you wish for
# I just counted to simulate bash's wait with no args
[ $c -eq 9 ] && kill $pid
c=$((c+1))
echo -n '.' # async feedback (but you don't know which one)
}
trap "kill_on_count" CHLD
function save_status() {
local i=$1;
local rc=$2;
# do whatever, and here you know which one stopped
# but remember, you're called from a subshell
# so vars have their values at fork time
}
# care must be taken not to spawn more than one child per loop
# e.g don't use `seq 0 9` here!
for i in {0..9}; do
(doCalculations $i; save_status $i $?) &
done
# wait for locking subprocess to be killed
wait $pid
echo
从那里可以轻松推断,并有一个触发器(触摸文件,发送信号)并更改计数标准(触摸计数文件,或其他)以响应该触发器。或者,如果您只想要“任何”非零rc,只需从save_status中取消锁定。
答案 26 :(得分:0)
在等待该过程之前,可能会完成该过程。如果我们触发等待已经完成的进程,它将触发错误,例如pid不是此外壳的子级。为了避免这种情况,可以使用以下函数查找该过程是否完成:
isProcessComplete(){
PID=$1
while [ -e /proc/$PID ]
do
echo "Process: $PID is still running"
sleep 5
done
echo "Process $PID has finished"
}
答案 27 :(得分:0)
我认为并行运行作业并检查状态的最直接方法是使用临时文件。已经有几个类似的答案(例如Nietzche-jou和mug896)。
#!/bin/bash
rm -f fail
for i in `seq 0 9`; do
doCalculations $i || touch fail &
done
wait
! [ -f fail ]
上面的代码不是线程安全的。如果您担心上面的代码将与其本身同时运行,则最好使用更唯一的文件名,例如fail。$$。最后一行是满足要求的:“当任何子进程以代码!= 0结尾时,返回退出代码1”。我在那里提出了一个额外的要求进行清理。这样写可能更清楚了:
#!/bin/bash
trap 'rm -f fail.$$' EXIT
for i in `seq 0 9`; do
doCalculations $i || touch fail.$$ &
done
wait
! [ -f fail.$$ ]
这里有一个类似的代码片段,用于收集来自多个作业的结果:我创建了一个临时目录,将所有子任务的输出放在一个单独的文件中,然后将它们转储以进行检查。这与问题不完全匹配-我将其作为奖励:
#!/bin/bash
trap 'rm -fr $WORK' EXIT
WORK=/tmp/$$.work
mkdir -p $WORK
cd $WORK
for i in `seq 0 9`; do
doCalculations $i >$i.result &
done
wait
grep $ * # display the results with filenames and contents
答案 28 :(得分:0)
这是我使用的东西:
#wait for jobs
for job in `jobs -p`; do wait ${job}; done
答案 29 :(得分:0)
我几乎陷入了使用jobs -p
来收集PID的陷阱,如果孩子已经退出,这是行不通的,如下面的脚本所示。我选择的解决方案只是简单地调用了wait -n
N次,其中N是我所拥有的孩子的数量,而我恰好是确定性地知道。
#!/usr/bin/env bash
sleeper() {
echo "Sleeper $1"
sleep $2
echo "Exiting $1"
return $3
}
start_sleepers() {
sleeper 1 1 0 &
sleeper 2 2 $1 &
sleeper 3 5 0 &
sleeper 4 6 0 &
sleep 4
}
echo "Using jobs"
start_sleepers 1
pids=( $(jobs -p) )
echo "PIDS: ${pids[*]}"
for pid in "${pids[@]}"; do
wait "$pid"
echo "Exit code $?"
done
echo "Clearing other children"
wait -n; echo "Exit code $?"
wait -n; echo "Exit code $?"
echo "Waiting for N processes"
start_sleepers 2
for ignored in $(seq 1 4); do
wait -n
echo "Exit code $?"
done
输出:
Using jobs
Sleeper 1
Sleeper 2
Sleeper 3
Sleeper 4
Exiting 1
Exiting 2
PIDS: 56496 56497
Exiting 3
Exit code 0
Exiting 4
Exit code 0
Clearing other children
Exit code 0
Exit code 1
Waiting for N processes
Sleeper 1
Sleeper 2
Sleeper 3
Sleeper 4
Exiting 1
Exiting 2
Exit code 0
Exit code 2
Exiting 3
Exit code 0
Exiting 4
Exit code 0
答案 30 :(得分:0)
我遇到了类似的情况,但是循环子shell有各种各样的问题,确保这里的其他解决方案不起作用,所以我让我的循环编写了我要运行的脚本,最后等待。有效:
#!/bin/bash
echo > tmpscript.sh
for i in `seq 0 9`; do
echo "doCalculations $i &" >> tmpscript.sh
done
echo "wait" >> tmpscript.sh
chmod u+x tmpscript.sh
./tmpscript.sh
愚蠢,但很简单,并在之后帮助调试了一些东西。
如果我有时间,我会更深入地了解 GNU 并行,但是我自己的“doCalculations”过程很困难。
答案 31 :(得分:-2)
我想也许会运行doCalculations;回声“$?”发送到后台的子shell 中的&gt;&gt; / tmp / acc,然后等待,然后 / tmp / acc 将包含退出状态,每行一个。但是,我不知道附加到累加器文件的多个进程的任何后果。
以下是对此建议的试用:
档案:doCalcualtions
#!/bin/sh random -e 20 sleep $? random -e 10
档案:尝试
#!/bin/sh rm /tmp/acc for i in $( seq 0 20 ) do ( ./doCalculations "$i"; echo "$?" >>/tmp/acc ) & done wait cat /tmp/acc | fmt rm /tmp/acc
跑步的输出./try
5 1 9 6 8 1 2 0 9 6 5 9 6 0 0 4 9 5 5 9 8