ব্যাকগ্রাউন্ড প্রক্রিয়া নির্ভরযোগ্য রিটার্ন কোড


14

আসুন ব্যাশ কোডের নীচের অংশটি ধরে নিই:

foo > logfile 2>&1 &
foo_pid=$!

while ps -p$foo_pid
do
    ping -c 1 localhost
done

wait $foo_pid

if [[ $? == 0 ]]
then
    echo "foo success"
fi

এটা কি নিরাপদ বলে যে নিরাপদে $?রিটার্ন কোড রয়েছে fooএবং না তার রিটার্ন কোড রয়েছে ping? যদি এই প্রশ্নের উত্তরটি হয়: "আপনি এটি ধরে নিতে পারবেন না।" তারপরে আমি কীভাবে এই কোডের টুকরোটি সংশোধন করতে পারি তা নিশ্চিত হতে যে $?সর্বদা রিটার্ন কোড থাকে foo?

উত্তর:


12

সঙ্গে bash, আপনি যে গ্যারান্টি হবে যদি না আপনি অন্য পটভূমি কাজ শুরু করেছি (এবং হুঁশিয়ার করে পটভূমি কাজ দিয়ে শুরু করা যেতে পারে &কিন্তু সঙ্গে coprocমধ্যবর্তী এবং প্রক্রিয়া প্রতিকল্পন সঙ্গে) foo &এবং wait

পসিক্সের প্রয়োজন যে কোনও শেল কমপক্ষে 25 টি কাজ সেরে যাওয়ার পরে তার প্রস্থান স্থিতিbash মনে রাখে তবে এর চেয়ে অনেক বেশি মনে পড়ে।

এখন, আপনি যদি:

foo & pid=$!
...
bar &
wait "$pid"

আপনার কাছে কোনও গ্যারান্টি নেই যা barআপনাকে একই ধরণের পিড দেওয়া হবে না foo(যদি fooসময় barশুরু হওয়ার সাথে সাথে শেষ করা হয় ), তবে এটি অসম্ভব হলেও, wait "$pid"আপনাকে প্রস্থান স্থিতি দিতে পারে bar

আপনি এটি দিয়ে পুনরুত্পাদন করতে পারেন:

bash -c '(exit 12; foo) & pid=$!
         while : bar & [ "$pid" != "$!" ]; do :;done
         wait "$pid"; echo "$?"'

যা (শেষ পর্যন্ত) 0পরিবর্তে আপনাকে দেবে 12

সমস্যা এড়ানোর জন্য, একটি উপায় হ'ল এটি লিখুন:

{
  foo_pid=$!

  while ps -p "$foo_pid"
  do
      ping -c 1 localhost
  done

  bar &
  ...

  read <&3 ret
  if [ "$ret" = 0 ]; then
    echo foo was sucessful.
  fi
} 3< <(foo > logfile 2>&1; echo "$?")

4

হ্যাঁ, আপনি wait "$!"একটি ব্যাকগ্রাউন্ড কাজের স্থিতি পাওয়ার জন্য নির্ভর করতে পারেন । স্ক্রিপ্ট হিসাবে চলাকালীন, ব্যাশ স্বয়ংক্রিয়ভাবে সম্পূর্ণ পটভূমি কাজ সংগ্রহ করে না। সুতরাং আপনি যদি চালানো হয় wait, এটি সময় waitবলা হয় কাজ জড়ো করা হবে ।

আপনি এটি একটি সাধারণ স্ক্রিপ্ট দিয়ে পরীক্ষা করতে পারেন:

#!/bin/bash
sh -c 'sleep 1; exit 22' &
sleep 5
echo "FG: $?"
wait %1
echo "BG: $?"

যা আউটপুট দেবে:

FG: 0
BG: 22

এই বিবৃতিটির মূল অংশটি শুরু ছিল, "যখন স্ক্রিপ্ট হিসাবে চলমান"। ইন্টারেক্টিভ যখন waitকাজ করে না। প্রক্রিয়াটি সংগ্রহ করা হয় এবং প্রম্পট প্রদর্শিত হওয়ার আগেই ডিফল্ট স্থিতি বাতিল করা হয় (ডিফল্টরূপে)।
প্যাট্রিক

আমি এটি কেবল মাত্র 4.2.37, 4.1.2, এবং 3.2.48 এ চেষ্টা করেছি। তাদের সবাই ঠিক একই আচরণ করে (আমার উত্তরে কোডের আক্ষরিক অনুলিপি / পেস্ট)। wait %1"ঘুম 5" শেষ হওয়ার সাথে সাথে পটভূমি প্রক্রিয়াটি সংগ্রহ করা হওয়ায় "এ জাতীয় কোনও কাজ নয়" নিয়ে ব্যর্থ The
প্যাট্রিক

