আপনি কীভাবে বাশ স্ক্রিপ্ট থেকে সমান্তরালে একাধিক প্রোগ্রাম পরিচালনা করবেন?


245

আমি একটি .sh ফাইল লেখার চেষ্টা করছি যা একই সাথে অনেকগুলি প্রোগ্রাম চালায়

আমি এই চেষ্টা করেছিলাম

prog1 
prog2

তবে এটি প্রগ 1 চালায় এবং প্রগ 1 শেষ হওয়া পর্যন্ত অপেক্ষা করে এবং তারপরে প্রগ 2 শুরু হয় ...

সুতরাং আমি কীভাবে তাদের সমান্তরালভাবে চালাতে পারি?

উত্তর:


216
prog1 &
prog2 &

49
ভুলে যাবেন না wait! হ্যাঁ, ব্যাশে আপনি স্ক্রিপ্টের শিশু প্রক্রিয়াগুলির জন্য অপেক্ষা করতে পারেন।
ডমি 100001

5
আরেকটি বিকল্প হ'ল nohupশেলটি স্তব্ধ হয়ে যাওয়ার পরে প্রোগ্রামটি মারা যাওয়ার হাত থেকে রক্ষা করার জন্য ব্যবহার করা।
ফিলিপ

@ লায়লং: হ্যাঁ, এটি তিন বা ততোধিক প্রোগ্রামের সাথেও কাজ করবে।
স্মৃতি 22

302

কেমন:

prog1 & prog2 && fg

এটা হবে:

  1. স্টার্ট prog1
  2. এটি ব্যাকগ্রাউন্ডে প্রেরণ করুন, তবে এর আউটপুট মুদ্রণ চালিয়ে যান।
  3. স্টার্ট prog2এবং পুরোভূমিতে এটা রাখা , তাই আপনি এটি দিয়ে বন্ধ করে দিতে পারেন ctrl-c
  4. আপনি যখন ঘনিষ্ঠ prog2, আপনি ফিরে আসবেন prog1'র ফোরগ্রাউন্ড , তাই আপনাকে আরো ঘনিষ্ঠ এটা দিয়ে করতে পারেন ctrl-c

9
সেখানে একটি সহজ উপায় বিনষ্ট হয় prog1যখন prog2বন্ধ? চিন্তা করুন node srv.js & cucumberjs
জেপি

20
এটি কেবল চেষ্টা করে দেখুন, এবং এটি আমার জন্য প্রত্যাশার মতো কার্যকর হয়নি। তবে, একটি সামান্য পরিবর্তন কাজ করেছে: prog1 & prog2 ; fg এটি একবারে একাধিক এসএস টানেল চালানোর জন্য। আশা করি এটি কাউকে সাহায্য করবে।
jnadro52

2
@ jnadro52 আপনার সমাধানটির প্রভাব রয়েছে যে যদি prog2অবিলম্বে চলতে ব্যর্থ হয় তবে আপনি prog1অগ্রভাগে ফিরে আসবেন । এটি যদি পছন্দসই হয় তবে ঠিক আছে।
ওরে ব্যান্ড

3
এসএসএইচ শেল-এ আপনি যদি কোনও কমান্ড এভাবে চালিত করেন তবে প্রোগ 1 কে হত্যা করা দুষ্কর হবে। Ctrl-c আমার পক্ষে কাজ করে না। এমনকি পুরো টার্মিনালটি বামে প্রগ 1 চালিয়ে যাচ্ছে।
পারদ0114

14
@ jnadro52 উভয় প্রক্রিয়া একবারে সমাপ্ত করার একটি উপায় prog1 & prog2 && kill $!
zaboco

79

আপনি ব্যবহার করতে পারেন wait:

some_command &
P1=$!
other_command &
P2=$!
wait $P1 $P2

