الأحد، 19 أغسطس 2012

شل سكربت باستخدام Case.

تقريباً أنا وقعت في حب الشل السكربتنج D:
امبارح كتبت سكربت بسيط خالص -وبدائي خالص برده D:- بقالي يومين منشكح وليا مزاج أعمل حاجة جديدة انهارده، فقولت اكتب شوية عن السكربت ده (وﻷ مش ناوي أستمر في الكتابة اللي من النوع ده، مجرد تغيير ليس إلا) وبكره العيد يعني ده وقت المرح :-)

متأكد إنه ممكن يتحسن عن كدا، وكمان أكيد في طرق تانية تؤدي نفس الغرض، بس أنا وصلت للطريقة دي ... على قدي يعني :-)

السكربت بيقوم بالتحقق من تاريخ اليوم وينفذ أمر معين إذا جه التاريخ ده ... إزاي يعني؟
طيب نبدأ مع الحكاية الافتراضية :-)

* * * * *

عباس عنده تلات عيال، شادي وفادي وهادي D: مشكلة عباس مع عياله بسيطة جداً وفي نفس الوقت رخمة جداً! المشكلة هي إن عياله مش بتنضف الأوض بتاعتها بانتظام، وبالتالي أمهم هي اللي بتشيل الليله وتكون مضطرة للتعامل مع ٣ غرف لـ ٣ مراهقين! وما أدراك ما الشباب المراهقين!

فراح عاملهم جدول شهري وحدد فيه أيام معينه، كل واحد منهم - اللي هم شادي وفادي وهادي D:- يقوم بتنضيف غرفته فيها، بس الأيام دي مش زي بعض كل شهر، يعني فادي ممكن ينضف الشهر ده يوم ٣ والشهر اللي بعده يوم ٧ والشهر اللي بعده يوم ٢٧! وهكذا فالجدول ده بيتغير كل شهر.


شهر في التاني في التالت، الغرف لسه زي ما هي! شادي وفادي وهادي D: كانوا ديماً بيقولوا لأبوهم إنهم نسيوا اليوم اللي عليهم يقوموا فيه بتنضيف الأوض بتاعتهم!

اممممم إيه العمل؟ عباس صاحبنا ده كان كمبيوتر جيك (Geek) ومبياكلش معاه الكلام ده D:
عباس راح عمل إيه بقى؟ كتب برنامج صغير (سكربت) بلغة شل (Shell Script)، اللي هي موجودة بشكل أساسي في كل أنظمة اليونكس/اللينوكس. عباس عنده سرفر عليه الموقع بتاعه في ألمانيا، وبطبيعة الحال السرفر ده شغال ٢٤ ساعة وبالتالي هو مكان مناسب جداً عشان يحط عليه السكربت بتاعه بحيث يضمن إن جهاز الكمبيوتر (السرفر) ديما شغالً عشان يشغل السكربت اللي كتبه.

المشهور في شل سكربت لما حد يجي يتحقق من قيمة أو حاجة معينة بيستخدم قاعدة IF، لو كذا حصل، إعمل كذا لو محصلش إعمل كذا ... مثلاً لو انهاردة يوم ١٨ في الشهر ابعت إيميل للعنوان الفلاني، أبسط شكل لقاعدة IF في الشل سكربت بتكون بالشكل ده:
if [ الشرط ]
 then
       في حالة تحقق الشرط نفذ أمر معين
 else
       في حالة عدم تحقق الشرط نفذ أمر تاني
       (أو ممكن مينفذش حاجة)
fi
لكن للأسف في الحالة اللي عندنا دلوقتي مش مناسبة مع IF، بالرغم من إننا ممكن نستعمل IF لكن هنضطر نكرر أجزاء كتيرة على الفاضي، ليه؟ عشان في كذا شرط (كل واحد من أولاد عباس ليه كذا يوم في الشهر مش يوم واحد)، وفي كذا فعل (أمر معين يتنفذ لكل ابن من أبناء عباس)

عشان كدا عباس استخدم تركيب تاني في الشل سكربت وهي case، الشكل البسيط لـ case بيكون بالشكل التالي:
case $متغير in
 حالة١|حالة٢|حالة٣)
      الأمر المطلوب تنفيذه إذا تطابق المتغير مع واحد من الحالات.
   ;;    
esac

وعلى ذلك، كتب عباس السكربت بتاعه بالشكل ده:
#!/bin/bash

