বাশ স্ক্রিপ্টে ত্রুটি বাড়ান


109

"টেস্ট কেস ব্যর্থ হয়েছে !!!" বার্তা সহ আমি বাশ স্ক্রিপ্টে ত্রুটি বাড়াতে চাই। বাশে এটি কীভাবে করবেন?

উদাহরণ স্বরূপ:

if [ condition ]; then
    raise error "Test cases failed !!!"
fi

4
আপনি কি এই ত্রুটি ঘটতে চান? আপনার লিপিটি কীভাবে বলা হয়? এটি কি কেবল একটি স্ক্রিপ্ট বা অনেকগুলি স্ক্রিপ্ট? আপনার স্ক্রিপ্টের ব্যবহারগুলি দেখতে দেখতে কেমন হবে?
এটান রিজনার

মাত্র একটি স্ক্রিপ্ট আমি ওবুন্টু টার্মিনালটি ./script/test.sh এর মতো ব্যবহার করে বলেছি
নবীন কুমার



কোন ভালবাসা echo you screwed up at ... | mail -s BUG $bugtrackeremailaddress?
ইনপিক্সড

উত্তর:


126

এটি নির্ভর করে আপনি কোথায় ত্রুটি বার্তাটি সঞ্চয় করতে চান।

আপনি নিম্নলিখিতটি করতে পারেন:

echo "Error!" > logfile.log
exit 125

বা নিম্নলিখিত:

echo "Error!" 1>&2
exit 64

আপনি যখন একটি ব্যতিক্রম উত্থাপন করেন আপনি প্রোগ্রামটির সম্পাদন বন্ধ করেন।

আপনি অপারেটিং সিস্টেমে (0 থেকে 255 পর্যন্ত) ফিরে আসতে চান এমন ত্রুটি কোডটি exit xxxকোথায় রয়েছে xxxএমন কিছু ব্যবহার করতে পারেন । এখানে 125এবং 64কেবল র্যান্ডম কোডগুলি দিয়ে আপনি বেরিয়ে আসতে পারেন। যখন আপনাকে ওএসকে নির্দেশ করতে হবে যে প্রোগ্রামটি অস্বাভাবিকভাবে বন্ধ হয়ে গেছে (উদাহরণস্বরূপ একটি ত্রুটি ঘটেছে), আপনাকে একটি শূন্য-বহির্গমন প্রস্থান কোডটি পাস করতে হবে exit

@ চ্যাপনার যেমন উল্লেখ করেছেন , আপনি এটি করতে পারেন exit 1, যার অর্থ একটি অনির্দিষ্ট ত্রুটি


12
অথবা আপনি এটি স্টাডারে প্রেরণ করতে পারেন, যেখানে ত্রুটিগুলি যাওয়ার কথা।

স্টাডারকে কীভাবে প্রেরণ করবেন?
নবীন কুমার

4
@ ব্যবহারকারী 3078630, আমি স্রেফ আমার উত্তরটি সম্পাদনা করেছি। 1>&2কৌতুকটি করবে
ফোর্সব্রু 6'15

যদি এটি ত্রুটি হয় তবে আপনার শূন্য-বহির্গমন স্থিতিতেও বেরিয়ে আসা উচিতexitনিজে সম্প্রতি সম্পন্ন কমান্ডের প্রস্থান অবস্থা, যা হতে পারে 0. ব্যবহার
chepner

4
যদি আপনার মনে একটি নির্দিষ্ট অর্থ না থাকে তবে আপনার কেবল ব্যবহার করা উচিত exit 1, যা কনভেনশন দ্বারা একটি অনির্দিষ্ট ত্রুটি।
চিপনার

38

বেসিক ত্রুটি পরিচালনা

যদি আপনার পরীক্ষার কেস রানার ব্যর্থ পরীক্ষার জন্য একটি শূন্য কোড না দেয় তবে আপনি কেবল লিখতে পারেন:

test_handler test_case_x; test_result=$?
if ((test_result != 0)); then
  printf '%s\n' "Test case x failed" >&2  # write error message to stderr
  exit 1                                  # or exit $test_result
fi

বা আরও ছোট:

if ! test_handler test_case_x; then
  printf '%s\n' "Test case x failed" >&2
  exit 1
fi

বা সংক্ষিপ্ততম:

test_handler test_case_x || { printf '%s\n' "Test case x failed" >&2; exit 1; }

টেস্ট_হ্যান্ডলারের প্রস্থান কোড সহ প্রস্থান করতে:

test_handler test_case_x || { ec=$?; printf '%s\n' "Test case x failed" >&2; exit $ec; }

উন্নত ত্রুটি পরিচালনা

আপনি যদি আরও বিস্তৃত পদ্ধতি গ্রহণ করতে চান তবে আপনার একটি ত্রুটি হ্যান্ডলার থাকতে পারে:

exit_if_error() {
  local exit_code=$1
  shift
  [[ $exit_code ]] &&               # do nothing if no error code passed
    ((exit_code != 0)) && {         # do nothing if error code is 0
      printf 'ERROR: %s\n' "$@" >&2 # we can use better logging here
      exit "$exit_code"             # we could also check to make sure
                                    # error code is numeric when passed
    }
}

তারপরে আপনার পরীক্ষার কেস চালানোর পরে এটি প্রার্থনা করুন:

run_test_case test_case_x
exit_if_error $? "Test case x failed"

বা

run_test_case test_case_x || exit_if_error $? "Test case x failed"

ত্রুটি হ্যান্ডলারের মতো সুবিধাগুলি হ'ল exit_if_error:

  • আমরা লগিং , স্ট্যাক ট্রেস প্রিন্ট করা , বিজ্ঞপ্তি, ক্লিনআপ করা ইত্যাদির মতো সমস্ত ত্রুটি পরিচালনা করার যুক্তিকে মানিক করে তুলতে পারি, এক জায়গায়
  • ত্রুটি হ্যান্ডলারটিকে ত্রুটি কোডটি একটি আর্গুমেন্ট হিসাবে পাওয়ার মাধ্যমে, আমরা কলারের ব্লাঙ্কের হাত থেকে বাঁচাতে ifপারি যা ত্রুটির জন্য প্রস্থান কোডগুলি পরীক্ষা করে
  • যদি আমাদের একটি সিগন্যাল হ্যান্ডলার থাকে ( ফাঁদ ব্যবহার করে ), আমরা সেখান থেকে ত্রুটি হ্যান্ডলারটি ডেকে আনতে পারি

লাইব্রেরি পরিচালনা ও লগ করার সময় ত্রুটি

এখানে ত্রুটি পরিচালনা ও লগিংয়ের সম্পূর্ণ বাস্তবায়ন দেওয়া হয়েছে:

https://github.com/codefirester/base/blob/master/lib/stdlib.sh


সম্পর্কিত পোস্ট


9

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

শেল কমান্ডগুলি সাধারণত কিছু অপ্রত্যাশিত ইভেন্টের কারণে সফল হয় বা ব্যর্থ হয় কিনা তা শেলকে জানাতে ফিরে আসা প্রস্থান-কোডগুলির উপর নির্ভর করে।

সুতরাং আপনি যা করতে চান তা এই দুটি বিভাগে পড়ে

  • ত্রুটি থেকে প্রস্থান করুন
  • ত্রুটি থেকে প্রস্থান এবং সাফ আপ

আপনি কোনটি করতে চান তার উপর নির্ভর করে ব্যবহারের জন্য শেল বিকল্প রয়েছে। প্রথম ক্ষেত্রে, শেলটি একটি বিকল্প সরবরাহ করেset -e এবং দ্বিতীয় জন্য আপনি একটি কাজ করতে পারে trapউপরEXIT

exitআমার স্ক্রিপ্ট / ফাংশন ব্যবহার করা উচিত ?

