كيفية اعتراض الأخطاء في نصوص Bash على نظام Linux
نشرت: 2022-08-27
بشكل افتراضي ، يقوم برنامج Bash النصي على Linux بالإبلاغ عن خطأ ولكنه يستمر في العمل. نوضح لك كيفية التعامل مع الأخطاء بنفسك حتى تتمكن من تحديد ما يجب أن يحدث بعد ذلك.
معالجة الخطأ في البرامج النصية
معالجة الأخطاء جزء من البرمجة. حتى إذا كتبت رمزًا لا تشوبه شائبة ، فلا يزال بإمكانك مواجهة حالات الخطأ. تتغير البيئة على جهاز الكمبيوتر الخاص بك بمرور الوقت ، حيث تقوم بتثبيت البرامج وإلغاء تثبيتها وإنشاء الدلائل وإجراء الترقيات والتحديثات.
على سبيل المثال ، يمكن أن يواجه البرنامج النصي الذي تم استخدامه للتشغيل بدون مشكلة صعوبات إذا تغيرت مسارات الدليل أو تم تغيير الأذونات في أحد الملفات. الإجراء الافتراضي لقذيفة Bash هو طباعة رسالة خطأ ومواصلة تنفيذ البرنامج النصي. هذا تقصير خطير.
إذا كان الإجراء الذي فشل أمرًا بالغ الأهمية لبعض العمليات أو الإجراءات الأخرى التي تحدث لاحقًا في النص البرمجي ، فلن ينجح هذا الإجراء المهم. يعتمد مدى كارثة ذلك على ما يحاول السيناريو القيام به.
سيكتشف مخطط أكثر قوة الأخطاء ويسمح للبرنامج النصي بالعمل إذا كان بحاجة إلى إيقاف التشغيل أو محاولة معالجة حالة الخطأ. على سبيل المثال ، إذا كان دليل أو ملف مفقودًا ، فقد يكون من المقبول إعادة إنشاء البرنامج النصي لهما.
إذا واجه البرنامج النصي مشكلة يتعذر عليه التعافي منها ، فيمكن إيقاف تشغيله. إذا كان يجب إيقاف البرنامج النصي ، فيمكن أن تتاح له الفرصة لإجراء أي تنظيف مطلوب ، مثل إزالة الملفات المؤقتة أو كتابة حالة الخطأ وسبب الإغلاق في ملف السجل.
كشف حالة الخروج
تُنشئ الأوامر والبرامج قيمة يتم إرسالها إلى نظام التشغيل عند إنهائها. هذا يسمى حالة خروجهم. لها قيمة صفرية إذا لم تكن هناك أخطاء ، أو قيمة غير صفرية إذا حدث خطأ.
يمكننا التحقق من حالة الخروج - المعروفة أيضًا باسم كود الإرجاع - للأوامر التي يستخدمها البرنامج النصي ، وتحديد ما إذا كان الأمر ناجحًا أم لا.
في Bash ، الصفر يساوي true. إذا كانت الاستجابة من الأمر غير صحيحة ، فنحن نعلم حدوث مشكلة ويمكننا اتخاذ الإجراء المناسب.
انسخ هذا النص في محرر ، واحفظه في ملف يسمى “bad_command.sh.”
#! / بن / باش إذا (! bad_command) ؛ ومن بعد صدى "وضع علامة bad_command على خطأ." خروج 1 فاي
ستحتاج إلى جعل النص البرمجي قابلاً للتنفيذ باستخدام الأمر chmod
. هذه خطوة مطلوبة لجعل أي نص برمجي قابلاً للتنفيذ ، لذلك إذا كنت ترغب في تجربة البرامج النصية على جهازك الخاص ، تذكر أن تفعل ذلك لكل منها. استبدل اسم البرنامج النصي المناسب في كل حالة.
chmod + x bad_command.sh
عندما نقوم بتشغيل البرنامج النصي نرى رسالة الخطأ المتوقعة.
./bad_command.sh
لا يوجد أمر مثل "bad_command" ، ولا هو اسم دالة داخل البرنامج النصي. لا يمكن تنفيذه ، لذا فإن الاستجابة ليست صفرًا. إذا لم تكن الإجابة صفرًا - يتم استخدام علامة التعجب هنا كعامل NOT
المنطقي - يتم تنفيذ نص عبارة if
.
في نص برمجي حقيقي ، يمكن أن يؤدي هذا إلى إنهاء النص ، وهو ما يفعله مثالنا ، أو قد يحاول معالجة حالة الخطأ.
قد يبدو أن خط exit 1
زائد عن الحاجة. بعد كل شيء ، لا يوجد شيء آخر في البرنامج النصي وسوف ينتهي على أي حال. لكن استخدام الأمر exit
يسمح لنا بتمرير حالة الخروج إلى الصدفة. إذا تم استدعاء البرنامج النصي الخاص بنا من أي وقت مضى من خلال برنامج نصي ثانٍ ، فسيعرف هذا البرنامج النصي الثاني أن هذا البرنامج النصي واجه أخطاء.
يمكنك استخدام عامل التشغيل المنطقي OR
مع حالة الخروج لأمر ما ، واستدعاء أمر آخر أو وظيفة في البرنامج النصي الخاص بك إذا كانت هناك استجابة غير صفرية من الأمر الأول.
command_1 || الأمر_2
يعمل هذا لأن الأمر الأول يتم تشغيله OR
الثاني. يتم تشغيل الأمر الموجود في أقصى اليسار أولاً. إذا نجح الأمر الثاني فلن يتم تنفيذه. ولكن إذا فشل الأمر الأول ، فسيتم تنفيذ الأمر الثاني. لذلك يمكننا هيكلة كود مثل هذا. هذا هو "logical-or./sh."
#! / بن / باش معالج الأخطاء() { صدى "خطأ: ($؟) $ 1" خروج 1 } أمر سيء || error_handler "فشل bad_command ، السطر: $ {LINENO}"
لقد حددنا وظيفة تسمى error_handler
. هذا يطبع حالة الخروج من الأمر الفاشل ، المحفوظة في المتغير $?
وسطر نص يتم تمريره إليه عند استدعاء الوظيفة. يتم الاحتفاظ بهذا في المتغير $1
. تقوم الوظيفة بإنهاء البرنامج النصي بحالة خروج واحدة.
يحاول البرنامج النصي تشغيل bad_command
والذي من الواضح أنه فشل ، لذا فإن الأمر الموجود على يمين عامل التشغيل المنطقي OR
، ||
، يتم تنفيذ. هذا يستدعي الدالة error_handler
ويمرر سلسلة تسمي الأمر الذي فشل ، ويحتوي على رقم سطر الأمر الفاشل.
سنقوم بتشغيل البرنامج النصي لرؤية رسالة معالج الخطأ ، ثم التحقق من حالة الخروج من البرنامج النصي باستخدام echo.
./logical-or.sh
صدى $؟
توفر وظيفة error_handler
الصغيرة لدينا حالة الخروج لمحاولة تشغيل bad_command
واسم الأمر ورقم السطر. هذه معلومات مفيدة عندما تقوم بتصحيح برنامج نصي.

