වෙනත් ක්‍රියාවලියකට පිටවන තත්වය ලබා ගන්න


318

මට ක්‍රියාවලි දෙකක් ඇති fooඅතර bar, නලයකට සම්බන්ධ කර ඇත:

$ foo | bar

barසෑම විටම 0 පිටවෙයි; මම පිටවීමේ කේතය ගැන උනන්දු වෙමි foo. එය ලබා ගැනීමට ක්‍රමයක් තිබේද?


Answers:


282

ඔබ භාවිතා කරන්නේ නම් , නල මාර්ගයේ එක් එක් මූලද්‍රව්‍යයේ පිටවීමේ තත්ත්වය ලබා ගැනීමට 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(උපුටා දැක්වීම් නොමැතිකම සැලකිල්ලට ගන්න!).


10
සහ pipestatuszsh වලින්. අවාසනාවට වෙනත් ෂෙල් වෙඩි වල මෙම අංගය නොමැත.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

9
සටහන: zsh හි අරා දර්ශක 1 හි ප්‍රතිවිරුද්ධ ලෙස ආරම්භ වේ, එබැවින් එය echo "$pipestatus[1]" "$pipestatus[2]"වේ.
ක්‍රිස්ටෝෆ් වර්ම්

6
ඔබට සම්පූර්ණ නල මාර්ගය මේ ආකාරයට පරීක්ෂා කළ හැකිය:if [ `echo "${PIPESTATUS[@]}" | tr -s ' ' + | bc` -ne 0 ]; then echo FAIL; fi
l0b0

8
An ජන්හුඩෙක්: සමහර විට ඔබ මගේ පිළිතුරේ පළමු වචන පහ කියවිය යුතුයි. ප්‍රශ්නය පොසික්ස් පමණක් පිළිතුරක් ඉල්ලා සිටියේ කොතැනද යන්න කාරුණිකව පෙන්වා දෙන්න.
camh

13
An ජන්හුඩෙක්: පොසික්ස් ලෙස ටැග් කර නැත. පිළිතුර පොසික්ස් විය යුතු යැයි ඔබ සිතන්නේ ඇයි? එය නිශ්චිතව දක්වා නැති නිසා මම සුදුසුකම් ලත් පිළිතුරක් ලබා දුන්නා. මගේ පිළිතුරෙහි කිසිදු වැරැද්දක් නොමැත, තවද වෙනත් අවස්ථා විසඳීම සඳහා බහුවිධ පිළිතුරු ඇත.
camh

256

මෙය කිරීමට පොදු ක්‍රම 3 ක් ඇත:

පයිප්ෆේල්

පළමු ක්රමය සකස් කිරීමට pipefailවිකල්පය ( ksh, zshහෝ bash). මෙය සරලම දේ වන අතර එය කරන්නේ මූලික වශයෙන් $?ශුන්‍ය නොවන පිටවීම සඳහා අවසාන වැඩසටහනේ පිටවීමේ කේතයට පිටවීමේ තත්වය සැකසීමයි (හෝ සියල්ල සාර්ථකව පිටව ගියහොත් ශුන්‍ය වේ).

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

IP PIPESTATUS

අන්තිම නල මාර්ගයේ ඇති සියලුම වැඩසටහන් වල පිටවීමේ තත්වය අඩංගු වන $PIPESTATUS( $pipestatusin zsh) නමින් අරාව විචල්‍යයක් Bash සතුව ඇත .

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

ඔබට අවශ්‍ය නල මාර්ගයේ නිශ්චිත අගය ලබා ගැනීමට ඔබට 3 වන විධාන උදාහරණය භාවිතා කළ හැකිය.

වෙනම ක්‍රියාත්මක කිරීම්

මෙය විසඳුම්වල වඩාත්ම නොසැලකිලිමත්කමයි. සෑම විධානයක්ම වෙන වෙනම ධාවනය කර තත්වය අල්ලා ගන්න

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

2
ඩාර්න්! මම PIPESTATUS ගැන පළ කරන්නයි ගියේ.
slm

1
යොමු කිරීම සඳහා මෙම SO ප්‍රශ්නයේ තවත් ශිල්පීය ක්‍රම කිහිපයක් සාකච්ඡා කර ඇත: stackoverflow.com/questions/1221833/…
slm

1
P පැට්‍රික් පයිප්ස්ටැටස් ද්‍රාවණය බාෂ් මත ක්‍රියා කරයි, මම ksh ස්ක්‍රිප්ට් භාවිතා කරන්නේ නම් අපට පයිප්ස්ටැටස් හා සමාන දෙයක් සොයාගත හැකි යැයි ඔබ සිතන්නේද? , (මේ අතර ksh සහාය නොදක්වන පයිප්පස්ටැටස් මට පෙනේ)
yael