এটি ভেরিয়েবলগুলিকে ব্যাকগ্রাউন্ড প্রোগ্রাম পিআইডি বরাদ্দ করে ( $!এটি সর্বশেষ প্রবর্তিত প্রক্রিয়া 'পিআইডি), তারপরে waitকমান্ডটি তাদের জন্য অপেক্ষা করে। এটি দুর্দান্ত কারণ আপনি যদি স্ক্রিপ্টটি হত্যা করেন তবে এটি প্রক্রিয়াগুলিকেও মারবে!


4
আমার অভিজ্ঞতায় , অপেক্ষার হত্যাকান্ড অন্যান্য প্রক্রিয়াগুলিকেও হত্যা করে না।
কুইন কমেন্ডেন্ট

1
যদি আমি একটি লুপে ব্যাকগ্রাউন্ড প্রক্রিয়াগুলি শুরু করি তবে পরবর্তী কমান্ডগুলির সেটটি কার্যকর করার সাথে আমি কীভাবে প্রতিটি পটভূমি প্রক্রিয়াটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে পারি। #!/usr/bin/env bash ARRAY='cat bat rat' for ARR in $ARRAY do ./run_script1 $ARR & done P1=$! wait $P1 echo "INFO: Execution of all background processes in the for loop has completed.."
যশ

@ যশ আমি মনে করি আপনি প্রক্রিয়া আইডিগুলিকে একটি অ্যারেতে সংরক্ষণ করতে পারেন, তারপরে অ্যারেতে কল করুন। আমি মনে করি ${}এটি একটি স্ট্রিং তালিকায় বা অনুরূপ মধ্যে ইন্টারপোলেট করতে আপনাকে ব্যবহার করতে হবে।
trusktr

সেরা উত্তর, এবং আমার জন্য স্ক্রিপ্টটি হত্যার ফলে প্রক্রিয়াগুলিও খুব মারে!
ম্যাকস

67

জিএনইউ সমান্তরাল http://www.gnu.org/software/parallel/ এর সাথে এটি সহজ:

(echo prog1; echo prog2) | parallel

বা আপনি যদি পছন্দ করেন:

parallel ::: prog1 prog2

আরও জানুন:

  • দ্রুত পরিচয়ের জন্য ইন্ট্রো ভিডিওটি দেখুন: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
  • টিউটোরিয়াল (ম্যান প্যারালাল_ টিউটোরিয়াল) দিয়ে যান। আপনার কমান্ড লাইন এটির জন্য আপনাকে ভালবাসবে।
  • পড়ুন: ওলে টাঙে, জিএনইউ সমান্তরাল 2018 (ওলে টাঞ্জ, 2018)।

4
এটি লক্ষণীয় যে parallelবিভিন্ন সিনট্যাক্স সহ বিভিন্ন সংস্করণ রয়েছে । উদাহরণস্বরূপ, ডেবিয়ান ডেরিভেটিভস moreutilsপ্যাকেজে প্যাকেজে একটি আলাদা কমান্ড রয়েছে parallelযা একেবারেই আলাদা আচরণ করে।
জোয়েল ক্রস

4
হয় parallelব্যবহার বেশী ভালো &?
অপ্টিমাস প্রাইম

2
@ অপ্টিমাসপ্রাইম এটি সত্যই নির্ভর করে। জিএনইউ সমান্তরাল কিছু ওভারহেড পরিচয় করিয়ে দেয় তবে এর বিনিময়ে আপনাকে চলমান কাজ এবং আউটপুটকে আরও অনেক বেশি নিয়ন্ত্রণ দেয়। যদি দুটি কাজ একই সময়ে মুদ্রণ করা হয় তবে জিএনইউ সমান্তরাল আউটপুট মিশ্রিত না হয়েছে তা নিশ্চিত করবে।
ওলে টাঞ্জ

1
parallelকোরের তুলনায় আরও বেশি চাকরি থাকলে @ অপটিমাসপ্রাইম আরও ভাল হয়, এক্ষেত্রে কোর &প্রতি একাধিক কাজ একবারে চালানো হবে। (সিএফ। পায়রাহোল নীতি )
জেরেমিয়া

2
@ ওলেট্যাঞ্জ " আপনার কমান্ড লাইন এটির জন্য আপনাকে ভালবাসবে Me" আমিও। ☺
জেরেমিয়া

55

আপনি যদি সহজেই একাধিক প্রক্রিয়াটি সহজে চালাতে ও মারতে সক্ষম হতে চান তবে ctrl-cএটি আমার প্রিয় পদ্ধতি: একটি (…)সাবশেলে একাধিক ব্যাকগ্রাউন্ড প্রক্রিয়া তৈরি করে এবং সম্পাদন SIGINTকরতে ট্র্যাপ kill 0, যা সাব-শেল গ্রুপে তৈরি সমস্ত কিছুকে মেরে ফেলবে:

(trap 'kill 0' SIGINT; prog1 & prog2 & prog3)

আপনার জটিল প্রক্রিয়া সম্পাদন কাঠামো থাকতে পারে এবং সমস্ত কিছু একক দিয়ে বন্ধ হয়ে যাবে ctrl-c(কেবল নিশ্চিত করুন যে শেষ প্রক্রিয়াটি অগ্রভাগে চালিত হয়েছে, অর্থাত্ &পরে কোনওটি অন্তর্ভুক্ত করবেন নাprog1.3 ):

(trap 'kill 0' SIGINT; prog1.1 && prog1.2 & (prog2.1 | prog2.2 || prog2.3) & prog1.3)

এটি এখন পর্যন্ত সেরা উত্তর।
নিক

10

xargs -P <n> আপনি চালানোর অনুমতি দেয় <n> সমান্তরালভাবে কমান্ড ।

যদিও -P একটি নন-মানসম্পন্ন বিকল্প, জিএনইউ (লিনাক্স) এবং ম্যাকোএস / বিএসডি বাস্তবায়ন উভয়ই এটি সমর্থন করে।

নিম্নলিখিত উদাহরণ:

  • সর্বাধিক রানএক সাথে সমান্তরালে 3 টি কমান্ড ,
  • অতিরিক্ত কমান্ডগুলি কেবল তখনই শুরু করা হয় যখন আগে চালু করা প্রক্রিয়াটি শেষ হয়।
time xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF'
sleep 1; echo 1
sleep 2; echo 2
sleep 3; echo 3
echo 4
EOF

আউটপুটটি এমন দেখাচ্ছে:

1   # output from 1st command 
4   # output from *last* command, which started as soon as the count dropped below 3
2   # output from 2nd command
3   # output from 3rd command

real    0m3.012s
user    0m0.011s
sys 0m0.008s

সময়টি দেখায় যে কমান্ডগুলি সমান্তরালভাবে চালিত হয়েছিল (শেষ কমান্ডটি মূল 3 টি প্রথম সমাপ্ত হওয়ার পরে শুরু হয়েছিল তবে খুব দ্রুত কার্যকর করা হয়েছিল)।

xargsকমান্ড নিজেই ফিরে আসবে না যতক্ষণ না সব কমান্ড সমাপ্ত করেছেন, কিন্তু আপনার নিয়ন্ত্রণ অপারেটর সঙ্গে এটি সসীম দ্বারা পটভূমিতে এটা নির্বাহ করতে পারেন &এবং তারপর ব্যবহার waitbuiltin সমগ্র জন্য অপেক্ষা করতে xargsহুকুম শেষ করতে।

{
  xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF'
sleep 1; echo 1
sleep 2; echo 2
sleep 3; echo 3
echo 4
EOF
} &

# Script execution continues here while `xargs` is running 
# in the background.
echo "Waiting for commands to finish..."

# Wait for `xargs` to finish, via special variable $!, which contains
# the PID of the most recently started background process.
wait $!

বিঃদ্রঃ:

  • বিএসডি / ম্যাকোস xargsআপনাকে সমান্তরালভাবে স্পষ্টভাবে চলতে কমান্ডের গণনা নির্দিষ্ট করতে হবে , যেখানে জিএনইউ xargsআপনাকে সমান্তরালে যতটা সম্ভব-P 0 চালানোর জন্য নির্দিষ্ট করতে দেয় ।

  • সমান্তরালভাবে চালিত প্রক্রিয়াগুলি থেকে আউটপুট উত্পন্ন হওয়ার সাথে সাথে উপস্থিত হয় , সুতরাং এটি অনির্দেশ্যভাবে আন্তঃবিশ্বাস্য হবে

    • জিএনইউ parallel, যেমন ওলে এর উত্তরে উল্লিখিত হয়েছে ( বেশিরভাগ প্ল্যাটফর্মের সাথে স্ট্যান্ডার্ড আসে না ), প্রতিটি প্রক্রিয়া ভিত্তিতে আউটপুটটি সুবিধামত সিরিয়ালাইজ করে (গোষ্ঠীগুলি) দেয় এবং আরও অনেক উন্নত বৈশিষ্ট্য সরবরাহ করে।

9
#!/bin/bash
prog1 & 2> .errorprog1.log; prog2 & 2> .errorprog2.log

পৃথক লগগুলিতে ত্রুটিগুলি পুনর্নির্দেশ করুন।


13
আপনাকে পুনর্নির্দেশগুলির পরে অ্যাম্পারস্যান্ডগুলি স্থাপন করতে হবে এবং সেমিকোলনটি ছাড়তে হবে (অ্যাম্পারস্যান্ড কমান্ড বিভাজকের কাজটিও সম্পাদন করবে):prog1 2> .errorprog1.log & prog2 2> .errorprog2.log &
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

সেমিকোলন উভয় কোমন্ডকে কার্যকর করে, এটি ভালভাবে কাজ করে দেখতে আপনি ডি বাশকে পরীক্ষা করতে পারেন;) উদাহরণ: pwd & 2> .errorprog1.log; প্রতিধ্বনি "wop" & 2> .errorprog2.log আপনি যখন প্রোগ্রাম রাখেন এবং আপনি পটভূমিতে রাখেন এবং তত্ক্ষণাত্ পরবর্তী কমান্ডটি কার্যকর করেন।
ফারমিন

