একটি পটভূমি প্রক্রিয়া প্রস্থান কোড পান


130

আমার প্রধান বোর্ন শেল স্ক্রিপ্ট থেকে একটি কমান্ড সিএমডি কল এসেছে যা চিরকালের জন্য লাগে।

আমি স্ক্রিপ্টটি নিম্নরূপে সংশোধন করতে চাই:

  1. পটভূমি প্রক্রিয়া ( CMD &) হিসাবে সমান্তরালভাবে সিএমডি কমান্ডটি চালান ।
  2. মূল স্ক্রিপ্টে, প্রতি কয়েক সেকেন্ডে স্পাড কমান্ডটি পর্যবেক্ষণ করতে একটি লুপ রাখুন। লুপটি স্ক্রিপ্টের অগ্রগতি নির্দেশ করে স্টাডাউটকে কিছু বার্তা প্রতিধ্বনিত করে।
  3. স্প্যানড কমান্ডটি শেষ হয়ে গেলে লুপ থেকে প্রস্থান করুন।
  4. তৈরি হওয়া প্রক্রিয়াটির প্রস্থান কোড ক্যাপচার করুন এবং প্রতিবেদন করুন।

কেউ কি এটি সম্পাদন করার জন্য আমাকে পয়েন্টার দিতে পারেন?


1
...এবং বিজয়ী?
সত্যই

1
@ ট্রাইওয়াই .. বব যখন সে প্রশ্ন জিজ্ঞাসা করেছে সেদিন থেকে লগ ইন হয়নি। আমরা কখনও জানার সম্ভাবনা নেই!
ঘোটি

উত্তর:


126

1: ব্যাশে, $!সম্পাদিত শেষ পটভূমি প্রক্রিয়াটির পিআইডি ধারণ করে। এটি আপনাকে জানাবে যে কীভাবে প্রক্রিয়াটি পর্যবেক্ষণ করা উচিত।

৪: wait <n>পিআইডি সহ প্রক্রিয়াটি শেষ না হওয়া পর্যন্ত অপেক্ষা করে <n>(প্রক্রিয়াটি শেষ না হওয়া পর্যন্ত এটি ব্লক হয়ে যাবে, সুতরাং প্রক্রিয়াটি সম্পন্ন হওয়ার বিষয়ে নিশ্চিত না হওয়া পর্যন্ত আপনি এটিকে কল করতে নাও চাইবেন) এবং তারপরে সম্পূর্ণ প্রক্রিয়াটির প্রস্থান কোডটি ফেরত দিন।

2, 3: psবা ps | grep " $! "প্রক্রিয়াটি এখনও চলছে কিনা তা আপনাকে বলতে পারে। কীভাবে আউটপুটটি বোঝা যায় এবং এটি সমাপ্তির কতটা কাছাকাছি তা সিদ্ধান্ত নেওয়া আপনার পক্ষে up ( ps | grepনির্বোধ-প্রমাণ নয়। আপনার যদি সময় থাকে তবে প্রক্রিয়াটি এখনও চলছে কিনা তা জানার জন্য আরও শক্তিশালী উপায় নিয়ে আসতে পারেন)।

এখানে একটি কঙ্কাল লিপি আছে:

# simulate a long process that will have an identifiable exit code
(sleep 15 ; /bin/false) &
my_pid=$!

while   ps | grep " $my_pid "     # might also need  | grep -v grep  here
do
    echo $my_pid is still in the ps output. Must still be running.
    sleep 3
done

echo Oh, it looks like the process is done.
wait $my_pid
# The variable $? always holds the exit code of the last command to finish.
# Here it holds the exit code of $my_pid, since wait exits with that code. 
my_status=$?
echo The exit status of the process was $my_status


54
kill -0 $!কোনও প্রক্রিয়া এখনও চলছে কিনা তা বলার আরও ভাল উপায়। এটি আসলে কোনও সংকেত প্রেরণ করে না, কেবলমাত্র প্রক্রিয়াটি বেঁচে রয়েছে কিনা তা পরীক্ষা করে বাহ্যিক প্রক্রিয়াগুলির পরিবর্তে শেল্ট বিল্ট-ইন ব্যবহার করে। যেমনটি man 2 killবলা হয়েছে, "যদি সিগ 0 হয় তবে কোনও সিগন্যাল প্রেরণ করা হয় না, তবু ত্রুটি পরীক্ষা করা কার্যকর হয়; এটি একটি প্রক্রিয়া আইডি বা প্রক্রিয়া গ্রুপ আইডির অস্তিত্বের জন্য পরীক্ষা করতে ব্যবহৃত হতে পারে।"
প্রাক্তন