todaydate=`date +%m-%d`
ftodaydate=`date +%F`
cmonth=08

shady="Shady Abbass"
fady="fady Abbass"
hady="Hady Abbass"

case $todaydate in
 "$cmonth-10"|"$cmonth-18"|"$cmonth-25")
 echo -e "\nDear $shady, please remember you have to clean your room today (w ela enta 3arf eh elly ha7ssalk!). \n\nBob!" | mail -r "Room Cleaning Reminder! " -s "$shady, Remember! You have to clean your room today. ($ftodaydate)" shady.abbas@gmail.com abbas@gmail.com
   ;;
 "$cmonth-7"|"$cmonth-16"|"$cmonth-25")
 echo -e "\nDear $fady, please remember you have to clean your room today (w ela enta 3arf eh elly ha7ssalk!). \n\nBob!" | mail -r "Room Cleaning Reminder! " -s "$fady, Remember! You have to clean your room today. ($ftodaydate)" fady.abbas@gmail.com abbas@gmail.com
   ;;
 "$cmonth-2"|"$cmonth-11"|"$cmonth-20")
 echo -e "\nDear $hady, please remember you have to clean your room today (w ela enta 3arf eh elly ha7ssalk!). \n\nBob!" | mail -r "Room Cleaning Reminder! " -s "$hady, Remember! You have to clean your room today. ($ftodaydate)" hady.abbas@gmail.com abbas@gmail.com
   ;;
 *)
 exit 0
esac

الاول نبدأ بالمتغيرات، المتغيرات في شل عبارة عن قيمة بتحددها لعنصر لقيمة تانية، يعني مثلاً انت بتحتاج تكتب عنوان بيتكم كذا مرة في السكربت وطبعاً عنوان بيتكم ده طويل (البيت رقم كذا في الشارع الفلاني في المنطقة الفلانية في الحي الفلاني ... إلخ) وبالتالي مش كل شوية هتقعد تكتب فيه؟ هتكتبه مرة واحدة وتستعمل المتغير بتاعه اللي انت حددته، كدا يعني:
myaddress=("101 Paul st, first call, Islets of Langerhans, Pancreas.")
وبعد كدا تستعمل القيمة اللي انت حددتها وقبلها علامة الدولار $ ، يعني مثلاً بعد تحديد المتغير اكتب الأمر ده:
echo "My Address Is: $myaddress"
الناتج هيكون كدا:
My Address Is: 101 Paul st, first call, Islets of Langerhans, Pancreas.


المهم، نكمل مع السكربت، عرفنا فكرة المتغيرات، نعرف بقى المتغيرات اللي استخدمناها في السكربت، أول حاجة هي:
todaydate=`date +%m-%d`
الأمر date بيعرض التاريخ بتاع انهارده، بالشكل ده Sat Aug 18 10:57:49 EET 2012 طبعاً إحنا مش عاوزين كل ده.

مخرجات الأمر date ليها كذا هيئة، مثلاً إنت مش عاوز كل ده، عاوز بس تاريخ انهارده بالارقام فتكتب date +%F أو عاوز بس يوم فتكتب date +%d وهكذا (تقدر تعرف كل حاجة عن أي أمر بكتابة (man date في الترمينال بتاعت الشل). اخدنا بس %m %d عشان يطلعلنا الشهر واليوم بس.

تاني حاجة هي ftodaydate وزي ما قولت، ده التاريخ كامل بالارقام زي كدا 18\8\2012
ftodaydate=`date +%F`

تالت حاجة cmonth أو الشهر الحالي، وده عشان لما نحب نغير الأيام بالشهر في السكربت منقعدش نجري ورا كل يوم كتبنا فيه الشهر، تغيير واحد ونستخدم المتغير ده بدل الشهر (أو القيمة %m مع الأمر date)
cmonth=08

بعد كدا أسماء العيال، لإن زي ما قولت، ليه نكتب اسم كبير كل مرة طالما نقدر نستخدم متغير صغير؟
shady="Shady Abbass"
fady="fady Abbass"
hady="Hady Abbass"

التوضيح بتاع بقية السكربت: هكتب السكربت بدون متغيرات، إذا تطابقت القيمة 08-18 (يوم ١٨ من شهر ٨) مع أي قيمة من القيم اللي بعد كدا ( يوم ١٠ أو ١٨ أو ٢٥ من شهر ٨)، هيبعت إيميل باسم الابن اللي عليه الدور في التنضيف.
case 08-18 in
08-10 | 08-18 | 08-25 )
echo -e "\nDear $shady, please remember you have to clean your room today (w ela enta 3arf eh elly ha7ssalk!). \n\nBob!" | mail -r "Room Cleaning Reminder! " -s "$shady, Remember! You have to clean your room today. ($ftodaydate)" shady.abbas@gmail.com abbas@gmail.com
;;
esac