ব্যবহার exitসাধারণভাবে ব্যবহারযোগ্যতা পঠনযোগ্যতা বৃদ্ধি নির্দিষ্ট রুটিনগুলিতে, উত্তরটি একবার জানার পরে আপনি কলিং রুটিনে অবিলম্বে প্রস্থান করতে চান। রুটিনটি যদি এমনভাবে সংজ্ঞায়িত করা হয় যে কোনও ত্রুটি সনাক্ত করে এটির জন্য আর কোনও পরিষ্কার-পরিচ্ছন্নতার প্রয়োজন হয় না, তাত্ক্ষণিকভাবে বেরিয়ে না আসার অর্থ হল আপনাকে আরও কোড লিখতে হবে।

সুতরাং স্ক্রিপ্টের সমাপ্তি পরিষ্কার করার জন্য যদি আপনাকে স্ক্রিপ্টে ক্লিন-আপ ক্রিয়াকলাপ করতে হয় তবে এটি ব্যবহার না করা পছন্দ করা উচিতexit

set -eপ্রস্থান করার সময় আমার কি ত্রুটির জন্য ব্যবহার করা উচিত ?

না!

set -eশেলের সাথে "স্বয়ংক্রিয় ত্রুটি সনাক্তকরণ" যুক্ত করার চেষ্টা ছিল। এর লক্ষ্যটি ছিল যে কোনও সময় কোনও ত্রুটি ঘটলে শেলটি বাতিল করতে হয়েছিল, তবে এটি প্রচুর সম্ভাব্য সমস্যা নিয়ে আসে উদাহরণস্বরূপ,

  • যদি পরীক্ষার একটি অংশ হয় এমন কমান্ডগুলি অনাক্রম্য are উদাহরণস্বরূপ, আপনি যদি testঅস্তিত্বের ডিরেক্টরিতে চেকটি ভেঙে ফেলার প্রত্যাশা করেন, তবে তা হবে না, এটি অন্য অবস্থার মধ্যে দিয়ে যায়

    set -e
    f() { test -d nosuchdir && echo no dir; }
    f
    echo survived
    
  • শেষটি ব্যতীত পাইপলাইনে কমান্ডগুলি অনাক্রম্য। নীচের উদাহরণে, কারণ সর্বাধিক সম্পাদিত (ডানদিকের) কমান্ডের প্রস্থান কোডটি বিবেচনা করা হয় ( cat) এবং এটি সফল হয়েছিল। এটি set -o pipefailবিকল্প দ্বারা সেট করে এড়ানো যেতে পারে তবে এটি এখনও একটি সতর্কীকরণ।

    set -e
    somecommand that fails | cat -
    echo survived 
    

ব্যবহারের জন্য প্রস্তাবিত - trapপ্রস্থান করার সময়

রায় যদি অন্ধ থেকে প্রস্থান পরিবর্তে ব্যবহার করার পরিবর্তে একটি ত্রুটি হ্যান্ডেল পাবে চাই set -e, একটি ব্যবহার trapউপর ERRছদ্ম সংকেত।

ERRযখন শেল নিজেই একটি নন-জিরো ত্রুটি কোডের মাধ্যমে প্রস্থান করে ফাঁদ কোড চালানোর জন্য করা হয় না, কিন্তু যখন (যদি মত যে শেল যে একটি শর্ত অংশ নয় যে কোনো কমান্ড রান cmd, অথবাcmd || একটি নন-জিরো প্রস্থান অবস্থা সহ) প্রস্থানের ।

সাধারণ অনুশীলনটি হ'ল আমরা কোনও ট্র্যাপ হ্যান্ডলারটি সংজ্ঞায়িত করি যে কোন লাইনে এবং কী কারণে প্রস্থান হওয়ার কারণে অতিরিক্ত ডিবাগ তথ্য সরবরাহ করতে। শেষ কমান্ডের প্রস্থান কোডটি মনে রাখুন যার ফলে ERRসিগন্যালটি এখনও এই সময়ে উপলব্ধ থাকবে।