14
kill -0আপনার যদি চলমান কোনও প্রক্রিয়ায় সিগন্যাল প্রেরণের অনুমতি না থাকে তবে @Phemient অ-শূন্যকে ফিরিয়ে দেবে। দুর্ভাগ্যক্রমে এটি 1এই ক্ষেত্রে এবং সেই প্রক্রিয়া উভয় ক্ষেত্রেই ফিরে আসে যেখানে প্রক্রিয়াটি বিদ্যমান নেই। আপনি যদি প্রক্রিয়াটির মালিক না হন তবে এটি এটিকে দরকারী করে তোলে - যদি এমন কোনও সরঞ্জাম sudoজড়িত থাকে বা যদি তারা সেটআপ হয় (এবং সম্ভবত ছদ্মবেশ ছেড়ে দেয়) তবে আপনি তৈরি প্রক্রিয়াগুলির ক্ষেত্রেও এটি হতে পারে।
ক্রেগ রিঞ্জার

13
waitভেরিয়েবলের প্রস্থান কোড ফেরত দেয় না $?। এটি কেবলমাত্র প্রস্থান কোডটি ফেরত দেয় এবং $?সর্বশেষতম অগ্রভাগ প্রোগ্রামের প্রস্থান কোড।
মাইন্ডলেস রেঞ্জার

7
অনেক লোকের জন্য ভোট দেওয়া kill -0। এখানে এসওর থেকে সমকক্ষ পর্যালোচনা হওয়া রেফারেন্সটি দেখায় যা ক্রেগরিঞ্জারের মন্তব্যটি বৈধতা সম্পর্কিত: kill -0চলমান প্রক্রিয়াগুলির জন্য অ-শূন্য ps -pফিরে আসবে ... তবে যে কোনও চলমান প্রক্রিয়ার জন্য সর্বদা 0 ফিরে আসবে
ট্রেভর বয়ড স্মিথ

57

যখন আমার অনুরূপ প্রয়োজন হয়েছিল তখনই আমি এটি সমাধান করেছি:

# Some function that takes a long time to process
longprocess() {
        # Sleep up to 14 seconds
        sleep $((RANDOM % 15))
        # Randomly exit with 0 or 1
        exit $((RANDOM % 2))
}

pids=""
# Run five concurrent processes
for i in {1..5}; do
        ( longprocess ) &
        # store PID of process
        pids+=" $!"
done

# Wait for all processes to finish, will take max 14s
# as it waits in order of launch, not order of finishing
for p in $pids; do
        if wait $p; then
                echo "Process $p success"
        else
                echo "Process $p fail"
        fi
done

আমি এই পদ্ধতির পছন্দ।
কেমিন চৈ

ধন্যবাদ! এটি আমার কাছে সহজতম পদ্ধতি বলে মনে হচ্ছে।
লুক ডেভিস

4
এই সমাধানটি # 2 প্রয়োজনীয়তা পূরণ করে না: ব্যাকগ্রাউন্ড প্রক্রিয়া প্রতি পর্যবেক্ষণ লুপ lo waits কারণের স্ক্রিপ্টটি (প্রতিটি) প্রক্রিয়াটির একেবারে শেষ অবধি অপেক্ষা করতে থাকবে।
ডিসক্রুট

সহজ এবং সুন্দর পদ্ধতির .. বেশ কিছুদিন এই সমাধানটির সন্ধান করা হয়েছে ..
সন্তোষ কুমার অর্জুনান

এটি কাজ করে না .. বা আপনি যা চান তা করে না: এটি ব্যাকগ্রাউন্ড প্রক্রিয়াগুলি প্রস্থান স্থিতিগুলি পরীক্ষা করে না?
কনিকে

10

