बैश स्क्रिप्ट प्रक्रियाओं के लिए प्रतीक्षा करें और रिटर्न कोड प्राप्त करें


13

मैं एक स्क्रिप्ट बनाने की कोशिश कर रहा हूं जो कई पृष्ठभूमि कमांड शुरू करेगा। प्रत्येक पृष्ठभूमि कमांड के लिए मुझे रिटर्न कोड प्राप्त करने की आवश्यकता है।

मैं निम्नलिखित स्क्रिप्ट की कोशिश कर रहा हूँ:

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

मेरा मुद्दा प्रतीक्षा लूप के दौरान है, यदि पहले एक से पहले दूसरा पिड खत्म हो जाता है, तो मैं रिटर्न कोड प्राप्त नहीं कर पाऊंगा।

मुझे पता है कि मैं pid1 pid2 प्रतीक्षा कर सकता हूं, लेकिन इस आदेश के साथ मुझे सभी आदेशों का रिटर्न कोड नहीं मिल सकता है।

कोई उपाय ?

जवाबों:


6

आप एक अस्थायी निर्देशिका का उपयोग करके ऐसा कर सकते हैं।

# 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

मुद्दा आपके साथ ज्यादा है

for i in ${#pid[@]}

कौन सा है for i in 2

बल्कि होना चाहिए:

for i in 1 2

या

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

wait "$pid" नौकरी के निकास कोड bash(और POSIX गोले, लेकिन नहीं zsh) के साथ वापस आ जाएगा , भले ही नौकरी पहले ही समाप्त हो गई waitथी जब शुरू किया गया था।


5

अस्थायी फ़ाइलों के बिना एक सामान्य कार्यान्वयन।

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

धन्यवाद :-) यह वही है जो मैं देख रहा था!
कोरबानी

0

स्टीफन का जवाब अच्छा है, लेकिन मैं पसंद करूंगा

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

जो pidसरणी की कुंजियों पर पुनरावृत्ति करेगा , चाहे जो भी प्रविष्टियां अभी भी मौजूद हैं, इसलिए आप इसे अनुकूलित कर सकते हैं, लूप से बाहर आ सकते हैं और पूरे लूप को फिर से शुरू कर सकते हैं और यह सिर्फ काम करेगा। और आपको iशुरू करने के लिए लगातार मूल्यों की आवश्यकता नहीं है ।

बेशक, यदि आप हजारों प्रक्रियाओं के साथ काम कर रहे हैं, तो शायद गैर-विरल सूची होने पर स्टेपेन का दृष्टिकोण आंशिक रूप से अधिक कुशल होगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.