2
এটি কাজ করে না - ত্রুটিগুলি ফাইলে পুনঃনির্দেশিত হয় না। সঙ্গে চেষ্টা করুন: ls notthere1 & 2> .errorprog1.log; ls notthere2 & 2>.errorprog2.log। ত্রুটিগুলি কনসোলে যায় এবং উভয় ত্রুটি ফাইল খালি থাকে। @ ডেনিস উইলিয়ামসন &যেমন বলেছেন যে বিভাজনকারী ;, তেমনি (ক) কমান্ডের শেষে যেতে হবে (যে কোনও পুনর্নির্দেশের পরে), এবং (খ) আপনার একেবারেই দরকার নেই ;:-)
স্মারক

8

একটি খুব দরকারী প্রোগ্রাম যা নোহুপকে কল করে।

     nohup - run a command immune to hangups, with output to a non-tty

4
nohupনিজেই ব্যাকগ্রাউন্ডে কিছু চালায় না, এবং ব্যাকগ্রাউন্ডে nohupকাজগুলি চালনার জন্য প্রয়োজনীয়তা বা পূর্বশর্ত প্রয়োজন নয়। এগুলি প্রায়শই একসাথে দরকারী তবে যেমন প্রশ্নের উত্তর দেয় না।
ট্রিপলি

