الأفخاخ في Bash

من موسوعة حسوب
اذهب إلى: تصفح، ابحث

عام

قد تجد حالات لا تريد فيها من يستخدم شيفراتك النصية أن يخرج قبل الوقت المحدد عن طريق اختصارات لوحة المفاتيح حين تحتاج إلى مدخلات مثلًا أو عند القيام بعملية تنظيف، ويمكن استخدام أمر trap ليلتقط إشارات لوحة المفاتيح تلك، ويمكن برمجته مسبقًا لينفِّذ قائمة أوامر عند التقاط تلك الإشارات.

قواعد أمر trap واضحة ومباشرة:
trap [الإشارات] [الأوامر]
هذا يجعل أمر trap يلتقط الإشارات المُعطاة له، والتي قد تكون أسماء إشارات مع سابقة SIG أو بدونها، أو تكون أرقام إشارات. وإن كانت الإشارة 0 أو EXIT فإن الأوامر التي حُددت يتم تنفيذها عند إغلاق الصدفة، أما إن كانت إحدى الإشارات DEBUG فإن قائمة الأوامر تُنفَّذ بعد كل أمر بسيط.

وإذا حدِّدَت إشارة ما كـ ERR فإن الأوامر في تلك الحالة تُنفَّذ عند كل أمر بسيط يخرج بحالة غير صفرية. لاحظ أن تلك الأوامر لن تُنفَّذ إن أتت حالة الخروج غير الصفرية من جزء من عبارة if أو من الحلقة التكرارية while أو until، وكذلك لن تُنفَّذ الأوامر إن كان رمز حالة الخروج (exit code) لمعامِل منطقي مثل && (AND) أو || (OR) قيمةً غير صفرية، أو عند استخدام معامِل مثل ! حيث يكون خرج الأمر معكوسًا.

وخرج أمر trap نفسه هو 0 إلا في حالة وجود تفصيل غير صحيح لإشارة ما. ستجد الخيارات التي يأخذها أمر trap مفصلة في صفحات دليل info.

إليك الآن مثالًا بسيطًا يلتقط ctrl+c من المستخدم ثم يطبع رسالة، لن يحدث شيء إذا حاولت أن تقتل هذا البرنامج دون تحديد إشارة KILL:
#!/bin/bash
# traptest.sh

trap "echo Booh!" SIGINT SIGTERM
echo "pid is $$"

while :			# "while true" يعطي هذا نفس نتيجة.
do
        sleep 60	# لا يفعل هذا النص أي شيء.
done

كيف تفسر الصدفةُ الأفخاخ

حين تلتقط bash إشارة تم ضبط فخ لها أثناء انتظار انتهاء أمر ما، فلن يتم تنفيذ الفخ حتى ينتهي الأمر، إلا في حالة انتظار أمر عبر أمر wait المُضمَّن، فحينها يتسبب التقاط الإشارة في خروج أمر wait فورًا بحالة خروج أكبر من 128، مباشرة بعد تنفيذ الفخ المضبوط لتلك الإِشارة.

المزيد من الأمثلة

اكتشاف استخدام متغيرٍ ما

قد ترغب في أن تعطي متغيرًا ما خاصية trace أثناء تصحيح (debugging) شيفرة نصية طويلة، وتضع فخًا لرسائل DEBUG لهذا المتغير، وإن كنت تصرّح عن متغير باستخدام شيء مثل VARIABLE=value فإن استبدال الأسطر التالية بإعلان المتغير يعطيك معلومات قيِّمة عما تفعله شيفرتُك:
declare -t VARIABLE=value

trap "echo VARIABLE is being used here." DEBUG

# بقية الشيفرة النصية

حذف المهملات عند الخروج

يعتمد أمر whatis على قاعدة بيانات تُبنى بانتظام باستخدام شيفرة makewhatis.cron مع cron:
#!/bin/bash

LOCKFILE=/var/lock/makewhatis.lock

# السابق بنجاح makewhatis يجب أن يُنفَّذ ملف

[ -f $LOCKFILE ] && exit 0

# عند الخروج lockfile احذف.

trap "{ rm -f $LOCKFILE ; exit 255; }" EXIT

touch $LOCKFILE
makewhatis -u -w
exit 0

ملخص

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

انظر أيضًا

مصادر