2
@yael මම භාවිතා නොකරමි ksh, නමුත් එහි මෑන්පේජ් දෙස කෙටියෙන් බැලූ විට එය සහාය නොදක්වයි $PIPESTATUS. එය pipefailවිකල්පයට සහය දක්වයි .
පැට්‍රික්

1
අසාර්ථක විධානයෙහි තත්වය ලබා ගැනීමට මට ඉඩ සලසන බැවින් මම පයිප්ෆයිල් සමඟ යාමට තීරණය කළෙමි:LOG=$(failed_command | successful_command)
vmrob

58

විශේෂිත විසඳුම් හෝ තාවකාලික ලිපිගොනු භාවිතා නොකර මෙම විසඳුම ක්‍රියාත්මක වේ. පාරිතෝෂිකය: අවසානයේදී පිටවීමේ තත්වය ඇත්ත වශයෙන්ම පිටවීමේ තත්වයක් මිස ගොනුවක ඇති සමහර වචන නොවේ.

තත්ත්වය:

someprog | filter

ඔබට පිටවීමේ තත්වය someprogසහ ප්‍රතිදානය අවශ්‍ය වේ filter.

මෙන්න මගේ විසඳුම:

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

මෙම ඉදිකිරීමේ ප්‍රති result ලය ඉදිකිරීම් වල stdout filterලෙසත්, පිටවීමේ තත්වයෙන් ඉදිකිරීම් වල පිටවීමේ තත්වය someprogලෙසත් වේ.


මෙම ඉදිකිරීම උප-ෂෙල් {...}වෙනුවට සරල විධාන කණ්ඩායම්කරණය සමඟ ද ක්‍රියා කරයි (...). subhells හි යම් ඇඟවුම් ඇති අතර අනෙක් ඒවා අතර කාර්ය සාධන පිරිවැයක් ඇත. වැඩි විස්තර සඳහා සියුම් බාෂ් අත්පොත කියවන්න: 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

අවාසනාවට, ව්‍යාකරණ ව්‍යාකරණ සඳහා වක්‍ර වරහන් සඳහා අවකාශ සහ අර්ධ සළකුණු අවශ්‍ය වන අතර එමඟින් ඉදිකිරීම් වඩාත් ඉඩකඩ සහිත වේ.

මෙම පා text යේ ඉතිරි කොටස සඳහා මම උපසෙල් ප්‍රභේදය භාවිතා කරමි.