আহ ঠিক আছে, দুঃখিত, আমি এখন এটি পেয়েছি। আমি তোমার হাতছাড়া হয়ে গেলো %1এর জায়গা $!
স্টাফেন চেজেলাস

নোট করুন bash -c '(sleep 1;exit 5) & sleep 2; wait %1; echo $?'(পাশাপাশি অ-ইন্টারেক্টিভ পাশাপাশি) সেই মৃত কাজের প্রস্থান স্থিতি পেতেও ব্যর্থ। বাগের মতো শোনাচ্ছে।
স্টাফেন চেজেলাস

আমি অন্তর্ভুক্ত না করা পর্যন্ত এটি একটি মেকফিল রেসিপিটিতে আমার পক্ষে কাজ করে না set +e। দেখে মনে হচ্ছে set -ewait
বাশের

0

আমি বিশ্বাস করি আপনার অনুমানটি সঠিক is man bashব্যাকগ্রাউন্ড প্রক্রিয়াগুলির জন্য অপেক্ষা করা থেকে এখানে একটি নির্যাস ।

যদি এন একটি অ-বিদ্যমান প্রক্রিয়া বা কাজ নির্দিষ্ট করে, তবে রিটার্নের স্ট্যাটাসটি 127 Otherwise অন্যথায়, রিটার্নের স্থিতি হ'ল শেষ প্রক্রিয়া বা কাজের অপেক্ষার প্রস্থান স্থিতি।

সুতরাং সম্ভবত আপনার 127 পরীক্ষা করা উচিত

সাহায্যের চেয়ে সম্পূর্ণ ভিন্ন উত্তর সহ একই রকম প্রশ্ন রয়েছে।

প্রক্রিয়াটির জন্য বাশ স্ক্রিপ্ট অপেক্ষা করে এবং রিটার্ন কোড পান

সম্পাদনা 1

@ স্টিফেনের মন্তব্য এবং উত্তরগুলি দ্বারা অনুপ্রাণিত হয়ে আমি তাঁর স্ক্রিপ্টটি প্রসারিত করেছি। ট্র্যাকটি শিথিল হওয়া শুরু হওয়ার আগে আমি প্রায় 34 টি পটভূমি প্রক্রিয়াগুলি শুরু করতে পারি।

tback

$ cat tback 
plist=()
elist=()
slist=([1]=12 [2]=15 [3]=17 [4]=19 [5]=21 [6]=23)
count=30

#start background tasksto monitor
for i in 1 2 3 4
do
  #echo pid $i ${plist[$i]} ${slist[$i]}
  (echo $BASHPID-${slist[$i]} running; exit ${slist[$i]}) & 
  plist[$i]=$!
done

echo starting $count background echos to test history
for i in `eval echo {1..$count}`
do
  echo -n "." &
  elist[$i]=$! 
done
# wait for each background echo to complete
for i in `eval echo {1..$count}`
do
  wait ${elist[$i]}
  echo -n $? 
done
echo ""
# Now wait for each monitored process and check return status with expected
failed=0
for i in 1 2 3 4
do
  wait ${plist[$i]}
  rv=$?
  echo " pid ${plist[$i]} returns $rv should be ${slist[$i]}"
  if [[ $rv != ${slist[$i]} ]] 
  then
    failed=1
  fi
done

wait
echo "Complete $failed"
if [[ $failed = "1" ]]
then
  echo Failed
else
  echo Success
fi
exit $failed
$ 

আমার সিস্টেম উত্পাদন করে

$ bash tback
14553-12 running
14554-15 running
14555-17 running
starting 30 background echos to test history
14556-19 running
..............................000000000000000000000000000000
 pid 14553 returns 12 should be 12
 pid 14554 returns 15 should be 15
 pid 14555 returns 17 should be 17
 pid 14556 returns 19 should be 19
Complete 0
Success

1
না, উমলাউটের উত্তরে আমার মন্তব্য দেখুন , এবং এটি নিজের জন্য চেষ্টা করে দেখুনbash -c '(exit 12) & sleep 1; wait "$!"; echo "$?"'
স্টাফেন চেজেলাস

আমি কখনই bashlooseিলে seen ালা ট্র্যাকটি দেখিনি (এমনকি হাজার হাজার কাজ শুরু করার পরেও), আমার উদাহরণটি হ'ল পিডটিকে পুনরায় ব্যবহার করা হচ্ছে তা প্রদর্শন করছিল, যা আপনার ক্ষেত্রেও আপনি লক্ষ্য করেছেন।
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.