Bash script süreçleri bekle ve dönüş kodunu al


13

Birçok arka plan komutunu başlatacak bir komut dosyası oluşturmaya çalışıyorum. Her arka plan komutu için dönüş kodunu almam gerekiyor.

Aşağıdaki komut dosyasını deniyorum:

 #!/bin/bash
set -x
pid=()
return=()


for i in 1 2
do
 echo start $i
 ssh mysql "/root/test$i.sh" &
 pid[$i]=$!
done

for i in ${#pid[@]}
do
echo ${pid[$i]}
wait ${pid[$i]}
return[$i]=$?

if [ ${return[$i]} -ne 0 ]
then
  echo mail error
fi

done

echo ${return[1]}
echo ${return[2]}

Benim sorunum bekleme döngüsü sırasında, ilk pid önce ikinci pid bitirmek, ben dönüş kodu almak mümkün olmayacaktır.

Bekleme pid1 pid2 çalıştırabileceğini biliyorum, ama bu komutla tüm komutların dönüş kodunu alamıyorum.

Herhangi bir fikir ?

Yanıtlar:


6

Bunu geçici bir dizin kullanarak yapabilirsiniz.

# Create a temporary directory to store the statuses
dir=$(mktemp -d)

# Execute the backgrouded code. Create a file that contains the exit status.
# The filename is the PID of this group's subshell.
for i in 1 2; do
    { ssh mysql "/root/test$i.sh" ; echo "$?" > "$dir/$BASHPID" ; } &
done

# Wait for all jobs to complete
wait

# Get return information for each pid
for file in "$dir"/*; do
    printf 'PID %d returned %d\n' "${file##*/}" "$(<"$file")"
done

# Remove the temporary directory
rm -r "$dir"

9

Sorun sizin

for i in ${#pid[@]}

Hangi for i in 2.

Daha doğrusu:

for i in 1 2

veya

for ((i = 1; i <= ${#pid[@]}; i++))

wait "$pid" olacak olan işin çıkış kodunu döndürür bash(ve POSIX kabukları, ancak zshne zaman iş zaten sonlandırıldı olsa bile) waitbaşlandı.


5

Geçici dosyaları olmayan genel bir uygulama.

#!/usr/bin/env bash

## associative array for job status
declare -A JOBS

## run command in the background
background() {
  eval $1 & JOBS[$!]="$1"
}

## check exit status of each job
## preserve exit status in ${JOBS}
## returns 1 if any job failed
reap() {
  local cmd
  local status=0
  for pid in ${!JOBS[@]}; do
    cmd=${JOBS[${pid}]}
    wait ${pid} ; JOBS[${pid}]=$?
    if [[ ${JOBS[${pid}]} -ne 0 ]]; then
      status=${JOBS[${pid}]}
      echo -e "[${pid}] Exited with status: ${status}\n${cmd}"
    fi
  done
  return ${status}
}

background 'sleep 1 ; false'
background 'sleep 3 ; true'
background 'sleep 2 ; exit 5'
background 'sleep 5 ; true'

reap || echo "Ooops! Some jobs failed"

Teşekkür ederim :-) Bu tam olarak aradığım şey!
Qorbani

0

Stéphane'nin cevabı iyi, ama tercih ederim

for i in ${!pid[@]}
do
    wait ${pid[i]}
    return[i]=$?
    unset "pid[$i]"
done

hangi pidgirişlerin mevcut olduğuna bakılmaksızın , dizinin anahtarları üzerinde yinelenir , böylece uyarlayabilir, döngüden çıkabilir ve tüm döngüyü yeniden başlatabilirsiniz ve sadece çalışır. Ve ibaşlamak için ardışık değerlerine ihtiyacınız yok .

Tabii ki, binlerce işlemle uğraşıyorsanız, seyrek olmayan bir listeniz olduğunda belki de Stépane'in yaklaşımı fraksiyonel olarak daha verimli olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.