অন্যটিতে পাইপযুক্ত প্রক্রিয়াটির প্রস্থান স্থিতি পান


286

আমার দুটি প্রক্রিয়া আছে fooএবং bar, পাইপের সাথে যুক্ত:

$ foo | bar

barসর্বদা 0 থেকে প্রস্থান করে; আমি এর প্রস্থান কোড আগ্রহী foo। এটি পেতে কোনও উপায় আছে?


উত্তর:


255

আপনি যদি ব্যবহার করেন তবে আপনি পাইপলাইনের প্রতিটি উপাদানটির প্রস্থান স্থিতি পেতে অ্যারে ভেরিয়েবলটি bashব্যবহার করতে পারেন PIPESTATUS

$ false | true
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
1 0

আপনি যদি ব্যবহার করেন তবে zshতাদের অ্যারে বলা হয় pipestatus(কেস ম্যাটার্স!) এবং অ্যারে সূচকগুলি এক থেকে শুরু হয়:

$ false | true
$ echo "${pipestatus[1]} ${pipestatus[2]}"
1 0

মানগুলি হারাবে না এমনভাবে একটি ফাংশনের মধ্যে তাদের একত্রিত করতে:

$ false | true
$ retval_bash="${PIPESTATUS[0]}" retval_zsh="${pipestatus[1]}" retval_final=$?
$ echo $retval_bash $retval_zsh $retval_final
1 0

উপরের চালনা করুন bashবা zshআপনি একই ফলাফল পাবেন; শুধুমাত্র একটি retval_bashএবং retval_zshসেট করা হবে। অন্যটি ফাঁকা থাকবে। এটি কোনও ফাংশনটি দিয়ে শেষ হতে দেয় return $retval_bash $retval_zsh(উদ্ধৃতিগুলির অভাবটি নোট করুন!)।


9
এবং pipestatuszsh এ। দুর্ভাগ্যক্রমে অন্যান্য শেলগুলিতে এই বৈশিষ্ট্যটি নেই।
গিলস

8
দ্রষ্টব্য: zsh এ অ্যারেগুলি সূচক 1 এ বিপরীতে শুরু হয়, তাই এটি echo "$pipestatus[1]" "$pipestatus[2]"
ক্রিস্টোফ উর্ম

5
আপনি পুরো পাইপলাইনটি if [ `echo "${PIPESTATUS[@]}" | tr -s ' ' + | bc` -ne 0 ]; then echo FAIL; fi
এটির

7
@ জানহুদেক: আমার উত্তরটির প্রথম পাঁচটি শব্দ আপনার পড়া উচিত। এছাড়াও দয়া করে বিন্দুভাবে নির্দেশ করুন যেখানে প্রশ্নটি একটি পসইক্স-উত্তর উত্তর চেয়েছিল।
ক্যামহ

12
@ জানহুদেক: এটিও পসিক্স ট্যাগ ছিল না। আপনি কেন অনুমান করেন যে উত্তরটি অবশ্যই পসিএক্স হতে হবে? এটি নির্দিষ্ট করা হয়নি তাই আমি একটি যোগ্য উত্তর সরবরাহ করেছি। আমার উত্তর সম্পর্কে ভুল কিছু নেই, এবং অন্যান্য ক্ষেত্রে সম্বোধন করার জন্য একাধিক উত্তর রয়েছে।
ক্যামহ

236

এটি করার 3 টি সাধারণ উপায় রয়েছে:

Pipefail

প্রথম উপায়টি pipefailবিকল্প ( ksh, zshবা bash) সেট করা । এটি সবচেয়ে সহজ এবং এটি যা করে তা $?অ-শূন্য থেকে বেরিয়ে আসার জন্য শেষ প্রোগ্রামের প্রস্থান কোডে প্রস্থান স্থিতি নির্ধারণ করে (বা সমস্ত সফলভাবে উপস্থিত থাকলে শূন্য)।

$ false | true; echo $?
0
$ set -o pipefail
$ false | true; echo $?
1

$ PIPESTATUS

বাশ-এ $PIPESTATUS( $pipestatusইন zsh) নামে একটি অ্যারে ভেরিয়েবল রয়েছে যা সর্বশেষ পাইপলাইনে সমস্ত প্রোগ্রামের প্রস্থান স্থিতি ধারণ করে।

$ true | true; echo "${PIPESTATUS[@]}"
0 0
$ false | true; echo "${PIPESTATUS[@]}"
1 0
$ false | true; echo "${PIPESTATUS[0]}"
1
$ true | false; echo "${PIPESTATUS[@]}"
0 1

আপনার প্রয়োজনীয় পাইপলাইনে নির্দিষ্ট মান পেতে আপনি তৃতীয় কমান্ড উদাহরণটি ব্যবহার করতে পারেন।

ফাঁসি কার্যকর করা

এটি সমাধানগুলির সবচেয়ে অপ্রয়োজনীয়। প্রতিটি কমান্ড পৃথকভাবে চালান এবং স্থিতি ক্যাপচার

$ OUTPUT="$(echo foo)"
$ STATUS_ECHO="$?"
$ printf '%s' "$OUTPUT" | grep -iq "bar"
$ STATUS_GREP="$?"
$ echo "$STATUS_ECHO $STATUS_GREP"
0 1

2
অভিশাপ! আমি কেবল পাইপস্ট্যাটাস সম্পর্কে পোস্ট করব।
SLM

1
: অবগতির জন্য বেশ কিছু অন্যান্য প্রযুক্তি এই তাই প্রশ্ন আলোচনা করা হয়েছে stackoverflow.com/questions/1221833/...
SLM

1
@ পেট্রিক পাইপস্ট্যাটাস সলিউশন বাশ নিয়ে কাজ করছে, আমি যদি ksh স্ক্রিপ্ট ব্যবহার করি তবে আপনি কী ভাবেন যে আমরা পাইপস্ট্যাটাসের অনুরূপ কিছু খুঁজে পাব? (Meenwhile আমি ksh দ্বারা সমর্থিত নয় pipestatus দেখুন)
Yael

2
@ আইয়েল আমি ব্যবহার করি না ksh, তবে এটির ম্যানপেজের উপর এক সংক্ষিপ্ত দৃষ্টিকোণ থেকে, এটি সমর্থন করে না $PIPESTATUSবা এর অনুরূপ কিছু দেয় না । এটি pipefailযদিও বিকল্পটি সমর্থন করে ।
প্যাট্রিক

