প্রক্রিয়া প্রস্থান কোডের উপর ভিত্তি করে শেল স্ক্রিপ্ট প্রস্থান করুন


378

আমার কাছে একটি শেল স্ক্রিপ্ট রয়েছে যা বেশ কয়েকটি কমান্ড কার্যকর করে। কোনও শূন্য-বহির্গমন কোড সহ কোনও কমান্ড প্রস্থান করলে আমি কীভাবে শেল স্ক্রিপ্টটি প্রস্থান করব?


3
আমি উত্তর দিয়েছি আপনি ধরে নিচ্ছেন ব্যবহার করে, কিন্তু এটি যদি খুব আলাদা শেল হয় তবে আপনি কি আপনার পোস্টে নির্দিষ্ট করতে পারবেন?
মার্টিন ডব্লিউ

হার্ড পদ্ধতি: $?প্রতিটি কমান্ডের পরে মান পরীক্ষা করুন । সহজ পদ্ধতি: আপনার বাশ স্ক্রিপ্টের শীর্ষে set -eবা রাখুন #!/bin/bash -e
mwfearnley

উত্তর:


494

প্রতিটি কমান্ডের পরে, প্রস্থান কোডটি $?ভেরিয়েবলে পাওয়া যায় যাতে আপনার মতো কিছু থাকে:

ls -al file.ext
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

পাইপযুক্ত কমান্ডগুলি $?সম্পর্কে আপনাকে সতর্কতা অবলম্বন করা উচিত যেহেতু কেবলমাত্র পাইপে শেষ উপাদানটির রিটার্ন কোড দেয় তাই কোডটিতে:

ls -al file.ext | sed 's/^/xx: /"

ফাইলটি উপস্থিত না থাকলে একটি ত্রুটি কোডটি ফেরত দেবে না (যেহেতু sedপাইপলাইনের অংশটি আসলে কাজ করে, 0 ফিরে)।

bashশেল আসলে একটি অ্যারের যা সেই ক্ষেত্রে সাহায্য করতে পারেন প্রদান করে যে হচ্ছে PIPESTATUS। এই অ্যারেতে প্রতিটি পাইপলাইন উপাদানগুলির জন্য একটি উপাদান রয়েছে যা আপনি স্বতন্ত্রভাবে এগুলি অ্যাক্সেস করতে পারেন ${PIPESTATUS[0]}:

pax> false | true ; echo ${PIPESTATUS[0]}
1

নোট করুন যে এটি আপনাকে falseপুরো পাইপলাইনের নয়, কমান্ডের ফলাফল দিচ্ছে । আপনি যথাযথ দেখতে দেখতে পুরো তালিকাটি প্রক্রিয়া করতেও পাবেন:

pax> false | true | false; echo ${PIPESTATUS[*]}
1 0 1

আপনি যদি পাইপলাইন থেকে বৃহত্তম ত্রুটি কোডটি পেতে চান তবে আপনি এমন কিছু ব্যবহার করতে পারেন:

true | true | false | true | false
rcs=${PIPESTATUS[*]}; rc=0; for i in ${rcs}; do rc=$(($i > $rc ? $i : $rc)); done
echo $rc

এটি প্রতিটি PIPESTATUSউপাদানের মধ্য দিয়ে যায় , rcযদি এটি পূর্বের rcমানের চেয়ে বেশি হয় তবে এটি সঞ্চয় করে ।


39
পোর্টেবল কোডের এক লাইনে একই বৈশিষ্ট্য: ls -al file.ext || exit $?([[]] বহনযোগ্য নয়)
এইচ

19
মার্চএইচ, আমি মনে করি আপনি এটি [[ ]]দেখতে বেশ সুন্দর পোর্টেবল bash, এটিই যা প্রশ্নটি ট্যাগ করা হয়েছে :-) আশ্চর্যজনকভাবে যথেষ্ট, এটি lsকাজ করে না command.comতাই এটি পোর্টেবল হয় না, স্পষ্টতই আমি জানি, তবে এটি একই ধরণের যুক্তি আপনি বর্তমান।
paxdiablo