cleanup() {
    exitcode=$?
    printf 'error condition hit\n' 1>&2
    printf 'exit code returned: %s\n' "$exitcode"
    printf 'the command executing at the time of the error was: %s\n' "$BASH_COMMAND"
    printf 'command present on line: %d' "${BASH_LINENO[0]}"
    # Some more clean up code can be added here before exiting
    exit $exitcode
}

এবং আমরা কেবলমাত্র হ্যান্ডলারটি ব্যর্থ হচ্ছি এমন স্ক্রিপ্টের উপরে হিসাবে ব্যবহার করি

trap cleanup ERR

এটিকে একটি সাধারণ স্ক্রিপ্টে একসাথে রাখলে তাতে falseলাইন 15 অন্তর্ভুক্ত থাকে, যে তথ্যটি আপনি পাবেন

error condition hit
exit code returned: 1
the command executing at the time of the error was: false
command present on line: 15

trapএছাড়াও অপশন ত্রুটি নির্বিশেষে শুধু শেল সমাপ্তির করো (উদাঃ আপনার শেল স্ক্রিপ্ট প্রস্থানের) এ পরিষ্করণ চালানোর জন্য সংকেত উপর, প্রদান করে EXIT। আপনি একই সময়ে একাধিক সিগন্যালের ফাঁদে ফেলতে পারেন। ট্র্যাপে সমর্থিত সংকেতগুলির তালিকাটি ট্র্যাপ .1 পি-লিনাক্স ম্যানুয়াল পৃষ্ঠায় পাওয়া যাবে

আরেকটি বিষয় লক্ষ্য করার বিষয়টি হ'ল বুঝতে হবে যে প্রদত্ত পদ্ধতিগুলির কোনওটিই কাজ করে না যদি আপনি সাব-শেলগুলির সাথে সম্পর্কিত হন তবে কোন ক্ষেত্রে আপনার নিজের ত্রুটি পরিচালনা করতে হবে।

  • একটি উপ-শেলের সাথে set -eকাজ করবে না। falseউপ-শেল অবধি সীমিত থাকবে এবং কখনও পিতা বা মাতা শেল প্রচারিত হয়। এখানে ত্রুটি পরিচালনা করার জন্য, আপনার নিজের যুক্তি যুক্ত করুন(false) || false

    set -e
    (false)
    echo survived
    
  • একই সাথে ঘটে trap। উপরে বর্ণিত কারণে নীচের যুক্তি কাজ করবে না।

    trap 'echo error' ERR
    (false)
    

5

এখানে একটি সহজ ফাঁদ যা STDERR এ যা ব্যর্থ হয়েছিল তার শেষ যুক্তি মুদ্রণ করে, এতে যে লাইনটি ব্যর্থ হয়েছিল তার প্রতিবেদন করে এবং প্রস্থান কোড হিসাবে লাইন নম্বর সহ স্ক্রিপ্টটি প্রস্থান করে। নোট করুন এটি সর্বদা দুর্দান্ত ধারণা নয়, তবে এটি আপনি তৈরি করতে পারেন এমন কিছু সৃজনশীল অ্যাপ্লিকেশন প্রদর্শন করে।

trap 'echo >&2 "$_ at $LINENO"; exit $LINENO;' ERR

আমি এটি পরীক্ষা করার জন্য একটি লুপ দিয়ে একটি স্ক্রিপ্টে রেখেছি। আমি কেবল কয়েকটি এলোমেলো সংখ্যায় একটি হিট পরীক্ষা করেছি; আপনি প্রকৃত পরীক্ষা ব্যবহার করতে পারেন। যদি আমার জামিনের দরকার হয়, আমি যে বার্তাটি ছুঁড়ে দিতে চাইছি তার সাথে আমি মিথ্যা (যা ফাঁদে ফেলা) ডাকে call

