দুটি ব্যাকগ্রাউন্ড কমান্ড দেওয়া হয়েছে, উভয়ই প্রস্থান করলে বাকীটি বন্ধ করুন


14

আমার কাছে একটি সরল বাশ স্ক্রিপ্ট রয়েছে যা দুটি সার্ভার শুরু করে:

#!/bin/bash
(cd ./frontend && gulp serve) & (cd ./backend && gulp serve --verbose)

যদি দ্বিতীয় কমান্ডটি প্রস্থান করে, মনে হয় প্রথম কমান্ডটি চলমান থাকবে।

আমি কীভাবে এটি পরিবর্তন করতে পারি যাতে যদি কমান্ডটি প্রস্থান হয়, অন্যটি বন্ধ হয়ে যায়?

নোট করুন যে আমাদের ব্যাকগ্রাউন্ড প্রক্রিয়াগুলির ত্রুটি স্তরগুলি পরীক্ষা করার দরকার নেই, কেবল সেগুলি বেরিয়ে এসেছে কিনা।


না কেন gulp ./fronend/serve && gulp ./backend/serve --verbose?
হিমাইল

serveএকটি আর্গুমেন্ট, কোনও ফাইল নয়, সুতরাং বর্তমান ডিরেক্টরিটি সেট করা দরকার।
blah238

1
এছাড়াও এগুলি দীর্ঘ-চলমান প্রক্রিয়াগুলি যা একই সাথে চালানো দরকার, দুঃখিত যদি তা পরিষ্কার না হয়।
blah238

উত্তর:


22

এটি উভয় প্রক্রিয়া শুরু করে, প্রথমটির জন্য অপেক্ষা করে যা শেষ হয় এবং তারপরে অন্যটিকে হত্যা করে:

#!/bin/bash
{ cd ./frontend && gulp serve; } &
{ cd ./backend && gulp serve --verbose; } &
wait -n
pkill -P $$

কিভাবে এটা কাজ করে

  1. শুরু করুন:

    { cd ./frontend && gulp serve; } &
    { cd ./backend && gulp serve --verbose; } &
    

    উপরের দুটি কমান্ড দুটি পটভূমিতে প্রসেস শুরু করে।

  2. অপেক্ষা করুন

    wait -n

    এটি উভয় পটভূমি কাজ সমাপ্ত হওয়ার জন্য অপেক্ষা করে।

    -nবিকল্পের কারণে, এর জন্য 4.3 বা তার বেশি বাশ প্রয়োজন।

  3. বধ

    pkill -P $$

    এটি এমন কোনও কাজকে হত্যা করে যার জন্য বর্তমান প্রক্রিয়াটি পিতামাতার। অন্য কথায়, এটি যে কোনও পটভূমি প্রক্রিয়া চলছে যা এখনও চলছে kill

    আপনার সিস্টেমে না থাকলে pkillএই লাইনটি প্রতিস্থাপনের চেষ্টা করুন:

    kill 0

    যা বর্তমান প্রক্রিয়া গোষ্ঠীকে হত্যা করে

সহজেই পরীক্ষার যোগ্য উদাহরণ

স্ক্রিপ্ট পরিবর্তন করে, আমরা এটি gulpইনস্টল না করেও এটি পরীক্ষা করতে পারি :

$ cat script.sh 
#!/bin/bash
{ sleep $1; echo one;  } &
{ sleep $2; echo two;  } &
wait -n
pkill -P $$
echo done

উপরের স্ক্রিপ্টটি চালানো যেতে পারে bash script.sh 1 3এবং প্রথম প্রক্রিয়াটি প্রথমে সমাপ্ত হয়। বিকল্পভাবে, একজন এটি হিসাবে চালাতে পারে bash script.sh 3 1এবং দ্বিতীয় প্রক্রিয়াটি প্রথমে সমাপ্ত হবে। উভয় ক্ষেত্রেই, কেউ দেখতে পাবে যে এটি পছন্দসইভাবে কাজ করে।


এটি দুর্দান্ত দেখাচ্ছে। দুর্ভাগ্যক্রমে এই আদেশগুলি আমার বাশ পরিবেশে (এমএসএসজিট) কাজ করে না। এটি নির্দিষ্ট না করার জন্য এটি আমার খারাপ। যদিও আমি এটি একটি বাস্তব লিনাক্স বাক্সে চেষ্টা করব।
blah238

