Como esperar em bash para vários subprocessos para terminar e saída de retorno código! = 0 quando qualquer pontas subprocesso com código! = 0?

StackOverflow https://stackoverflow.com/questions/356100

  •  21-08-2019
  •  | 
  •  

Pergunta

Como esperar em um script bash para vários subprocessos gerados a partir desse script para acabamento e regresso código de saída! = 0 quando qualquer um dos subprocessos termina com código! = 0?

script simples:

#!/bin/bash
for i in `seq 0 9`; do
  doCalculations $i &
done
wait

O script acima irá esperar por todos os 10 subprocessos desovado, mas vai sempre dar status de saída 0 (veja help wait). Como posso modificar esse script para que ele irá descobrir status de saída de subprocessos desovado e código 1 saída de retorno quando qualquer um dos subprocessos termina com código! = 0?

Existe alguma solução melhor para isso do que a coleta PIDs dos subprocessos, esperar por eles em ordem e soma status de saída?

Foi útil?

Solução

wait também (opcionalmente) converte o PID do processo para esperar, e com US $! você começa a PID do último comando lançado em background. Modificar o circuito para armazenar o PID de cada sub-processo gerado para uma matriz, e em seguida, repetir novamente à espera em cada 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

Outras dicas

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

Se você tem GNU Parallel instalado, você pode fazer:

# If doCalculations is a function
export -f doCalculations
seq 0 9 | parallel doCalculations {}

GNU Parallel lhe dará o código de saída:

  • 0 -. Todos os trabalhos correu sem erros

  • 1-253 - Alguns dos trabalhos falhou. O status de saída dá o número de trabalhos com falha

  • 254 - Mais de 253 postos de trabalho falhou

  • .
  • 255 -. Outro erro

Assista os vídeos de introdução para saber mais: http://pi.dk/1

Aqui está o que eu vim acima com a medida. Eu gostaria de ver como interromper o comando de sono, se uma criança termina, de modo que um não teria que ajustar WAITALL_DELAY a sua utilização.

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

Aqui está um exemplo simples usando wait.

executar alguns processos:

$ sleep 10 &
$ sleep 10 &
$ sleep 20 &
$ sleep 20 &

Em seguida, esperar por eles com o comando wait:

$ wait < <(jobs -p)

Ou wait apenas (sem argumentos) para todos.

Isto irá esperar por todas as tarefas em segundo plano estão concluídas.

Se a opção -n é fornecido, aguarda o próximo trabalho para terminar e retorna seu estado de saída.

Veja:. help wait e help jobs para a sintaxe

No entanto, a desvantagem é que este irá retornar apenas no status do último ID, então você precisa para verificar o estado de cada subprocesso e armazená-lo na variável.

Ou fazer a sua função de cálculo para criar algum arquivo em caso de falha (vazio ou com falha log), em seguida, verificar de que arquivo se existe, por exemplo.

$ sleep 20 && true || tee fail &
$ sleep 20 && false || tee fail &
$ wait < <(jobs -p)
$ test -f fail && echo Calculation failed.

Que tal simplesmente:

#!/bin/bash

pids=""

for i in `seq 0 9`; do
   doCalculations $i &
   pids="$pids $!"
done

wait $pids

...code continued here ...

Update:

Como apontado por vários comentadores, as esperas acima para todos os processos para ser concluída antes de continuar, mas não sair e não conseguem se um deles falhar, ele pode ser feito a ver com a seguinte modificação sugerida por @Bryan, @SamBrightman , e outros:

#!/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 ...

Para paralelizar isso ...

for i in $(whatever_list) ; do
   do_something $i
done

traduzi-lo para isso ...

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 {}
      }' 
   )
  • Se ocorrer um erro em um processo, não vai interromper os outros processos, mas que irá resultar em um código de saída diferente de zero a partir da sequência como um todo .
  • Exportar funções e variáveis ??pode ou não ser necessário, em qualquer caso particular.
  • Você pode definir --max-procs baseado em quanto paralelismo você quer (meios 0 "tudo de uma vez").
  • GNU paralelas ofertas alguns recursos adicionais quando usado no lugar de xargs - mas isn 't sempre instalado por padrão.
  • O loop for não é estritamente necessário, neste exemplo, desde echo $i é basicamente apenas regenerar a saída do $(whatever_list). Eu só acho que o uso da palavra-chave for torna um pouco mais fácil ver o que está acontecendo.
  • manipulação de strings Bash pode ser confuso -. Eu descobri que usando aspas simples funciona melhor para acondicionamento de scripts não triviais
  • Você facilmente pode interromper toda a operação (usando ^ C ou similar), ao contrário da abordagem mais direta para Bash paralelismo .

Aqui está um exemplo de trabalho simplificado ...