8

সমান্তরালে সর্বোচ্চ এন প্রক্রিয়া চালানোর জন্য আমি এখানে একটি ফাংশন ব্যবহার করছি (উদাহরণে এন = 4):

max_children=4

function parallel {
  local time1=$(date +"%H:%M:%S")
  local time2=""

  # for the sake of the example, I'm using $2 as a description, you may be interested in other description
  echo "starting $2 ($time1)..."
  "$@" && time2=$(date +"%H:%M:%S") && echo "finishing $2 ($time1 -- $time2)..." &

  local my_pid=$$
  local children=$(ps -eo ppid | grep -w $my_pid | wc -w)
  children=$((children-1))
  if [[ $children -ge $max_children ]]; then
    wait -n
  fi
}

parallel sleep 5
parallel sleep 6
parallel sleep 7
parallel sleep 8
parallel sleep 9
wait

যদি ম্যাক্স_চিল্ডেন কোরগুলির সংখ্যায় সেট করা থাকে তবে এই ফাংশনটি নিষ্ক্রিয় কোরগুলি এড়াতে চেষ্টা করবে।


1
চমৎকার স্নিপেট, তবে আমি আমার ব্যাশের আওতায় "ওয়েট-এন" এর ব্যাখ্যা খুঁজে পাই না এটি বলে যে এটি একটি অবৈধ বিকল্প। টাইপো নাকি আমি কিছু মিস করেছি?
এমমানুয়েল দেবাক্স

1
@EmmanuelDevaux: wait -nপ্রয়োজন bash4.3+ এবং এটি জন্য অপেক্ষা করতে যুক্তিবিজ্ঞান পরিবর্তন কোন নিদিষ্ট / উহ্য প্রক্রিয়ার বিনষ্ট।
mklement0

যদি কোনও কাজটি যদি ব্যর্থ হয় তবে আমি স্ক্রিপ্টগুলি শেষ করতে চাই?
52coder

@ 52 কোডার আপনি একটি ব্যর্থ শিশুকে ক্যাপচার করতে ফাংশনটি সামঞ্জস্য করতে পারেন, যেমন: "$ @" &&2 2 = $ (তারিখ + "% এইচ:% এম:% এস") এবং & প্রতিধ্বনি "সমাপ্তি $ 2 ($ সময় 1 - $ সময় 2) ) ... "|| ত্রুটি = 1 &। তারপরে "যদি" অংশে ত্রুটির জন্য পরীক্ষা করুন এবং প্রয়োজনে ফাংশনটি বাতিল করুন
আর্নালডোকান