একটি পটভূমি শিশু প্রক্রিয়া এর পিড stored মধ্যে সংরক্ষণ করা হয় ! । আপনি সমস্ত শিশু প্রসেসের পিডগুলিকে একটি অ্যারেতে রাখতে পারেন, যেমন পিআইডিএস []

wait [-n] [jobspec or pid …]

প্রতিটি প্রক্রিয়া আইডি পিড বা জব স্পেসিফিকেশন জবস্পেক প্রস্থান করে নির্দিষ্ট শিশু প্রক্রিয়াটি না হওয়া পর্যন্ত অপেক্ষা করুন এবং অপেক্ষা করা শেষ কমান্ডের প্রস্থান স্থিতি ফিরে আসুন। যদি কোনও কাজের বৈশিষ্ট্য দেওয়া হয়, তবে কাজের সমস্ত প্রক্রিয়াগুলির জন্য অপেক্ষা করা হয়। যদি কোনও যুক্তি না দেওয়া হয় তবে বর্তমানে সমস্ত সক্রিয় শিশু প্রক্রিয়াগুলির জন্য অপেক্ষা করা হচ্ছে, এবং প্রত্যাবর্তনের অবস্থা শূন্য। যদি -n বিকল্প সরবরাহ করা হয়, অপেক্ষা করুন কোনও কাজ শেষ হওয়ার জন্য অপেক্ষা করে এবং তার প্রস্থান স্থিতি ফিরে আসে। যদি জবস্পেক বা পিড উভয়ই শেলের একটি সক্রিয় শিশু প্রক্রিয়া নির্দিষ্ট করে না, তবে রিটার্নের স্থিতি 127।

আপনি সমস্ত শিশু প্রক্রিয়া শেষ হওয়ার জন্য অপেক্ষা করতে পারেন অপেক্ষার কমান্ডটি ব্যবহার করুন , ইতিমধ্যে আপনি via এর মাধ্যমে প্রতিটি শিশু প্রসেসের প্রস্থান স্থিতি পেতে পারেন ? এবং স্ট্যাটাসে স্টোর স্থিতি [] । তারপরে আপনি স্ট্যাটাসের উপর নির্ভর করে কিছু করতে পারেন।

আমি নিম্নলিখিত 2 সমাধানগুলি চেষ্টা করেছি এবং সেগুলি ভালভাবে চালিত হয়। সমাধান 01 আরও সংক্ষিপ্ত, যখন সমাধান 02 কিছুটা জটিল।

solution01

#!/bin/bash

# start 3 child processes concurrently, and store each pid into array PIDS[].
process=(a.sh b.sh c.sh)
for app in ${process[@]}; do
  ./${app} &
  PIDS+=($!)
done

# wait for all processes to finish, and store each process's exit code into array STATUS[].
for pid in ${PIDS[@]}; do
  echo "pid=${pid}"
  wait ${pid}
  STATUS+=($?)
done

# after all processed finish, check their exit codes in STATUS[].
i=0
for st in ${STATUS[@]}; do
  if [[ ${st} -ne 0 ]]; then
    echo "$i failed"
  else
    echo "$i finish"
  fi
  ((i+=1))
done

solution02

#!/bin/bash

# start 3 child processes concurrently, and store each pid into array PIDS[].
i=0
process=(a.sh b.sh c.sh)
for app in ${process[@]}; do
  ./${app} &
  pid=$!
  PIDS[$i]=${pid}
  ((i+=1))
done

# wait for all processes to finish, and store each process's exit code into array STATUS[].
i=0
for pid in ${PIDS[@]}; do
  echo "pid=${pid}"
  wait ${pid}
  STATUS[$i]=$?
  ((i+=1))
done

# after all processed finish, check their exit codes in STATUS[].
i=0
for st in ${STATUS[@]}; do
  if [[ ${st} -ne 0 ]]; then
    echo "$i failed"
  else
    echo "$i finish"
  fi
  ((i+=1))
done

আমি চেষ্টা করেছি এবং প্রমাণ করেছি যে এটি ভাল চলছে। আপনি কোডে আমার ব্যাখ্যা পড়তে পারেন।
টেরি

