প্রক্রিয়া প্রতিস্থাপন অর্জনের জন্য পোর্টেবল (পসিক্স) উপায় কী?


25

কিছু শেল যেমন প্রসেস সাবস্টিটিউশনকেbash সমর্থন করে যা প্রক্রিয়া আউটপুটটিকে কোনও ফাইল হিসাবে উপস্থাপন করার একটি উপায় এটি:

$ diff <(sort file1) <(sort file2)

তবে, এই নির্মাণটি পসিক্স নয় এবং অতএব, বহনযোগ্য নয়। পসিক্স- বান্ধব উপায়ে (অর্থাত্ যেটি এতে কাজ করে ) কীভাবে বিকল্প প্রতিস্থাপন করা যায় ?/bin/sh

দ্রষ্টব্য: প্রশ্নটি দুইটি বাছাই করা ফাইলগুলিকে কীভাবে আলাদা করতে পারে তা জিজ্ঞাসা করছে না - এটি প্রক্রিয়া প্রতিস্থাপন প্রদর্শনের জন্য কেবল একটি স্বতন্ত্র উদাহরণ !




1
পসিক্সের কোনও /bin/shপসিক্স শেল হওয়ার দরকার হয় না , কেবলমাত্র এমন একটি কমান্ড পাওয়া shযায় যেখানে সঠিক পরিবেশে পসিক্স অনুগত হয়। উদাহরণস্বরূপ, সোলারিস 10-এ /bin/shকোনও পসিক্স শেল নয়, এটি একটি প্রাচীন বোর্ন শেল এবং পসিক্স শেলটি রয়েছে /usr/xpg4/bin/sh
স্টাফেন চেজেলাস

উত্তর:


17

এই বৈশিষ্ট্যটি প্রথম চালু করা হয়েছিল ksh(ksh86 এ প্রথম নথিভুক্ত) এবং /dev/fd/nবৈশিষ্ট্যটি ব্যবহার করা হচ্ছে (কিছু বিএসডি এবং এটিএন্ডটি সিস্টেমের মধ্যে স্বাধীনভাবে যুক্ত হয়েছিল)। ইন kshএবং ksh93u পর্যন্ত, এটা কাজ যদি না আপনার সিস্টেম সমর্থনের জন্য, / dev / FD / N ছিল করত না। zsh, বাশ এবং ksh93u+তারও বেশি উপরে অস্থায়ী নামযুক্ত পাইপগুলি ব্যবহার করা যেতে পারে (আমি বিশ্বাস করি যে সিসিআইআই তে যুক্ত নামযুক্ত পাইপগুলি) যেখানে / ডিভ / এফডি / এন উপলব্ধ নেই।

যেসব সিস্টেমে উপলব্ধ রয়েছে (POSIX সেগুলিকে নির্দিষ্ট করে না), আপনি নিজের পরিবর্তে প্রক্রিয়া বদল করতে পারেন ( ):/dev/fd/ndiff <(cmd1) <(cmd2)

{
  cmd1 4<&- | {
    # in here fd 3 points to the reading end of the pipe
    # from cmd1, while fd 0 has been restored from the original
    # stdin (saved on fd 4, now closed as no longer needed)

    cmd2 3<&- | diff /dev/fd/3 -

  } 3<&0 <&4 4<&- # restore the original stdin for cmd2

} 4<&0 # save a copy of stdin for cmd2

তবে ksh93এটি লিনাক্সের মতো সেখানে কাজ করে না , পাইপগুলির পরিবর্তে /dev/fd/3সকেট পাইপগুলি প্রয়োগ করা হয় এবং খোলার যেখানে সকেটের এফডি 3 পয়েন্ট লিনাক্সে কাজ করে না।