7

আপনি পিপিএস চেষ্টা করতে পারেন । পিপিএস বরং শক্তিশালী - আপনি একটি মিনি-ক্লাস্টার তৈরি করতে পারেন। এক্সার্গস-পিও আপনাকে দরকারী করতে পারে যদি আপনার কাছে বিব্রতকরভাবে সমান্তরাল প্রক্রিয়াকরণের একটি ব্যাচ পেয়ে থাকে।


7

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

#!/bin/bash

# Add the full path processes to run to the array
PROCESSES_TO_RUN=("/home/joao/Code/test/prog_1/prog1" \
                  "/home/joao/Code/test/prog_2/prog2")
# You can keep adding processes to the array...

for i in ${PROCESSES_TO_RUN[@]}; do
    ${i%/*}/./${i##*/} > ${i}.log 2>&1 &
    # ${i%/*} -> Get folder name until the /
    # ${i##*/} -> Get the filename after the /
done

# Wait for the processes to finish
wait

সূত্র: http://joaoperibeiro.com/execute-m Multipleple-program-and-redirect-their-outputs-linux/


4

প্রক্রিয়া স্প্যানিং ম্যানেজার

অবশ্যই, প্রযুক্তিগতভাবে এগুলি প্রক্রিয়া, এবং এই প্রোগ্রামটিকে প্রকৃতপক্ষে একটি প্রক্রিয়া স্প্যানিং ম্যানেজার বলা উচিত, তবে এটি কেবল যখন এম্পারস্যান্ড ব্যবহার করে কাঁটাচামচ করে তখন এটি কাজ করে সেই পথেই এটি কাঁটা () বা সম্ভবত ক্লোন () সিস্টেম কল ব্যবহার করে যা pthread_create () এর মত স্মৃতি ভাগ করে নেওয়ার চেয়ে আলাদা মেমরি স্পেসে ক্লোন করে। যদি BASH পরবর্তীকে সমর্থন করে তবে প্রতিটি "মৃত্যুদন্ডের ক্রম" ঠিক একই রকম কাজ করবে এবং আরও দক্ষ মেমরির পদচিহ্ন অর্জনের সময় এটি প্রচলিত থ্রেড হিসাবে অভিহিত হতে পারে। কার্যকরীভাবে তবে এটি একইরকম হয় যদিও গ্লোবাল ভেরিয়েবলগুলি প্রতিটি কর্মী ক্লোনটিতে উপলব্ধ না হওয়ার কারণে কিছুটা জটিল হয়ে যায় তাই সমালোচনামূলক বিভাগগুলি পরিচালনা করতে আন্ত-প্রক্রিয়া যোগাযোগ ফাইল এবং মূল ফ্লক সেমফোরের ব্যবহার। অবশ্যই বেস থেকে প্রার্থনা করা এখানে প্রাথমিক উত্তর তবে আমি মনে করি যেন মানুষ তা জানে তবে কেবল এটি কাঁটাচামচ না করে বরং কী তৈরি হয়েছে তা পরিচালনা করতে চাইছেন এবং ভুলে যাবেন। এটি একটি একক সংস্থান অ্যাক্সেসের জন্য কাঁটাচামচ প্রক্রিয়াগুলির 200 টি দৃষ্টান্ত পরিচালনা করার একটি উপায় প্রদর্শন করে। স্পষ্টতই এটি ওভারকিল তবে আমি এটি লেখা উপভোগ করেছি তাই আমি চালিয়ে গেলাম। সেই অনুযায়ী আপনার টার্মিনালের আকার বৃদ্ধি করুন। আশা করি এটি আপনার কাজে লাগবে।

ME=$(basename $0)
IPC="/tmp/$ME.ipc"      #interprocess communication file (global thread accounting stats)
DBG=/tmp/$ME.log
echo 0 > $IPC           #initalize counter
F1=thread
SPAWNED=0
COMPLETE=0
SPAWN=1000              #number of jobs to process
SPEEDFACTOR=1           #dynamically compensates for execution time
THREADLIMIT=50          #maximum concurrent threads
TPS=1                   #threads per second delay
THREADCOUNT=0           #number of running threads
SCALE="scale=5"         #controls bc's precision
START=$(date +%s)       #whence we began
MAXTHREADDUR=6         #maximum thread life span - demo mode