උදාහරණය 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 උරුම වේ. ගොනු විස්තර 3 someprogවෙත ලියන්නේ නම් එය පිටවීමේ තත්වය බවට පත්වේ. 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ක්රියාත්මක පෙර ගොනුව descriptor වැසුනු 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 සමඟ stdout වෙත හරවා යවමිනි. මෙයින් අදහස් කරන්නේ උපලේඛනයේ විස්තර කර ඇති 4 ලිපිගොනුව සඳහා මුද්‍රණය කර ඇති ඕනෑම දෙයක් සමස්ත ඉදිකිරීමේ මූලික පියවර ලෙස අවසන් වන බවයි.
  2. පයිප්පයක් සාදනු ලබන අතර වම් ( #part3) සහ දකුණේ ( #part2) විධාන ක්‍රියාත්මක වේ. exit $xsපයිප්පයේ අවසාන විධානය ද වන අතර එයින් අදහස් කරන්නේ stdin වෙතින් වන නූල සමස්ත ඉදිකිරීමේ පිටවීමේ තත්වය වනු ඇති බවයි.
  3. ලිපිගොනු විස්තර 3 සමඟ stdout වෙත හරවා යවනු ලැබේ. මෙයින් අදහස් කරන්නේ මෙම උපලේඛනයේ විස්තර 3 සඳහා මුද්‍රණය කර ඇති ඕනෑම දෙයක් අවසන් වන #part2අතර අනෙක් අතට එය සම්පූර්ණ ඉදිකිරීම් වල පිටවීමේ තත්වය වනු ඇති බවයි.
  4. පයිප්පයක් සාදනු ලබන අතර වම් ( #part5සහ #part6) සහ දකුණේ ( filter >&4) විධාන ක්‍රියාත්මක වේ. ප්‍රතිදානය filterගොනු විස්තර #part1කරන්නා 4 වෙත හරවා යවනු ලැබේ. ගොනු විස්තරය 4 හි stdout වෙත හරවා යවන ලදි. මෙයින් අදහස් කරන්නේ ප්‍රතිදානය filterයනු සමස්ත ඉදිකිරීම් වලම ස්ථායීතාවය බවයි.
  5. සිට පිටවීමේ තත්වය #part6ගොනු විස්තර කරන්නා 3 වෙත මුද්‍රණය කර ඇත. #part3ගොනු විස්තරයේ 3 වෙත හරවා යවන ලදි #part2. මෙයින් අදහස් කරන්නේ පිටවීමේ තත්වය #part6සමස්ත ඉදිකිරීම් සඳහා අවසාන පිටවීමේ තත්වය වනු ඇති බවයි.
  6. someprogක්‍රියාත්මක වේ. පිටවීමේ තත්වය ගනු ලැබේ #part5. Stdout පයිප්පයෙන් ගෙන #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
උපසිරැසි

37

ඔබ ඉල්ලූ දේ හරියටම නොවූවත්, ඔබට භාවිතා කළ හැකිය

#!/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ස්ක්‍රිප්ට් එක තුළ වඩාත් ශක්තිමත් විය යුතුය, උදා bash foo.sh.
maxschlepzig

එය ක්‍රියාත්මක වන්නේ කෙසේද? ඔබට උදාහරණයක් තිබේද?
ජොහාන්

2
-o pipefailPOSIX හි නොමැති බව සලකන්න .
scy

2
මෙය මගේ BASH 3.2.25 (1) මුදා හැරීම තුළ ක්‍රියා නොකරයි. / Tmp / ff මුදුනේ මා සතුව ඇත #!/bin/bash -o pipefail. දෝෂය:/bin/bash: line 0: /bin/bash: /tmp/ff: invalid option name
ෆෙලිපේ අල්වරෙස්

2
@FelipeAlvarez: සමහර පරිසරය (linux ඇතුළුව) මත විග්රහ කළ අවකාශයන් කරන්න #!පළමු එක ඔබ්බට මාර්ග, සහ මෙම බවට පත් එසේ /bin/bash -o pipefail /tmp/ff, අවශ්ය වෙනුවට /bin/bash -o pipefail /tmp/ff- getopt(හෝ ඒ හා සමාන) මාණකරනය ක්රියාත්මක භාවිතා optargඉදිරි අයිතමය වන, ARGVඑම තර්කය ලෙස, වෙත -o, එබැවින් එය අසමත් වේ. ඔබ bash-pfexec /bin/bash -o pipefail "$@"#!
එතුමෙකු සෑදුවහොත්

22

හැකි සෑම විටම මම කරන්නේ පිටවීමේ කේතය සිට පෝෂණය fooකිරීමයි bar. උදාහරණයක් ලෙස, fooකිසි විටෙකත් ඉලක්කම් සහිත රේඛාවක් නිපදවන්නේ නැති බව මා දන්නේ නම්, මට පිටවීමේ කේතය සම්බන්ධ කර ගත හැකිය:

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

නැතහොත් ප්‍රතිදානයෙන් fooකිසි විටෙකත් සාධාරණ රේඛාවක් අඩංගු නොවන බව මා දන්නේ නම් .:

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

barඅන්තිම පේළිය හැර අන් සියල්ලටම වැඩ කිරීමට ක්‍රමයක් තිබේ නම් මෙය සැමවිටම කළ හැකි අතර අවසාන පේළියේ පිටවීමේ කේතය ලෙස සම්මත කරන්න.

නම් barවෙනස් ගොනු descriptor මත පිටවීම් කේතය මුද්රණය විසින් සිය නිමැවුම් ඔබ ඔබ, ඔබට හැකි අවශ්ය නැහැ එය කොටසක් බයිපාස් සංකීර්ණ නල වේ.

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
තාවකාලික ලිපිගොනු ප්‍රවේශය භාවිතා කරන විට, පිටපත මිය ගියත් කුණු කසළ ඉතිරි නොවන පරිදි සියලු තාවකාලික ලිපිගොනු ඉවත් කරන උගුලක් එක් කිරීමට මම කැමැත්තෙමි
ප්‍රාතිහාර්යය

17

නල මාර්ගයෙන් ආරම්භ කිරීම:

foo | bar | baz

POSIX shell පමණක් භාවිතා කරන සාමාන්‍ය විසඳුමක් මෙන්න තාවකාලික ලිපිගොනු:

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.

මම සිතන්නේ මෙය ඇතුළත සිට වඩාත් හොඳින් පැහැදිලි කර ඇති බවයි - command1 එහි නිත්‍ය ප්‍රතිදානය stdout (ගොනු විස්තර 1) මත ක්‍රියාත්මක කර මුද්‍රණය කරනු ඇත, පසුව එය අවසන් වූ පසු printf විසින් එහි stdout හි command1 හි පිටවීමේ කේතය ක්‍රියාත්මක කර මුද්‍රණය කරනු ඇත, නමුත් එම stdout වෙත හරවා යවනු ලැබේ. ගොනු විස්තර 3.

විධාන 1 ක්‍රියාත්මක වන අතර, එහි stdout විධාන 2 වෙත නල කරනු ලැබේ. ඉන්පසුව අපි විධාන 2 හි ප්‍රතිදානය ගොනු විස්තර 4 වෙත හරවා යවන අතර එමඟින් එය ගොනු විස්තර 1 න් බැහැරව පවතී - අපට ගොනු විස්තරය 1 ටික කලකට පසුව නොමිලේ අවශ්‍ය නිසා, අපි ගොනු විස්තර 3 හි printf ප්‍රතිදානය නැවත ගොනු විස්තරයට ගෙන එනු ඇත. 1 - එය විධාන ආදේශනය (බැක්ටික්ස්) ග්‍රහණය කර ගන්නා අතර එය විචල්‍යයට ඇතුළත් වේ.

මැජික් වල අවසාන කොටස නම් මුලින්ම exec 4>&1අපි කළේ වෙනම විධානයක් ලෙසයි - එය බාහිර කවචයේ stdout හි පිටපතක් ලෙස ගොනු විස්තර 4 විවෘත කරයි. විධාන ආදේශනය එහි ඇති විධාන දෘෂ්ටි කෝණයෙන් සම්මතයෙන් ලියා ඇති ඕනෑම දෙයක් ග්‍රහණය කරගනු ඇත - නමුත්, විධාන ආදේශනය සම්බන්ධයෙන් විධාන 2 හි ප්‍රතිදානය විස්තර කරන්නා 4 ගොනු කිරීමට යන බැවින්, විධාන ආදේශනය එය ග්‍රහණය නොකරයි - කෙසේ වෙතත්, විධාන ආදේශනයෙන් එය "ඉවත්" වූ පසු, එය තවමත් ස්ක්‍රිප්ට්හි සමස්ත ගොනු විස්තර 1 වෙත යයි.

( exec 4>&1මෙය වෙනම විධානයක් විය යුතුය, මන්ද ඔබ විධාන ආදේශකයක් තුළ ගොනු විස්තර කරන්නෙකුට ලිවීමට උත්සාහ කරන විට බොහෝ පොදු කවච එයට අකමැති වන අතර එය ආදේශකය භාවිතා කරන "බාහිර" විධානයෙන් විවෘත වේ. එබැවින් මෙය එය කළ හැකි සරලම අතේ ගෙන යා හැකි ක්‍රමය.)

ඔබට එය අඩු තාක්‍ෂණික හා සෙල්ලක්කාර ආකාරයකින් බැලීමට හැකිය, විධානවල ප්‍රතිදානයන් එකිනෙක පිම්මක් මෙන්: විධාන 1 පයිප්ප විධාන 2 වෙතට, එවිට printf හි ප්‍රතිදානය විධාන 2 හරහා පනින අතර එමගින් විධාන 2 එය අල්ලා නොගනී. විධාන 2 හි ප්‍රතිදානය විධාන ආදේශකයෙන් පිටතට හා පිටතට පනිනවා, ආදේශනය අල්ලා ගැනීමට නියමිත වේලාවට මුද්‍රණය වන විට එය විචල්‍යයෙන් අවසන් වන අතර විධාන 2 හි ප්‍රතිදානය සම්මත ප්‍රතිදානයට ලියා ඇති ආකාරයටම විනෝදජනක ලෙස ඉදිරියට යයි. සාමාන්‍ය පයිප්පයක.

එසේම, මා තේරුම් ගත් පරිදි, $?පයිප්පයේ දෙවන විධානයේ ආපසු කේතය තවමත් අඩංගු වනු ඇත, මන්ද විචල්‍ය පැවරුම්, විධාන ආදේශක සහ සංයුක්ත විධාන සියල්ලම ඔවුන් තුළ ඇති විධානයේ ආපසු කේතයට විනිවිද පෙනෙන බැවින් නැවත පැමිණීමේ තත්වය command2 ප්‍රචාරය කළ යුතුය - මෙය, සහ අතිරේක ශ්‍රිතයක් නිර්වචනය නොකිරීම නිසා, මෙය ලෙස්මානා විසින් යෝජනා කරන ලද විසඳුමට වඩා තරමක් හොඳ විසඳුමක් විය හැකි යැයි මම සිතමි.

ලෙස්මානා සඳහන් කර ඇති පරිදි, විධාන 1 යම් අවස්ථාවක දී ගොනු විස්තර 3 හෝ 4 භාවිතා කිරීමට ඉඩ ඇත, එබැවින් වඩාත් ශක්තිමත් වීමට නම් ඔබ කරන්නේ:

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.
ජී-මෑන් පවසන්නේ 'මොනිකා නැවත

@ ජී-මෑන් රයිට්, මම සාමාන්‍යයෙන් භාවිතා කරන ෂෙල් වෙඩි (කාර්යබහුල පෙට්ටිය සමඟ එන අළු) මෙන් නොව, ගොනු විස්තර කිරීමේදී ගොනු කරන්නේ කුමක් දැයි මා නොදන්නා බව අමතක කරමි. මම සතුටු වන ක්‍රියාමාර්ගයක් ගැන සිතන විට මම ඔබට දන්වන්නම්. මේ අතර ඔබ සතුව ඩෙබියන් පෙට්ටියක් තිබේ නම් ඔබට එය ඉරකින් උත්සාහ කළ හැකිය, නැතහොත් ඔබට කාර්යබහුල පෙට්ටියක් තිබේ නම් ඔබට එය කාර්යබහුල පෙට්ටිය අළු / ෂා සමඟ උත්සාහ කළ හැකිය.
mtraceur

@ ජී-මෑන් මම විධානය කිරීමට බලාපොරොත්තු වන දේ සහ එය වෙනත් ෂෙල් වෙඩි වලින් කරන්නේ කුමක්ද යන්න විධාන 1 වෙතින් stdout වෙත හරවා යවන බැවින් එය විධාන ආදේශනයට හසු නොවනු ඇත, නමුත් විධාන ආදේශනයට පිටතින් වරක් එය පහත වැටේ fd3 නැවත stdout වෙත යන්න, එබැවින් එය විධාන 2 ට අපේක්ෂිත පරිදි නල මාර්ගයක් බවට පත් කරයි. විධාන 1 පිටවන විට, printf එහි පිටවීමේ තත්වය වෙඩි තබා මුද්‍රණය කරයි, එය විධාන ආදේශනය මඟින් විචල්‍යයට හසු වේ. මෙහි ඉතා සවිස්තරාත්මක බිඳවැටීමක්: stackoverflow.com/questions/985876/tee-and-exit-status/… එසේම, ඔබේ එම ප්‍රකාශය කියවා ඇත්තේ එය තරමක් අපහාසයක් ලෙසද?
mtraceur

මා ආරම්භ කළ යුත්තේ කොතැනින්ද? (1) ඔබට අපහාසයක් දැනුනේ නම් මට කණගාටුයි. “සිත්ගන්නාසුළුයි” යන්නෙන් අදහස් කළේ උනන්දුවෙන්; ඔබ බලාපොරොත්තු වූවා සේම වැඩ කළ හැකි තරම් සංයුක්ත යමක් තිබේ නම් එය ඉතා හොඳ වේ. ඉන් ඔබ්බට, මම කියන්නේ, සරලවම, ඔබේ විසඳුම කුමක් කළ යුතු දැයි මට නොතේරුණි. මම යුනික්ස් සමඟ දීර් time කාලයක් තිස්සේ වැඩ කරමින් / සෙල්ලම් කරමින් සිටිමි (ලිනක්ස් පැවතීමට පෙර සිට), සහ මට යමක් තේරෙන්නේ නැත්නම්, එය රතු කොඩියක් විය හැකිය, සමහර විට අනෙක් පුද්ගලයින්ට එය නොතේරෙනු ඇති අතර එය වැඩි පැහැදිලි කිරීමක් අවශ්‍යයි (IMNSHO). … (ඉදිරියට)
ජී-මෑන් පවසන්නේ 'නැවත

(Cont'd)… ඔබ “… සාමාන්‍ය පුද්ගලයාට වඩා සෑම දෙයක් ගැනම [ඔබ] තේරුම් ගෙන ඇති බව සිතීමට කැමති බැවින් ”, සමහර විට ඔබ මතක තබා ගත යුත්තේ Stack Exchange හි පරමාර්ථය විධාන ලිවීමේ සේවාවක් නොවිය යුතු බවයි. සුළු වශයෙන් පැහැදිලි ප්‍රශ්න සඳහා දහස් ගණනක් එකවර විසඳුම් ලබා දීම; ඒ වෙනුවට තමන්ගේ ගැටළු විසඳන ආකාරය මිනිසුන්ට ඉගැන්වීමට. ඒ සඳහා, “සාමාන්‍ය පුද්ගලයෙකුට” එය තේරුම් ගත හැකි වන පරිදි ඔබ දේවල් හොඳින් පැහැදිලි කළ යුතුය. විශිෂ්ට පැහැදිලි කිරීමකට උදාහරණයක් ලෙස ලෙස්මනගේ පිළිතුර දෙස බලන්න. … (ඉදිරියට)
ජී-මෑන් පවසන්නේ 'මොනිකා නැවත

7

ඉහත සඳහන් ලෙස්මානාගේ විසඳුම { .. }ඒ වෙනුවට භාවිතා කිරීමෙන් කැදැලි උපසිරැසි ආරම්භ කිරීමකින් තොරව කළ හැකිය (මෙම කාණ්ඩගත විධාන සෑම විටම අර්ධ සළකුණු වලින් අවසන් කළ යුතු බව මතක තබා ගන්න). මේ වගේ දෙයක්:

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

මම මෙම ඉදිකිරීම ඩෑෂ් අනුවාදය 0.5.5 සහ බාෂ් අනුවාද 3.2.25 සහ 4.2.42 සමඟ පරීක්ෂා කර ඇත්තෙමි, එබැවින් සමහර ෂෙල් වෙඩි { .. }කණ්ඩායම්කරණයට සහය නොදක්වුවද එය තවමත් පොසික්ස් අනුකූල වේ.


NetBSD sh, pdksh, mksh, dash, bash ඇතුළුව මම එය අත්හදා බැලූ බොහෝ ෂෙල් වෙඩි සමඟ මෙය හොඳින් ක්‍රියා කරයි. කෙසේ වෙතත්, මට එය AT&T Ksh (93s +, 93u +) හෝ zsh (4.3.9, 5.2) සමඟ වැඩ set -o pipefailකිරීමට නොහැකි අතර , ksh වලින් හෝ ඉසින ලද waitවිධාන ගණනක් සමඟ වුවද. මම සිතන්නේ, එය අවම වශයෙන් ksh සඳහා විග්‍රහ කිරීමේ ගැටලුවක් විය හැකි අතර, මම උප-ෂෙල් භාවිතා කිරීමට ඇලී සිටිනවා සේම එය හොඳින් ක්‍රියාත්මක වේ, නමුත් ifksh සඳහා උපසෙල් ප්‍රභේදය තෝරා ගැනීමට වුවද, අනෙක් අයට සංයුක්ත විධානයන් තබන්න, එය අසමත් වේ .
ග්‍රෙග් ඒ. වුඩ්ස්

5

ඔබට පොදු විසඳුම් වලින් එකක් භාවිතා කිරීමට නොහැකි නම් පහත දැක්වෙන්නේ at පැට්‍රික්ගේ පිළිතුරට අතිරේකයක් ලෙස ය.

මෙම පිළිතුර පහත දැක්වේ:

  • ඔබ නොදන්නා $PIPESTATUSහෝ නොදන්නා කවචයක් තිබේset -o pipefail
  • සමාන්තරව ක්‍රියාත්මක කිරීම සඳහා ඔබට පයිප්පයක් භාවිතා කිරීමට අවශ්‍ය බැවින් තාවකාලික ලිපිගොනු නොමැත.
  • ඔබ ස්ක්‍රිප්ටයට බාධා කරන්නේ නම්, හදිසි විදුලිය ඇනහිටීමක් නිසා අමතර අවුල් ජාලාවක් ඇති කර ගැනීමට ඔබට අවශ්‍ය නැත.
  • මෙම විසඳුම අනුගමනය කිරීමට සාපේක්ෂව පහසු විය යුතු අතර කියවීමට පිරිසිදු විය යුතුය.
  • අමතර උපසිරැසි හඳුන්වා දීමට ඔබට අවශ්‍ය නැත.
  • ඔබට දැනට පවතින ගොනු විස්තර කරන්නන් සමඟ සම්බන්ධ විය නොහැක, එබැවින් stdin / out / err ස්පර්ශ නොකළ යුතුය (කෙසේ වෙතත් ඔබට තාවකාලිකව නව එකක් හඳුන්වා දිය හැකිය)

අතිරේක උපකල්පන. ඔබට සියල්ල ඉවත් කළ හැකිය, නමුත් මෙම වට්ටෝරුව ඕනෑවට වඩා වැඩි කරයි, එබැවින් එය මෙහි ආවරණය නොවේ:

  • ඔබට දැන ගැනීමට අවශ්‍ය වන්නේ PIPE හි ඇති සියලුම විධානයන්ට පිටවීමේ කේතය 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
  • මෙම තාවකාලික ගොනුව ලිවීම සඳහා FD 9 සහ කියවීම සඳහා FD 8 වෙත හරවා යවනු ලැබේ
  • එවිට තාවකාලික ගොනුව වහාම මකා දමනු ලැබේ. එෆ්ඩී දෙකම නොපවතින තෙක් එය විවෘතව පවතී.
  • දැන් නළය ආරම්භ කර ඇත. සෑම පියවරක්ම FD 9 ට එකතු කරන්නේ දෝෂයක් ඇත්නම් පමණි.
  • මෙම waitසඳහා අවශ්ය kshනිසා, kshවෙන අවසන් කිරීමට සියලු නල විධාන සඳහා බලා නැත. කෙසේ වෙතත් සමහර පසුබිම් කාර්යයන් තිබේ නම් අනවශ්‍ය අතුරු ආබාධ ඇති බව කරුණාවෙන් සලකන්න, එබැවින් මම එය පෙරනිමියෙන් අදහස් දැක්වුවෙමි. බලා සිටීම හානියක් නොවන්නේ නම්, ඔබට එය අදහස් දැක්විය හැකිය.
  • පසුව ගොනුවේ අන්තර්ගතය කියවනු ලැබේ. එය හිස් නම් (සියල්ල වැඩ කළ නිසා) readනැවත පැමිණේ false, එබැවින් trueදෝෂයක් දක්වයි

මෙය එක් විධානයක් සඳහා ප්ලගීන ආදේශකයක් ලෙස භාවිතා කළ හැකි අතර පහත සඳහන් දෑ පමණක් අවශ්‍ය වේ:

  • භාවිතයට නොගත් FDs 9 සහ 8
  • තාවකාලික ගොනුවේ නම රඳවා ගැනීමට තනි පරිසර විචල්‍යයකි
  • මෙම වට්ටෝරුව IO යළි හරවා යැවීමට ඉඩ සලසන ඕනෑම ෂෙල් එකකට අනුවර්තනය කළ හැකිය
  • එසේම එය තරමක් වේදිකා අ nost ෙයවාදියා වන අතර එවැනි දේ අවශ්‍ය නොවේ /proc/fd/N

දෝෂ:

මෙම ස්ක්‍රිප්ටයේ දෝෂයක් තිබේ නම් /tmpඑය හිස්ව පවතී. ඔබට මෙම කෘතිම නඩුවෙන් ආරක්ෂාව අවශ්‍ය නම්, ඔබට එය පහත පරිදි කළ හැකිය, කෙසේ වෙතත් මෙය අවාසිය ඇත, 0in 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සහ අවසාන නල විධානය සඳහා පමණක් බලා ඇති සමාන ෂෙල් අවශ්ය waituncommented

  • පසුගිය උදාහරණයක් භාවිතා printf "%1s" "$?"කරනවා වෙනුවට echo -n "$?"මෙම වැඩි අතේ ගෙන යා හැකි නිසා. සෑම වේදිකාවක්ම -nනිවැරදිව අර්ථ නිරූපණය නොකරයි .

  • printf "$?"කෙසේ වෙතත් printf "%1s"ඔබ එය ස්ක්‍රිප්ට් එක සැබවින්ම බිඳුණු වේදිකාවක ධාවනය කරන්නේ නම් සමහර කොනවල් අල්ලා ගනී. (කියවන්න: ඔබ වැඩසටහනට පිවිසෙන්නේ නම් paranoia_mode=extreme.)

  • බහු ඉලක්කම් සඳහා සහාය වන වේදිකාවල FD 8 සහ FD 9 වැඩි විය හැකිය. AFAIR POSIX අනුකූලතා කවචයකට අවශ්‍ය වන්නේ තනි ඉලක්කම් සඳහා පමණි.

  • ඩේබියන් 8.2 සමග පරීක්ෂා කරන ලදී sh, bash, ksh, ash, sashපවා හාcsh


4

මෙය අතේ ගෙන යා හැකි ය, එනම් ඕනෑම POSIX අනුකූල කවචයක් සමඟ ක්‍රියා කරයි, වත්මන් නාමාවලිය ලිවිය යුතු නොවන අතර එකම උපක්‍රමය භාවිතා කරමින් බහු ස්ක්‍රිප්ට එකවර ක්‍රියාත්මක වීමට ඉඩ දෙයි.

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

සංස්කරණය කරන්න: ගිලෙස්ගේ අදහස් දැක්වීමෙන් පසුව වඩා ශක්තිමත් අනුවාදයක් මෙන්න:

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

Edit2: සහ සැක සහිත ජිම් අදහස් දැක්වීමෙන් පසුව තරමක් සැහැල්ලු ප්‍රභේදයක් මෙහි ඇත:

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

3
මෙය හේතු කිහිපයක් නිසා ක්‍රියා නොකරයි. 1. තාවකාලික ගොනුව ලිවීමට පෙර කියවිය හැකිය. 2. පුරෝකථනය කළ හැකි නමක් සහිත හවුල් නාමාවලියක තාවකාලික ගොනුවක් සෑදීම අනාරක්ෂිත ය (සුළු සුළු DoS, symlink race). 3. එකම ස්ක්‍රිප්ට් එක කිහිප වතාවක් මෙම උපක්‍රමය භාවිතා කරන්නේ නම්, එය සෑම විටම එකම ගොනු නාමය භාවිතා කරයි. 1 විසඳීමට, නල මාර්ගය අවසන් වූ පසු ගොනුව කියවන්න. 2 සහ 3 විසඳීමට, අහඹු ලෙස ජනනය කළ නමක් හෝ පුද්ගලික නාමාවලියක තාවකාලික ගොනුවක් භාවිතා කරන්න.
ගිලෙස්ගේ SO- නපුරු වීම නවත්වන්න '

+1 හොඳයි $ {PIPESTATUS [0] පහසුය, නමුත් ගිලෙස් සඳහන් කරන ගැටළු පිළිබඳව යමෙකු දන්නේ නම් මෙහි මූලික අදහස ක්‍රියාත්මක වේ.
ජොහාන්

ඔබට උපසෙල් කිහිපයක් ඉතිරි කළ හැකිය : (s=/tmp/.$$_$RANDOM;{foo;echo $?>$s;}|bar; exit $(cat $s;rm $s)). O ජොහාන්: බාෂ් සමඟ එය පහසු බව මම එකඟ වෙමි, නමුත් සමහර සන්දර්භය තුළ, බාෂ් වළක්වා ගන්නේ කෙසේදැයි දැන ගැනීම වටී.
dubiousjim

3

ටිකක් පූර්වාරක්ෂාව සමඟ, මෙය ක්‍රියාත්මක විය යුතුය:

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

Jlliagre වැනි පිරිසිදු කිරීමට කෙසේද? ඔබ foo-status නමින් ගොනුවක් තබන්නේ නැද්ද?
ජොහාන්

O ජොහාන්: ඔබ මගේ යෝජනාවට කැමති නම්, එය ඡන්දය දීමට පසුබට නොවන්න;) ගොනුවක් හැරයාමට අමතරව, එකවර එකවර ක්‍රියාත්මක කිරීමට බහුවිධ ක්‍රියාවලියන්ට ඉඩ දීමේ වාසියක් ඇති අතර වර්තමාන නාමාවලිය ලිවිය යුතු නොවේ.
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එමඟින් එහි stdout සහ stderr "$ haconf_out" වෙත ධාවනය කර ගබඩා කරනු ඇත . ආපසු ලබා දුන් අගය haconfසත්‍ය නම්, 'if' කොටස ක්‍රියාත්මක වන අතර grep"$ haconf_out" කියවනු ඇත, එය "දැනටමත් ලිවිය හැකි පොකුරට" ගැලපීමට උත්සාහ කරයි.

පයිප්ප ස්වයංක්‍රීයව පිරිසිදු වන බව සැලකිල්ලට ගන්න; නැවත හරවා යැවීම සමඟ "$ 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

(අවම වශයෙන් bash සමඟ) set -eඑක් අයෙකු සමඟ සංයෝජනය කිරීමෙන් නල දෝෂ පැහැදිලිව අනුකරණය කිරීමට සහ නල දෝෂයෙන් පිටවීමට උපසෙල් භාවිතා කළ හැකිය

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

එබැවින් fooකිසියම් හේතුවක් නිසා අසමත් වුවහොත් - ඉතිරි වැඩසටහන ක්‍රියාත්මක නොවන අතර අනුරූප දෝෂ කේතය සමඟ ස්ක්‍රිප්ට් පිටවෙයි. (මෙය උපකල්පනය කරන්නේ fooතමන්ගේම දෝෂයක් මුද්‍රණය කරන අතර එය අසාර්ථක වීමට හේතුව තේරුම් ගැනීමට ප්‍රමාණවත් වේ)


-1

සංස්කරණය කරන්න : මෙම පිළිතුර වැරදියි, නමුත් සිත්ගන්නා සුළුය, එබැවින් මම එය අනාගත යොමු කිරීම සඳහා තබමි.


!විධානයට a එකතු කිරීමෙන් ආපසු කේතය ප්‍රතිලෝම වේ.

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, නැති පිටවීම කේතය talk තෝරාගැනුම ප්රතිලෝම කරන්නbogus_command
මයිකල් Mrozek

2
එම පිළිතුර ආපසු ඇද ගැනීමට මම යෝජනා කරමි.
maxschlepzig

3
හොඳයි, පෙනෙන විදිහට මම මෝඩයෙක්. OP ට අවශ්‍ය දේ කළා යැයි සිතීමට පෙර මම මෙය ස්ක්‍රිප්ට් එකක භාවිතා කර ඇත්තෙමි. හොඳ දෙයක් මම එය වැදගත් දෙයකට භාවිතා
නොකළෙමි
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.