وهنا استخدمنا حاجتين، echo و mail ...
إيكو، ببساطة بيطبع الكلام اللي إنت حددته، بياخد -e عشان يقدر يفهم علامة "\" اللي بيجي معاها حرف n يعني يطبع الكلام على سطر جديد مش نفس السطر.
أما ميل، فهو البرنامج المسئول عن إرسال الرسالة، نص الرسالة بياخده من مخرجات الأمر إيكو، عنوان الرسالة بيجي بعد - ‎(subject) ‎ ‎s‎ واسم المرسل وإيميله بيكون بعد -r (بنفس الصيغة دي) أخيراً الإيميل اللي هيتبعتله الرسالة، وطبعاً هنا عباس كتب إيميل ابنه وإيميله عشان مفيش حد من عياله يحاول يلعب بديله ويقول "أصل الرسالة موصلتليش!" وبالتالي حطهم في خانة اليك!

وكمان عباس استخدم المتغير بتاع اسم كل ابن من ابناءه في عنوان كل رسالةبحيث يظهر اسم الابن اللي اتبعتله الرسالة في عنوان الرسالة، عشان عباس في آخر الشهر ميلاقيش الإيميل بتاعه فيه ٢٠ رسالة بنفس العنوان وميعرفش كل رسالة بتاعت مين بالظبط.

بعدين الـ ٢ سيمي كولون أو الفاصلة المنقوطة ";;" بيهم تنتهي الفقرة الأولى وتبدأ فقرة تانية بحالات تانية.
أخيراً esac دي كلمة case لكم معكوسة واللي بتدل على نهاية بناء جملة case، ودي طريقة شائعة في صدفات يونكس/لينوكس.


طيب لحد كدا وكويس أوي، بس ازاي السكربت ده هيشتغل؟ هيفضل شغال طول اليوم؟ لمدة شهر؟ لأ طبعاً! هنستعمل الأداة الرائعة في لينوكس اللي اسمها Cron ودي ببساطة بتقوم بتشغيل أو تنفيذ حاجة معينة في فترة معينة كل (كل يوم أو كل أسبوع أو كل شهر مثلاً) وبالتالي هنخليها تشغل السكربت كل يوم الساعة ١.٠٠ صباحا (الفجر)، السكربت يتأكد إذا كان في حد عليه ترتيب غرفته انهارده ولا ﻷ، إذا لقى حد يبعت الميل، إذا ملقاش حد يقفل نفسه زي الشاطر.

هنعدل الكرون جوبز (cron jobs):
crontab -e

هنضيف السكربت فيه كدا:
* 1 * * * /root/room_cleaning_reminder.sh

بكدا السكربت هيشتغل كل يوم الساعة ١,٠٠ الفجر ويتأكد إذا اليوم ده يوافق يوم من الأيام اللي المفروض الأوض تتنضف فيها وبعد كدا السكربت يتقفل لحد اليوم التاني الساعة ١,٠٠ وهكذا.

كرون ده موضوع طويل عريض، فمفيش نية للدخول فيه، هكتفي بالصورة اللي فوق دي للتوضيح، واللي عاوز يستزيد فيه ممكن يشوف التالي:

HowTo: Add Jobs To cron Under Linux or UNIX?
Scheduling Tasks with Cron Jobs.

معلومات أكتر عن Case بالإنجليزي:

The case statement - Linux Shell Scripting Tutorial - A Beginner's handbook


وبكدا المشكلة تكون اتحلت، شادي وفادي وهادي هينضفوا اوضهم بمزاجهم أو غصب عنهم، لإن زي ما احنا عارفين، مفيش حد بيعرف يسد قصاد الجييكس ... عشان كدا زي ما بقول ديماً لا تفكر في إغضاب جيك فالعواقب ربما تكون أسوء مما تتصور D:


بس كدا ... عيد فطر رائع عليكم، حاولوا تستمتعوا على قد ما تقدروا! :-)

هناك تعليق واحد:

  1. تدوينه ممتازه عن الشيل اسكربت ..
    شكرا أحمد م.أبوزيد

    ردحذف