LOWER=$[$THREADLIMIT*100*90/10000]   #90% worker utilization threshold
UPPER=$[$THREADLIMIT*100*95/10000]   #95% worker utilization threshold
DELTA=10                             #initial percent speed change

threadspeed()        #dynamically adjust spawn rate based on worker utilization
{
   #vaguely assumes thread execution average will be consistent
   THREADCOUNT=$(threadcount)
   if [ $THREADCOUNT -ge $LOWER ] && [ $THREADCOUNT -le $UPPER ] ;then
      echo SPEED HOLD >> $DBG
      return
   elif [ $THREADCOUNT -lt $LOWER ] ;then
      #if maxthread is free speed up
      SPEEDFACTOR=$(echo "$SCALE;$SPEEDFACTOR*(1-($DELTA/100))"|bc)
      echo SPEED UP $DELTA%>> $DBG
   elif [ $THREADCOUNT -gt $UPPER ];then
      #if maxthread is active then slow down
      SPEEDFACTOR=$(echo "$SCALE;$SPEEDFACTOR*(1+($DELTA/100))"|bc)
      DELTA=1                            #begin fine grain control
      echo SLOW DOWN $DELTA%>> $DBG
   fi

   echo SPEEDFACTOR $SPEEDFACTOR >> $DBG

   #average thread duration   (total elapsed time / number of threads completed)
   #if threads completed is zero (less than 100), default to maxdelay/2  maxthreads

   COMPLETE=$(cat $IPC)

   if [ -z $COMPLETE ];then
      echo BAD IPC READ ============================================== >> $DBG
      return
   fi

   #echo Threads COMPLETE $COMPLETE >> $DBG
   if [ $COMPLETE -lt 100 ];then
      AVGTHREAD=$(echo "$SCALE;$MAXTHREADDUR/2"|bc)
   else
      ELAPSED=$[$(date +%s)-$START]
      #echo Elapsed Time $ELAPSED >> $DBG
      AVGTHREAD=$(echo "$SCALE;$ELAPSED/$COMPLETE*$THREADLIMIT"|bc)
   fi
   echo AVGTHREAD Duration is $AVGTHREAD >> $DBG

   #calculate timing to achieve spawning each workers fast enough
   # to utilize threadlimit - average time it takes to complete one thread / max number of threads
   TPS=$(echo "$SCALE;($AVGTHREAD/$THREADLIMIT)*$SPEEDFACTOR"|bc)
   #TPS=$(echo "$SCALE;$AVGTHREAD/$THREADLIMIT"|bc)  # maintains pretty good
   #echo TPS $TPS >> $DBG

}
function plot()
{
   echo -en \\033[${2}\;${1}H

   if [ -n "$3" ];then
         if [[ $4 = "good" ]];then
            echo -en "\\033[1;32m"
         elif [[ $4 = "warn" ]];then
            echo -en "\\033[1;33m"
         elif [[ $4 = "fail" ]];then
            echo -en "\\033[1;31m"
         elif [[ $4 = "crit" ]];then
            echo -en "\\033[1;31;4m"
         fi
   fi
      echo -n "$3"
      echo -en "\\033[0;39m"
}

trackthread()   #displays thread status
{
   WORKERID=$1
   THREADID=$2
   ACTION=$3    #setactive | setfree | update
   AGE=$4

   TS=$(date +%s)

   COL=$[(($WORKERID-1)/50)*40]
   ROW=$[(($WORKERID-1)%50)+1]

   case $ACTION in
      "setactive" )
         touch /tmp/$ME.$F1$WORKERID  #redundant - see main loop
         #echo created file $ME.$F1$WORKERID >> $DBG
         plot $COL $ROW "Worker$WORKERID: ACTIVE-TID:$THREADID INIT    " good
         ;;
      "update" )
         plot $COL $ROW "Worker$WORKERID: ACTIVE-TID:$THREADID AGE:$AGE" warn
         ;;
      "setfree" )
         plot $COL $ROW "Worker$WORKERID: FREE                         " fail
         rm /tmp/$ME.$F1$WORKERID
         ;;
      * )

      ;;
   esac
}