বিশদ কার্যকারিতা জন্য, ফাঁদ একটি প্রক্রিয়াকরণ ফাংশন কল করুন। আপনার যদি আরও পরিষ্কার করার প্রয়োজন হয় তবে আপনি সর্বদা আপনার আর্গ (case _) এ কেস স্টেটমেন্ট ব্যবহার করতে পারেন, সামান্য সিনট্যাকটিক চিনির জন্য কোনও ভারতে বরাদ্দ করুন -

trap 'echo >&2 "$_ at $LINENO"; exit $LINENO;' ERR
throw=false
raise=false

while :
do x=$(( $RANDOM % 10 ))
   case "$x" in
   0) $throw "DIVISION BY ZERO" ;;
   3) $raise "MAGIC NUMBER"     ;;
   *) echo got $x               ;;
   esac
done

নমুনা আউটপুট:

# bash tst
got 2
got 8
DIVISION BY ZERO at 6
# echo $?
6

অবশ্যই, আপনি করতে পারেন

runTest1 "Test1 fails" # message not used if it succeeds

নকশা উন্নতির জন্য প্রচুর ঘর।

ড্র ব্যাকগুলিতে এই সত্যটি অন্তর্ভুক্ত করা হয় যা falseসুন্দর নয় (এইভাবে চিনি), এবং ফাঁদে ফেলে আসা অন্যান্য জিনিসগুলি কিছুটা বোকা লাগতে পারে। তবুও, আমি এই পদ্ধতিটি পছন্দ করি।


4

আপনার কাছে দুটি বিকল্প রয়েছে: স্ক্রিপ্টের আউটপুট কোনও ফাইলে পুনর্নির্দেশ করুন, স্ক্রিপ্টে একটি লগ ফাইল প্রবর্তন করুন এবং

  1. একটি ফাইলে আউটপুট পুনর্নির্দেশ :

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

./runTests &> output.log

উপরের কমান্ডটি আপনার লগ ফাইলটিতে স্ট্যান্ডার্ড আউটপুট এবং ত্রুটি আউটপুট উভয়ই পুনর্নির্দেশ করে।

এই পদ্ধতির ব্যবহার করে আপনাকে স্ক্রিপ্টে কোনও লগ ফাইল প্রবর্তন করতে হবে না এবং তাই যুক্তিটি সামান্য সহজ bit

  1. স্ক্রিপ্টে একটি লগ ফাইল পরিচয় করিয়ে দিন :

আপনার স্ক্রিপ্টে একটি লগ ফাইল হার্ড কোডিং দ্বারা এটি যুক্ত করুন:

logFile='./path/to/log/file.log'

বা এটি একটি পরামিতি দ্বারা পাস:

logFile="${1}"  # This assumes the first parameter to the script is the log file

স্ক্রিপ্টের শীর্ষে লগ ফাইলে মৃত্যুদন্ড কার্যকর করার সময় টাইমস্ট্যাম্প যুক্ত করা ভাল ধারণা:

date '+%Y%-m%d-%H%M%S' >> "${logFile}"

তারপরে আপনি আপনার ত্রুটি বার্তাগুলি লগ ফাইলে পুনর্নির্দেশ করতে পারেন

if [ condition ]; then
    echo "Test cases failed!!" >> "${logFile}"; 
fi

এটি লগ ফাইলটিতে ত্রুটি সংযোজন করবে এবং কার্যকর করা চালিয়ে যাবে। গুরুতর ত্রুটি দেখা দিলে আপনি যদি মৃত্যুদণ্ড বন্ধ করতে চান, আপনি exitস্ক্রিপ্টটি করতে পারেন :

if [ condition ]; then
    echo "Test cases failed!!" >> "${logFile}"; 
    # Clean up if needed
    exit 1;
fi