দয়া করে " আমি কীভাবে একটি ভাল উত্তর লিখব? " পড়ুন যেখানে আপনি নিম্নলিখিত তথ্যগুলি পেয়ে যাবেন: ... আপনার উত্তরে কোনও সীমাবদ্ধতা, অনুমান বা সরলকরণ উল্লেখ করার চেষ্টা করুন। ব্রেভিটি গ্রহণযোগ্য, তবে পূর্ণাঙ্গ ব্যাখ্যা আরও ভাল। আপনার উত্তরটি তাই গ্রহণযোগ্য, তবে আপনি যদি সমস্যা এবং সমাধানের বিষয়টি বিস্তারিতভাবে জানাতে পারেন তবে আপভোস্টগুলি পাওয়ার আরও অনেক ভাল সম্ভাবনা রয়েছে। :-)
নোয়েল ওয়াইডার

1
pid=$!; PIDS[$i]=${pid}; ((i+=1))আরও সহজভাবে রচনা করা যেতে পারে PIDS+=($!)যা সূচক বা পিড নিজেই পৃথক পরিবর্তনশীল ব্যবহার না করে কেবল অ্যারেতে যুক্ত হয় end একই জিনিস STATUSঅ্যারের জন্য প্রযোজ্য ।
কোডফোরস্টার

1
@ কোডফোরস্টার, আপনার উত্সাহের জন্য আপনাকে ধন্যবাদ, আমি আমার ইনিটাল কোডটিকে সলিউশন01 এ পরিবর্তন করেছি, এটি আরও সংক্ষিপ্ত দেখাচ্ছে looks
টেরি

একই জিনিসটি অন্য জায়গাগুলিতেও প্রযোজ্য যেখানে আপনি জিনিসগুলিকে অ্যারেতে যুক্ত করছেন।
কোডফোরস্টার

8

আমি দেখতে পাচ্ছি প্রায় সমস্ত উত্তর psপটভূমি প্রক্রিয়াটির অবস্থাটি পোল করতে বাহ্যিক উপযোগিতা (বেশিরভাগ ) ব্যবহার করে। আরও একটি ইউনিকেশ সমাধান রয়েছে, যা SIGCHLD সিগন্যালটি ধরে। সিগন্যাল হ্যান্ডলারটিতে এটি পরীক্ষা করতে হবে যে কোন শিশু প্রক্রিয়াটি বন্ধ হয়েছিল। এটি kill -0 <PID>অন্তর্নির্মিত (সার্বজনীন) বা /proc/<PID>ডিরেক্টরি (লিনাক্স নির্দিষ্ট) এর অস্তিত্ব যাচাই বা jobsবিল্ট-ইন ব্যবহার করে করা যেতে পারে (নির্দিষ্ট. jobs -lপিড রিপোর্ট। এই ক্ষেত্রে আউটপুট এর 3 য় ক্ষেত্রটি বন্ধ করা যাবে | চলমান | সম্পন্ন | প্রস্থান করুন। )।

এখানে আমার উদাহরণ।

লঞ্চ প্রক্রিয়া বলা হয় loop.sh। এটি -xআর্গুমেন্ট হিসাবে গ্রহণ করে বা একটি সংখ্যা। জন্য -xপ্রস্থান কোড 1. একটি সংখ্যা এটা NUM * 5 সেকেন্ড অপেক্ষা সঙ্গে প্রস্থানের হয়। প্রতি 5 সেকেন্ডের মধ্যে এটি তার পিআইডি প্রিন্ট করে।

লঞ্চার প্রক্রিয়াটি বলা হয় launch.sh:

#!/bin/bash