39
আমি জানি এটি প্রাচীন, তবে এটি লক্ষ করা উচিত যে আপনি অ্যারের মাধ্যমে পাইপটিতে কমান্ডগুলির প্রস্থান কোড পেতে পারেন PIPESTATUS(যেমন, ${PIPESTATUS[0]}প্রথম কমান্ডের ${PIPESTATUS[1]}জন্য, দ্বিতীয়টির জন্য, বা ${PIPESTATUS[*]}সমস্ত প্রস্থান স্থিতির তালিকার জন্য
দেবসোলার

11
এটি জোর দেওয়া প্রয়োজন যে মার্জিত এবং idiomatic শেল স্ক্রিপ্টিং খুব কমই $?সরাসরি পরীক্ষা করা প্রয়োজন। আপনি সাধারণত কিছু চান if ls -al file.ext; then : nothing; else exit $?; fiযা অবশ্যই @ মার্সএইচএইচ এর সমান বলে মনে হয় ls -al file.ext || exit $?তবে যদি thenবা elseক্লজগুলি কিছুটা জটিল হয় তবে এটি আরও রক্ষণাবেক্ষণযোগ্য।
ট্রিপলি

9
[[ $rc != 0 ]]আপনাকে একটি 0: not foundবা 1: not foundত্রুটি দেবে give এটিতে পরিবর্তন করা উচিত [ $rc -ne 0 ]। এছাড়াও rc=$?সরানো এবং সবেমাত্র ব্যবহার করা যেতে পারে [ $? -ne 0 ]
কার্টিসলাইবোলিন

223

আপনি যদি with? নিয়ে কাজ করতে চান, আপনার প্রতিটি কমান্ডের পরে এটি পরীক্ষা করা দরকার, যেহেতু $? প্রতিটি কমান্ড প্রস্থান করার পরে আপডেট করা হয়। এর অর্থ হ'ল আপনি যদি পাইপলাইন চালান, আপনি কেবল পাইপলাইনে শেষ প্রক্রিয়ার প্রস্থান কোড পাবেন।

আরেকটি পদ্ধতি হ'ল এটি করা:

set -e
set -o pipefail

আপনি যদি এটি শেল স্ক্রিপ্টের শীর্ষে রাখেন তবে দেখে মনে হচ্ছে বাশ এটি আপনার যত্ন নেবে। পূর্ববর্তী পোস্টার হিসাবে উল্লিখিত হয়েছে, "সেট-ই" কোনও সাধারণ কমান্ডের ত্রুটি সহ বাশকে প্রস্থান করবে। "সেট-পাইপফেইল" কোনও পাইপলাইনে কোনও কমান্ডে ত্রুটি সহ বাশকে প্রস্থান করবে।

এই সমস্যাটি নিয়ে আরও আলোচনার জন্য এখানে বা এখানে দেখুন । সেট বিল্টিনে বাশ ম্যানুয়াল বিভাগটি এখানে


6
এটি সত্যই শীর্ষস্থানীয় উত্তর হওয়া উচিত: PIPESTATUSসর্বত্রই প্রস্থান কোড ব্যবহার এবং চেক করার চেয়ে এটি করা অনেক বেশি সহজ easier
ক্যান্ডু

2
#!/bin/bash -eশেল স্ক্রিপ্ট শুরু করার একমাত্র উপায়। আপনি যদি সর্বদা foo || handle_error $?প্রস্থান স্থিতিগুলি পরীক্ষা করতে চান তবে আপনি সর্বদা জিনিস ব্যবহার করতে পারেন ।
ডেভিস হেরিং

53

" set -e" সম্ভবত এটি করার সবচেয়ে সহজ উপায়। আপনার প্রোগ্রামে কোনও কমান্ডের আগে এটি রেখে দিন।


6
@ স্বরূপচ set -eআপনার স্ক্রিপ্টের কোনও আদেশ যদি ত্রুটি স্থিতি দিয়ে প্রস্থান করে এবং আপনি এই ত্রুটিটি পরিচালনা করেন নি তবে আপনার স্ক্রিপ্টটি বাতিল করে দেবে।
অ্যান্ড্রু

2
set -eএটি 100% এর সমান set -o errexitযা পূর্বের অনুসন্ধানের মতো নয়। অফিসিয়াল ডকুমেন্টেশনের জন্য ওপেনগ্রুপ + errexit অনুসন্ধান করুন।
এইচ

30

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

কমান্ড 1 || থেকে প্রস্থান;
কমান্ড 2 || থেকে প্রস্থান;

বাশ চলক in? এ শেষ কমান্ডের প্রস্থান কোডও সংরক্ষণ করবে store



21

http://cfaj.freeshell.org/shell/cus-faq-2.html#11

  1. আমি প্রস্থান কোড পেতে পারি cmd1মধ্যেcmd1|cmd2

    প্রথম, নোট করুন cmd1প্রস্থান কোডটি শূন্য নয় এবং এখনও ত্রুটি বোঝায় না mean এটি উদাহরণস্বরূপ ঘটে

    cmd | head -1

    আপনি 141 (বা 269 ksh93 সহ) প্রস্থান স্থিতি পর্যবেক্ষণ করতে পারেন cmd1তবে এটি একটি লাইন পড়ার পরে সমাপ্ত হওয়ার পরে cmdএকটি SIGPIPE সিগন্যালের মাধ্যমে বাধা পেয়েছিল head -1

    একটি পাইপলাইনের উপাদানগুলির প্রস্থান স্থিতি জানতে cmd1 | cmd2 | cmd3

    ক। zsh সহ:

    প্রস্থান কোডগুলি পাইপস্ট্যাটাস বিশেষ অ্যারেতে সরবরাহ করা হয়। cmd1প্রস্থান কোডে হয় $pipestatus[1], cmd3মধ্যে প্রস্থান কোড $pipestatus[3]যে, তাই $?সবসময় হিসাবে একই $pipestatus[-1]

    খ। বাশ সহ:

    প্রস্থান কোডগুলি PIPESTATUSবিশেষ অ্যারেতে সরবরাহ করা হয়। cmd1প্রস্থান কোডে হয় ${PIPESTATUS[0]}, cmd3মধ্যে প্রস্থান কোড ${PIPESTATUS[2]}যে, তাই $?সবসময় হিসাবে একই ${PIPESTATUS: -1}

    ...

    আরও তথ্যের জন্য নীচের লিঙ্কটি দেখুন


19

বাশ জন্য:

# this will trap any errors or commands with non-zero exit status
# by calling function catch_errors()
trap catch_errors ERR;

#
# ... the rest of the script goes here
#  

function catch_errors() {
   # do whatever on errors
   # 
   #
   echo "script aborted, because of errors";
   exit 0;
}

19
সম্ভবত "প্রস্থান 0" হওয়া উচিত নয়, যেহেতু এটি সাফল্যের ইঙ্গিত দেয়।
নোবার

3
exit_code = $ ?; প্রতিধ্বনি "স্ক্রিপ্ট কারণ ত্রুটি, বন্ধ্যা"; প্রস্থান $ exit_code
RaSergiy

1
@ HAL9001 আপনার কাছে কি এর প্রমাণ আছে? আইবিএম ডকুমেন্টেশন অন্যথায় বলে
প্যাট্রিক জেমস ম্যাকডুগল

11

ব্যাশে এটি সহজ, কেবল তাদের && এর সাথে একত্র করুন:

command1 && command2 && command3

আপনি যদি নির্মাণ করেন তবে নেস্টেড ব্যবহার করতে পারেন:

if command1
   then
       if command2
           then
               do_something
           else
               exit
       fi
   else
       exit
fi

+1 এটি আমি সন্ধান করছিলাম এমন সহজ সমাধান। এছাড়াও, আপনি if (! command)যদি কমান্ড থেকে ননজারো ত্রুটি কোডটি আশা করেন তবে আপনি লিখতেও পারেন।
বার্সি

এটি ধারাবাহিক কমান্ডের জন্য .. আমি যদি 3 টি সমান্তরালভাবে চালু করতে এবং তাদের মধ্যে কোনও একটি ব্যর্থ হয় তবে সবাইকে হত্যা করতে চাইলে কী হবে?
ভ্যাসিল সুরডু

4
#
#------------------------------------------------------------------------------
# run a command on failure exit with message
# doPrintHelp: doRunCmdOrExit "$cmd"
# call by:
# set -e ; doRunCmdOrExit "$cmd" ; set +e
#------------------------------------------------------------------------------
doRunCmdOrExit(){
    cmd="$@" ;

    doLog "DEBUG running cmd or exit: \"$cmd\""
    msg=$($cmd 2>&1)
    export exit_code=$?

    # if occured during the execution exit with error
    error_msg="Failed to run the command:
        \"$cmd\" with the output:
        \"$msg\" !!!"

    if [ $exit_code -ne 0 ] ; then
        doLog "ERROR $msg"
        doLog "FATAL $msg"
        doExit "$exit_code" "$error_msg"
    else
        #if no errors occured just log the message
        doLog "DEBUG : cmdoutput : \"$msg\""
        doLog "INFO  $msg"
    fi

}
#eof func doRunCmdOrExit

2
ব্যবহার করার খুব কম কারণ আছে $*; "$@"পরিবর্তে স্পেস এবং ওয়াইল্ডকার্ড সংরক্ষণ করতে ব্যবহার করুন।
ডেভিস হেরিং
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.