1
আমি পাইপফেইলে যাওয়ার সিদ্ধান্ত নিয়েছিলাম কারণ এটি আমাকে এখানে ব্যর্থ কমান্ডের স্থিতি পেতে দেয়:LOG=$(failed_command | successful_command)
ভিএমরোব

51

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

পরিস্থিতি:

someprog | filter

আপনি থেকে প্রস্থান স্থিতি someprogএবং আউটপুট চান filter

এখানে আমার সমাধান:

((((someprog; echo $? >&3) | filter >&4) 3>&1) | (read xs; exit $xs)) 4>&1

এই কনস্ট্রাক্টের ফলাফলটি স্ট্রাউট filterহিসাবে কনস্ট্রাক্ট এবং স্ট্রাউট স্ট্যাটাস someprogহিসাবে কনস্ট্রাক্টের প্রস্থান স্থিতি হিসাবে।


এই কনস্ট্রাক্টটি {...}সাব-শেলের পরিবর্তে সাধারণ কমান্ড গ্রুপিংয়ের সাথেও কাজ করে (...)। সাবশেলের কিছু জড়িত রয়েছে, অন্যদের মধ্যে পারফরম্যান্স ব্যয়, যা আমাদের এখানে প্রয়োজন নেই। আরও বিশদের জন্য সূক্ষ্ম বাশ ম্যানুয়ালটি পড়ুন: https://www.gnu.org/software/bash/manual/html_node/Command-Grouping.html

{ { { { someprog; echo $? >&3; } | filter >&4; } 3>&1; } | { read xs; exit $xs; } } 4>&1

দুর্ভাগ্যক্রমে বাশ ব্যাকরণের জন্য কোঁকড়া ধনুর্বন্ধনীগুলির জন্য ফাঁকা স্থান এবং সেমিকোলন প্রয়োজন যাতে নির্মাণ আরও অনেক প্রশস্ত হয়।

এই পাঠ্যের বাকী অংশের জন্য আমি সাব-শেল রূপটি ব্যবহার করব।


উদাহরণ someprogএবং filter:

someprog() {
  echo "line1"
  echo "line2"
  echo "line3"
  return 42
}

filter() {
  while read line; do
    echo "filtered $line"
  done
}

((((someprog; echo $? >&3) | filter >&4) 3>&1) | (read xs; exit $xs)) 4>&1

echo $?

উদাহরণ আউটপুট:

filtered line1
filtered line2
filtered line3
42

দ্রষ্টব্য: শিশু প্রক্রিয়া পিতামাতার কাছ থেকে খোলা ফাইল বর্ণনাকারীদের উত্তরাধিকার সূত্রে পায়। এর অর্থ someprogউন্মুক্ত ফাইল বর্ণনাকারী 3 এবং 4 উত্তরাধিকার সূত্রে প্রাপ্ত হবে If যদি someprogবিবরণী 3 ফাইল লিখতে থাকে তবে সেটি প্রস্থান স্থিতিতে পরিণত হবে। আসল প্রস্থান স্থিতি এড়ানো হবে কারণ readশুধুমাত্র একবার পড়বে ।

আপনি যদি উদ্বেগ প্রকাশ করেন যে আপনার someprogসম্ভবত 3 বা 4 ফাইল বিবরণীতে লিখতে পারে তবে কল করার আগে ফাইল বর্ণনাকারী বন্ধ করে দেওয়া ভাল someprog

(((((exec 3>&- 4>&-; someprog); echo $? >&3) | filter >&4) 3>&1) | (read xs; exit $xs)) 4>&1

exec 3>&- 4>&-সামনে someprogচালানোর আগে ফাইল বর্ণনাকারী বন্ধ someprogতাই someprogঐ ফাইল বর্ণনাকারী কেবল কোন অস্তিত্ব নেই।

এটিও এভাবে লেখা যেতে পারে: someprog 3>&- 4>&-


ধাপে ধাপে নির্মাণের ব্যাখ্যা:

( ( ( ( someprog;          #part6
        echo $? >&3        #part5
      ) | filter >&4       #part4
    ) 3>&1                 #part3
  ) | (read xs; exit $xs)  #part2
) 4>&1                     #part1