handle_chld() {
    local tmp=()
    for((i=0;i<${#pids[@]};++i)); do
        if [ ! -d /proc/${pids[i]} ]; then
            wait ${pids[i]}
            echo "Stopped ${pids[i]}; exit code: $?"
        else tmp+=(${pids[i]})
        fi
    done
    pids=(${tmp[@]})
}

set -o monitor
trap "handle_chld" CHLD

# Start background processes
./loop.sh 3 &
pids+=($!)
./loop.sh 2 &
pids+=($!)
./loop.sh -x &
pids+=($!)

# Wait until all background processes are stopped
while [ ${#pids[@]} -gt 0 ]; do echo "WAITING FOR: ${pids[@]}"; sleep 2; done
echo STOPPED

আরও ব্যাখ্যার জন্য দেখুন: ব্যাশ স্ক্রিপ্ট থেকে একটি প্রক্রিয়া শুরু করা ব্যর্থ


1
যেহেতু আমরা বাশ সম্পর্কে কথা বলছি, ফর লুপটি এমনভাবে লেখা যেতে পারে: for i in ${!pids[@]};প্যারামিটার বিস্তৃতি ব্যবহার করে।
প্লাজমাবিন্টুরং

7
#/bin/bash

#pgm to monitor
tail -f /var/log/messages >> /tmp/log&
# background cmd pid
pid=$!
# loop to monitor running background cmd
while :
do
    ps ax | grep $pid | grep -v grep
    ret=$?
    if test "$ret" != "0"
    then
        echo "Monitored pid ended"
        break
    fi
    sleep 5

done

wait $pid
echo $?

2
এড়াতে এখানে একটি কৌশল grep -v। আপনি সন্ধানটি লাইনের শুরুতে সীমাবদ্ধ করতে পারেন: grep '^'$pidপ্লাস, আপনি ps p $pid -o pid=যাইহোক , করতে পারেন । এছাড়াও, tail -fআপনি এটি হত্যা না করা অবধি শেষ হবে না তাই আমি এটি ডেমো করার খুব ভাল উপায় বলে মনে করি না (কমপক্ষে এটি নির্দেশ না করে)। আপনি আপনার psকমান্ডের আউটপুটটিতে পুনর্নির্দেশ করতে চাইতে পারেন /dev/nullবা এটি প্রতিটি পুনরাবৃত্তিতে স্ক্রিনে যাবে। আপনার exitকারণগুলি waitএড়িয়ে যেতে হবে - এটি সম্ভবত একটি হওয়া উচিত break। কিন্তু while/ psএবং waitঅপ্রয়োজনীয় না?
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

5
কেন সবাই ভুলে যায় kill -0 $pid? এটি আসলে কোনও সংকেত প্রেরণ করে না, কেবলমাত্র প্রক্রিয়াটি বেঁচে রয়েছে কিনা তা পরীক্ষা করে বাহ্যিক প্রক্রিয়ার পরিবর্তে শেল বিল্ট-ইন ব্যবহার করে।
প্রকাশিত

3
কারণ আপনি কেবল নিজের মালিকানাধীন একটি প্রক্রিয়াটিকে হত্যা করতে পারেন:bash: kill: (1) - Operation not permitted
errant.info

2
লুপটি নিরর্থক। শুধু অপেক্ষা করুন। কম কোড => কম প্রান্তের কেস।
ব্রেইস গাবিন

@ ব্রাইস গাবিন মনিটরিং লুপটি প্রশ্নের প্রয়োজন # 2
ডিক্রোট

5

আমি আপনার পদ্ধতির কিছুটা পরিবর্তন করব কমান্ডটি এখনও বেঁচে থাকলে এবং বার্তাটি প্রতিবেদন করার জন্য প্রতি কয়েক সেকেন্ডের মধ্যে পরীক্ষা করার পরিবর্তে, আরও একটি প্রক্রিয়া রয়েছে যা প্রতি কয়েক সেকেন্ডে প্রতিবেদন করে যে কমান্ডটি এখনও চলছে এবং কমান্ডটি শেষ হয়ে গেলে সেই প্রক্রিয়াটি মেরে ফেলুন। উদাহরণ স্বরূপ:

#! / বিন / SH

সেমিডি () {ঘুম 5; প্রস্থান 24; }

সেমিডি ও # দীর্ঘ চলমান প্রক্রিয়াটি চালান
PID = $! # পিড রেকর্ড করুন

# একটি প্রক্রিয়া স্প্যান করুন যা নিয়মিতভাবে রিপোর্ট করে যে কমান্ডটি এখনও চলছে
যখন প্রতিধ্বনি "$ (তারিখ): $ পিড এখনও চলছে"; ঘুমাও 1; সম্পন্ন &
echoer = $!

# প্রক্রিয়াটি শেষ হলে প্রতিবেদককে হত্যা করার জন্য একটি ফাঁদ সেট করুন
ফাঁদ 'কিল $ ইকোয়ার' 0

# প্রক্রিয়াটি শেষ হওয়ার জন্য অপেক্ষা করুন
যদি অপেক্ষা $ pid; তারপর
    প্রতিধ্বনি "সেন্টিমিডি সফল"
আর
    প্রতিধ্বনি "সেমিডি ফেইলড !! (ফিরে এসেছেন?)"
ফাই

দুর্দান্ত টেমপ্লেট, ভাগ করে নেওয়ার জন্য ধন্যবাদ! আমি বিশ্বাস করি যে while kill -0 $pid 2> /dev/null; do X; done
ফাঁদগুলির

3

আমাদের টিমের একটি দূরবর্তী এসএসএইচ-এক্সিকিউটেড স্ক্রিপ্টের একই চাহিদা ছিল যা 25 মিনিটের নিষ্ক্রিয়তার পরে সময় নির্ধারণ করে। প্রতি সেকেন্ডে ব্যাকগ্রাউন্ড প্রক্রিয়াটি পরীক্ষা করে নিরীক্ষণ লুপের সাথে একটি সমাধান দেওয়া হয়েছে তবে নিষ্ক্রিয়তার সময়সীমা দমন করতে প্রতি 10 মিনিটে কেবল মুদ্রণ করা হচ্ছে।

long_running.sh & 
pid=$!

# Wait on a background job completion. Query status every 10 minutes.
declare -i elapsed=0
# `ps -p ${pid}` works on macOS and CentOS. On both OSes `ps ${pid}` works as well.
while ps -p ${pid} >/dev/null; do
  sleep 1
  if ((++elapsed % 600 == 0)); then
    echo "Waiting for the completion of the main script. $((elapsed / 60))m and counting ..."
  fi
done

# Return the exit code of the terminated background process. This works in Bash 4.4 despite what Bash docs say:
# "If neither jobspec nor pid specifies an active child process of the shell, the return status is 127."
wait ${pid}

2

উপরের সমাধানগুলির মতো একটি সাধারণ উদাহরণ। এর জন্য কোনও প্রক্রিয়া আউটপুট নিরীক্ষণের প্রয়োজন হয় না। পরবর্তী উদাহরণ আউটপুট অনুসরণ করতে লেজ ব্যবহার করে।

$ echo '#!/bin/bash' > tmp.sh
$ echo 'sleep 30; exit 5' >> tmp.sh
$ chmod +x tmp.sh
$ ./tmp.sh &
[1] 7454
$ pid=$!
$ wait $pid
[1]+  Exit 5                  ./tmp.sh
$ echo $?
5

প্রক্রিয়া আউটপুট অনুসরণ করতে লেজ ব্যবহার করুন এবং প্রক্রিয়াটি সম্পূর্ণ হলে প্রস্থান করুন।

$ echo '#!/bin/bash' > tmp.sh
$ echo 'i=0; while let "$i < 10"; do sleep 5; echo "$i"; let i=$i+1; done; exit 5;' >> tmp.sh
$ chmod +x tmp.sh
$ ./tmp.sh
0
1
2
^C
$ ./tmp.sh > /tmp/tmp.log 2>&1 &
[1] 7673
$ pid=$!
$ tail -f --pid $pid /tmp/tmp.log
0
1
2
3
4
5
6
7
8
9
[1]+  Exit 5                  ./tmp.sh > /tmp/tmp.log 2>&1
$ wait $pid
$ echo $?
5

1

আরেকটি সমাধান হ'ল প্রোক ফাইল সিস্টেমের মাধ্যমে প্রক্রিয়াগুলি নিরীক্ষণ করা (পিএস / গ্রেপ কম্বোর চেয়ে নিরাপদ); আপনি যখন কোনও প্রক্রিয়া শুরু করেন এটির / proc / $ পিডে সম্পর্কিত ফোল্ডার থাকে, সুতরাং সমাধানটি হতে পারে

#!/bin/bash
....
doSomething &
local pid=$!
while [ -d /proc/$pid ]; do # While directory exists, the process is running
    doSomethingElse
    ....
else # when directory is removed from /proc, process has ended
    wait $pid
    local exit_status=$?
done
....

আপনার পছন্দ অনুযায়ী এখন আপনি $स्थान_স্থানীয় ভেরিয়েবলটি ব্যবহার করতে পারেন।


ব্যাশে কাজ করে না? Syntax error: "else" unexpected (expecting "done")
বেনজমিং

1

এই পদ্ধতির সাহায্যে আপনার স্ক্রিপ্টটির ব্যাকগ্রাউন্ড প্রক্রিয়াটির জন্য অপেক্ষা করতে হবে না, আপনাকে প্রস্থান স্থিতির জন্য কেবল একটি অস্থায়ী ফাইল নিরীক্ষণ করতে হবে।

FUNCmyCmd() { sleep 3;return 6; };

export retFile=$(mktemp); 
FUNCexecAndWait() { FUNCmyCmd;echo $? >$retFile; }; 
FUNCexecAndWait&

এখন, আপনার স্ক্রিপ্টটি অন্য কিছু করতে পারে যখন আপনাকে কেবল retFile এর বিষয়বস্তুগুলি পর্যবেক্ষণ করতে হবে (এতে প্রস্থান সময়ের মতো আপনি চাইলে অন্য কোনও তথ্যও থাকতে পারে)।

পিএস .: বিটিডব্লিউ, আমি ব্যাশে চিন্তাভাবনা করেছিলাম


0

এটি আপনার প্রশ্নের বাইরেও প্রসারিত হতে পারে, তবে আপনি যদি সময়ের প্রক্রিয়াগুলির দৈর্ঘ্যের বিষয়ে উদ্বিগ্ন হন তবে আপনি সময়ের ব্যবধানের পরে পটভূমি প্রক্রিয়াগুলির চলমানের অবস্থানটি পরীক্ষা করতে আগ্রহী হতে পারেন। কোন শিশু পিআইডি এখনও ব্যবহার করে চলছে তা যাচাই করা যথেষ্ট সহজ pgrep -P $$, তবে ইতিমধ্যে মেয়াদ শেষ হয়ে গেছে এমন পিআইডিদের প্রস্থান স্থিতি পরীক্ষা করার জন্য আমি নীচের সমাধানটি নিয়ে এসেছি:

cmd1() { sleep 5; exit 24; }
cmd2() { sleep 10; exit 0; }

pids=()
cmd1 & pids+=("$!")
cmd2 & pids+=("$!")

lasttimeout=0
for timeout in 2 7 11; do
  echo -n "interval-$timeout: "
  sleep $((timeout-lasttimeout))

  # you can only wait on a pid once
  remainingpids=()
  for pid in ${pids[*]}; do
     if ! ps -p $pid >/dev/null ; then
        wait $pid
        echo -n "pid-$pid:exited($?); "
     else
        echo -n "pid-$pid:running; "
        remainingpids+=("$pid")
     fi
  done
  pids=( ${remainingpids[*]} )

  lasttimeout=$timeout
  echo
done

কোন ফলাফল:

interval-2: pid-28083:running; pid-28084:running; 
interval-7: pid-28083:exited(24); pid-28084:running; 
interval-11: pid-28084:exited(0); 

দ্রষ্টব্য: আপনি চাইলে $pidsজিনিসগুলি সরল করতে অ্যারের চেয়ে স্ট্রিং ভেরিয়েবলে পরিবর্তন করতে পারেন।


0

আমার সমাধানটি ছিল একটি মনিটরিং লুপের স্থিতিটি পাস করার জন্য একটি বেনামে পাইপ ব্যবহার করা। স্থিতি আদান প্রদানের জন্য কোনও অস্থায়ী ফাইল ব্যবহার করা হয় নি তাই পরিষ্কারের জন্য কিছুই নেই। আপনি যদি ব্যাকগ্রাউন্ড জবসের সংখ্যা সম্পর্কে অনিশ্চিত থাকেন তবে ব্রেকের অবস্থা হতে পারে [ -z "$(jobs -p)" ]

#!/bin/bash

exec 3<> <(:)

{ sleep 15 ; echo "sleep/exit $?" >&3 ; } &

while read -u 3 -t 1 -r STAT CODE || STAT="timeout" ; do
    echo "stat: ${STAT}; code: ${CODE}"
    if [ "${STAT}" = "sleep/exit" ] ; then
        break
    fi
done
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.