سؤال

أنا noob في وضع القذيفة. أرغب في طباعة رسالة والخروج من البرنامج النصي في حالة فشل الأمر. لقد حاولت:

my_command && (echo 'my_command failed; exit)

لكنها لم تعمل. يستمر في تنفيذ التعليمات التي تلي هذا السطر في البرنامج النصي. أنا أستخدم Ubuntu و Bash.

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

المحلول

محاولة:

my_command || { echo 'my_command failed' ; exit 1; }

أربعة تغييرات:

  • يتغيرون && ل ||
  • يستخدم { } بدلاً من ( )
  • تقديم ; بعد exit و
  • مسافات بعد { و قبل }

نظرًا لأنك تريد طباعة الرسالة والخروج فقط عندما يفشل الأمر (يخرج بقيمة غير صفرية) ، فأنت بحاجة إلى أ || ليس &&.

cmd1 && cmd2

سوف يركض cmd2 متى cmd1 تنجح (قيمة الخروج 0). بينما

cmd1 || cmd2

سوف يركض cmd2 متى cmd1 يفشل (قيمة الخروج غير صفرية).

استخدام ( ) يجعل الأمر بداخلهم يعمل في قشرة فرعية ودعوة أ exit من هناك يجعلك تخرج من القشرة الفرعية وليس قذيتك الأصلية ، ومن ثم يستمر التنفيذ في قشرة الأصلية.

للتغلب على هذا الاستخدام { }

التغييرات الأخيرة مطلوبة من قبل باش.

نصائح أخرى

غطت الإجابات الأخرى السؤال المباشر جيدًا ، ولكن قد تكون مهتمًا أيضًا باستخدام set -e. مع ذلك ، أي أمر يفشل (خارج سياقات محددة مثل if الاختبارات) سوف يتسبب في إحباط البرنامج النصي. لبعض البرامج النصية ، إنه مفيد للغاية.

إذا كنت تريد هذا السلوك لجميع الأوامر في البرنامج النصي الخاص بك ، فما عليك سوى إضافة إضافة

  set -e 
  set -o pipefail

في بداية البرنامج النصي. يخبر هذا الزوج من الخيارات مترجم Bash بالخروج عندما يعود الأمر برمز خروج غير صفري.

هذا لا يسمح لك بطباعة رسالة خروج ، رغم ذلك.

لاحظ أيضًا ، يتم تخزين حالة خروج كل أمر في متغير Shell $؟ ، والتي يمكنك التحقق منها مباشرة بعد تشغيل الأمر. تشير الحالة غير الصفر إلى الفشل:

my_command
if [ $? -eq 0 ]
then
    echo "it worked"
else
    echo "it failed"
fi

لقد اخترقت المصطلح التالي:

echo "Generating from IDL..."
idlj -fclient -td java/src echo.idl
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Compiling classes..."
javac *java
if [ $? -ne 0 ]; then { echo "Failed, aborting." ; exit 1; } fi

echo "Done."

تسبق كل أمر مع صدى إعلامي ، واتبع كل أمر مع ذلك
if [ $? -ne 0 ];... خط. (بالطبع ، يمكنك تحرير رسالة الخطأ هذه إذا كنت تريد.)

قدمت my_command تم تصميمه بشكل قانوني ، بمعنى آخر يعود 0 عندما ينجح ، ثم && هو بالضبط عكس ما تريد. انت تريد ||.

لاحظ أيضا ذلك ( لا يبدو لي على حق في باش ، لكن لا يمكنني المحاولة من حيث أنا. أخبرني.

my_command || {
    echo 'my_command failed' ;
    exit 1; 
}

يمكنك أيضًا استخدام ، إذا كنت تريد الحفاظ على حالة خطأ الخروج ، ولديك ملف قابل للقراءة مع أمر واحد لكل سطر:

my_command1 || exit $?
my_command2 || exit $?

هذا ، ومع ذلك لن يطبع أي رسالة خطأ إضافية. ولكن في بعض الحالات ، سيتم طباعة الخطأ بواسطة الأمر الفاشل على أي حال.

ال trap يتيح Shell Buildin الإشارات الصيد ، وغيرها من الشروط المفيدة ، بما في ذلك تنفيذ الأوامر الفاشلة (أي حالة عودة غير صفرية). لذلك إذا كنت لا ترغب في اختبار حالة الإرجاع بشكل صريح لكل أمر واحد يمكنك قوله trap "your shell code" ERR وسيتم تنفيذ رمز shell في أي وقت يعيد الأمر حالة غير صفرية. علي سبيل المثال:

trap "echo script failed; exit 1" ERR

لاحظ أنه كما هو الحال مع الحالات الأخرى من اصطياد الأوامر الفاشلة ، تحتاج خطوط الأنابيب إلى معاملة خاصة ؛ ما سبق لن يصطاد false | true.

تعمل الوظائف التالية فقط على صدى الأخطاء في حالة فشل الأمر:

silently () {
    label="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${label}: ${error}" >&2
        exit 1
    fi
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top