تطوير برامج Bash جيدة

من موسوعة حسوب
< Bash
مراجعة 14:35، 6 سبتمبر 2018 بواسطة أسامه-دمراني (نقاش | مساهمات) (مراجعة 6: إضافة تصانيف، تعديل حالة حرف Bash)
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)
اذهب إلى التنقل اذهب إلى البحث

خصائص الشيفرات الجيدة

هذا الشرح عن آخر وحدة بناء للصدفة وهي الشيفرات النصية. إليك بعض الأمور التي يجب أن تراعيها قبل أن نكمل:

  1. يجب أن تعمل الشيفرة بدون أخطاء.
  2. يجب أن تنفذ المهمة التي كُتبت لها.
  3. يجب أن يكون منطق البرنامج محددًا وظاهرًا.
  4. لا تنفذ الشيفرة مهامًا غير ضرورية.
  5. ينبغي أن تكون الشيفرة قابلة لإعادة استخدامها.

الهيكل Structure

يجب أن يكون هيكل شيفرة الصدفة مرنًا للغاية، فرغم أن bash بها حرية ظاهرة، إلا أنه يجب تحقيق منطق صحيح وتحكم في التدفق والكفاءة بحيث يستطيع المستخدم تنفيذ الشيفرة بشكل صحيح وبسهولة، ولضمان ذلك، سل نفسك هذه الأسئلة حين تكتب شيفرة نصية جديدة:

  • هل سأحتاج أي بيانات من المستخدم أو من بيئته؟
  • كيف سأخزِّن تلك البيانات؟
  • هل هناك أي ملفات يجب إنشاؤها؟ وإن كان فأين يجب إنشاؤها وما الأذونات المناسبة لها، ومن المستخدم الذي سيعطَى ملكيتَها؟
  • ما الأوامر التي سأستخدمها؟ وهل تملك أنظمةُ التشغيل التي ستعمل عليها الشيفرةُ تلك الأوامر بإصداراتها المناسبة؟
  • هل يحتاج المستخدم أي إشعارات؟ متى ولماذا؟

الاصطلاح Terminology

يعطي الجدول التالي نظرة عامة عن المصطلحات البرمجية التي ينبغي أن تفهمها جيدًا:

نظرة عامة على المصطلحات البرمجية

المصطلح الوصف
التحكم في الأمر (command control) اختبار حالة الخروج للأمر لتحديد ما إن كان يجب تنفيذ جزء معين من البرنامج أم لا.
التفرع الشرطي (conditional branch) نقطة منطقية في البرنامج، يحدِّد فيها شرط ما الخطوة التالية
التدفق المنطقي (logic flow) التصميم العام للبرنامج، ويحدد التسلسل المنطقي للمهام لضمان نتيجة ناجحة ومحددة.
الحلقة التكرارية (loop) جزء من البرنامج يتم تنفيذه "س" مرة، حيث س تساوي صفر أو أكثر.
مدخلات المستخدم (user input) البيانات التي يتم إدخالها بواسطة مصدر خارجي أثناء عمل البرنامج، ويمكن تخزينها واستدعاءها عند الحاجة.

النظام والترتيب أولًا

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

استخدم لغتك التي تتحدث بها في وصف المهام التي سينفذها برنامجك كي تنشئ صورة مفهومة عنه، ثم تستطيع بعدها استبدال أوامر الصدفة وكلماتها بما وصفته بلغتك العادية.

ويقدم الشرح الآتي مثالًا عن تصميم منطقي لتنفيذ أوامر برنامج يصف دورانًا لملفات السجل (log files)، فيعرض احتمالًا لحلقة تكرارية (loop) يُتحكَّم بها عن طريق عدد ملفات السجل الأساسية التي تريد تدويرها:

  1. هل تريد تدوير السجلات؟
    1. في حالة نعم:
      1. أدخل اسم المجلد الذي يحتوي السجلات التي تريد تدويرها.
      2. أدخل الاسم الأساسي لملف السجل.
      3. أدخل عدد الأيام التي يجب أن تُحفظ سجلاتُها.
      4. ثبِّت الإعدادات بجعلها دائمة في ملف crontab الخاص بالمستخدم.
    2. في حالة لا: اذهب إلى خطوة 3.
  2. هل تريد تدوير مجموعة أخرى من السجلات؟
    1. في حالة نعم: كرر خطوة 1.
    2. في حالة لا: اذهب إلى خطوة 3.
  3. اخرج.

ينبغي أن يقدم المستخدم بيانات للبرنامج كي يتصرف، ويجب أن تُسجل مدخلات المستخدم وتُحفظ، ويُرسل إشعار إلى المستخدم أن ملف crontab الخاص به ستحدث به تغييرات.

مثال لشيفرة نصية: mysystem.sh

تُنفذ شيفرة mysystem.sh بالأسفل بعض الأوامر المشهورة (date، w، uname، uptime) من أجل عرض بعض البيانات عنك وعن حاسوبك.