(1) সমস্ত সংস্করণ কমান্ডের বিকল্পটিকে bashসমর্থন করে -nনা wait। (২) আমি প্রথম বাক্যটির সাথে 100% সম্মত হই - আপনার সমাধানটি দুটি প্রক্রিয়া শুরু করে, প্রথমটির সমাপ্তির জন্য অপেক্ষা করে এবং পরে অন্যটিকে হত্যা করে। তবে প্রশ্নটি বলে ... "যদি কমান্ড ত্রুটি থেকে যায় তবে অন্যটি বন্ধ হয়ে যায়?" আমি বিশ্বাস করি যে আপনার সমাধানটি ওপি যা চায় তা নয়। (৩) আপনি কেন বদলে (…) &গেলেন { …; } &? &বাহিনী তালিকা (গ্রুপ কমান্ড) যা হোক একটি subshell চালানোর জন্য। আইএমএইচও, আপনি চরিত্রগুলি যুক্ত করেছেন এবং সম্ভবত কোনও বিভ্রান্তি ঘটিয়েছেন (এটি বুঝতে দু'বার আমার দৃষ্টিপাত করতে হবে) কোনও লাভ নেই।
জি-ম্যান

1
জন সঠিক, তারা ওয়েব সার্ভার যা সাধারণত কোনওরকমই চলমান রাখা উচিত যদি ত্রুটি না ঘটে বা তাদের সমাপ্তির লক্ষণ না দেওয়া হয়। সুতরাং আমি মনে করি না যে আমাদের প্রতিটি প্রক্রিয়াটির ত্রুটি স্তরটি পরীক্ষা করা দরকার, ঠিক এটি এখনও চলছে কিনা।
blah238

2
pkillআমার জন্য উপলব্ধ না কিন্তু kill 0একই প্রভাব আছে বলে মনে হচ্ছে। এছাড়াও আমি উইন্ডোজ পরিবেশের জন্য আমার গিট আপডেট করেছি এবং এটি wait -nএখনকার মতো মনে হচ্ছে , তাই আমি এই উত্তরটি গ্রহণ করছি।
blah238

1
মজাদার. যদিও আমি দেখতে যে যে আচরণের জন্য নথিভুক্ত করা কিছু সংস্করণে এর kill। আমার সিস্টেমে ডকুমেন্টেশন এটি উল্লেখ করে না। যাইহোক, যাইহোক kill 0কাজ করে। গুড ফাইন্ড!
1024

1

এটা কৌতুকপূর্ণ। আমি যা পরিকল্পনা করেছি তা এখানে; এটি সরলকরণ / প্রবাহিত করা সম্ভব হতে পারে:

#!/bin/sh

pid1file=$(mktemp)
pid2file=$(mktemp)
stat1file=$(mktemp)
stat2file=$(mktemp)

while true; do sleep 42; done &
main_sleeper=$!

(cd frontend && gulp serve           & echo "$!" > "$pid1file";
    wait "$!" 2> /dev/null; echo "$?" > "$stat1file"; kill "$main_sleeper" 2> /dev/null) &
(cd backend  && gulp serve --verbose & echo "$!" > "$pid2file";
    wait "$!" 2> /dev/null; echo "$?" > "$stat2file"; kill "$main_sleeper" 2> /dev/null) &
sleep 1
wait "$main_sleeper" 2> /dev/null

if stat1=$(<"$stat1file")  &&  [ "$stat1" != "" ]  &&  [ "$stat1" != 0 ]
then
        echo "First process failed ..."
        if pid2=$(<"$pid2file")  &&  [ "$pid2" != "" ]
        then
                echo "... killing second process."
                kill "$pid2" 2> /dev/null
        fi
fi
if [ "$stat1" = "" ]  &&  \
   stat2=$(<"$stat2file")  &&  [ "$stat2" != "" ]  &&  [ "$stat2" != 0 ]
then
        echo "Second process failed ..."
        if pid1=$(<"$pid1file")  &&  [ "$pid1" != "" ]
        then
                echo "... killing first process."
                kill "$pid1" 2> /dev/null
        fi
fi

wait
if stat1=$(<"$stat1file")
then
        echo "Process 1 terminated with status $stat1."
else
        echo "Problem getting status of process 1."
fi
if stat2=$(<"$stat2file")
then
        echo "Process 2 terminated with status $stat2."
else
        echo "Problem getting status of process 2."
fi
  • প্রথমে এমন একটি প্রক্রিয়া শুরু করুন ( while true; do sleep 42; done &) যা চিরকাল ঘুমায় / বিরাম দেয়। যদি আপনি নিশ্চিত হন যে আপনার দুটি কমান্ড নির্দিষ্ট সময়ের মধ্যে শেষ হয়ে যাবে (উদাহরণস্বরূপ, এক ঘন্টা), আপনি এটি একক ঘুমে পরিবর্তন করতে পারেন যা এর চেয়ে বেশি হবে (যেমন, sleep 3600)। সময়সীমা হিসাবে এটি ব্যবহার করার জন্য আপনি নীচের যুক্তি পরিবর্তন করতে পারেন; অর্থাত্, প্রক্রিয়াগুলি যদি তারা এখনও অনেক সময়ের পরে চলমান থাকে তবে হত্যা করুন। (দ্রষ্টব্য যে উপরের স্ক্রিপ্টটি বর্তমানে এটি করে না))
  • দুটি অ্যাসিনক্রোনাস (সমবর্তী পটভূমি) প্রক্রিয়া শুরু করুন।
    • আপনি প্রয়োজন হবে না ./জন্য cd
    • command & echo "$!" > somewhere; wait "$!" একটি কৌতূহলোদ্দীপক গঠন যা অ্যাসিক্রোনাল পদ্ধতিতে একটি প্রক্রিয়া শুরু করে, এর পিআইডি ক্যাপচার করে এবং তার জন্য অপেক্ষা করে; এটি অগ্রণী (সিঙ্ক্রোনাস) প্রক্রিয়া অনুসারে তৈরি করে। তবে এটি এমন একটি (…)তালিকার মধ্যে ঘটে যা সম্পূর্ণরূপে পটভূমিতে থাকে, সুতরাং gulpপ্রক্রিয়াগুলি অবিচ্ছিন্নভাবে চালিত হয়।
    • যে কোনও gulpপ্রক্রিয়াটি প্রস্থান করার পরে , একটি স্থায়ী ফাইলে এর স্থিতি লিখুন এবং "চিরতরে ঘুম" প্রক্রিয়াটি মেরে ফেলুন।
  • sleep 1 এমন একটি দৌড়ের অবস্থা থেকে সুরক্ষিত করার জন্য যেখানে দ্বিতীয়টি ফাইলটিতে তার পিআইডি লেখার সুযোগ পাওয়ার আগে প্রথম ব্যাকগ্রাউন্ড প্রক্রিয়াটি মারা যায়।
  • "চিরদিনের ঘুম" প্রক্রিয়াটি শেষ হওয়ার জন্য অপেক্ষা করুন। উপরে উল্লিখিত হিসাবে উভয়gulp প্রক্রিয়াটি প্রস্থান করার পরে এটি ঘটে ।
  • কোন পটভূমি প্রক্রিয়াটি সমাপ্ত হয়েছে তা দেখুন। যদি এটি ব্যর্থ হয় তবে অন্যটিকে হত্যা করুন।
  • যদি একটি প্রক্রিয়া ব্যর্থ হয় এবং আমরা অন্যটিকে হত্যা করি, তবে দ্বিতীয়টি মোড়ানোর জন্য অপেক্ষা করুন এবং একটি ফাইলে তার স্থিতি সংরক্ষণ করুন। যদি প্রথম প্রক্রিয়াটি সফলভাবে শেষ হয় তবে দ্বিতীয়টি শেষ হওয়ার জন্য অপেক্ষা করুন।
  • দুটি প্রক্রিয়া স্থিতি পরীক্ষা করুন।

1

সম্পূর্ণতার জন্য এখানে আমি ব্যবহার করে শেষ করেছি:

#!/bin/bash
(cd frontend && gulp serve) &
(cd backend && gulp serve --verbose) &
wait -n
kill 0

এটি আমার জন্য উইন্ডোজ 2.5.3 64-বিটের জন্য গিতে কাজ করে। পুরানো সংস্করণগুলি -nবিকল্পটি গ্রহণ নাও করতে পারে wait


1

আমার সিস্টেম (CentOS) তারিখে, waitনেই -nতাই আমি এটা করেছে:

{ sleep 3; echo one;  } &
FOO=$!
{ sleep 6; echo two;  } &
wait $FOO
pkill -P $$

এটি "হয়" এর জন্য অপেক্ষা করে না, বরং প্রথমটির জন্য অপেক্ষা করে। তবে এখনও কোন সার্ভারটি বন্ধ করা হবে তা যদি আপনি জানেন তবে এটি সহায়তা করতে পারে।


অপশন waitরয়েছে কিনা -nতা নির্ভর করে আপনি যে শেলটি ব্যবহার করছেন তার উপর নির্ভর করে, লিনাক্স বিতরণ নয়।
কুসালানন্দ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.