যদিও পসিক্স নির্দিষ্ট করে না । এটি নামযুক্ত পাইপ নির্দিষ্ট করে না। নামক পাইপগুলি ফাইল পাইপগুলি থেকে অ্যাক্সেস করতে পারলে সাধারণ পাইপের মতো কাজ করে। এখানে সমস্যাটি হ'ল আপনাকে অস্থায়ী ফাইল তৈরি করতে হবে এবং তারপরে পরিষ্কার করতে হবে যা নির্ভরযোগ্যভাবে করা কঠিন, বিশেষ করে বিবেচনা করে যে অস্থায়ী ফাইল বা ডিরেক্টরি তৈরি করার জন্য পসিক্সের কোনও স্ট্যান্ডার্ড মেকানিজম নেই ( যেমন কিছু সিস্টেমে পাওয়া গেছে), এবং সিগন্যাল বহনযোগ্যভাবে পরিচালনা করছেন (হ্যাং-আপ বা মেরে ক্লিন-আপ করা) বহনযোগ্যভাবে করাও শক্ত।/dev/fd/nmktemp -d

আপনি যেমন কিছু করতে পারেন:

tmpfifo() (
  n=0
  until
    fifo=$1.$$.$n
    mkfifo -m 600 -- "$fifo" 2> /dev/null
  do
    n=$((n + 1))
    # give up after 20 attempts as it could be a permanent condition
    # that prevents us from creating fifos. You'd need to raise that
    # limit if you intend to create (and use at the same time)
    # more than 20 fifos in your script
    [ "$n" -lt 20 ] || exit 1
  done
  printf '%s\n' "$fifo"
)

cleanup() { rm -f -- "$fifo"; }
fifo=$(tmpfifo /tmp/fifo) || exit

cmd2 > "$fifo" & cmd1 | diff - "$fifo"
rm -f -- "$fifo"

(এখানে সিগন্যাল পরিচালনার যত্ন নিচ্ছেন না))


নামক পাইপ উদাহরণটি আমার কাছে সম্পূর্ণ পরিষ্কার (আমার ধারণা 10 একটি নির্বিচারে সীমা?) তবে আমি আপনার /dev/fd/nউদাহরণটি বের করতে পারি না । বর্ণনাকারী 4 কেন দু'বার বন্ধ? (এবং বর্ণনাকারী 3 হয়।) আমি হারিয়েছি।
ওয়াইল্ডকার্ড

@ উইল্ডকার্ড, এটি যে কমান্ডগুলির দরকার নেই তার জন্য এটি বন্ধ রয়েছে। এখানে কেবল ডিফের দরকার হয় যে এফডি 3 প্রয়োজন হয় না, এফডি 4 এর কোনও প্রয়োজন হয় না, এটি কেবল আসল স্টিডিনের cmd2( dup2(0,4)বাইরের দিকে {...}, dup2(4,0)অভ্যন্তরের সাথে পুনরুদ্ধার করা {...}) প্রচার করতে ব্যবহৃত হয় ।
স্টাফেন চেজেলাস

আপনি mktemp -dফিফো পেতে পারেন তা নিশ্চিত করতে আপনি সাহায্য করতে পারেন, কারণ আপনার ব্র্যান্ড-নতুন এলোমেলো অস্থায়ী ডিরেক্টরিতে কেউ লিখতে হবে না।
ড্যানিয়েল এইচ

@ ড্যানিয়েলএইচ, আমি ইতিমধ্যে উল্লেখ করেছি mktemp -d। তবে এটি কোনও স্ট্যান্ডার্ড / পসিক্স কমান্ড নয়।
স্টাফেন চেজেলাস

হু, আমি বুঝতে পারিনি। উফ। দ্রুত অনুসন্ধানে দেখা যাচ্ছে যে বেশিরভাগ সিস্টেমগুলি সমর্থন করে, তাই এটি এখনও বহনযোগ্য হতে পারে, তবে এটি পসিক্স নয়।
ড্যানিয়েল এইচ

-1

cmd | while read A B Cপরিবর্তে দরকারী , পরিবর্তে ভেরিয়েবল এড়ানোর প্রয়োজন হলে :

VAR="before"
while read A B C 
do
  VAR="$A $VAR"
done < <(cmd)
echo "$VAR"

তুমি ব্যবহার করতে পার:

VAR="before"
while read A B C 
do
  VAR="$A $VAR"
done << EndOfText
`cmd`
EndOfText
echo "$VAR"

সুতরাং প্রশ্নের উত্তর দিতে:

sort file1 | diff /dev/stdin /dev/stdout 2<<EOT
`sort file2`
EOT
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.