নীচে থেকে:

  1. স্ট্যান্ডআউটে পুনর্নির্দেশ করা ফাইল বর্ণনাকারী 4 সহ একটি সাবশেল তৈরি করা হয়েছে। এর অর্থ এই যে সাবসিলে 4 ডেস্ক্রিপ্টর ফাইল করতে যা কিছু মুদ্রিত হয় তা সম্পূর্ণ নির্মাণের স্টাডআউট হিসাবে শেষ হবে।
  2. একটি পাইপ তৈরি করা হয় এবং বাম ( #part3) এবং ডান ( #part2) কমান্ডগুলি কার্যকর করা হয়। exit $xsপাইপের শেষ কমান্ডও এবং এর অর্থ হল স্টিডিনের স্ট্রিংটি সম্পূর্ণ নির্মাণের প্রস্থান স্থিতি হবে।
  3. স্ট্যান্ডআউটে পুনঃনির্দেশিত ফাইল বর্ণনাকারী 3 সহ একটি সাব-শেল তৈরি করা হয়েছে। এর অর্থ হ'ল এই সাবশেলে 3 ডেস্ক্রিপ্টর ফাইল করার জন্য যা কিছু মুদ্রিত হয়েছে তা শেষ হয়ে যাবে এবং ফলস্বরূপ #part2পুরো নির্মাণের প্রস্থান স্থিতি হবে status
  4. একটি পাইপ তৈরি করা হয় এবং বাম ( #part5এবং #part6) এবং ডান ( filter >&4) কমান্ডগুলি কার্যকর করা হয়। এর বর্ণনা আউটপুটটি filterডেস্ক্রিপ্টর 4 ফাইলের দিকে পুনঃনির্দেশিত করা #part1হয়। ফাইল বিবরণীতে 4 স্ট্যাডআউটে পুনর্নির্দেশ করা হয়েছিল। এর অর্থ filterহ'ল আউটপুট হ'ল সম্পূর্ণ নির্মাণের স্টাডআউট d
  5. থেকে প্রস্থান স্থিতি #part6ফাইল বর্ণনাকারী 3 এ মুদ্রিত হয় #part3ফাইল বিবরণীতে 3 এ পুনঃনির্দেশিত হয়েছিল #part2। এর অর্থ এই যে প্রস্থানের স্থিতিটি #part6সম্পূর্ণ নির্মাণের জন্য চূড়ান্ত প্রস্থান স্থিতি হবে।
  6. someprogমৃত্যুদন্ড কার্যকর করা হয় প্রস্থান স্থিতি নেওয়া হয় #part5। স্টাডাউটটি পাইপটি দ্বারা takenোকানো হয় #part4এবং এতে ফরোয়ার্ড করা হয় filter। উল্লিখিত হিসাবে আউটপুট filterপরিবর্তে stdout পৌঁছাবে#part4

1
খুশী হলাম। ফাংশনটির জন্য আমি কেবল করতে পারি(read; exit $REPLY)
jthill

5
(exec 3>&- 4>&-; someprog)থেকে সহজসাধ্য someprog 3>&- 4>&-
রজার পেট

এই পদ্ধতিটি { { { { someprog 3>&- 4>&-; echo $? >&3; } | filter >&4; } 3>&1; } | { read xs; exit $xs; }; } 4>&1
সাব

36

আপনি যা চেয়েছিলেন ঠিক তেমন না হলেও আপনি ব্যবহার করতে পারেন

#!/bin/bash -o pipefail

যাতে আপনার পাইপগুলি সর্বশেষ নন শূন্য ফেরত দেয়।

কিছুটা কম কোডিং হতে পারে

সম্পাদনা: উদাহরণ

[root@localhost ~]# false | true
[root@localhost ~]# echo $?
0
[root@localhost ~]# set -o pipefail
[root@localhost ~]# false | true
[root@localhost ~]# echo $?
1

9
set -o pipefailস্ক্রিপ্টের অভ্যন্তরে আরও দৃ be় হওয়া উচিত, উদাহরণস্বরূপ, কেউ যদি স্ক্রিপ্টের মাধ্যমে কার্যকর করে bash foo.sh
ম্যাক্সলেপজিগ

ওটা কিভাবে কাজ করে? তোমার কি উদাহরণ আছে?
জোহান

2
নোট যেটি -o pipefailপসিক্সে নেই।
scy

2
এটি আমার BASH 3.2.25 (1) -রিজলে কাজ করে না। আমার কাছে / টিএমপি / এফএফ শীর্ষে আছে #!/bin/bash -o pipefail। ত্রুটি:/bin/bash: line 0: /bin/bash: /tmp/ff: invalid option name
ফিলিপ আলভারেজ

2
@FelipeAlvarez: কিছু পরিবেশের (লিনাক্সের সহ) উপর স্পেস পার্স না #!প্রথমটি পরলোক লাইন, এবং তাই এই হয়ে /bin/bash -o pipefail /tmp/ffপ্রয়োজনীয় পরিবর্তে /bin/bash -o pipefail /tmp/ff- getoptব্যবহার (বা অনুরূপ) পার্সিং optarg, যা পরবর্তী আইটেম ARGV, আর্গুমেন্ট হিসাবে যাও -o, যাতে এটি ব্যর্থ হয়। আপনি যদি একটি মোড়কের (বলুন করতে, হলে bash-pfযে শুধু করেনি exec /bin/bash -o pipefail "$@", এবং যে করা #!লাইন, যে কাজ করবে আরো দেখুন:। En.wikipedia.org/wiki/Shebang_%28Unix%29
lindes

22

সম্ভব হলে আমি যা করি তা হ'ল বাইরে থেকে প্রস্থান কোডটি ফিড fooকরা bar। উদাহরণস্বরূপ, যদি আমি জানি যে fooকখনই কেবল অঙ্কের সাথে কোনও লাইন তৈরি করে না, তবে আমি কেবলমাত্র প্রস্থান কোডটি মোকাবেলা করতে পারি:

{ foo; echo "$?"; } | awk '!/[^0-9]/ {exit($0)} {…}'

বা যদি আমি জানি যে আউটপুটটিতে fooকখনও ন্যায়বিচারের সাথে একটি লাইন থাকে না .:

{ foo; echo .; echo "$?"; } | awk '/^\.$/ {getline; exit($0)} {…}'

এটি সর্বদা করা যেতে পারে যদি barশেষ লাইন ব্যতীত অন্য সকলের সাথে কাজ করার কোনও উপায় থাকে এবং শেষ লাইনে এর প্রস্থান কোড হিসাবে চলে যায়।

যদি barকোনও জটিল পাইপলাইন যার আউটপুট আপনার প্রয়োজন হয় না, আপনি আলাদা ফাইল বিবরণীতে প্রস্থান কোড প্রিন্ট করে এর অংশটি বাইপাস করতে পারেন।

exit_codes=$({ { foo; echo foo:"$?" >&3; } |
               { bar >/dev/null; echo bar:"$?" >&3; }
             } 3>&1)

এরপর $exit_codesসাধারণত foo:X bar:Y, কিন্তু এটা হতে পারে bar:Y foo:Xযদি barতার ইনপুট সব পড়ার আগে বা যদি অপয়া করছি শোধবোধ। আমি মনে করি 512 বাইট অবধি পাইপগুলিতে লেখা সমস্ত ইউনিসগুলিতে পারমাণবিক, সুতরাং যতক্ষণ না ট্যাগ স্ট্রিং 507 বাইটের নিচে থাকে ততক্ষণ foo:$?এবং bar:$?অংশগুলি সংমিশ্রিত হবে না।

আপনার যদি আউটপুট ক্যাপচার করতে হয় তবে barএটি কঠিন হয়ে পড়ে। আপনি barকখনই কোনও লাইন ধারণ করবেন না যা বহির্গমন কোড ইঙ্গিতের মতো দেখায় না তার আউটপুট সাজিয়ে আপনি উপরের কৌশলগুলিকে একত্রিত করতে পারেন তবে এটি খুব কমই যায়।

output=$(echo;
         { { foo; echo foo:"$?" >&3; } |
           { bar | sed 's/^/^/'; echo bar:"$?" >&3; }
         } 3>&1)
nl='
'
foo_exit_code=${output#*${nl}foo:}; foo_exit_code=${foo_exit_code%%$nl*}
bar_exit_code=${output#*${nl}bar:}; bar_exit_code=${bar_exit_code%%$nl*}
output=$(printf %s "$output" | sed -n 's/^\^//p')

এবং, অবশ্যই, স্থিতি সংরক্ষণের জন্য একটি অস্থায়ী ফাইল ব্যবহার করার সহজ বিকল্প রয়েছে । সরল, কিন্তু না যে উৎপাদনে সহজ:

  • যদি একই সাথে একাধিক স্ক্রিপ্ট চলমান থাকে, বা একই স্ক্রিপ্টটি বেশ কয়েকটি জায়গায় এই পদ্ধতিটি ব্যবহার করে তবে আপনাকে অবশ্যই বিভিন্ন অস্থায়ী ফাইলের নাম ব্যবহার করা উচিত তা নিশ্চিত করতে হবে।
  • একটি ভাগ করা ডিরেক্টরিতে নিরাপদে একটি অস্থায়ী ফাইল তৈরি করা শক্ত। প্রায়শই, /tmpএকমাত্র জায়গা যেখানে স্ক্রিপ্ট ফাইলগুলি লিখতে সক্ষম হবে তা নিশ্চিত। ব্যবহার করুন mktemp, যা পসিক্স নয় তবে আজকাল সমস্ত গুরুতর সংযোগগুলিতে উপলভ্য।
foo_ret_file=$(mktemp -t)
{ foo; echo "$?" >"$foo_ret_file"; } | bar
bar_ret=$?
foo_ret=$(cat "$foo_ret_file"; rm -f "$foo_ret_file")

1
অস্থায়ী ফাইল পদ্ধতির ব্যবহার করার সময় আমি
EXIT- র

17

পাইপলাইন থেকে শুরু:

foo | bar | baz

কেবলমাত্র পসিক্স শেল এবং অস্থায়ী ফাইল ব্যবহার করে এখানে একটি সাধারণ সমাধান রয়েছে:

exec 4>&1
error_statuses="`((foo || echo "0:$?" >&3) |
        (bar || echo "1:$?" >&3) | 
        (baz || echo "2:$?" >&3)) 3>&1 >&4`"
exec 4>&-

$error_statuses প্রতিটি কমান্ডটি কোন আদেশকে নির্গত করে তা নির্ধারণের জন্য সূচি সহ কোনও ব্যর্থ প্রক্রিয়ার স্থিতি কোড রয়েছে।

# if "bar" failed, output its status:
echo "$error_statuses" | grep '1:' | cut -d: -f2

# test if all commands succeeded:
test -z "$error_statuses"

# test if the last command succeeded:
! echo "$error_statuses" | grep '2:' >/dev/null

$error_statusesআমার পরীক্ষাগুলির চারপাশে উদ্ধৃতিগুলি নোট করুন ; তাদের ছাড়া grepপার্থক্য করতে পারে না কারণ নিউলাইনগুলি ফাঁকা জায়গায় জোর করে।


12

সুতরাং আমি লেসমানার মতো একটি উত্তর অবদান রাখতে চেয়েছিলাম, তবে আমি মনে করি আমার সম্ভবত কিছুটা সহজ এবং কিছুটা সুবিধাজনক খাঁটি-বোর্ন শেল সমাধান:

# You want to pipe command1 through command2:
exec 4>&1
exitstatus=`{ { command1; printf $? 1>&3; } | command2 1>&4; } 3>&1`
# $exitstatus now has command1's exit status.

আমি মনে করি এটি ভিতরে থেকে সর্বোত্তমভাবে ব্যাখ্যা করা হয়েছে - কমান্ড 1 তার নিয়মিত আউটপুটটি স্টাডআউট (ফাইল বর্ণনাকারী 1) এ কার্যকর করবে এবং মুদ্রণ করবে, তারপরে এটি শেষ হয়ে গেলে, প্রিন্টফ তার স্টাডাউটে কমান্ড 1 এর প্রস্থান কোডটি কার্যকর করবে এবং প্রিন্ট করবে, কিন্তু সেই স্টাডআউটটি পুনঃনির্দেশিত হবে ফাইল বর্ণনাকারী 3।

কমান্ড 1 চলমান থাকাকালীন, এর স্টডআউটটি কমান্ড 2 এ পাইপ করা হচ্ছে (প্রিন্টফের আউটপুট কখনই এটি কমান্ড 2 এ পরিণত হয় না কারণ আমরা এটি 1 এর পরিবর্তে 3 ফাইল-ডেস্ক্রিপ্টারে প্রেরণ করি, যা পাইপটি পড়ে)। তারপরে আমরা কমান্ড 2 এর আউটপুটটিকে ফাইল বর্ণনাকারী 4 এ পুনঃনির্দেশ করি, যাতে এটি ফাইল বর্ণনাকারী 1 এর বাইরেও থাকে - কারণ আমরা ফাইল বর্ননকারীকে কিছুটা পরে ফ্রি চাই, কারণ আমরা ফাইল বিবরণীতে প্রিন্টফ আউটপুট 3 ফিরিয়ে আনব ফাইল ডেস্ক্রিপ্টারে 1 - কারণ এটি হ'ল কমান্ড সাবস্টিটিউশন (ব্যাকটিক্স) ক্যাপচার করবে এবং এটি ভেরিয়েবলের মধ্যে স্থাপন করবে।

ম্যাজিকের চূড়ান্ত বিটটি হ'ল প্রথমটি exec 4>&1আমরা পৃথক কমান্ড হিসাবে করি - এটি বাহ্যিক শেলের স্টডআউটটির অনুলিপি হিসাবে ফাইল বর্ণনাকারী 4 খুলবে। কমান্ড প্রতিস্থাপন স্ট্যান্ডার্ডে যা লেখা আছে তার ভিতরে থাকা কমান্ডের দৃষ্টিকোণ থেকে তা ক্যাপচার করবে - তবে, যেহেতু কমান্ড 2 এর আউটপুট বর্ণনাকারী 4 ফাইল করবে, কমান্ড প্রতিস্থাপনের ক্ষেত্রে কমান্ড প্রতিস্থাপন এটি ক্যাপচার করে না - তবে, একবার কমান্ড প্রতিস্থাপনের "আউট" হয়ে গেলে, এটি কার্যকরভাবে এখনও স্ক্রিপ্টের সামগ্রিক ফাইল বর্ণনাকারী 1 এ যায়।

( exec 4>&1এটি একটি পৃথক কমান্ড হতে হবে কারণ আপনি যখন কমান্ড সাবস্টিটিউশনের অভ্যন্তরে কোনও ফাইল বর্ণনাকারীর কাছে লেখার চেষ্টা করেন তখন প্রচলিত শেলগুলি এটি পছন্দ করে না, এটি "বহিরাগত" কমান্ডে খোলা হয় যা প্রতিস্থাপনটি ব্যবহার করছে। তাই এটি হ'ল এটি করার সহজতম পোর্টেবল উপায়))

আপনি এটিকে কম প্রযুক্তিগত এবং আরও কৌতুকপূর্ণ উপায়ে দেখতে পারেন, যেন কমান্ডের আউটপুটগুলি একে অপরকে লাফিয়ে ফেলা হয়: কমান্ড 1-তে কমান্ড 1 পাইপস, তারপরে প্রিন্টফের আউটপুট কমান্ড 2-এর উপরে লাফ দেয় যাতে কমান্ড 2 এটি ধরা না দেয় এবং তারপরে কমান্ড 2 এর আউটপুট কমান্ড প্রতিস্থাপনের বাইরে ছড়িয়ে পড়ে ঠিক একই সময়ে প্রিন্টফ স্থির করে নিতে পারে যাতে এটি ভেরিয়েবলের মধ্যে শেষ হয়, এবং কমান্ড 2 এর আউটপুটটি তার আনন্দের পথে স্ট্যান্ডার্ড আউটপুটে লেখা হয়, ঠিক যেমন একটি সাধারণ পাইপে

এছাড়াও, যেমনটি আমি এটি বুঝতে পেরেছি, $?পাইপটিতে এখনও দ্বিতীয় কমান্ডের রিটার্ন কোড থাকবে, কারণ পরিবর্তনশীল কার্যভার, কমান্ডের বিকল্প এবং যৌগিক কমান্ডগুলি তাদের অভ্যন্তরের কমান্ডের রিটার্ন কোডের জন্য কার্যকরভাবে স্বচ্ছ, সুতরাং এর রিটার্নের স্থিতি কমান্ড 2 এর প্রচার করা উচিত - এটি এবং অতিরিক্ত ক্রিয়াকলাপটি সংজ্ঞায়িত না করাই আমি কেন লেসমানার প্রস্তাবিত চেয়ে কিছুটা ভাল সমাধান হতে পারে বলে আমি মনে করি।

ক্যাভিয়েটস লেসমানার উল্লেখ অনুসারে, সম্ভবত কমান্ড 1 ফাইল বর্ণনাকারী 3 বা 4 ব্যবহার করে শেষ হবে, যাতে আরও দৃ rob় হয়, আপনি এটি করতে পারেন:

exec 4>&1
exitstatus=`{ { command1 3>&-; printf $? 1>&3; } 4>&- | command2 1>&4; } 3>&1`
exec 4>&-

মনে রাখবেন যে আমি আমার উদাহরণে যৌগিক আদেশগুলি ব্যবহার করি তবে সাবশেলগুলি (এর ( )পরিবর্তে ব্যবহার { }করাও কার্যকর হবে, যদিও এটি সম্ভবত কম দক্ষ হতে পারে))

কমান্ডগুলি ফাইল প্রবর্তনকারী প্রক্রিয়া থেকে ফাইল বর্ণনাকারীদের উত্তরাধিকার সূত্রে প্রাপ্ত হয়, সুতরাং সম্পূর্ণ দ্বিতীয় লাইনে ফাইল বর্ণনাকারী চারটি উত্তরাধিকার সূত্রে প্রাপ্ত হয় এবং এরপরে যৌগিক কমান্ডটি 3>&1ফাইল বর্ণনাকারী তিনটি উত্তরাধিকার সূত্রে প্রাপ্ত হয়। সুতরাং এটি 4>&-নিশ্চিত করে যে অভ্যন্তরীণ যৌগ কমান্ডটি ফাইল বর্ণনাকারী চারটি 3>&-উত্তরাধিকার সূত্রে প্রাপ্ত হবে না এবং তিনটি ফাইল বর্ণনাকারীর অধিকারী হবে না, সুতরাং কমান্ড 1 একটি 'ক্লিনার', আরও মানক পরিবেশ পায়। আপনি অভ্যন্তরের 4>&-পাশের পাশেও সরে যেতে পারতেন 3>&-তবে আমি বুঝতে পারি কেন কেবল তার সুযোগটি যতটা সম্ভব সীমাবদ্ধ করা যায় না।

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


আকর্ষণীয় দেখায়, তবে আপনি এই আদেশটি কী করবেন বলে আমি যথেষ্ট অনুমান করতে পারি না এবং আমার কম্পিউটারও তা করতে পারে না; আমি পেতে -bash: 3: Bad file descriptor
জি ম্যান

@ জি-ম্যান রাইট, আমি সাধারণত ভুলে যাচ্ছি যে আমি সাধারণত যে শেলগুলি ব্যবহার করি (ব্যস্তবক্সের সাথে আসা ছাই) এর বিপরীতে বর্ণনাকারীদের ফাইল দেওয়ার সময় এটি কী করছে তা কোনও ধারণা নেই ash বাশকে খুশী করে এমন কোনও কাজের কথা ভাবলে আমি আপনাকে জানাব know ইতিমধ্যে আপনি যদি একটি ডেবিয়ান বাক্স হাতে পেলেন তবে আপনি এটি ড্যাশ করে দেখতে পারেন, বা যদি আপনি ব্যস্তবক্সে হাত পাতেন তবে ব্যস্তবক্স অ্যাশ / এসএস দিয়ে চেষ্টা করে দেখতে পারেন।
mtraceur

@ জি-ম্যান আমি কমান্ডটি কী করব এবং অন্যান্য শেলগুলিতে এটি কী করে তা প্রত্যাখ্যান করে হ'ল কমান্ড 1 থেকে স্টাডআউট পুনর্নির্দেশ করা হয় যাতে এটি কমান্ড প্রতিস্থাপনের দ্বারা ধরা পড়ে না, তবে একবার কমান্ড প্রতিস্থাপনের বাইরে চলে গেলে তা কমে যায় drops stdout এ ফিরে fd3 তাই এটি কমান্ড 2 প্রত্যাশা অনুযায়ী পাইপযুক্ত। কমান্ড 1 প্রস্থান করার পরে, প্রিন্টফ গুলি প্রস্থান করে এবং তার প্রস্থান স্থিতি মুদ্রণ করে, যা কমান্ড প্রতিস্থাপনের দ্বারা পরিবর্তনশীলতে ক্যাপচার করা হয়। এখানে খুব বিস্তারিত ভাঙ্গন: stackoverflow.com/questions/985876/tee-and-exit-status/… এছাড়াও, আপনার এই মন্তব্যটি এমনভাবে পড়েছিল যেন এটাকে বিনীত অবমাননা বলে বোঝানো হয়েছিল?
mtraceur

আমি কোথায় শুরু করব? (1) আপনি আপত্তি বোধ করলে আমি দুঃখিত। "আকর্ষণীয় দেখতে" অর্থ আন্তরিকতার সাথে বোঝানো হয়েছিল; যদি আপনি এটি প্রত্যাশা করেছিলেন তেমন কমপ্যাক্টের মতো কিছু কাজ করে তবে এটি দুর্দান্ত হবে। এর বাইরে, আমি বলছিলাম, সহজভাবে, আপনার সমাধানটি কী করবে বলে আমি বুঝতে পারি নি। আমি দীর্ঘদিন ধরে ইউনিক্সের সাথে কাজ করছি / খেলছি (যেহেতু লিনাক্সের অস্তিত্বের আগে) এবং আমি যদি কিছু বুঝতে না পারি তবে এটি একটি লাল পতাকা যা সম্ভবত অন্য লোকেরা এটি বুঝতে পারে না এবং এটিও আরও ব্যাখ্যা (আইএমএনএসএইচও) দরকার। … (চালিয়ে যাওয়া)
জি-ম্যান

(চালিয়ে যাওয়া) ... যেহেতু আপনি "... ভাবতে চান ... যে [আপনি] গড়পড়তা ব্যক্তির চেয়ে বেশি কিছু সম্পর্কে" বুঝতে পারেন ", তাই আপনার মনে রাখা উচিত যে স্ট্যাক এক্সচেঞ্জের উদ্দেশ্য কোনও কমান্ড-রাইটিং সার্ভিস নয়, মন্থন তুচ্ছ স্বতন্ত্র প্রশ্নের হাজার হাজার ওয়ান-অফ সমাধান; বরং লোকেরা কীভাবে তাদের নিজস্ব সমস্যা সমাধান করতে হয় তা শেখানো। এবং এই লক্ষ্যে, সম্ভবত আপনার যথেষ্ট পরিমাণে জিনিসগুলি ব্যাখ্যা করতে হবে যা একজন "গড়পড়তা ব্যক্তি" এটি বুঝতে পারে। একটি দুর্দান্ত ব্যাখ্যার উদাহরণের জন্য লেসমানার জবাবটি দেখুন। … (চালিয়ে যাওয়া)
জি-ম্যান


7

উপরের লেসমানার সমাধানটি নেস্টেড সাবপ্রসেসেসগুলি ব্যবহার { .. }না করে ব্যবহারের পরিবর্তে ওভারহেড ছাড়াও করা যেতে পারে (মনে রাখবেন যে গ্রুপযুক্ত কমান্ডগুলির এই ফর্মটি সর্বদা সেমিকোলন দিয়ে শেষ করতে হবে)। এটার মতো কিছু:

{ { { { someprog; echo $? >&3; } | filter >&4; } 3>&1; } | stdintoexitstatus; } 4>&1

আমি এই নির্মাণটি ড্যাশ সংস্করণ ০.০.৫ এবং ব্যাশ সংস্করণ ৩.২.২৫ এবং ৪.২.৪২ সহ পরীক্ষা করেছি, সুতরাং কিছু শেল গোষ্ঠীকরণকে সমর্থন না { .. }করলেও এটি পসিক্স অনুগত।


এটি নেটবিএসডি এস, পিডিএক্স, ম্যাক্স, ড্যাশ, ব্যাশ সহ বেশিরভাগ শেলগুলির সাথে সত্যিই ভাল কাজ করে। তবে আমি এটিটি এন্ড টি টি Ksh (93s +, 93u +) বা zsh (4.3.9, 5.2) এর সাথে কাজ করতে পারি না, এমনকি set -o pipefailksh বা কোনও সংখ্যক ছিটিয়ে waitকমান্ড দিয়েও । আমি মনে করি এটি কমপক্ষে, ksh এর জন্য পার্সিং ইস্যু হতে পারে, যদি আমি সাবশেলগুলি ব্যবহার করতে আটকে থাকি তবে এটি ঠিক কাজ করে, তবে ifকেএসএসের জন্য সাব-শেল বৈকল্পিক বেছে নিতে অন্যের জন্য যৌগিক আদেশগুলি ছেড়ে দেয়, এটি ব্যর্থ হয় ।
গ্রেগ এ উডস

4

এটি পোর্টেবল, অর্থাত্ কোনও পসিক্স কমপ্লায়েন্ট শেল নিয়ে কাজ করে, বর্তমান ডিরেক্টরিটি লেখার প্রয়োজন হয় না এবং একই কৌশল ব্যবহার করে একাধিক স্ক্রিপ্টগুলি একই সাথে চালানোর অনুমতি দেয়।

(foo;echo $?>/tmp/_$$)|(bar;exit $(cat /tmp/_$$;rm /tmp/_$$))

সম্পাদনা করুন: গিলসের মন্তব্যের পরে এখানে একটি শক্তিশালী সংস্করণ রয়েছে:

(s=/tmp/.$$_$RANDOM;((foo;echo $?>$s)|(bar)); exit $(cat $s;rm $s))

সম্পাদনা 2: এবং এখানে সন্দেহভাজন জিম মন্তব্যের পরে কিছুটা হালকা বৈকল্পিক:

(s=/tmp/.$$_$RANDOM;{foo;echo $?>$s;}|bar; exit $(cat $s;rm $s))

3
এটি বেশ কয়েকটি কারণে কাজ করে না। 1. অস্থায়ী ফাইলটি লেখার আগে পড়তে পারে। ২. অনুমানযোগ্য নামের সাথে একটি ভাগ করা ডিরেক্টরিতে একটি অস্থায়ী ফাইল তৈরি করা অনিরাপদ (তুচ্ছ ডোস, সিমলিংক রেস)। ৩. একই স্ক্রিপ্টটি যদি এই কৌশলটি বেশ কয়েকবার ব্যবহার করে তবে এটি সর্বদা একই ফাইলের নাম ব্যবহার করবে। 1 সমাধান করতে পাইপলাইন শেষ হওয়ার পরে ফাইলটি পড়ুন। 2 এবং 3 সমাধানের জন্য, এলোমেলোভাবে উত্পাদিত নাম বা একটি ব্যক্তিগত ডিরেক্টরিতে একটি অস্থায়ী ফাইল ব্যবহার করুন।
গিলস

+1 ঠিক আছে {{পাইপস্ট্যাটাস [0]। সহজ তবে গিলস যে সমস্যার উল্লেখ করেছেন সে সম্পর্কে যদি কেউ জানে তবে এখানে প্রাথমিক ধারণাটি কাজ করে।
জোহান

আপনি কয়েক subshells সংরক্ষণ করতে পারেন: (s=/tmp/.$$_$RANDOM;{foo;echo $?>$s;}|bar; exit $(cat $s;rm $s))। @ জোহান: আমি সম্মত যে বাশের সাথে এটি আরও সহজ তবে কিছু প্রসঙ্গে, কীভাবে বাশকে এড়ানো যায় তা জেনে রাখা উপযুক্ত।
সন্দেহভাজন

4

নিম্নলিখিতটি @ পেট্রিকের উত্তরের সংযোজন হিসাবে বোঝানো হয়েছে, যদি আপনি সাধারণ সমাধানগুলির মধ্যে একটিও ব্যবহার করতে সক্ষম না হন।

এই উত্তরটি নিম্নলিখিতটি ধরে নিয়েছে:

  • আপনি শেল যার জানে না আছে $PIPESTATUSনাset -o pipefail
  • আপনি সমান্তরাল সম্পাদনের জন্য একটি পাইপ ব্যবহার করতে চান, তাই কোনও অস্থায়ী ফাইল নেই।
  • সম্ভবত আপনি হঠাৎ বিদ্যুৎ বিভ্রাট হয়ে স্ক্রিপ্টটি বাধাগ্রস্থ করেন তবে আপনার চারপাশে অতিরিক্ত বিশৃঙ্খলা থাকতে হবে না।
  • এই সমাধানটি অনুসরণ করতে তুলনামূলকভাবে সহজ এবং পড়ার জন্য পরিষ্কার হওয়া উচিত।
  • আপনি অতিরিক্ত সাবস্কেলগুলি প্রবর্তন করতে চান না।
  • আপনি বিদ্যমান ফাইল বর্ণনাকারীদের সাথে কোলাহল করতে পারবেন না, সুতরাং স্টিডিন / আউট / এরর স্পর্শ করা উচিত নয় (তবে আপনি কিছু নতুনকে অস্থায়ীভাবে পরিচয় করিয়ে দিতে পারেন)

অতিরিক্ত অনুমান। আপনি সমস্ত থেকে মুক্তি পেতে পারেন, তবে এই ক্লোবারগুলি রেসিপিটি খুব বেশি, তাই এটি এখানে আচ্ছাদিত নয়:

  • আপনি যা জানতে চান তা হ'ল পিআইপিইতে সমস্ত কমান্ডের প্রস্থান কোড 0 রয়েছে।
  • আপনার অতিরিক্ত সাইড ব্যান্ডের তথ্য লাগবে না।
  • আপনার শেল সমস্ত পাইপ কমান্ড ফিরে আসার অপেক্ষা করে না।

পূর্বে: foo | bar | bazতবে এটি কেবল সর্বশেষ কমান্ডের প্রস্থান কোড ( baz) প্রদান করে

চেয়েছিল: পাইপের কোনও কমান্ড ব্যর্থ হলে $?অবশ্যই 0(সত্য) হওয়া উচিত নয়

পরে:

TMPRESULTS="`mktemp`"
{
rm -f "$TMPRESULTS"

{ foo || echo $? >&9; } |
{ bar || echo $? >&9; } |
{ baz || echo $? >&9; }
#wait
! read TMPRESULTS <&8
} 9>>"$TMPRESULTS" 8<"$TMPRESULTS"

# $? now is 0 only if all commands had exit code 0

ব্যাখ্যা:

  • দিয়ে একটি টেম্পাইল তৈরি করা হয় mktemp। এটি সাধারণত তত্ক্ষণাত্ একটি ফাইল তৈরি করে/tmp
  • এই টেম্পাইলটি তখন লেখার জন্য এফডি 9 এবং পড়ার জন্য এফডি 8 এ পুনঃনির্দেশিত হয়
  • তারপরে টেম্পাইলটি ততক্ষণে মুছে ফেলা হয়। উভয় এফডি অস্তিত্বের বাইরে না যাওয়া পর্যন্ত এটি খোলা থাকে।
  • এখন পাইপ শুরু হয়েছে। প্রতিটি পদক্ষেপ কেবল এফডি 9 এ যুক্ত হয়, যদি কোনও ত্রুটি ছিল।
  • waitকার্যকলাপের জন্য দরকারি ksh, কারণ kshসব নল শেষ কমান্ড জন্য অন্য অপেক্ষা করে না। তবে দয়া করে মনে রাখবেন যে কিছু পটভূমি কাজ উপস্থিত থাকলে অযাচিত পার্শ্ব প্রতিক্রিয়া রয়েছে, তাই আমি এটি ডিফল্টরূপে মন্তব্য করেছি। অপেক্ষাটি যদি ক্ষতি না করে তবে আপনি এটিতে মন্তব্য করতে পারেন।
  • এরপরে ফাইলের বিষয়বস্তু পড়তে হবে। যদি এটি খালি থাকে (কারণ সমস্ত কাজ করা হয়েছে) readফিরে আসে false, সুতরাং trueএকটি ত্রুটি নির্দেশ করে

এটি একটি একক কমান্ডের জন্য প্লাগইন প্রতিস্থাপন হিসাবে ব্যবহার করা যেতে পারে এবং কেবল নিম্নলিখিতগুলির প্রয়োজন:

  • 9 এবং 8 অব্যবহৃত এফডি
  • টেম্পাইলটির নাম ধরে রাখতে একটি একক পরিবেশের পরিবর্তনশীল
  • এবং এই রেসিপিটি মোটামুটি কোনও শেলের সাথে মানিয়ে নেওয়া যেতে পারে যা আইও পুনঃনির্দেশের অনুমতি দেয়
  • এছাড়াও এটি মোটামুটি প্লটফর্ম অজিনস্টিক এবং এর মতো জিনিসগুলির প্রয়োজন হয় না /proc/fd/N

বাগ:

এই স্ক্রিপ্টের /tmpজায়গাগুলি ফুরিয়ে যাওয়ার ক্ষেত্রে একটি বাগ রয়েছে । আপনি এই কৃত্রিম ক্ষেত্রে বিরুদ্ধে সুরক্ষা প্রয়োজন হয়, তাহলে খুব, আপনি এটি নিম্নরূপ কি করতে পারেন, তবে এই অসুবিধা আছে, যে সংখ্যা 0মধ্যে 000পাইপে কমান্ড সংখ্যার উপর নির্ভর করে, তাই এটি সামান্য বেশি জটিল:

TMPRESULTS="`mktemp`"
{
rm -f "$TMPRESULTS"

{ foo; printf "%1s" "$?" >&9; } |
{ bar; printf "%1s" "$?" >&9; } |
{ baz; printf "%1s" "$?" >&9; }
#wait
read TMPRESULTS <&8
[ 000 = "$TMPRESULTS" ]
} 9>>"$TMPRESULTS" 8<"$TMPRESULTS"

বহনযোগ্যতা নোট:

  • kshএবং অনুরূপ শেলগুলি যা কেবলমাত্র শেষ পাইপ কমান্ডের জন্য অপেক্ষা করে তাদের waitনিরক্ষিত প্রয়োজন

  • শেষ উদাহরণটি printf "%1s" "$?"পরিবর্তে ব্যবহার করে echo -n "$?"কারণ এটি আরও বহনযোগ্য। প্রতিটি প্ল্যাটফর্ম -nসঠিকভাবে ব্যাখ্যা করে না।

  • printf "$?"এটিও করত, তবে printf "%1s"কিছু সত্যিকারের ভাঙা প্ল্যাটফর্মে স্ক্রিপ্ট চালানোর ক্ষেত্রে কিছু কোণার কেস ধরা পড়ে। (পড়ুন: আপনি প্রোগ্রামে ঘটলে paranoia_mode=extreme।)

  • প্লাটফর্মগুলিতে এফডি 8 এবং এফডি 9 উচ্চতর হতে পারে যা একাধিক সংখ্যা সমর্থন করে। একটি পসিক্স কনফরম্যান্ট শেলটি AFAIR কেবলমাত্র একক সংখ্যা সমর্থন করার প্রয়োজন নেই।

  • ডেবিয়ান 8.2 সাথে পরীক্ষিত হয়েছিল sh, bash, ksh, ash, sashএবং এমনকিcsh


3

কিছুটা সতর্কতা সহ, এটি কাজ করা উচিত:

foo-status=$(mktemp -t)
(foo; echo $? >$foo-status) | bar
foo_status=$(cat $foo-status)

জেলিয়াগ্রের মতো কীভাবে পরিষ্কার করবেন? আপনি foo- স্ট্যাটাস নামক একটি ফাইল পিছনে ছেড়ে না?
জোহান

@ জোহান: আপনি যদি আমার পরামর্শটিকে পছন্দ করেন তবে এটিকে ভোট দিতে দ্বিধা করবেন না;) কোনও ফাইল না রেখেও এর একাধিক প্রক্রিয়া একই সাথে চালানোর অনুমতি দেওয়ার সুবিধা রয়েছে এবং বর্তমান ডিরেক্টরিটি লেখার প্রয়োজন নেই।
jlliagre

2

নিম্নলিখিত 'if' ব্লক কেবল 'কমান্ড' সফল হলে চলবে:

if command; then
   # ...
fi

বিশেষভাবে বলতে গেলে, আপনি এই জাতীয় কিছু চালাতে পারেন:

haconf_out=/path/to/some/temporary/file

if haconf -makerw > "$haconf_out" 2>&1; then
   grep -iq "Cluster already writable" "$haconf_out"
   # ...
fi

যা haconf -makerwএটির স্টডআউট এবং স্টডারকে "$ haconf_out" এ চালাবে এবং সংরক্ষণ করবে । যদি থেকে প্রাপ্ত মানটি haconfসত্য হয়, তবে 'যদি' ব্লকটি কার্যকর করা grepহবে এবং "ক্লাস্টার ইতিমধ্যে লিখনযোগ্য" এর বিপরীতে এটি মিলানোর চেষ্টা করে "$ হ্যাকনফ_আউট" পড়বে।

লক্ষ্য করুন পাইপগুলি স্বয়ংক্রিয়ভাবে নিজেকে পরিষ্কার করে; পুনঃনির্দেশের সাহায্যে আপনার কাজ শেষ হয়ে গেলে "$ haconf_out" মুছে ফেলার জন্য যত্নবান হতে হবে।

এর মতো মার্জিত নয় pipefail, তবে বৈধ বিকল্প যদি এই কার্যকারিতাটি নাগালের মধ্যে না থাকে।


1
Alternate example for @lesmana solution, possibly simplified.
Provides logging to file if desired.
=====
$ cat z.sh
TEE="cat"
#TEE="tee z.log"
#TEE="tee -a z.log"

exec 8>&- 9>&-
{
  {
    {
      { #BEGIN - add code below this line and before #END
./zz.sh
echo ${?} 1>&8  # use exactly 1x prior to #END
      #END
      } 2>&1 | ${TEE} 1>&9
    } 8>&1
  } | exit $(read; printf "${REPLY}")
} 9>&1

exit ${?}
$ cat zz.sh
echo "my script code..."
exit 42
$ ./z.sh; echo "status=${?}"
my script code...
status=42
$

0

(কমপক্ষে বাশ সহ) একত্রিত হয়ে set -eসুস্পষ্টভাবে পাইপফিল অনুকরণ করতে পাইপ ত্রুটি থেকে প্রস্থান করতে সাবশেল ব্যবহার করতে পারেন

set -e
foo | bar
( exit ${PIPESTATUS[0]} )
rest of program

সুতরাং যদি fooকোনও কারণে ব্যর্থ হয় - বাকি প্রোগ্রামটি কার্যকর করা হবে না এবং স্ক্রিপ্টটি সংশ্লিষ্ট ত্রুটি কোড সহ প্রস্থান করবে। (এটি ধরে নিয়েছে যে fooএটির নিজস্ব ত্রুটিটি মুদ্রণ করে, যা ব্যর্থতার কারণটি বোঝার জন্য যথেষ্ট)


-1

সম্পাদনা : এই উত্তরটি ভুল, তবে আকর্ষণীয়, তাই আমি এটি ভবিষ্যতের রেফারেন্সের জন্য রেখে দেব।


!কমান্ডটিতে একটি যুক্ত করা রিটার্ন কোডকে উল্টে দেয়।

http://tldp.org/LDP/abs/html/exit-status.html

# =========================================================== #
# Preceding a _pipe_ with ! inverts the exit status returned.
ls | bogus_command     # bash: bogus_command: command not found
echo $?                # 127

! ls | bogus_command   # bash: bogus_command: command not found
echo $?                # 0
# Note that the ! does not change the execution of the pipe.
# Only the exit status changes.
# =========================================================== #

1
আমি মনে করি এটি সম্পর্কিত নয়। আপনার উদাহরণে, আমি প্রস্থানের কোডটি জানতে চাই ls, এর প্রস্থান কোডটি bogus_command
উল্টাবেন না

2
আমি উত্তর ফিরে আঁকার পরামর্শ দিই।
maxschlepzig

3
ঠিক আছে, দেখা যাচ্ছে আমি একজন বোকা। ওপি যা চেয়েছিল তা করার আগে আমি এটি আসলে একটি স্ক্রিপ্টে ব্যবহার করেছি। ভাল জিনিস আমি এটি গুরুত্বপূর্ণ কোনও কিছুর জন্য ব্যবহার করি নি
ফালমারি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.