মনে রাখবেন যে exit 1 নির্দেশ করে যে কোনও অনির্দিষ্ট ত্রুটির কারণে প্রোগ্রামটি কার্যকর করা বন্ধ করে দেয়। আপনি যদি পছন্দ করেন তবে এটি কাস্টমাইজ করতে পারেন।

এই পদ্ধতির ব্যবহার করে আপনি আপনার লগগুলি কাস্টমাইজ করতে পারেন এবং আপনার স্ক্রিপ্টের প্রতিটি উপাদানগুলির জন্য আলাদা লগ ফাইল রাখতে পারেন।


আপনার যদি অপেক্ষাকৃত ছোট স্ক্রিপ্ট থাকে বা অন্যের স্ক্রিপ্টটি প্রথম পদ্ধতির মধ্যে পরিবর্তন না করেই চালিত করতে চান তবে এটি উপযুক্ত।

আপনি যদি সর্বদা লগ ফাইলটি একই স্থানে থাকতে চান তবে এটি ২-এর আরও ভাল বিকল্প Also বিকল্প।


3

আমি প্রায়শই ত্রুটি বার্তাগুলি পরিচালনা করতে কোনও ফাংশন লিখতে দরকারী মনে করি যাতে কোডটি সামগ্রিকভাবে পরিষ্কার হয়।

# Usage: die [exit_code] [error message]
die() {
  local code=$? now=$(date +%T.%N)
  if [ "$1" -ge 0 ] 2>/dev/null; then  # assume $1 is an error code if numeric
    code="$1"
    shift
  fi
  echo "$0: ERROR at ${now%???}${1:+: $*}" >&2
  exit $code
}

এটি পূর্ববর্তী কমান্ড থেকে ত্রুটি কোড নেয় এবং পুরো স্ক্রিপ্ট থেকে বেরিয়ে আসার সময় এটি ডিফল্ট ত্রুটি কোড হিসাবে ব্যবহার করে। এটি সেই সময়টিও নোট করে যেখানে মাইক্রোসেকেন্ডগুলি সমর্থিত হয় (জিএনইউ তারিখটি %Nন্যানোসেকেন্ডস, যা আমরা পরে মাইক্রোসেকেন্ডগুলিতে ছিন্ন করি)।

প্রথম বিকল্পটি যদি শূন্য বা ধনাত্মক পূর্ণসংখ্যার হয় তবে এটি প্রস্থান কোড হয়ে যায় এবং আমরা বিকল্পগুলির তালিকা থেকে এটি সরিয়ে ফেলি। তারপরে আমরা স্ক্রিপ্টটির নাম, "ERROR" শব্দ এবং সময় সহ স্ট্যান্ডার্ড ত্রুটির প্রতি বার্তাটি জানাই (আমরা প্যারামিটার সম্প্রসারণটি মাইক্রোসেকেন্ডগুলিতে ন্যানোসেকেন্ডগুলি কাটাতে, বা নন-জিএনইউ বারের জন্য, যেমন কাটাতে 12:34:56.%Nব্যবহার করি12:34:56 )। ERROR শব্দের পরে একটি কোলন এবং স্পেস যুক্ত করা হয় তবে কেবল যখন সরবরাহ করা ত্রুটি বার্তা থাকে। অবশেষে, আমরা পূর্ব নির্ধারিত প্রস্থান কোডটি ব্যবহার করে স্ক্রিপ্টটি প্রস্থান করি, কোনও ট্র্যাপকে সাধারণ হিসাবে ট্রিগার করে।

কিছু উদাহরণ (ধরে নিই কোডটি বাস করে script.sh):

if [ condition ]; then die 123 "condition not met"; fi
# exit code 123, message "script.sh: ERROR at 14:58:01.234564: condition not met"

$command |grep -q condition || die 1 "'$command' lacked 'condition'"
# exit code 1, "script.sh: ERROR at 14:58:55.825626: 'foo' lacked 'condition'"

$command || die
# exit code comes from command's, message "script.sh: ERROR at 14:59:15.575089"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.