حالة الخروج من البرنامج النصي واحدة. تعني حالة الخروج 127 التي تم الإبلاغ عنها بواسطة error_handler
"الأمر غير موجود". إذا أردنا ، يمكننا استخدام ذلك كحالة الخروج من البرنامج النصي عن طريق تمريره إلى الأمر exit
.
هناك طريقة أخرى تتمثل في توسيع error_handler
للتحقق من القيم المختلفة المحتملة لحالة الخروج وتنفيذ إجراءات مختلفة وفقًا لذلك ، باستخدام هذا النوع من الإنشاءات:
exit_code = $؟ إذا [$ exit_code -eq 1] ؛ ومن بعد صدى "العملية غير مسموح بها" elif [$ exit_code -eq 2] ؛ ومن بعد صدى "إساءة استخدام شل البنايات" . . . elif [$ status -eq 128]؛ ومن بعد صدى "وسيطة غير صالحة" فاي
باستخدام مجموعة لفرض الخروج
إذا كنت تعلم أنك تريد إنهاء البرنامج النصي الخاص بك كلما حدث خطأ ، فيمكنك إجباره على القيام بذلك. هذا يعني أنك تتخلى عن فرصة أي تنظيف - أو أي ضرر آخر أيضًا - لأن النص البرمجي ينتهي بمجرد اكتشافه لخطأ ما.
للقيام بذلك ، استخدم الأمر set
مع خيار -e
(خطأ). يخبر هذا البرنامج النصي بالخروج كلما فشل الأمر أو أعاد رمز خروج أكبر من الصفر. كما أن استخدام الخيار -E
يضمن عمل اكتشاف الأخطاء والملاءمة في وظائف الصدفة.
للقبض على المتغيرات غير المهيأة أيضًا ، أضف الخيار -u
(unset). للتأكد من اكتشاف الأخطاء في تسلسلات الأنابيب ، أضف الخيار -o pipefail
. بدون ذلك ، تكون حالة الخروج من تسلسل الأوامر عبر الأنابيب هي حالة الخروج للأمر الأخير في التسلسل. لن يتم الكشف عن أمر فاشل في منتصف تسلسل الأنابيب. يجب أن يأتي الخيار -o pipefail
في قائمة الخيارات.
التسلسل المراد إضافته إلى الجزء العلوي من البرنامج النصي هو:
مجموعة -Eeuo pipefail
هذا نص قصير يسمى “unset-var.sh” ، مع متغير غير محدد فيه.
#! / بن / باش مجموعة -Eeou pipefail صدى "$ unset_variable" صدى "هل نرى هذا الخط؟"
عندما نقوم بتشغيل البرنامج النصي ، يتم التعرف على unset_variable كمتغير غير مهيأ ويتم إنهاء البرنامج النصي.
./unset-var.sh
لا يتم تنفيذ أمر echo
الثاني أبدًا.
استخدام المصيدة مع الأخطاء
يتيح لك الأمر Bash trap تسمية أمر أو وظيفة ينبغي استدعاؤها عند رفع إشارة معينة. عادةً ما يتم استخدام هذا لالتقاط إشارات مثل SIGINT
التي يتم رفعها عند الضغط على مجموعة المفاتيح Ctrl + C. هذا البرنامج النصي هو "sigint.sh."
#! / بن / باش اعتراض "echo -e '\ n تم إنهاؤه بواسطة Ctrl + c' ؛ قم بإنهاء" SIGINT العداد = 0 احيانا صحيح فعل صدى "رقم الحلقة:" $ ((عداد ++)) النوم 1 فعله
يحتوي الأمر trap
على أمر echo
وأمر exit
. سيتم تشغيله عند رفع SIGINT
. باقي النص عبارة عن حلقة بسيطة. إذا قمت بتشغيل البرنامج النصي وضغطت على Ctrl + C ، فسترى الرسالة من تعريف trap
، وسيتم إنهاء البرنامج النصي.
./sigint.sh
يمكننا استخدام trap
مع إشارة ERR
للقبض على الأخطاء عند حدوثها. يمكن بعد ذلك إطعامها إلى أمر أو وظيفة. هذا هو "trap.sh." نحن نرسل إعلامات خطأ إلى وظيفة تسمى error_handler
.
#! / بن / باش اعتراض 'error_handler $؟ خطأ $ LINENO معالج الأخطاء() { صدى "خطأ: ($ 1) حدث في $ 2" } رئيسي() { صدى "داخل الوظيفة الرئيسية ()" أمر سيء ثانيا الثالث الخروج $؟ } ثانيا() { صدى "بعد استدعاء main ()" صدى "داخل الثانية () وظيفة" } الثالث() { صدى "داخل الوظيفة () الثالثة" } رئيسي
يقع الجزء الأكبر من النص داخل الوظيفة main
، والتي تستدعي الوظيفتين second
third
. عند مواجهة خطأ - في هذه الحالة ، بسبب عدم وجود bad_command
- تقوم عبارة trap
بتوجيه الخطأ إلى دالة error_handler
. يقوم بتمرير حالة الخروج من الأمر الفاشل ورقم السطر إلى وظيفة error_handler
.
./trap.sh
تقوم وظيفة error_handler
تفاصيل الخطأ في النافذة الطرفية. إذا أردت ، يمكنك إضافة أمر exit
إلى الوظيفة لإنهاء البرنامج النصي. أو يمكنك استخدام سلسلة من عبارات if/elif/fi
لتنفيذ إجراءات مختلفة لأخطاء مختلفة.
قد يكون من الممكن معالجة بعض الأخطاء ، والبعض الآخر قد يتطلب توقف البرنامج النصي.
نصيحة أخيرة
غالبًا ما يعني اكتشاف الأخطاء استباق الأشياء التي يمكن أن تسوء ، ووضع تعليمات برمجية للتعامل مع تلك الاحتمالات في حالة ظهورها. هذا بالإضافة إلى التأكد من صحة تدفق التنفيذ والمنطق الداخلي للبرنامج النصي الخاص بك.
إذا كنت تستخدم هذا الأمر لتشغيل البرنامج النصي الخاص بك ، فسوف يعرض لك Bash إخراج التتبع أثناء تنفيذ البرنامج النصي:
bash -x your-script.sh
يكتب Bash إخراج التتبع في النافذة الطرفية. يعرض كل أمر مع وسيطاته - إذا كان يحتوي على أي منها. يحدث هذا بعد توسيع الأوامر ولكن قبل تنفيذها.
يمكن أن تكون مساعدة هائلة في تعقب الأخطاء المراوغة.
ذات صلة: كيفية التحقق من صحة بناء جملة نص Linux Bash قبل تشغيله