for i in {0..5} ; do echo $i ; done |xargs -I{} --max-procs 2 bash -c '
   {
   echo sleep {}
   sleep 2s
   }'

Eu não acredito que é possível com a funcionalidade embutida de Bash.

Você pode obter uma notificação quando uma criança sai:

#!/bin/sh
set -o monitor        # enable script job control
trap 'echo "child died"' CHLD

No entanto não há nenhuma maneira aparente para obter status de saída da criança no manipulador de sinal.

Conseguir que o estado da criança é geralmente o trabalho da família wait de funções no nível inferior POSIX APIs. Infelizmente o apoio do Bash para isso é limitado - você pode esperar por um processo filho específico (e obter seu status de saída) ou você pode esperar por todas deles, e sempre obter uma 0 resultado.

O que parece impossível de fazer é o equivalente a waitpid(-1), que bloqueia até qualquer processos criança retornos.

Eu vejo muitos bons exemplos listados aqui, queria jogar mina no bem.

#! /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

Eu uso algo muito semelhante ao iniciar / servidores de parada / serviços em paralelo e verificar cada estado de saída. Funciona muito bem para mim. Espero que isso ajude alguém!

O código a seguir irá aguardar a conclusão de todos os cálculos e saída de retorno de estado 1 se qualquer um de doCalculations falha.

#!/bin/bash
for i in $(seq 0 9); do
   (doCalculations $i >&2 & wait %1; echo $?) &
done | grep -qv 0 && exit 1

Apenas armazenar os resultados para fora da casca, por exemplo, em um arquivo.

#!/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

Aqui está a minha versão que funciona para várias pids, registra avisos se a execução leva muito tempo, e pára os subprocessos se a execução demora mais do que um determinado valor.

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
}

Exemplo, espera para todos os três processos para acabamento, ingresse um aviso se a execução leva loger de 5 segundos, parar todos os processos se a execução demora mais do que 120 segundos. Não programa de saída de falhas.

function something {

    sleep 10 &
    pids="$!"
    sleep 12 &
    pids="$pids;$!"
    sleep 9 &
    pids="$pids;$!"

    WaitForTaskCompletion $pids 5 120 ${FUNCNAME[0]} false
}
# Launch the function
someting

Se você tem o bash 4.2 ou posterior disponível o seguinte pode ser útil para você. Ele usa arrays associativos para armazenar os nomes de tarefas e seu "código", bem como os nomes das tarefas e suas pids. Eu também têm construído em um método de limitação de taxa simples, que pode vir a calhar se suas tarefas consomem muita CPU ou I / hora O e você quiser limitar o número de tarefas simultâneas.

Os lançamentos de script todas as tarefas do primeiro ciclo e consome os resultados na segunda.

Este é um exagero bit para casos simples mas permite muito material puro. Por exemplo, pode armazenar mensagens de erro para cada tarefa em outra matriz associativa e imprimi-los depois que tudo se acalmou.

#! /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

Eu apenas fui modificando um script para fundo e parallelise um processo.

Eu fiz algumas experiências (no Solaris com ambos bash e ksh) e descobriu que 'espera' emite o status de saída, se não é zero, ou uma lista de empregos que retornam não zero saída quando nenhum argumento PID é fornecido. Por exemplo.

Bash:

$ 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

Esta saída é escrito para stderr, então uma solução simples para o exemplo PO poderia ser:

#!/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

Enquanto isto:

wait 2> >(wc -l)

também irá retornar uma contagem, mas sem o arquivo tmp. Isso também pode ser usado desta forma, por exemplo:

wait 2> >(if [ `wc -l` -gt 0 ] ; then echo "ERROR"; fi)

Mas isso não é muito mais útil do que o arquivo tmp IMO. Eu não poderia encontrar uma maneira útil para evitar o arquivo tmp ao mesmo tempo, evitando a execução do "espera" em um subnível, que não vai funcionar em tudo.

Eu tive um ir neste e combinado todas as melhores partes de outros exemplos aqui. Este script irá executar a função checkpids quando qualquer sai do processo de fundo, e saída do estado de saída, sem recorrer a votação.

#!/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
#!/bin/bash
set -m
for i in `seq 0 9`; do
  doCalculations $i &
done
while fg; do true; done
  • set -m permite que você use fg & bg em um script
  • fg, além de colocar o último processo em primeiro plano, tem o mesmo status de saída como o processo que foregrounds
  • while fg vai parar de looping quando todas as saídas fg com um status de saída diferente de zero

Infelizmente isso não vai lidar com o caso quando um processo nas saídas de fundo com um status de saída diferente de zero. (O loop não será encerrado imediatamente. Ele vai esperar para os processos anteriores para ser concluído.)

Isso funciona, deve ser apenas como um bom se não melhor do que resposta de @ 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

e, claro, eu imortalizaram esse script, em um projeto NPM que lhe permite executar comandos bash em paralelo, útil para testar:

https://github.com/ORESoftware/generic-subshell

armadilha é seu amigo. Você pode prender em ERR em um monte de sistemas. Você pode prender saída, ou em DEBUG para executar um pedaço de código após cada comando.

Este, além de todos os sinais padrão.

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

O set -e no topo faz sua parada roteiro em caso de falha.

expect voltará 1 se houver subtarefa falhou.

Já há um monte de respostas aqui, mas estou surpreendido ninguém parece ter sugerido usando matrizes ... Então aqui está o que eu fiz - isso pode ser útil para alguns no futuro

.
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

Isso é algo que eu uso:

#wait for jobs
for job in `jobs -p`; do wait ${job}; done

Eu usei isso recentemente (graças a 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

A partir daí pode-se facilmente extrapolar, e tem um gatilho (tocar um arquivo, enviar um sinal) e alterar os critérios de contagem (arquivos contagem tocado, ou qualquer outro) para responder a esse gatilho. Ou se você quer apenas 'qualquer' rc não zero, apenas matar o bloqueio de save_status.

Eu precisava disso, mas o processo de destino não era uma criança de shell atual, caso em que wait $PID não funciona. Eu encontrei a seguinte alternativa em vez disso:

while [ -e /proc/$PID ]; do sleep 0.1 ; done

Isso depende da presença de procfs , que pode não estar disponível (Mac não fornecê-la por exemplo). Assim, para a portabilidade, você poderia usar este em vez disso:

while ps -p $PID >/dev/null ; do sleep 0.1 ; done

sinal Trapping CHLD pode não trabalho, porque você pode perder alguns sinais se eles chegaram ao mesmo tempo.

#!/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 !!!

solução para esperar por vários subprocessos e saída quando qualquer um deles sai com código de status diferente de zero é usando 'espera -n'

#!/bin/bash
wait_for_pids()
{
    for (( i = 1; i <= $#; i++ )) do
        wait -n $@
        status=$?
        echo "received status: "$status
        if [ $status -ne 0 ] && [ $status -ne 127 ]; then
            exit 1
        fi
    done
}

sleep_for_10()
{
    sleep 10
    exit 10
}

sleep_for_20()
{
    sleep 20
}

sleep_for_10 &
pid1=$!

sleep_for_20 &
pid2=$!

wait_for_pids $pid2 $pid1

código de status '127' é para o processo de não-existente, o que significa que a criança pode ter saído.

Pode haver um caso em que o processo está completo antes de aguardar o processo. Se desencadear esperar por um processo que já está terminado, ele irá acionar um erro como pid não é um filho deste shell. Para evitar tais casos, a seguinte função pode ser usada para descobrir se o processo está completo ou não:

isProcessComplete(){
PID=$1
while [ -e /proc/$PID ]
do
    echo "Process: $PID is still running"
    sleep 5
done
echo "Process $PID has finished"
}

Eu acho que a maneira mais simples para executar tarefas em paralelo e verifique se o status está usando arquivos temporários. Já existem algumas respostas semelhantes (por exemplo Nietzche-jou e mug896).

#!/bin/bash
rm -f fail
for i in `seq 0 9`; do
  doCalculations $i || touch fail &
done
wait 
! [ -f fail ]

O código acima não é thread-safe. Se você está preocupado que o código acima estará funcionando ao mesmo tempo como a própria, é melhor usar um nome de arquivo mais original, como falhar. $$. A última linha é para cumprir a exigência: "código de saída de retorno 1 quando qualquer um dos subprocessos termina com código = 0!?" Eu joguei um requisito adicional lá para limpar. Pode ter sido mais clara para escrevê-lo como este:

#!/bin/bash
trap 'rm -f fail.$$' EXIT
for i in `seq 0 9`; do
  doCalculations $i || touch fail.$$ &
done
wait 
! [ -f fail.$$ ] 

Aqui está um trecho semelhante para reunir os resultados de vários trabalhos: Eu criar um diretório temporário, história as saídas de todas as sub tarefas em um arquivo separado, e depois despejá-los para revisão. Isto realmente não coincidir com a pergunta - Eu estou jogando-o como um bônus:

#!/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

Estou pensando doCalculations talvez executados; echo "$?" >> / tmp / acc em um subshell , que é enviado para o fundo, então a espera, em seguida, / tmp / acc conteria os status de saída, um por linha. Eu não sei sobre quaisquer consequências dos múltiplos processos de anexação no arquivo acumulador, no entanto.

Aqui está um julgamento desta sugestão:

arquivo: doCalcualtions

#!/bin/sh

random -e 20
sleep $?
random -e 10

arquivo: tentativa

#!/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

Saída de correr ./try

5 1 9 6 8 1 2 0 9 6 5 9 6 0 0 4 9 5 5 9 8
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top