خروج قذيفة النصي على أساس عملية الخروج على القانون

StackOverflow https://stackoverflow.com/questions/90418

  •  01-07-2019
  •  | 
  •  

سؤال

لدي قذيفة النصي الذي ينفذ عددا من الأوامر.كيف يمكنني جعل شيل الخروج إذا كان أي من الأوامر الخروج مع غير الصفر خروج الرمز ؟

هل كانت مفيدة؟

المحلول

بعد كل أمر ، رمز الإنهاء يمكن العثور عليها في $? متغير لذلك سيكون لديك شيء من هذا القبيل:

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 القيمة.

نصائح أخرى

إذا كنت ترغب في العمل مع $?, سوف تحتاج إلى التحقق من ذلك بعد كل أمر ، منذ $?يتم تحديث بعد كل أمر مخارج.وهذا يعني أنه إذا قمت بتنفيذ خط أنابيب ، عليك فقط الحصول على كود الخروج من الماضي في خط أنابيب.

وثمة نهج آخر هو أن تفعل هذا:

set -e
set -o pipefail

إذا وضعت هذا في الجزء العلوي من شيل يبدو باش سوف تأخذ الرعاية من هذا لك.السابقة ملصق وأشار إلى أن "مجموعة -e" سوف يسبب باش للخروج مع خطأ على أي الأمر بسيط."مجموعة -o pipefail" سوف يسبب باش للخروج مع خطأ على أي أمر في خط أنابيب كذلك.

انظر هنا أو هنا للمزيد من النقاش حول هذه المشكلة. هنا هو باش دليل القسم على مجموعة مضمنة.

"set -e"هو على الأرجح أسهل طريقة للقيام بذلك.فقط ضع هذا قبل أي الأوامر في البرنامج.

إذا كنت مجرد دعوة للخروج في باش مع عدم وجود معلمات ، فإنه سيعود رمز إنهاء الأمر الأخير.جنبا إلى جنب مع أو باش ينبغي أن تحتج فقط الخروج ، إذا كان الأمر السابق فشل.ولكن لم يتم اختبار هذا.

command1 || exit;
command2 || exit;

باش أيضا تخزين رمز إنهاء الأمر الأخير في المتغير $?.

[ $? -eq 0 ] || exit $?; # exit for none-zero return code

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

  1. كيف يمكنني الحصول على كود الخروج من cmd1 في cmd1|cmd2

    أولا ملاحظة أن cmd1 رمز الإنهاء يمكن أن يكون غير الصفر و لا يعني خطأ.هذا يحدث على سبيل المثال في

    cmd | head -1
    

    قد نلاحظ 141 (أو 269 مع ksh93) حالة خروج من cmd1, ولكن بسبب cmd قاطعه SIGPIPE إشارة عندما head -1 إنهاء بعد قراءة سطر واحد.

    لمعرفة حالة خروج من عناصر خط أنابيب cmd1 | cmd2 | cmd3

    أ.مع zsh:

    خروج رموز في pipestatus خاصة مجموعة. cmd1 كود الخروج في $pipestatus[1], cmd3 كود الخروج في $pipestatus[3], بحيث $? هو دائما نفس $pipestatus[-1].

    ب.مع bash:

    خروج رموز في PIPESTATUS خاصة مجموعة. cmd1 كود الخروج في ${PIPESTATUS[0]}, cmd3 كود الخروج في ${PIPESTATUS[2]}, بحيث $? هو دائما نفس ${PIPESTATUS: -1}.

    ...

    لمزيد من التفاصيل راجع ما يلي الرابط.

بالنسبة باش:

# 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;
}

في هذا باش ويتم ربطها مع &&:

command1 && command2 && command3

يمكنك أيضا استخدام if المتداخلة بناء:

if command1
   then
       if command2
           then
               do_something
           else
               exit
       fi
   else
       exit
fi
#
#------------------------------------------------------------------------------
# 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top