একাধিক প্রক্রিয়া মধ্যে যোগাযোগ


13

আমার কাছে বাশ স্ক্রিপ্ট রয়েছে, যা এক্স-বারের জন্য পৃথক প্রক্রিয়া হিসাবে ম্যানেজার () ফাংশন চালায়। স্ক্রিপ্টের মধ্যে থেকে সমস্ত পরিচালক () প্রক্রিয়াগুলিতে বার্তা ফরোয়ার্ড করা কীভাবে সম্ভব?

আমি বেনামে পাইপগুলি সম্পর্কে পড়েছি তবে কীভাবে বার্তাগুলি এটির সাথে ভাগ করবেন সে সম্পর্কে আমার কোনও ধারণা নেই .. আমি নামযুক্ত পাইপগুলি দিয়ে এটি করার চেষ্টা করেছি, তবে এটি প্রতিটি প্রসেসের জন্য আলাদা আলাদা নামযুক্ত পাইপ তৈরি করতে হবে বলে মনে হচ্ছে?

এটি করার জন্য সবচেয়ে মার্জিত উপায় কী?

এখন পর্যন্ত আমার কোডটি এখানে:

#!/bin/bash

manager () {
    while :
    do
        echo "read what has been passed to \$line"
    done
}

x=1
while [ $x -le 5 ]
do
  manager x &
  x=$(( $x + 1 ))
done


while :
do
while read line
do
  echo "What has been passed through the pipe is ${line}"
  # should pass $line to every manager process

done < $1
done

exit 0

উত্তর:


25

আপনি যেটি সম্পাদনের চেষ্টা করছেন তার পদটি হ'ল মাল্টিপ্লেক্সিং

এটি ব্যাশে মোটামুটি সহজেই সম্পন্ন করা যায় তবে এর জন্য আরও কিছু উন্নত বাশ বৈশিষ্ট্য প্রয়োজন।

আমি আপনার উপর ভিত্তি করে একটি স্ক্রিপ্ট তৈরি করেছি যা আমি মনে করি আপনি যা করতে চেষ্টা করছেন তা করে। আমি এটি নীচে ব্যাখ্যা করব।

#!/bin/bash
manager() {
  while IFS= read -r line; do
    echo "manager[$1:$BASHPID]: $line"
  done
}

fds=()
for (( i=0; i<5; i++ )); do
  exec {fd}> >(manager $i)
  fds+=( $fd )
done

while IFS= read -r line; do
  echo "master: $line"
  for fd in "${fds[@]}"; do
    printf -- '%s\n' "$line" >&$fd
  done
done

