"টেস্ট কেস ব্যর্থ হয়েছে !!!" বার্তা সহ আমি বাশ স্ক্রিপ্টে ত্রুটি বাড়াতে চাই। বাশে এটি কীভাবে করবেন?
উদাহরণ স্বরূপ:
if [ condition ]; then
raise error "Test cases failed !!!"
fi
"টেস্ট কেস ব্যর্থ হয়েছে !!!" বার্তা সহ আমি বাশ স্ক্রিপ্টে ত্রুটি বাড়াতে চাই। বাশে এটি কীভাবে করবেন?
উদাহরণ স্বরূপ:
if [ condition ]; then
raise error "Test cases failed !!!"
fi
echo you screwed up at ... | mail -s BUG $bugtrackeremailaddress
?
উত্তর:
এটি নির্ভর করে আপনি কোথায় ত্রুটি বার্তাটি সঞ্চয় করতে চান।
আপনি নিম্নলিখিতটি করতে পারেন:
echo "Error!" > logfile.log
exit 125
বা নিম্নলিখিত:
echo "Error!" 1>&2
exit 64
আপনি যখন একটি ব্যতিক্রম উত্থাপন করেন আপনি প্রোগ্রামটির সম্পাদন বন্ধ করেন।
আপনি অপারেটিং সিস্টেমে (0 থেকে 255 পর্যন্ত) ফিরে আসতে চান এমন ত্রুটি কোডটি exit xxx
কোথায় রয়েছে xxx
এমন কিছু ব্যবহার করতে পারেন । এখানে 125
এবং 64
কেবল র্যান্ডম কোডগুলি দিয়ে আপনি বেরিয়ে আসতে পারেন। যখন আপনাকে ওএসকে নির্দেশ করতে হবে যে প্রোগ্রামটি অস্বাভাবিকভাবে বন্ধ হয়ে গেছে (উদাহরণস্বরূপ একটি ত্রুটি ঘটেছে), আপনাকে একটি শূন্য-বহির্গমন প্রস্থান কোডটি পাস করতে হবে exit
।
@ চ্যাপনার যেমন উল্লেখ করেছেন , আপনি এটি করতে পারেন exit 1
, যার অর্থ একটি অনির্দিষ্ট ত্রুটি ।
1>&2
কৌতুকটি করবে
exit
নিজে সম্প্রতি সম্পন্ন কমান্ডের প্রস্থান অবস্থা, যা হতে পারে 0. ব্যবহার
exit 1
, যা কনভেনশন দ্বারা একটি অনির্দিষ্ট ত্রুটি।
যদি আপনার পরীক্ষার কেস রানার ব্যর্থ পরীক্ষার জন্য একটি শূন্য কোড না দেয় তবে আপনি কেবল লিখতে পারেন:
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
__FILE__
, __LINE__
বাশেআরও কয়েকটি উপায় রয়েছে যা দিয়ে আপনি এই সমস্যার কাছে যেতে পারেন। ধরে নেওয়া আপনার প্রয়োজনীয়তার একটি হ'ল কয়েকটি শেল কমান্ড সম্বলিত একটি শেল স্ক্রিপ্ট / ফাংশন চালানো এবং স্ক্রিপ্টটি সফলভাবে চলেছে কিনা তা পরীক্ষা করে নেওয়া এবং ব্যর্থতার ক্ষেত্রে ত্রুটি নিক্ষেপ করা।
শেল কমান্ডগুলি সাধারণত কিছু অপ্রত্যাশিত ইভেন্টের কারণে সফল হয় বা ব্যর্থ হয় কিনা তা শেলকে জানাতে ফিরে আসা প্রস্থান-কোডগুলির উপর নির্ভর করে।
সুতরাং আপনি যা করতে চান তা এই দুটি বিভাগে পড়ে
আপনি কোনটি করতে চান তার উপর নির্ভর করে ব্যবহারের জন্য শেল বিকল্প রয়েছে। প্রথম ক্ষেত্রে, শেলটি একটি বিকল্প সরবরাহ করে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)
এখানে একটি সহজ ফাঁদ যা 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
সুন্দর নয় (এইভাবে চিনি), এবং ফাঁদে ফেলে আসা অন্যান্য জিনিসগুলি কিছুটা বোকা লাগতে পারে। তবুও, আমি এই পদ্ধতিটি পছন্দ করি।
আপনার কাছে দুটি বিকল্প রয়েছে: স্ক্রিপ্টের আউটপুট কোনও ফাইলে পুনর্নির্দেশ করুন, স্ক্রিপ্টে একটি লগ ফাইল প্রবর্তন করুন এবং
এখানে আপনি ধরে নিয়েছেন যে স্ক্রিপ্টটি সতর্কতা এবং ত্রুটি বার্তাসহ সমস্ত প্রয়োজনীয় তথ্য আউটপুট করে। তারপরে আপনি আউটপুটটিকে আপনার পছন্দের কোনও ফাইলে পুনর্নির্দেশ করতে পারেন।
./runTests &> output.log
উপরের কমান্ডটি আপনার লগ ফাইলটিতে স্ট্যান্ডার্ড আউটপুট এবং ত্রুটি আউটপুট উভয়ই পুনর্নির্দেশ করে।
এই পদ্ধতির ব্যবহার করে আপনাকে স্ক্রিপ্টে কোনও লগ ফাইল প্রবর্তন করতে হবে না এবং তাই যুক্তিটি সামান্য সহজ bit
আপনার স্ক্রিপ্টে একটি লগ ফাইল হার্ড কোডিং দ্বারা এটি যুক্ত করুন:
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 বিকল্প।
আমি প্রায়শই ত্রুটি বার্তাগুলি পরিচালনা করতে কোনও ফাংশন লিখতে দরকারী মনে করি যাতে কোডটি সামগ্রিকভাবে পরিষ্কার হয়।
# 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"