hsoub:~> cat -n mysystem.sh

    1 #!/bin/bash
    2 clear
    3 echo "This is information provided by mysystem.sh.  Program starts now."
    4
    5 echo "Hello, $USER"
    6 echo
    7
    8 echo "Today's date is `date`, this is week `date +"%V"`."
    9 echo
   10
   11 echo "These users are currently connected:"
   12 w | cut -d " " -f 1 - | grep -v USER | sort -u
   13 echo
   14
   15 echo "This is `uname -s` running on a `uname -m` processor."
   16 echo
   17
   18 echo "This is the uptime information:"
   19 uptime
   20 echo
   21
   22 echo "That's all folks!"

تبدأ الصدفة دومًا بنفس المَحرَفيْن !# ثم تُحدَّد الصدفة التي ستنفذ الأوامر التي سيأتي ذكرها بعد السطر الأول كما يلي:

  • بدأت الشيفرة أعلاه في سطر رقم 2 بمسح الأوامر الموجودة على الشاشة.
  • سطر 3 يطبع رسالة تخبر المستخدم عما سيحدث.
  • سطر 5 يحيِّي المستخدم.
  • الأسطر 6 و 9 و 13 و 16 و 20 موجودة من أجل الحفاظ على شكل منظم لمُخرجات الأمر.
  • يطبع سطر 8 التاريخ الحالي ورقم الأسبوع.
  • سطر 11 يطبع رسالة بها معلومات للمستخدم، تمامًا كسطر 3 و 18 و 22.
  • يهيئ سطر 12 خرج أمر w.
  • يعرض سطر 15 بيانات عن نظام التشغيل والمعالج.
  • يعرض سطر 19 بيانات وقت التشغيل والأحمال.

وبالنسبة لأمريْ echo و printf فكلاهما أمر مضمَّن في Bash، يخرج أولهما دومًا بحالة 0، ويطبع وسائط (arguments) متبوعة بمحرف نهاية السطر على الخرج العادي، في حين يسمح الثاني بتحديد نص تهيئة (formatting string) ويعطي حالة خروج غير صفرية عند الفشل.

إليك نفس الشيفرة باستخدام أمر printf:

hsoub:~> cat -n mysystem.sh
     1  #!/bin/bash
     2  clear
     3  echo "This is information provided by mysystem.sh.  Program starts now."
     4
     5  echo "Hello, $USER"
     6  echo
     7
     8  echo "Today's date is `date`, this is week `date +"%V"`."
     9  echo
    10
    11  echo "These users are currently connected:"
    12  w | cut -d " " -f 1 - | grep -v USER | sort -u
    13  echo
    14
    15  echo "This is `uname -s` running on a `uname -m` processor."
    16  echo
    17
    18  echo "This is the uptime information:"
    19  uptime
    20  echo
    21
    22  echo "That's all folks!"

انظر كتابة برامج Bash تفاعلية للمزيد عن إنشاء برامج Bash صديقة للمستخدم (user friendly) من حيث إدخاله للرسائل.

المسار الافتراضي لصدفة Bash

هذا يفترض أن برنامج Bash مثبَّت في bin/.

إن لم يكن stdout متاحًا

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

مثال لشيفرة init

تبدأ شيفرة init خدمات النظام على حواسيب يونكس ولينكس مثل عفريت سجل النظام (system log daemon) وعفريت إدارة الطاقة وعفاريت الاسم والبريد، فتلك الشيفرات التي تُعرف أيضًا بشيفرات بدء التشغيل مخزَّنة في أماكن محددة في النظام، مثل etc/rc.d/init.d/ أو etc/init.d/.

تقرأ العملية الأولى init ملفات إعداداتها لتقرر أي الخدمات التي يجب تشغيلها وإيقافها في كل مستوى تشغيل. ومستوى التشغيل هو سلسلة مرتبة من العمليات، وكل نظام به مستوى تشغيل وحيد للمستخدم (user run level) لتنفيذ مهام إدارية مثلًا يكون النظام خلالها غير مستخدم بقدر الإمكان، مثل استعادة نظام ملفات (file system) من نسخة احتياطية. أيضًا، فإن مستويات تشغيل Reboot و shutdown يتم إعدادهما كذلك.

وتُسرد المهام التي يجب تنفيذها عند تشغيل خدمة أو إيقافها في شيفرات بدء التشغيل، وتلك إحدى مهام مدير النظم أن يضبط إعدادات init بحيث تبدأ الخدمات وتتوقف في التوقيت الصحيح. ويجب أن يكون لديك فهم جيد لإجراءات التشغيل والإيقاف على نظامك، لذا ننصح أن تقرأ صفحات man لـ init وinittab قبل البدء في شيفرات التهيئة (initialization scripts) الخاصة بك.

إليك مثالًا بسيطًا يجب أن يشغِّل صوتًا عند تشغيل وإيقاف حاسوبك:

#!/bin/bash

# This script is for /etc/rc.d/init.d
# Link in rc3.d/S99audio-greeting and rc0.d/K01audio-greeting

case "$1" in
'start')
  cat /usr/share/audio/at_your_service.au > /dev/audio
  ;;
'stop')
  cat /usr/share/audio/oh_no_not_again.au > /dev/audio
  ;;
esac
exit 0

ستجد تفصيلًا عن عبارة case التي تُستخدم عادة في مثل ذلك النوع من الشيفرات في استخدام عبارة exit و if.

انظر أيضًا

مصادر