getfreeworkerid()
{
   for i in $(seq 1 $[$THREADLIMIT+1])
   do
      if [ ! -e /tmp/$ME.$F1$i ];then
         #echo "getfreeworkerid returned $i" >> $DBG
         break
      fi
   done
   if [ $i -eq $[$THREADLIMIT+1] ];then
      #echo "no free threads" >> $DBG
      echo 0
      #exit
   else
      echo $i
   fi
}

updateIPC()
{
   COMPLETE=$(cat $IPC)        #read IPC
   COMPLETE=$[$COMPLETE+1]     #increment IPC
   echo $COMPLETE > $IPC       #write back to IPC
}


worker()
{
   WORKERID=$1
   THREADID=$2
   #echo "new worker WORKERID:$WORKERID THREADID:$THREADID" >> $DBG

   #accessing common terminal requires critical blocking section
   (flock -x -w 10 201
      trackthread $WORKERID $THREADID setactive
   )201>/tmp/$ME.lock

   let "RND = $RANDOM % $MAXTHREADDUR +1"

   for s in $(seq 1 $RND)               #simulate random lifespan
   do
      sleep 1;
      (flock -x -w 10 201
         trackthread $WORKERID $THREADID update $s
      )201>/tmp/$ME.lock
   done

   (flock -x -w 10 201
      trackthread $WORKERID $THREADID setfree
   )201>/tmp/$ME.lock

   (flock -x -w 10 201
      updateIPC
   )201>/tmp/$ME.lock
}

threadcount()
{
   TC=$(ls /tmp/$ME.$F1* 2> /dev/null | wc -l)
   #echo threadcount is $TC >> $DBG
   THREADCOUNT=$TC
   echo $TC
}

status()
{
   #summary status line
   COMPLETE=$(cat $IPC)
   plot 1 $[$THREADLIMIT+2] "WORKERS $(threadcount)/$THREADLIMIT  SPAWNED $SPAWNED/$SPAWN  COMPLETE $COMPLETE/$SPAWN SF=$SPEEDFACTOR TIMING=$TPS"
   echo -en '\033[K'                   #clear to end of line
}

function main()
{
   while [ $SPAWNED -lt $SPAWN ]
   do
      while [ $(threadcount) -lt $THREADLIMIT ] && [ $SPAWNED -lt $SPAWN ]
      do
         WID=$(getfreeworkerid)
         worker $WID $SPAWNED &
         touch /tmp/$ME.$F1$WID    #if this loops faster than file creation in the worker thread it steps on itself, thread tracking is best in main loop
         SPAWNED=$[$SPAWNED+1]
         (flock -x -w 10 201
            status
         )201>/tmp/$ME.lock
         sleep $TPS
        if ((! $[$SPAWNED%100]));then
           #rethink thread timing every 100 threads
           threadspeed
        fi
      done
      sleep $TPS
   done

   while [ "$(threadcount)" -gt 0 ]
   do
      (flock -x -w 10 201
         status
      )201>/tmp/$ME.lock
      sleep 1;
   done

   status
}

clear
threadspeed
main
wait
status
echo

0

আপনার স্ক্রিপ্ট দেখতে হবে:

prog1 &
prog2 &
.
.
progn &
wait
progn+1 &
progn+2 &
.
.

ধরে নিচ্ছি আপনার সিস্টেমটি একবারে n জব নিতে পারে। একবারে কেবল n কাজ চালানোর জন্য অপেক্ষা করুন।


-1

সঙ্গে bashj ( https://sourceforge.net/projects/bashj/ ), আপনি না শুধুমাত্র একাধিক চালানোর জন্য সক্ষম হওয়া উচিত প্রসেস (উপায় অন্যদের পরামর্শ) কিন্তু একাধিক থ্রেড এক জেভিএম আপনার স্ক্রিপ্টটি থেকে নিয়ন্ত্রণ হবে। তবে অবশ্যই এটির জন্য জাভা জেডিকে দরকার। থ্রেডগুলি প্রক্রিয়াগুলির চেয়ে কম সংস্থান গ্রহণ করে।

এখানে একটি কার্যকারী কোড:

#!/usr/bin/bashj

#!java

public static int cnt=0;

private static void loop() {u.p("java says cnt= "+(cnt++));u.sleep(1.0);}

public static void startThread()
{(new Thread(() ->  {while (true) {loop();}})).start();}

#!bashj

j.startThread()

while [ j.cnt -lt 4 ]
do
  echo "bash views cnt=" j.cnt
  sleep 0.5
done
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.