managerএটি একটি বাশ ফাংশন যা কেবল STDIN থেকে পড়ে এবং এটি সনাক্তকারী এবং লাইনটি STDOUT এ লিখে দেয়। আমরা ব্যবহার $BASHPIDপরিবর্তে $$যেমন $$subshells জন্য আপডেট না (যা আমরা আরম্ভ করার জন্য ব্যবহার করা হবে manager

fdsএমন একটি অ্যারে যা বিভিন্ন ফাইলের এসটিডিআইএন পাইপগুলিকে নির্দেশ করে ফাইল বর্ণনাকারীদের ধরে রাখবে manager
তারপরে আমরা লুপ করি এবং 5 টি ম্যানেজার প্রক্রিয়া তৈরি করি। for (( ))আপনি এটি যেভাবে পরিষ্কার করছেন সেটির পরিবর্তে আমি সিনট্যাক্সটি ব্যবহার করি । এটি বাশ সুনির্দিষ্ট, তবে এই স্ক্রিপ্টটি বেশ কয়েকটি কাজ বিশেষভাবে নির্দিষ্ট করে বশ।
 

পরবর্তী আমরা পেতে exec {fd}> >(manager $i)। এটি আরও বেশ কয়েকটি বাশ নির্দিষ্ট জিনিস করে।
যার প্রথমটি হচ্ছে {fd}>। এটি 10 ​​নম্বর বা তার পরে পরবর্তী উপলব্ধ ফাইল বর্ণনাকারীটিকে ধরে ফেলবে, সেই ফাইলের বর্ণনাকারীকে নির্ধারিত পাইপের রাইটিং পাশের সাথে একটি পাইপ খুলবে এবং ভেরিয়েবলের জন্য ফাইল বর্ণনাকারী নম্বরটি বরাদ্দ করবে $fd

>(manager $i)লঞ্চ manager $iএবং মূলত পরিপূরক >(manager $i)যে প্রক্রিয়ার একটি stdin করার জন্য একটি পাথ উল্লেখ করুন। সুতরাং যদি managerপিআইডি 1234 হিসাবে চালু করা হয়, তবে এটি >(manager $i)বিকল্প হিসাবে পেতে পারে /proc/1234/fd/0(এটি ওএস নির্ভর)।

সুতরাং, পরবর্তী উপলব্ধ ফাইল বর্ণনাকারী সংখ্যাটি 10 ​​হিসাবে ধরে নেওয়া এবং ম্যানেজারটি পিআইডি 1234 দিয়ে চালু করা হয়, কমান্ডটি exec {fd}> >(manager $i)মূলত হয়ে যায় exec 10>/proc/1234/fd/0এবং ব্যাশের এখন সেই ফাইল ব্যবস্থাপকটি সেই ব্যবস্থাপকের এসটিডিআইএনকে নির্দেশ করে।
তারপরে যেহেতু বাশ সেই ফাইলের বর্ণনাকারী নম্বরটি রাখে $fd, আমরা সেই বর্ণনাকারীকে fdsপরবর্তী ব্যবহারের জন্য অ্যারেতে যুক্ত করব ।
 

এটির বাকিগুলি বেশ সহজ। মাস্টার STDIN থেকে একটি লাইন পড়েন, সমস্ত ফাইল বর্ণনাকারীর উপরে পুনরাবৃত্তি করে $fdsএবং সেই ফাইলটি ডিজিসিপ্টারে ( printf ... >&$fd) লাইনটি প্রেরণ করেন ।

 

ফলাফলটি এরকম দেখাচ্ছে:

$ /tmp/test.sh
hello
master: hello
manager[0:8876]: hello
manager[1:8877]: hello
manager[4:8880]: hello
manager[2:8878]: hello
manager[3:8879]: hello
world
master: world
manager[0:8876]: world
manager[1:8877]: world
manager[3:8879]: world
manager[2:8878]: world
manager[4:8880]: world

যেখানে আমি টাইপ করেছি helloএবং world


@ পেট্রিক দ্য ওয়ার্কস, কিন্তু আপনি একটি টাইপো পেয়েছেন, {fd} এবং এটি $ {fd} হওয়া উচিত
c4f4t0r

3
@ c4f4t0r এটি কোনও টাইপো নয়
প্যাট্রিক

@ পেট্রিক 11 স্যুসে "" বাশ টাইপ.বাশ টাইপ.বাশ: লাইন 10: এক্সিকিউ: {এফডি}: পাওয়া যায়নি "আমি
এক্সিকিউটিভ

2
@ c4f4t0r ওপেন স্যুস 11-এ বাশের সংস্করণটি বেশ প্রাচীন (2.২)। এই বৈশিষ্ট্যটি ব্যাশ ৪.০ এ প্রয়োগ করা হয়েছিল।
প্যাট্রিক

অনেক ভাল তথ্যের জন্য ধন্যবাদ! একটি নিটপিক: আমি বুঝতে পারি আপনি কেন বলবেন echo -- "$line"বা printf "%s\n" "$line"- তবে --যখন পরের যুক্তিটি হার্ড-কোডড (এবং এর সাথে শুরু হয় না -) কেন আপনাকে কেন ব্যবহার করতে হবে ?
স্কট

0

teeএবং bash:

cat foo | tee >(manager) >(manager) >(manager) >(manager) >(manager) >/dev/null

পরিচালকের সংখ্যাটি যদি কনফিগারযোগ্য হয় বা আপনি বিভিন্ন পরিচালকের আউটপুটটি মিশ্রিত না করতে চান:

export -f manager
cat foo | parallel --pipe --tee manager ::: {1..10}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.