اذهب إلى المحتوى

سامر سليمان

الأعضاء
  • المساهمات

    13
  • تاريخ الانضمام

  • تاريخ آخر زيارة

كل منشورات العضو سامر سليمان

  1. يثبت مستخدمي لينكس الكثير من الحزم البرمجية باستخدام الأداة apt لما تتيحه من سهولة في العمل، فيكفي أن يكتب المستخدم اسم الحزمة لتبدأ الأداة البحث عنها ضمن مخازن البرمجيات الخاصة بنظام التشغيل أوبونتو. تكمن المشكلة الأساسية عندما لا تكون الحزمة المطلوبة موجودة ضمن مخزن البرمجيات الخاص بنظام التشغيل أوبونتو وهنا يمكن للمستخدم أن يستخدم برمجيات خارجية -مطورة من طرف ثالث Third-party كما تسمى- إن رغب بذلك كما هو الحال عند تثبيت التطبيقات باستخدام PPA ويمكن أن يتم اللجوء إلى مخزن برمجيات خارجي وتوسعة قائمة مصادر التثبيت Source List المستخدمة عند البحث عن حزمة برمجية ما. يبحث المستخدم عادة عن التعليمات اللازمة لتثبيت الحزمة فيجد مجموعة من الأوامر التي يجب عليه تنفيذها كأن يثبّت أداة ما ومن إضافة شيء ما يتعلق بمفاتيح gpg إلى قائمة مصادر التثبيت وبعدها يمكن تثبيت الحزمة البرمجية. يستعرض المثال التالي التعليمات اللازمة لتثبيت مدير الحزم الخاص بلغة جافا سكريبت JavaScript على نظام أوبونتو: sudo apt install apt-transport-https curl curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - sudo sh -c 'echo "deb https://dl.yarnpkg.com/debian/ stable main" >> /etc/apt/sources.list.d/yarn.list' sudo apt update && sudo apt install yarn نجد العديد من هذه الأوامر عند تثبيت الأدوات البرمجية مباشرة من المطور وتعد المشكلة الأساسية فيها أن المستخدم ينفذ مجموعة من التعليمات الحساسة والتي تتطلب صلاحيات متقدمة بعض الشيء دون أن يدرك فعليًا دور كل أمر من الأوامر. يجب أن يدرك المستخدم الخطوات التي ينفذها مما يضمن نجاح عملية التثبيت من جهة ويسهل عملية حل المشاكل التي تصادفه. فهم إجرائية تثبيت الحزم من مخازن البرمجيات الخارجية يبين الشكل التالي توضيحًا للمخازن البرمجية ومحتوياتها ضمن نظام التشغيل لينكس. عندما نضيف مخزن برمجيات جديد إلى النظام فهذا يعني أن المستخدم يصبح قادرًا على تحميل وتثبيت الحزم البرمجية المتاحة ضمن هذا المخزن الجديد كما أنه يستطيع تحديث وترقية هذه الحزم عندما يتيحها المخزن مباشرة وذلك من ضمن عملية تحديث وترقية حزم النظام بتنفيذ الأمر apt update والأمر apt upgrade. تقسم هذه الإجرائية إلى أربعة أجزاء رئيسية وهي: الحصول على دعم بروتوكول https للأداة apt إضافة مفتاح GPG الخاص بمخزن البرمجيات البعيد إضافة عنوان مخزن البرمجيات البعيد إلى قائمة مصادر التثبيت الموثوقة تثبيت التطبيقات من المخزن البرمجي الذي تمت إضافته الجزء الأول: الحصول على دعم بروتوكول https للأداة apt بالعودة إلى التعليمات السابقة نجد أنها تبدأ بالأمر التالي: sudo apt install apt-transport-https curl تستخدم الأداة Curl لتحميل الملفات باستخدام سطر أوامر لينكس، أما الحزمة الثانية التي يتم تثبيتها فهي الأهم إذا كانت توزيعة لينكس المستخدمة قديمة بعض الشيء أما إذا كانت التوزيعة حديثة فلا داع لتنفيذ هذا الأمر. تُستخدم هذه الأداة لإجبار نظام تشغيل أوبونتو لاستخدام https بدلًا من http التي تعد البروتوكول الافتراضي. حتى أن دعم https لم يكن أساسيًا وذلك قبل الإصدار 1.5 من الأداة apt وأما بعد هذا الإصدار فلا يوجد داع لتثبيت الحزمة السابقة لأنها أصبحت مدمجة بشكل تلقائي في الأداة. يبين الشكل أدناه أنّ مخازن برمجيات أوبونتو تستخدم البروتوكول http إلا بعضًا منها التي أضافها المستخدم بشكل يدوي. إذا تضيف الحزمة "apt-transport-https" دعم https إلى الأداة apt ومن الطبيعي أن يتساءل المستخدم عن سبب غياب دعم بروتوكول https بشكل مباشر من قبل نظام أوبونتو علمًا أنه أكثر أمانًا من استخدام البروتوكول http وتجيب الفقرة التالية على هذا التساؤل. الجزء الثاني: إضافة مفتاح GPG الخاص بمخزن البرمجيات البعيد تستخدم مخازن برمجيات لينكس آلية حماية تعتمد على مفاتيح GPG المبنية ضمن مخزن البرمجيات. يضيف كل مخزن مفتاحه إلى قائمة المفاتيح الموثوقة الخاصة بمخازن البرمجيات. يتم توقيع الحزم البرمجية باستخدام هذا المفتاح وعند تثبيتها يتم التحقق من مطابقة المفتاح المخزّن لدى نظام التشغيل مع المفتاح المستخدم في عملية التوقيع للتحقق من أن الحزمة قد تم تثبيتها من المخزن البرمجي الصحيح. يظهر خطأ في حال فشل عملية التحقق ولا يثبت النظام الحزمة الجديدة أو لا يحدثها قبل ضمان نجاح عملية التحقق. نضيف في الخطوة التالية مفتاح GPG الخاص بالمخزن البرمجي البعيد إلى قائمة المفاتيح الموثوقة ضمن نظام التشغيل لينكس لكي يصبح قادرًا على الوثوق بالحزم البرمجية القادمة من ذلك المخزن وذلك بتنفيذ الأمر التالي: curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - يحمل الأمر السابق مفتاح GPG من الرابط الذي تمت إضافته، تفيد الراية sS إلى تفعيل النمط الصامت Silent mode حيث لا تظهر على الشاشة المعلومات التي يتم تبادلها أثناء عملية التحميل وتظهر منها الأخطاء فقط. يجب الانتباه إلى وجود الشريطة - في نهاية الأمر فهي المسؤولة على توجيه ما يتم تنزيله في الجزء الأول من الأمر إلى استدعاء الأداة apt-key في الأمر الثاني بدلًا من حفظه كملف. أي تتم إضافة المفتاح بشكل مباشر إلى النظام عبر تنفيذ الأمر apt-key add. يمكن استعراض مفاتيح GPG الخاصة بمخازن البرمجيات مختلفة ضمن نظام التشغيل باستخدام الأمر apt-key list فيظهر خرج مشابه لما يلي: توجد عدة طرق أخرى يمكن استخدامها لإضافة مفاتيح GPG أيضًا كما في الشكل التالي: sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9 يمكن أن يظهر تحذير بأن الأداة apt-key أصبحت قديمة وأنها لن تكون مدعومة بدءًا من الإصدار 22.04 الخاص بتوزيعة أوبونتو ويمكن تجاهل هذا التحذير. الجزء الثالث: إضافة عنوان مخزن البرمجيات البعيد إلى قائمة مصادر التثبيت الموثوقة يضيف الأمر التالي مُدخلًا جديدًا خاصًا بالمخزن الجديد إلى قائمة مصادر التثبيت الموثوقة من قبل نظام التشغيل، وبالتالي يتحقق نظام التشغيل من هذا المخزن عند الحاجة إلى تثبيت حزم جديدة أو تحديث وترقية الحزم القديمة. sudo sh -c 'echo "deb https://dl.yarnpkg.com/debian/ stable main" >> /etc/apt/sources.list.d/yarn.list' يتضمن الملف ‎/etc/apt/sources.list قائمة بعناوين مخازن البرمجيات الخاصة بنظام أوبونتو ويجب على المستخدم ألا يعدل هذا الملف نهائيًا وإنما يجب إنشاء ملف جديد على أن يكون له اللاحقة .list وتخزينه ضمن المجلد ‎/etc/apt/source.list.d كما في الشكل أدناه: تسهل هذه الإضافة عملية إدارة الحزم إذ يكفي عند الرغبة بإزالة مخزن ما من قائمة المصادر الموثوقة أن يتم حذف الملف الموافق من المجلّد السابق وبالتأكيد دون أن يتم تعديل الملف sources.list. بالعودة إلى الأمر السابق، يفيد استخدام sh إلى تشغيل الأمر ضمن نافذة جديدة من الصدفة shell. تفيد إضافة الراية ‎-c لتوجيه الأمر sh إلى قراء الأوامر من المعامل الذي يلي الراية ‎-c بدلاً من مدخلات المستخدم ومن ثم تتم إضافة السطر التالي: deb https://dl.yarnpkg.com/debian/ stable main باستخدام تعليمة echo إلى الملف ‎/etc/apt/sources.list.d/yarn.list الذي يتم إنشاؤه. توجد العديد من الطرق لتنفيذ عملية الإضافة السابقة أيضًا فيمكن الحصول على نفس النتيجة بتنفيذ الأمر التالي: echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list الجزء الرابع: تثبيت التطبيقات من المخزن البرمجي الذي تمت إضافته على الرغم من إضافة مفتاح GPG وعنوان المخزن البرمجي إلا أنّ نظام التشغيل لم يتعرّف على الحزم البرمجية الموجودة لدى هذا المخزن، لهذا يجب تحديث الذاكرة المخبئية cache الخاصة بالأداة apt للتعرف على الحزم البرمجية المتاحة وإصداراتها وذلك بتنفيذ الأمر التالي: sudo apt update يمكن البدء بتثبيت الحزم البرمجية بعد انتهاء تنفيذ الأمر السابق وعليه ننفذ الأمر التالي: sudo apt install yarn يمكن لتوفير الوقت أن يتم دمج الأمرين معًا بالشكل التالي: sudo apt update && sudo apt install yarn يضمن استخدام && أنّ الأمر الثاني لن ينفّذ قبل انتهاء تنفيذ الأمر الأول دون وجود أخطاء، وبهذا تكون قد اكتملت الإجرائية. الخلاصة يضطر معظم مستخدمي لينكس إلى إضافة مصادر تثبيت برمجيات إضافية، لهذا يجب إتقان كيفية إضافة هذه المصادر بشكل آمن إلى قائمة المصادر الموثوقة من قبل نظام التشغيل. تضمن هذا المقال تعريفًا بكيفية إضافة عنوان مخزن برمجي إلى المخازن الموثوقة من قبل نظام التشغيل المستخدم.كما تضمن مثالًا عمليًا لتثبيت حزمة برمجية غير موجودة ضمن مخازن البرمجيات الأساسية الخاصة بنظام تشغيل أوبونتو ترجمة وبتصرف للمقال Installing Packages From External Repositories in Ubuntu [Explained] لصاحبه Abhishek Prakash. اقرأ أيضًا أساسيات إدارة الحزم في أوبنتو ودبيان أساسيات إدارة الحزم: apt ،yum ،dnf ،pkg 10 أدوات مفيدة لمستخدمي لينكس ربما لم تسمع عنها من قبل
  2. يتعامل مستخدمي توزيعة ديبيان Debian وأوبونتو Ubuntu ومينت Mint وجميع مستخدمي توزيعات لينكس المعتمدة على أوبونتو أو ديبيان مع أوامر apt لتثبيت الحزم البرمجية المختلفة. نلاحظ بسهولة أنه ومنذ انطلاقة أوبونتو 16.04 قد شاع استخدام الأمر apt بشكل كبير إضافة إلى التوصية باستخدامها كمدير الحزم البرمجية ضمن نظام لينكس. يتضمن هذا المقال تعريفًا للراغبين بإتقان استخدام نظام لينكس وأدواته المختلفة وتحديدًا أداة تثبيت الحزم البرمجية والتي يضطر جميع المستخدمين الى التعامل معها عاجلًا أم آجلًا. ما هي الأداة apt؟ تمتلك كل توزيعة لينكس نظام تحزيم packaging system خاص بها والذي يتيح التطبيقات والبرامج ليثبتها المستخدم على نظام التشغيل. لا يحتاج المستخدم في كل مرة أن يبني البرنامج انطلاقًا من شيفرة المصدر. تستخدم توزيعة ديبيان نظام تحزيم اسمه dpkg ويمكن للمستخدم الاعتماد على أداة موجه الأوامر APT وهي اختصار للعبارة Advanced Package Tool للتفاعل مع نظام التحزيم الخاص بتوزيعات لينكس المبنية على أساس ديبيان. يمكن استخدام الأمر dpkg مباشرة ولكن يتيح الأمر apt المزيد من الخيارات مثل البحث عن الحزم الجديدة وترقيتها وإزالتها إضافة إلى أنها أكثر ملائمة للمستخدمين. يمكن استخدام الأوامر الخاصة بالأداة APT عن طريق تنفيذ الأمر apt في موجه الأوامر. نجد في العديد من المقالات والمراجع استخدام الأمر apt-get بدلًا من apt وذلك لتثبيت الحزم. شاع استخدام الأمر الأول لفترة طويلة من الزمن إلا أنّ الأمر الثاني قد حل مكانه بسبب بساطته وفعاليته في تنفيذ عمليات تثبيت الحزم. تحديث قاعدة بيانات الحزم باستخدام apt نستخدم في هذا المقال توزيعة أوبونتو 16.04 ولكن يمكن استخدام أية توزيعة لينكس معتمدة على أوبونتو أو ديبيان مثل مينت Mint و لايت Lite وغيرها. تستخدم الأداة apt قاعدة بيانات تتضمن الحزم المتاحة وفي حال عدم تحديث محتوى قاعدة البيانات هذه بشكل دوري فلن تعرف الأداة بأنّ إصدارات حديثة من الحزم أصبحت متاحة ولهذا يجب أن نبدأ العمل أولًا بتحديث قاعدة البيانات هذه بعد تثبيت نظام التشغيل لينكس لأول مرة. يتطلب هذا التحديث استخدام مستخدم ذي صلاحيات مناسبة Superuser ولهذا نستفيد من الأمر sudo بالشكل التالي: sudo apt update يظهر بعد تنفيذ هذا الأمر معلومات الحزم المتاحة والتي يتم الحصول عليها من عدة خوادم موزعة على أماكن جغرافية متعددة كما في الشكل التالي: نلاحظ من الشكل السابق أن معظم الأسطر التي تتعلق بالاتصال بالخوادم تبدأ بأحد الاحتمالات التالية: الإصابة Hit: يشير إلى أنّه لا يوجد تعديل بنسخة الحزمة الموجودة لدى الخادم والنسخة المثبتة على الحاسب التجاهل Ign: يشير إلى أنّه يجب تجاهل هذا التحديث إما لأنه لا يزال حديثًا وبالتالي يتم تأجيل تنفيذ هذا التحديث حتى يثبت استقرار التحديث الجديد أو أنه قد حدث خطأ ما أثناء طلب التحديث ولكن لا يمثّل هذا الخطأ خطورة ويمكن تجاهله. الجلب Get: يشير إلى أنّه تم اكتشاف إصدار أحدث وسيتم تنزيل المعلومات عن الحزم لكي يتم تثبيتها لاحقًا ويظهر في آخر السطر حجم المعلومات التي يتم تحميلها. ترقية الحزم المثبّتة باستخدام الأداة apt يمكن بعد تحديث قاعدة بيانات الحزم البدء بترقية الحزم المثبّتة على الحاسب، من المفضل أن تتم هذه الترقية بشكل دوري لجميع الحزم نظرًا لأن عمليات الترقية تحدث لحل مشاكل برمجية معينة أو لتحسين الأداء. نبدأ عملية الترقية باستخدام الأمر: sudo apt upgrade تظهر بعدها معلومات عن الحزم التي سيتم ترقيتها من حيث عدد هذه الحزم والحجم الكلي الذي سيتم تحميله من الإنترنت وكم يبلغ الحجم الإضافي الذي سيتم استهلاكه من الحاسب كما في الشكل التالي: يمكن أيضًا أن تتم عملية الترقية للحزم بتنفيذ أمر آخر على الشكل التالي: sudo apt full-upgrade يعمل هذا الأمر كسابقه إلا أنّه يثبت التحديثات المتعلّقة بترقية النظام والتي تتطلب إزالة حزمة موجودة على نظام التشغيل أما الأمر السابق فلا يستطيع تنفيذ مثل هذه العملية. ما الاختلاف بين الأمر apt update والأمر apt upgrade؟ يجب التذكر دومًا أنّ الأمر apt update يحدّث قاعدة بيانات الحزم فقط ولا يرقّي الحزم فعليًا. لنفرض أنه توجد حزمة مثبّتة على الحاسب الشخصي اسمها XYZ وكان الإصدار المثبت 1.3 فبعد تنفيذ الأمر apt update يتم تحديث قاعدة البيانات لتشير إلى الإصدار 1.4 المتاح للتثبيت، يمكن عندها تنفيذ الأمر apt upgrade لترقية الحزمة المطلوبة للإصدار الأحدث. يمكن دمج هذين الأمرين لتسريع هذه العملية بالشكل التالي: sudo apt update && sudo apt upgrade -y تثبيت الحزم الجديدة باستخدام الأداة apt يستخدم الأمر لتثبيت الحزم الجديدة التي يحتاجها المستخدم في عمله بالشكل التالي: sudo apt install <package_name> نضيف اسم الحزمة المطلوبة بدلًا من فعلى سبيل المثال يمكن من أجل تثبيت الحزمة mplayer تنفيذ الأمر التالي: sudo apt install mplayer يظهر عندها خرج مشابه للشكل التالي: تعد ميزة الإكمال التلقائي مفيدة جدًا عند عدم معرفة اسم الحزمة بشكل كامل وخصوصًا أن بعض الحزم يكون اسمها كبيرًا بعض الشيء. نكتب بضعة حروف من اسم الحزمة ومن ثم يمكن الضغط على مفتاح تاب tab ليتم اقتراح مجموعة الحزم المتاحة والتي تبدأ بالحروف التي تم إدخالها بالشكل التالي: تثبيت عدة حزم معًا باستخدام الأداة apt يمكن تثبيت دفعة من الحزم معًا وذلك في حال كان عدد الحزم المطلوبة للتثبيت كبيرًا فمن غير المجدي أن يتم تثبيتها واحدة تلو الأخرى. يتم ذكر اسم الحزم بشكل متتالي بحيث يفصل بينها فراغ واحد كما في الشكل التالي: sudo apt install <package_1> <package_2> <package_3> تنفيذ الأمر apt على حزمة مثبّتة بشكل مسبق يتم في هذه الحالة ترقية هذه الحزمة في حال وجود إصدار أحدث ضمن قاعدة البيانات ولا يسبب ذلك أية مشكلة إلا في حال عدم رغبة المستخدم أن يرقّي الحزمة لسبب ما. تثبيت الحزم دون تنفيذ عملية الترقية يمكن تثبيت حزمة ما دون الحاجة إلى تنفيذ أمر الترقية في حال رغب المستخدم بذلك عبر إضافة الخيار ‎--no-upgrade بالشكل التالي: sudo apt install <package_name> --no-upgrade يظهر عندها الخرج بالشكل التالي: ترقية حزمة موجودة دون تثبيتها في حال لم تكن مثبتة يمكن ترقية حزمة موجودة في حال وجودها بشكل مسبق على الحاسب دون أن يتم تثبيتها تلقائيًا في حال لم تكن مثبّتة بإضافة الخيار ‎--only-upgrade بالشكل التالي: sudo apt install <package_name> --only-upgrade يظهر عندها الخرج بالشكل التالي: تثبيت إصدار محدد من حزمة يتم اختيار النسخة الأحدث والأكثر استقرارًا للحزمة عند طلب المستخدم لتثبيتها بشكل افتراضي ولكن تظهر بعض الحالات التي يحتاج فيها المستخدم نسخة محددة من حزمة ما. يعد مثل هذا الشرط ضروريًا عند تجهيز وتثبيت بعض أنواع الخدمات والتي قد تشترط وجود حزمة بإصدار معين لكي تعمل بشكل صحيح حيث أنّها لا تكون متوافقة مع النسخ الأحدث. نستطيع تحقيق بالشكل التالي: sudo apt install <package_name>=<version_number> إزالة الحزم المثبّتة على باستخدام الأداة apt يستخدم الأمر apt أيضًا لإزالة الحزم المثبتة على الحاسب أيضًا، يتم ذلك بالشكل التالي: sudo apt remove <package_name> يظهر خرج مشابه للشكل التالي: يمكن الاستفادة من الإكمال التلقائي في استعراض الحزم المثبّتة وذلك بشكل مماثل لما قمنا به مسبقًا إذ يكفي كتابة بضعة أحرف من اسم الحزمة والضغط على المفتاح تاب tab ليتم عرض قائمة بالحزم المتاحة. يمكن إزالة الحزم أيضًا باستخدام الأمر purge وذلك بالشكل التالي: sudo apt purge <package_name> يحذف هذا الأمر كل ما يتعلق بالحزمة من ملفات إعداد وغيرها بينما يبقى الأمر remove على بعض ملفات الإعداد ضمن النظام إذ يعد ذلك مفيدًا في حال حذف المستخدم حزمة ما ورغب الاحتفاظ بالإعدادات التي نفّذها في حال رغبته بتثبيتها لاحقًا. أما الأمرpurge فيعد مناسبًا عندما يتم إتلاف ملفات الإعداد بشكل نهائي لا رجعة فيه وعندها يعد خيار إزالة كل ما يتعلق بالحزمة وتثبيته من البداية هو الأفضل. يتم عادة استخدام apt remove أكثر من الأمر apt purge لأن المستخدم لا يحتاج إلى تعديل إعدادات الحزم بشكل كبير. البحث عن الحزم في لينكس يمكن البحث عن حزمة محددة بكل بساطة باستخدام الأمر apt search ليتم عرض جميع الحزم التي تتضمن مصطلح البحث الذي تم إدخاله وذلك بتنفيذ الأمر: apt search <search term> ليظهر عندها الخرج بالشكل التالي: استعراض محتوى حزمة في لينكس نستعرض محتوى حزمة ما قبل إزالتها أو تثبيتها بتنفيذ الأمر التالي: apt show <package_name> تظهر عندها العديد من المعلومات المتعلقة بالحزمة مثل توصيف الحزمة واسم الحزم التي تعتمد عليها هذه الحزمة إضافة إلى رقم الإصدار الخاص بها وغيرها من المعلومات المهمة والتي يبينها الشكل التالي: استعراض قائمة الحزم الجاهزة للترقية وإصداراتها الحالية يمكن استعراض قائمة الحزم المثبّتة على الحاسب والتي يمكن ترقيتها إلى إصدار أحدث. يعد هذا الخيار مهمًا جدًا عندما يتم ترقية مجموعة من الحزم والتي تعتمد على بعضها بحيث نهتم برقم الإصدار الحالي ورقم الإصدار الجديد. نحصل على هذه القائمة بتنفيذ الأمر التالي: apt list --upgradable ليظهر عندها الخرج بالشكل التالي: كما نستطيع استعراض قائمة الحزم المثبّتة فقط على الحاسب وذلك بتنفيذ الأمر التالي: apt list --installed كما نستطيع استعراض قائمة التطبيقات المثبتة بجميع الإصدارات الموجودة على الحاسب، يعد هذا الأمر بالغ الأهمية للعودة إلى إصدار قديم من حزمة محددة كانت تعمل بشكل صحيح. نستعرض هذه القائمة بتنفيذ الأمر التالي: apt list --all-versions تنظيف النظام باستخدام الأداة apt نستخدم الأمر apt autoremove لإزالة أية حزم لم يعد هنالك حاجة لوجودها ضمن الحاسب إضافة لإزالة أية مكتبات برمجية أصبحت بلا فائدة والتي تستهلك مساحة تخزينية عند بقائها ضمن النظام. يتم ذلك بتنفيذ الأمر التالي: sudo apt autoremove لنحصل بعدها على الخرج التالي: الخاتمة تضمن هذا المقال تعريفًا بالأداة apt وتوضيحًا للخيارات العديدة التي يمكن الاستفادة منها في تثبيت الحزم وإدارتها. تعد هذه الأداة أساسية لجميع مستخدمي نظام لينكس والذين قد اختاروا توزيعات مبنية على أوبونتو أو ديبيان. ترجمة وبتصرف للمقال Using apt Commands in Linux [Complete Guide] لصاحبه Abhishek Prakash. اقرأ أيضًا ما هو نظام التشغيل لينكس؟ عشرون أمرا في لينكس يفترض أن يعرفها كل مدير نظم أساسيات إدارة الحزم: apt ،yum ،dnf ،pkg
  3. تتراكم البرامج والملفات الخاصة بالمستخدمين مع الزمن ضمن أي نظام تشغيل وحتى عندما يقوم المستخدم بإزالة بعض البرامج فقد تبقى عدة ملفات عالقة للأبد ضمن ملفات نظام التشغيل. يمكن للمستخدم الذي يمتلك مساحات تخزينية تفوق التيرا بايت Tera Byte أن يتجاهل هذه التراكمات، أما المستخدم الذي يمتلك قرصًا صلبًا من نوع SSD والذي يكون عادة بسعات منخفضة فقد يضطر إلى إزالة هذه التراكمات بشكل دوري. يتضمن هذا المقال أبسط الطرق الذي يستطيع المستخدم تنفيذها لتحرير المساحة ضمن توزيعة أوبونتو Ubuntu ويجب على المستخدم مراقبة المساحة الحرة ضمن جهازه باستمرار ليختار الوقت المناسب لتحرير المساحة. فحص المساحة الحرة ضمن توزيعة أوبونتو يستطيع المستخدم التحقق من المساحة الحرة المتبقية على حاسبه الشخصي باستخدام أداة تحليل استخدام القرص Disk Usage Analyzer المتاحة بشكل افتراضي ضمن توزيعة أوبونتو. يمكن البحث عن هذه الأداة ضمن القائمة الرئيسية وبعد تشغيلها يظهر القرص الصلب والمساحة الحرة المتبقية. يستطيع المستخدم البدء بتحرير المساحة عندما تبلغ المساحة المتبقية من القرص الحد الذي يراه مناسبًا ويمكن بعد الانتهاء من عملية التحرير إعادة تفقد المساحة باستخدام نفس الأداة. تحرير مساحة القرص ضمن توزيعتي أوبونتو و لينكس مينت توجد عدة طرق لتحرير مساحة القرص الصلب ضمن توزيعة أوبونتو أو أنظمة التشغيل المبنية على أوبونتو. منها ما يكون عن طريق تنفيذ الأوامر النصية ومنها ما يكون متاحًا باستخدام أدوات ذات واجهات رسومية. تجدر الإشارة إلى أنه من الأفضل أن يتجنب المستخدم العادي تنفيذ بعض العمليات التي لا يتقنها بشكل جيد تجنبًا لأية ضرر يمكن أن يصيب الحاسب. يتم الاعتماد على نسخة أوبنتو 16.04 في هذا المقال ولكن تبقى الخطوات ذاتها من أجل أوبونتو 18.04 وإصدارات أوبونتو المختلفة كما تنطبق هذه التعليمات على الأنظمة المعتمدة على أوبونتو مثل مينت وغيرها. 1. التخلص من الحزم غير المستخدمة قد تحتاج حزمة ما يقوم المستخدم بتثبيتها إلى تثبيت مجموعة من الحزم الضرورية لعملها، تظهر مشكلة عندما يتم إزالة هذه الحزمة دون أن تتم إزالة الحزم المرتبطة بها مما يؤدي إلى تراكمها واستهلاكها لمساحة تخزينية دون جدوى. وجدنا في [نضع هنا رابط المقالة رقم 7](رابط المقالة رقم 7) أنه يمكن استخدام الأمر apt-get الذي يستخدم لتثبيت الحزم من أجل إزالة الرزم عن طريق الأمر autoremove والذي يزيل هذه الرزم العالقة كما أنه يزيل أي نسخ قديمة من نواة نظام التشغيل لينكس والتي يمكن أن تصبح بلا فائدة بعد ترقية النظام. يتم ذلك عبر تنفيذ الأمر التالي في موجه الأوامر وبالطبع فإننا نحتاج إلى صلاحيات مناسبة لتنفيذ عمليات الحذف هذه: sudo apt-get autoremove يظهر الشكل أدناه أنه سيتم تحرير مساحة تعادل 300 ميغابايت من القرص الصلب بعد نجاح تنفيذ هذه العملية ويمكن أن تكون هذه المساحة أكبر وذلك تبعا لطريقة استخدام الحاسب والفترة الزمنية المنقضية منذ آخر عملية تحرير مساحة تم تنفيذها. 2. إزالة التطبيقات غير الضرورية توجد العديد من التطبيقات الموجودة بشكل افتراضي ضمن توزيعة أوبونتو، وقد تمر سنين دون أن يستخدمها أحد وخصوصًا الألعاب وبعض التطبيقات الإضافية وبالتالي يمكن إزالتها. كما ينطبق ذلك على بعض التطبيقات التي ثبّتها المستخدم واستخدمها مرة واحدة ونسي استخدامها أو أنه لم يعد بحاجتها لذلك يجب إزالة هذه التطبيقات إما بالاعتماد على مركز البرمجيات Software Center أو باستخدام موجه الأوامر وتنفيذ الأمر التالي: sudo apt-get remove package-name1 package-name2 3. تنظيف الذاكرة المخبئية Cache الخاصة بالأداة APT تستخدم توزيعة أوبونتو الأداة APT من أجل تثبيت وإدارة وإزالة الحزم البرمجية. تحتفظ هذه الأداة بنسخة من الحزم البرمجية التي تم تحميلها وتثبيتها مسبقًا حتى بعد أن تتم إزالة هذه الحزم البرمجية من النظام. يتم تخزين هذه الحزم ضمن المسار ‎/var/cache/apt/archives. يزداد حجم هذا المجلّد مع الزمن ويمكن التحقق من حجمه عبر تنفيذ الأمر: sudo du -sh /var/cahce/apt يظهر الشكل أنه تم إشغال حوالي 500 ميغابايت من القرص في المجلّد السابق ويجب تحرير هذه المساحة. يمكن تحرير هذه المساحة بطريقتين، إما عن طريق إزالة الرزم التي أصبحت قديمة جدًا والتي لا يمكن إعادة استخدامها بعد اعتماد تحديث ما مما يجعلها بلا قيمة ويتم ذلك بتنفيذ الأمر: sudo apt-get autoclean أو عبر حذف كامل هذه المساحة التخزينية مما يوفر الكثير من المساحة ولكنه قد يجبر المستخدم على تنزيل بعض الحزم البرمجية في حال احتاجها مرة ثانية في حال لم تكن هذه الحزم قديمة ويتم ذلك بتنفيذ الأمر: sudo apt-get clean 4. تفريغ ملفات السجلات ملاحظة: هذه الخطوة تتطلب معرفة متقدمة. تتضمن جميع توزيعات لينكس آليات تسجيل لحفظ جميع العمليات والقيم التي تتغير ضمن النظام. نجد سجلًا خاصًا بنواة نظام التشغيل وسجلًا خاصًا برسائل النظام وسجلًا يحتوي على الأخطاء الخاصة بجميع الخدمات التي تعمل ضمن نظام لينكس سواء كانت من ضمن نظام التشغيل أو أن المستخدم ثبتها على النظام. يزداد حجم هذه السجلات بسرعة كبيرة، إذ تسجّل هذه القيم دون توقف مما يجعل حجم هذه السجلات كبيرًا ويمكن الاطلاع على هذا الحجم عن طريق تنفيذ: journalctl --disk-usage تجدر الإشارة إلى أنه على عكس الحزم فلا يجب حذف جميع السجلات ويجب الاحتفاظ ببعضها لذلك من الشائع أن يحتفظ المستخدم بالسجلات التي لم يمض عليها زمن طويل، يتم تنفيذ الأمر أدناه لإزالة السجلات التي تتضمن المعطيات المتعلقة بالأداء منذ أكثر من ثلاث أيام: sudo journalctl --vacuum-time=3d يظهر الخرج أدناه بعد تنفيذ الأمر السابق: abhishek@itsfoss:~$ journalctl --disk-usage Archived and active journals take up 1.8G in the file system. abhishek@itsfoss:~$ sudo journalctl --vacuum-time=3d Vacuuming done, freed 1.7G of archived journals from /var/log/journal/1b9ab93094fa2984beba73fd3c48a39c 5. إزالة النسخ القديمة من التطبيقات المثبّتة باستخدام مدير الحزم Snap ملاحظة: هذه الخطوة تتطلب معرفة متقدمة. يتيح مدير الحزم Snap الكثير من التطبيقات التي تفيد المستخدمين ولهذا يكون لها شعبية كبيرة مقارنة بمدراء الحزم التقليديين، تكمن المشكلة الأساسية أنّ الحزم المثبّتة عن طريق مدير الحزم Snap تكون أكبر حجمًا من غيرها ومما يزيد من حجم المشكلة أن مدير الحزم Snap يحتفظ بنسختين على الأقل من نفس الحزمة التي يتم تثبيتها وذلك في حال رغب المستخدم العودة إلى نسخة أقدم من نفس الحزمة، نستعرض المساحة التي تستهلكها هذه الأداة عبر تنفيذ الأمر التالي ويظهر الخرج المبين أدناه بعد تنفيذها du -h /var/lib/snapd/snaps 4.0K /var/lib/snapd/snaps/partial 5.6G /var/lib/snapd/snaps نلاحظ أن المساحة المشغولة وصلت إلى خمسة غيغابايت وهذه المساحة كبيرة نسبيًا. مع تفاقم هذه المشكلة عمد أحد المطورين العاملين ضمن فريق تطوير مدير حزم Snap وهو آلان بوب إلى تطوير سكربت Script بسيط يزيل النسخ القديمة من التطبيقات المثبّتة باستخدام مدير الحزم Snap. ننشئ ملف نص برمجي ونضع فيه المحتوى التالي: #!/bin/bash # Removes old revisions of snaps # CLOSE ALL SNAPS BEFORE RUNNING THIS set -eu snap list --all | awk '/disabled/{print $1, $3}' | while read snapname revision; do snap remove "$snapname" --revision="$revision" done يجب إضافة الصلاحيات التنفيذية المناسبة لملف النص البرمجي السابق وتشغيله مع صلاحيات مدير باستخدام sudo. يتم تحرير المساحة المحجوزة التي يمكن تحريرها ونستعرض المساحة بنفس الطريقة السابقة ليكون الخرج بالشكل التالي: du -h /var/lib/snapd/snaps 4.0K /var/lib/snapd/snaps/partial 2.5G /var/lib/snapd/snaps فصلنا أكثر عن هذه الخطوة في مقال مسح حزم Snap المعطلة لتحرير المساحة في لينكس. 6. إزالة الذاكرة الوسيطة الخاصة بالصور المصغّرة thumbnail ملاحظة: هذه الخطوة تتطلب معرفة متقدمة. تنشئ توزيعة أوبونتو صور مُصغَّرة خاصة بالعرض ويخزنها في مجلّد مخفي ضمن المساحة التخزينية الخاصة بالمستخدم وهو ‎~/.cache/thumbnails. يزداد عدد هذه المصغّرات مع الزمن وبالتالي يزداد حجمها مع العلم بأن بعض هذه المصغرات تعود لصور لم تعد موجودة ولهذا يجب إزالتها. يمكن التحقق من حجم الذاكرة الوسيطة الخاصة بالمصغرات عبر تنفيذ الأمر التالي: du -sh ~/.cache/thumbnails يبين الشكل التالي نتيجة تنفيذ هذا الأمر: يفضل تحرير هذه المساحة كل بضعة أشهر ويمكن ذلك بتنفيذ الأمر التالي: rm -rf ~/.cache/thumbnails/* 7. إيجاد وحذف الملفات المتكررة يمكن أن تتكرر الملفات دون إدراك المستخدم وفي حال كانت هذه الملفات ذات حجوم كبيرة كملفات الفيديو أو الصور عالية الدقة فسوف يستهلك ذلك مساحة كبيرة ولهذا يمكن البحث عن هذه الملفات المكررة وإزالتها. يمكن تنفيذ ذلك باستخدام الأداة ذات الواجهات الرسومية FSlint أو باستخدام الأداة FDUPES التي تعمل ضمن موجه الأوامر والتي يبين الشكل أدناه مثالًا على عملها. يمكن للخبراء تنفيذ بعض الخطوات الإضافية لتحرير المزيد من المساحة، ولا يعني ربط الخطوات التالية بالخبراء أن المستخدم العادي لا يجب أن يحاول تنفيذ هذه الخطوات ولكن من الأفضل أن يكون حذرًا وأن يحتفظ بنسخة احتياطية لملفاته المهمة. 8. إزالة نوى لينكس القديمة التي تم تثبيتها بشكل يدوي ملاحظة: هذه الخطوة تتطلب خبرة متقدمة. ناقشنا في الخطوة رقم 1 السابقة استخدام أمر لإزالة نواة نظام لينكس القديمة ولكن يجب الانتباه أنّ هذا الأمر لا يزيل نواة لينكس التي يثبتها المستخدم بشكل يدوي وإنما فقط يزيل ما ثبّته النظام تلقائيًا. تحرر عملية الإزالة هذه الكثير من المساحة وللتحقق من وجود هذه النوى على الجهاز يمكن تنفيذ الأمر التالي: sudo dpkg --list 'linux-image*' لا تختلف إزالة نواة نظام التشغيل عن إزالة أية حزمة برمجية، فبعد أن يظهر الأمر السابق النوى المتاحة يتم تسجيل رقم الإصدار VERSION الذي يجب إزالته وننفذ الأمر التالي: sudo apt-get remove linux-image-VERSION يوصي الخبراء أن يحافظ المستخدم على نسختين أو ثلاث من نوى نظم التشغيل ومن ضمنه أحدث نسخة للنواة مما يتيح العودة إلى نسخة أقدم من النواة في حال ظهور مشكلة ضمن النواة الجديدة. 9. إزالة الحزم اليتيمة ملاحظة: هذه الخطوة تتطلب خبرة متقدمة. نعرّف الحزم اليتيمة على أنّها الحزم التي يتم تثبيتها ضمن النظام لكونها متطلّبًا لحزمة أساسية أخرى وقد حذف المستخدم هذه الخدمة الأساسية وبقيت الحزمة اليتيمة ضمن النظام. وجدنا في الخطوة رقم 1 أنه يمكن تنفيذ أمر لإزالة هذه الحزم ولكن تكمن المشكلة الأساسية إذا ثبت المستخدم هذه الحزم المكمّلة لحزمة ما بشكل يدوي وبالتالي لن يستطيع الأمر السابق إزالتها لأنه لا يستطيع الجزم بأن المستخدم ثبت هذه الحزمة لحاجته لها أم أنها كانت متطلّبًا لحزمة أخرى فيضطر إلى تجاوزها. يجب أن يبحث المستخدم عن هذه الحزم بشكل يدوي ولكن لحسن الحظ توجد عدة أدوات منها ما يمتلك واجهات رسومية مثل gtkorphan والتي تساعد في العثور على الحزم اليتيمة. يتم تثبيت هذه الأداة بتنفيذ الأمر التالي: sudo apt-get install gtkorphan يبين الشكل التالي الواجهة الأساسية للأداة وتجدر الإشارة إلى أنّ المستخدم لا يحتاج لهذه الأداة فعليًا إلا إذا كان بحاجة كل المساحة التخزينية المتاحة لسبب ما. ملاحظة: قد لا تكون الحزمة gtkorphan متوفرة أثناء قراءة المقال، لذا يمكنك استعمال البديل المناسب والمريح لك، مثل deborphan وغيرها. 10. استخدام الأدوات ذات الواجهات الرسومية لتحرير المساحة في أوبونتو توجد عدة سكربتات تستخدم لتحرير المساحة ضمن توزيعة أوبونتو وقد تم ذكر البعض منها كما توجد المزيد منها ما لم تشمله هذا المقال. يصبح تذكر الأوامر صعبًا لدى بعض المستخدمين ولهذا يمكن استخدام الأدوات ذات الواجهات الرسومية وتعد الأداة Stacer واحدة من أهم هذه الأدوات والتي تتسم بسهولة الاستخدام. الخاتمة تضمنت المقالة بعض الخطوات الأساسية لتحرير المساحة ضمن توزيعة أوبونتو والأنظمة المعتمدة عليها، حيث أنّ بعض هذه الخطوات بسيطة ويجب على جميع المستخدمين تنفيذها بشكل دوري ومنها ما يتطلب أنْ يكون المستخدم خبيرًا ويمكن تجنبها لوقت الحاجة الفعلية للمساحة ويترك تقدير ذلك للمستخدم وحاجته الفعلية للمساحة. ترجمة وبتصرف للمقال ‎7 Simple Ways to Free Up Space on Ubuntu and Linux Mint لصاحبه Abhishek Prakash. اقرأ أيضًا التعرف على اختناقات الأداء في نظام لينكس باستخدام الأدوات مفتوحة المصدر كيفية تثبيت التطبيقات في لينكس كيف تفهم هيكلية نظام الملفات في لنكس
  4. يعد نظام Flatpak بأنه نظام تحزيم عالمي جديد يتيح صيغة format جديدة لتثبيت التطبيقات ضمن توزيعات لينكس بسهولة. يمكن تثبيت التطبيقات ضمن نظام لينكس بعدة طرق، وأسهل هذه الطرق استخدام مركز البرمجيات Software Center للبحث عن التطبيق وتثبيته، أما التطبيقات غير الموجودة في المركز فيمكن أن يتم تثبيتها باستخدام حزم RPM أو DEB. أما بالنسبة لتوزيعات ديبيان والتوزيعات المبنية عليها فتستخدم حزم PPA للحصول على التطبيقات، وبشكل عام يمكن بناء أي تطبيق من الرماز المصدري الخاص به والمتاح حتمًا إذا كان التطبيق جاهزًا للعمل ضمن نظام تشغيل لينكس. توجد العديد من المشاكل التي يمكن أن تظهر عند استخدام الطرق السابقة، فمركز البرمجيات ومخازن تثبيت التطبيقات عمومًا قد لا تمتلك أحدث نسخة من التطبيق المطلوب. كما أن التعامل مع الحزم الضرورية لعمل تطبيق ما وتثبيتها بشكل صحيح يمكن أن يكون متعبًا في بعض الحالات، كما أن بعض الملفات المستخدمة في تثبيت البرمجيات يمكن أن تكون خطرة أما بناء التطبيق انطلاقًا من رماز المصدر الخاص به قد يكون صعبًا بالنسبة لبعض المستخدمين. ظهرت الحاجة إلى وجود نظام تحزيم عالمي بسبب الأسباب السابقة ومع ازدياد عدد وتنوع توزيعات لينكس بحيث يكون هذا النظام الجديد قادرًا على تثبيت وتشغيل التطبيق بغض النظر عن التوزيعة المستخدمة. طوّرت مجموعة Canonical نظام Snap لإيجاد حل لهذه المشاكل كما أن بعض المطورين المستقلين طوروا نظام تحزيم مستقل وأسموه AppImage والذي يحمّل التطبيق ويشغله دون تثبيته فعليًا على الحاسب. يوجد إلى جانب هذين النظامين نظام تحزيم عالمي مميز اسمه Flatpak والذي يمكن استخدامه على معظم توزيعات لينكس. ما هو نظام Flatpak؟ نعرّف نظام Flatpak على أنه إطار عمل للتطبيقات ضمن نظام التشغيل لينكس بغض النظر عن التوزيعة المستخدمة. يهدف نظام Flatpak إلى توفير حلول لمشاكل تثبيت التطبيقات مستقلة عن منصة العمل بالإضافة إلى العديد من المزايا الأخرى مما يسهل العمل على المطورين بحيث يكفي تطوير التطبيق مرة واحدة واستخدامه على جميع توزيعات نظام لينكس -التي تدعم نظام Flatpak- دون الحاجة إلى إيجاد طريقة للتثبيت لتناسب كل توزيعة على حدى. المزايا الأساسية لنظام Flatpak: يقدم هذا النظام واجهة موحّدة لتوزيعات لينكس المختلفة، ويضاف إلى ذلك إمكانية دمجه بالتوزيعات المختلفة بسهولة إذ يمكن تثبيت هذا النظام مباشرة من مراكز البرمجيات الخاصة بكل توزيعة فمثلًا يمكن تثبيت النظام Flatpak من ضمن مركز برمجيات Gnome ضمن أية توزيعة لينكس تستخدمه. تتميز تطبيقات Flatpak بأنها متوافقة مع النسخ التالية أيْ أنّ التطبيق يكون مناسبًا للاستخدام ضمن الإصدار التالي من التوزيعة دون تنفيذ أية تغييرات. الحفاظ على الحزم المتعلقة بالحزمة الأساسية بزمن التشغيل حيث تتم إضافة هذه الحزم وكأنها جزء من التطبيق. على الرغم من أنّ نظام Flatpak يتيح توزيع التطبيقات بشكل مركزي إلا أنّه يدعم أيضًا التوزيع اللامركزي للتطبيقات أيضًا. تفعيل دعم نظام Flatpak لتوزيعات لينكس المختلفة تنقسم عملية تثبيت نظام Flatpak إلى خطوتين أساسيتين، ففي الخطوة الأولى يتم تثبيت النظام flatpak وفي الخطوة الثانية يُضاف مخزن برمجيات Flatpak والذي يسمّى باسم Flathub إلى قائمة مصادر البرمجيات مما يسمح باستخدامه لتثبيت التطبيقات. تثبيت Flatpak على أوبونتو Ubuntu ولينكس مينت Mint يتم تثبيت النظام بتنفيذ الأمر التالي: sudo apt install flatpak تثبيت Flatpak على توزيعات ريدهات Red hat يتم تثبيت النظام بتنفيذ الأمر التالي: sudo yum install flatpak تثبيت Flatpak على توزيعة openSUSE يتم تثبيت النظام بتنفيذ الأمر التالي: sudo zypper install flatpak تثبيت Flatpak على توزيعة آرتش Arch Linux يتم تثبيت النظام بتنفيذ الأمر التالي: sudo pacman -S flatpak حل مشكلة تثبيت النظام Flatpak يمكن في حال قد صادفت المستخدم مشكلة شبيهة بما يلي: error: runtime/org.freedesktop.Platform/x86_64/1.6 not installed أن تحل هذه المشكلة بتنفيذ الأمر التالي: flatpak update -v إذ أن هذه المشكلة تحدث بسبب عدم اكتمال التثبيت لسبب ما سواء كان اتصال الانترنت غير مستقرًا أو أنه قد تم إطفاء الحاسب لسبب ما. تحل هذه المشكلة عادة بتحديث قائمة مخازن برمجيات Flatpak عن طريق تنفيذ الأمر السابق. تفعيل دعم نظام Flatpak ضمن مركز البرمجيات تدار تطبيقات Flatpak بشكل كامل باستخدام الأوامر النصية، ولكن يفضل العديد من المستخدمين الواجهات الرسومية بدًلا من كتابة الأوامر وهنا تبرز أهمية نظام Flatpak. نجد نظام Flatpak مدمجًا بشكل مسبق ضمن العديد من توزيعات لينكس ولهذا لا يحتاج المستخدم تنفيذ أية عملية إضافية. أما في التوزيعات التي لا تتيح هذا الدعم بشكل مسبق فيجب تثبيت إضافة Gnome لتثبيت Flatpak باستخدام الواجهات الرسومية. ننفذ الأمر التالي لتحقيق ذلك ضمن توزيعة أوبونتو والتوزيعات المعتمدة عليها: sudo apt install gnome-software-plugin-flatpak أما في حالة التوزيعات الأخرى، فيجب استبدال مدير الحزم المستخدم في الأمر السابق فقط. نعيد تشغيل الحاسب أو خدمة مركز البرمجيات حسب ما يفضّله المستخدم. نحمل الملف الذي يملك اللاحقة ‎.flatpakref من الموقع الخاص بمطور التطبيق أو من موقع المتجر الرسمي لتطبيقات Flatpak. ننتقل إلى مجد التحميل وننقر مرتين على الملف لتظهر واجهة مركز البرمجيات والتي تحتوي خيارات التثبيت كما تظهر الصورة أدناه: يمكن أيضًا الضغط على الزر اليميني على الملف واختيار فتح الملف باستخدام مثبت البرمجيات الافتراضي (open with software install (default وذلك في حال لم تنجح عملية النقر المزدوج على الملف. نشغّل مركز البرمجيات بعد انتهاء التثبيت من قائمة التطبيقات ويكون النظام Flatpak جاهزًا للاستخدام. استخدام أوامر نظام Flatpak: مخصص للمستخدمين المتقدمين والخبراء يفضّل المستخدم الخبير الأوامر النصية عبر سطر الأوامر لأنها تتيح التحكم الكامل بالأدوات المختلفة. ملاحظة: تجدر الإشارة إلى أنّ الجزء التالي من المقال مخصص للمستخدمين الخبراء الذين يفضلون استخدام الأوامر على الواجهات الرسومية. إضافة مخازن البرمجيات من أجل تثبيت التطبيقات عن طريق Flatpak يحتاج استخدام نظام Flatpak وجود معلومات عن مخازن البرمجيات التي يتم استخدامها لتحميل التطبيقات. يجب إضافة مخزن Flathub إذ أنّه يتيح تثبيت عدد كبير من التطبيقات التي تهم جميع المستخدمين. تجدر الإشارة إلى أنّ مخزن البرمجيات هذا يعد الأكثر استخدامًا لغاية كتابة المقالة ولهذا تم استخدامه ويمكن للمستخدم الذي يفضّل مخزنًا آخرًا أن يستبدل اسم المخزن فقط في الأوامر التالية. نبدأ بإضافة المخزن البرمجي بتنفيذ الأمر التالي: flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo يمكن أن نجد أيضًا العديد من المخازن البرمجية المتاحية ويستطيع المستخدم إضافتهم إذا رغب بذلك. البحث عن حزمة ما باستخدام موجه الأوامر ضمن Flatpak يمكن البحث عن التطبيقات المتاحة عن طريق النظام Flatpak بتنفيذ الأمر التالي: flatpak search applicationname يجب أن يتطابق اسم التطبيق الذي يدخله المستخدم مع اسم التطبيق الفعلي وإلا فلن تظهر نتيجة البحث. تبين الصورة أدناه نتيجة البحث عن أحد التطبيقات الشهيرة: تظهر نتيجة البحث السابقة حقلين أساسيين لعملية تثبيت التطبيقات وهما معرف التطبيق "Application ID" وقائمة المخازن"Remotes". تثبيت تطبيقات Flatpak عبر سطر الأوامر يتم تثبيت تطبيقات Flatpak عن طريقة تنفيذ أمر من الشكل التالي: flatpak install <remotes> <ApplicationID> فمن أجل المثال السابق ننفذ الأمر التالي: flatpak install flathub org.libreoffice.LibreOffice تبدأ عندها عملية التثبيت كما في الشكل التالي: يتيح بعض مطوري التطبيقات مخزن البرمجيات الخاص بهم وعندها يمكن استخدام المسار الكامل لملف flatpakref الخاص بالتطبيق من أجل تثبيت التطبيقات كما يلي: flatpak install --from https://flathub.orf/repo/appstream/com.spotify.Client.flatpakref تثبيت تطبيقات Flatpak باستخدام ملف flatpakref يمكن استخدام ملف flatpakref في حال تحميله إلى الحاسب في تثبيت التطبيق، حيث ننتقل إلى المسار الذي يحوي الملف ومن ثم ننفذ الأمر التالي: flatpak install <ApplicationID>.flatpakref نفترض أن الملف الذي قمنا بتنزيله هو "net.poedit.Poedit.flatpakref" فيصبح الأمر الذي يجب تنفيذه بالشكل التالي: flatpak install net.poedit.Poedit.flatpakref تشغيل تطبيق تم تثبيته عن طريق النظام Flatpak يتم تشغيل التطبيقات التي تم تثبيتها باستخدام نظام Flatpak بتنفيذ الأوامر من الشكل التالي: flatpak run <ApplicationID> فبالعودة للمثال السابق، نشغل التطبيق spotify بتنفيذ الأمر التالي: flatpak run com.spotify.Client عرض جميع التطبيقات المثبّتة باستخدام Flatpak ضمن النظام يمكن عرض التطبيقات التي ثبتها المستخدم ضمن الحاسب بتنفيذ الأمر التالي: flatpak list ليظهر الخرج بالشكل التالي: إزالة تطبيق مثبت باستخدام النظام Flatpak تتم إزالة التطبيقات بتنفيذ أمر من الشكل التالي متضمنًا معرف التطبيق: flatpak uninstall <ApplicationID> ففي حال الرغبة بإزالة تطبيق spotify، ننفذ الأمر التالي: flatpak uninstall com.spotify.Client تحديث جميع التطبيقات المثبّتة باستخدام Flatpak يتم تنفيذ الأمر التالي لإتمام عملية التحديث: flatpak update تحرير المساحة بإزالة التطبيقات غير المستخدمة والمثبّتة باستخدام flatpak يجب تحرير المساحة الخاصة بالتطبيقات غير المستخدمة من فترة لأخرى. يمكن تنفيذ الأمر التالي لتحرير المساحة المرتبطة بتطبيقات ثبتها المستخدم باستخدام نظام Flatpak: flatpak uninstall --unused يستعرض هذا الأمر قائمة التطبيقات غير المستخدمة ويتيح للمستخدم خيار إزالتها. الخاتمة يتيح نظام Flatpak العديد من التطبيقات للمستخدمين حيث أنّ موقع Flathub وسيلة مريحة للعثور على التطبيقات التي يحتاجها المستخدم. يساعد هذا النظام المطورين على إنشاء حزمة واحدة قابلة للعمل على معظم توزيعات لينكس مما يوفر العناء من تطوير حل خاص بكل توزيعة على حدى كما أنّ ذلك يسهل عمليات الصيانة وحل المشاكل أيضًا. يمكن مقارنة هذا النظام بمنافسه Snap، وبمقارنة بسيطة بين هذين النظامين نجد أنّ النظام flatpak أكثر تعقيدًا إذ أنّ اعتماده على معرف التطبيق بدلًا من اسمه يزيد من تعقيده بالنسبة للمستخدم، إلا أنّ تثبيت وإزالة الحزم باستخدام flatpak لا يتطلب صلاحيات متقدمة لسبب ما وهذا الأمر جيد. ترجمة وبتصرف للمقال Using Flatpak on Ubuntu and Other Linux Distributions [Complete Guide]‎ لصاحبه Ambarish Kumar. اقرأ أيضًا كيفية تثبيت التطبيقات في لينكس مدخل إلى مستودعات أوبنتو
  5. توجد العديد من المقالات التي تناقش نظام التشغيل الأفضل بالنسبة للمستخدمين، يعد نظام التشغيل ويندوز Windows الأكثر شيوعًا بين المستخدمين حول العالم. تطور نظام التشغيل لينكس بشكل كبير في السنوات الأخيرة فعلى الرغم من أنه كان نظام التشغيل الأنسب للخوادم بسبب أداءه وموثوقيته العالية إلا أنّه أصبح اليوم مناسبًا لجميع المستخدمين بعد أن امتلك واجهات رسومية مناسبة ودعم العديد من الخدمات التي يحتاجها المستخدمون. تذكر العديد من المقالات أن نظام لينكس أفضل من ويندوز فهو أفضل من ناحية الأمان كما أن المستخدم ليس بحاجة إلى شراء رخصة وتجديدها باستمرار. يجد المستخدم عند رغبته بتثبيت نظام التشغيل لينكس على حاسبه العديد من الإصدارات المختلفة والتي يُطلق عليها اسم التوزيعات فمنها نجد توزيعة أوبونتو Ubuntu وتوزيعة فيدورا Fedora وتوزيعة مينت Mint وغيرها من التوزيعات التي يبلغ عددها المئات. نستنتج من هذا التنوع أمرًا مهمًا حول ماهية لينكس الحقيقية إذ أنّه عبارة عن نواة لنظام التشغيل وليس نظام تشغيل كما يعتقد الكثيرون. نقدم في هذا المقال تشبيهًا ليساعد المستخدم أن يفهم الفارق بين نواة نظام التشغيل والنظام بحد ذاته. على الرغم أن التشبيه مناسب لطرح الفكرة فهو يبقى توضيحًا ومساعدًا لفهم المبدأ وبالطبع لن نجد سؤالًا عن هذا التشبيه في امتحان رسمي أو في مقابلة عمل. لينكس عبارة عن نواة نظام تشغيل فقط تعتبر هذه العبارة واضحة وصحيحة ولكن إذا بحثنا في الكتب أو المقالات التقنية فقد نجد شكلًا يوضح بنية نواة لينكس كما في الشكل التالي: نشبه نظم التشغيل وكأنها مركبات مهما يكن نوعها، تمتلك أية مركبة محرك والذي يمثل أساس هذه المركبة والتي يمكن أيضًا أن نسميها النواة ومن البديهي أنه لا يمكن استخدام المركبة دون هذا الجزء الأساسي. على الرغم من أهميته إلا أنّ المستخدم لا يستطيع أن يقود المحرك مباشرة فهو بحاجة إلى العديد من الأدوات كي تتفاعل مع المحرك ليصل إلى الهدف المرغوب وهو قيادة المركبة، فهو بالحاجة إلى العجلات والمقود وعلبة السرعة والمكابح والكثير من الأدوات التي يتعامل معها مباشرة دون أن يتعامل مع المحرك بشكل مباشر. كذلك الأمر لا يمكن استخدام نواة نظام التشغيل بمفردها وإنما يحتاج المستخدم العديد من الأدوات ومنها الغلاف shell والأوامر والواجهات الرسومية والتي يشير إليها البعض باسم بيئة سطح المكتب وغيرها من الأدوات الأساسية التي يحتاجها المستخدم في أعماله اليومية. التفكير بنظم التشغيل على أنها مركبات نعتبر شركة مايكروسوفت Microsoft بأنها شركة تصنيع سيارات مخصصة لجميع الأغراض والذي يمثل نظام تشغيل ويندوز. تسيطر هذه السيارات على السوق المحلية والعالمية والتي تتضمن محركاتها المحمية ببراءات اختراع والمطورة ضمن الشركة نفسها والتي لا يستطيع أي شخص إنتاجها أو تعديلها دون موافقة الشركة، أي لا تسمح الشركة بتخصيص المحرك مثلًا كما يرغب المستخدم. وبالطبع توجد شركة أبل Apple لتصنيع السيارات أيضًا والتي تقدم السيارات الفخمة باهظة الثمن وفي حال واجهت المستخدم أية مشكلة فيستطيع الاتصال بالدعم الفني والذي يستبدل غالبا السيارة بأخرى. أما بحالة لينكس وتحديدًا محرك لينكس فلا توجد براءة اختراع تحمي هذا المحرك وتقيد المستخدم من تنفيذ التعديلات وعليه يمكن لأي مستخدم تعديل وبناء السيارات بشكل مجاني والتي تمثل أنظمة التشغيل الخاصة بالحواسب المكتبية والدراجات والتي تمثل الأنظمة الصغيرة المضمنة ضمن تجهيزات أخرى مثل الألعاب والتلفاز وغيرها إضافة إلى إنتاج الشاحنات القوية والتي تمثل الخوادم والطائرات النفاثة والتي تمثل الحواسب الفائقة. نلخص ما سبق بالقول: النواة = المحرك نواة لينكس = نوع محدد من أنواع المحركات أنظمة التشغيل للحواسب المكتبية = السيارات أنظمة التشغيل للخوادم = الشاحنات القوية الأنظمة المضمنة = الدراجات بيئة سطح المكتب = جسم السيارة إضافة إلى الأجزاء الداخلية الخاصة بها. السمات themes والأيقونات = طلاء السيارة وجميع المزايا القابلة للتخصيص من قبل المستخدم التطبيقات = الملحقات التي يمكن استخدامها لغرض محدد مثل نظام الموسيقا. لماذا توجد العديد من توزيعات/نظم تشغيل لينكس المتشابهة؟ بالعودة إلى التشبيه السابق فنطرح السؤال لماذا توجد الكثير من أنواع السيارات فتكون الإجابة ببساطة لأنه يوجد عدد كبير من مصنعي السيارات والذين يستخدمون ما أسميناه محرك لينكس وتختلف كل سيارة عن الأخرى بالنوع والغاية منها، وبما أن هذا المحرك متاح للاستخدام والتطوير بشكل مجاني فيستطيع أي شخص بناء مركبة بالاعتماد عليه ولهذا السبب توجد التوزيعات الشهيرة اليوم مثل أوبونتو Ubuntu وديبيان Debian وفيدورا Fedora ومانجارو Manjaro وغيرها من نظم التشغيل أو تسمى بالتوزيعات المعتمدة على نواة لينكس. يستطيع المستخدم أن يلاحظ بسهولة التشابه الكبير بين بعض التوزيعات المبنية على أساس نواة لينكس. يوضح الشكل مقارنة بين نسخة فيدورا بإصدار GNOME ونسخة ديبيان بإصدار GNOME والتي تبين أنهما متشابهان إلى حد كبير. ندعو المكون الذي يعطي لينكس مظهره باسم بيئة سطح المكتب وبالعودة إلى التشبيه الذي اعتمدناه فتمثل هذه البيئة الهيكل الخارجي للسيارة والأجزاء الداخلية الموافقة له. تتيح توزيعات لينكس المختلفة العديد من البيئات وتعرفنا في المثال السابق على إحداها والتي اسمها GNOME وتوجد أيضًا KDE وCinamon وMATE وغيرها. تستخدم الأنواع المختلفة من السيارات لأغراض مختلفة، فالسيارات الصغيرة مناسبة للاستخدام ضمن المدينة بينما تستخدم السيارات ذات الدفع الرباعي ضمن الأماكن الوعرة. يختلف استهلاك الوقود بين الأنواع السابقة وعلى المستخدم أن يختار ما يناسبه وفقًا لأهدافه. كذلك الأمر بالنسبة لبيئات سطح المكتب فالبيئة GNOME تتطلب أن يمتلك الحاسب ذاكرة RAM بحجم أكبر من 4 غيغابايت، بينما تتطلب البيئة Xfce حجم ذاكرة أقل ويبلغ 1 غيغابايت إلا أنه لا يعد الأفضل من حيث المظهر وخصوصًا مقارنة ببيئة GNOME. ارجع إلى مقال KDE Plasma مقابل GNOME: مقارنة بين أشهر بيئات سطح المكتب في لينكس الذي يعرض مقارنة بين أشهر بيئات سطح المكتب في لينكس لمزيد من التفصيل. هل تأتي بيئة سطح المكتب من ضمن التوزيعة أم يجب تثبيتها بشكل منفصل؟ يستطيع المستخدم تثبيت بيئة سطح المكتب التي يفضلها حتى ولو لم تُضمن بشكل مسبق في التوزيعة ونظرًا لأن لينكس مجاني فيستطيع أي مستخدم إجراء أي تعديل يرغب به ولكن بالطبع يجب أن يكون خبيرًا أو أنه قادر على التعلم بسرعة. تجدر الإشارة أن تثبيت بيئة سطح المكتب لن تتشابه في تجربتها مع بيئة أخرى أو بيئة قديمة استخدمتها بشكل كلي فيمكن أن يوجد اختلاف ببعض تطبيقات بيئات سطح المكتب وللأسف يمكن أن تظهر بعض المشاكل أيضًا فعلى سبيل المثال يمكن أن يختفي مؤشر البطارية أو غيرها. بالطبع يمكن أن يبذل المستخدم مجهودًا إضافيًا لحل هذه المشاكل إذا وجدها المستخدم مزعجة ولم يستطع التأقلم معها. تتعامل توزيعات لينكس بشكل مختلف مع التطبيقات تختلف التوزيعات عن بعضها بطريقة تعاملها مع إدارة الحزم البرمجية، تعني إدارة الحزم البرمجية كيفية الحصول على البرامج الجديدة والتحديثات الخاصة بها وبنظام التشغيل. تعود مسؤولية إتاحة التحديثات الأمنية والصيانة على نظام تشغيل/توزيعة لينكس. تتيح بعض نظم تشغيل لينكس البرمجيات الجديدة فور توفرها مباشرة بينما تستغرق بعض التوزيعات وقتًا أطول لاختبار البرمجية. تتيح بعض التوزيعات مثل أوبونتو وسائل مريحة لتثبيت البرمجيات بينما تكون هذه العملية معقدة شوي لبعض التوزيعات مثل غينتوو Gentoo. الخاتمة يعد اختيار توزيعة لينكس مناسبة أمرًا محيّرًا نظرًا للخيارات العديدة المتاحة، وقد تضمن المقال ذكر بعض العوامل الأساسية التي يجب أخذها بعين الاعتبار عند الاختيار. نضيف إلى العوامل سابقة الذكر الدعم الفني، فمما لا شك فيه أن أي مستخدم يرغب بوجود دعم فني قادر على حل المشاكل التي تواجهه وهذا ما ينطبق على لينكس فالتوزيعات مثل أوبونتو تمتلك دعمًا رسميًا مناسبًا إضافة إلى وجود موقع الكتروني يتيح طرح أي استفسار وحل أي مشكلة تواجه المستخدم ترجمة وبتصرف للمقال What is Linux and Why There are 100’s of Linux Distributions? لصاحبه Abhishek Prakash. اقرأ أيضًا عرض موجز لأشهر توزيعات لينكس موازنة بين توزيعة أوبنتو Ubuntu وآرتش Arch من لينكس Linux 10 طرق لتجربة نظام التشغيل لينكس Linux واستكشافه
  6. عندما يتعامل المستخدم مع مخدم بعيد عنه باستخدام جلسة الصدفة Shell فإن هذا الصدفة يجمع الكثير من المعلومات التي تحدد سلوك الخادم وطريقة النفاذ إلى الموارد. تكون بعض هذه الإعدادات محتواة ضمن الإعدادات وبعضها محتوى ضمن مدخلات المستخدم. يستخدم الصدفة مساحة مخصصة ينشئها عندما يتم تأسيس الجلسة مع الخادم حيث تحتوي هذه البيئة متغيرات تحدد خصائص النظام. نستعرض في المقال كيفية التعامل مع البيئة وقراءة وإعداد المتغيرات الخاصة بالبيئة والمتغيرات الخاصة بالصدفة بشكل مباشر وعن طريق ملفات الإعداد الدائمة. كيف تعمل البيئة ومتغيراتها يتم إنشاء عملية Process في كل مرة يتم فيها إنشاء جلسة صدفة جديدة، تعمل هذه العملية على جمع المعلومات التي يجب توفرها لعملية الصدفة والعمليات التي تتولد عنها. يتم الحصول على هذه المعلومات المتعلقة بالإعدادات من مجموعة متنوعة من الملفات وإعدادات النظام. توفر البيئة وسطًا تستطيع عملية الصدفة استخدامه لقراءة أو ضبط الإعدادات وتمرير هذه القيم إلى العمليات الناتجة عنها أيضًا. يتم صياغة البيئة على هيئة سلاسل نصية تمثل أزواجًا من القيم -مفتاح Key-values. ففي حال تمرير عدة قيم فيتم الفصل بينها بواسطة رمز النقطتين (:) حيث يبدو شكل كل زوج كما يلي: KEY=value1:value2:... يتم استخدام علامة التنصيص المزودجة في حال وجود فراغات ضمن القيمة كما في الشكل التالي: KEY="value with spaces" تمثل المفاتيح في هذه الحالة متغيرات والتي يمكن أن يكون لها أحد نوعين وهي إما متغيرات خاصة بالبيئة أو متغيرات خاصة بالصدفة. تعرّف متغيرات البيئة Environment Variables على أنها متغيرات يتم تعريفها من أجل جلسة الصدفة الحالية كما يتم توريثها إلى أية عمليات أو جلسات صدفة مرتبطة بالصدفة الأم. تستخدم متغيرات البيئة لتمرير المعلومات إلى العمليات التي يتم إنشاؤها من الصدفة الذي قام بإنشاء المتغير. أما متغيرات الصدفة Shell Variables فهي متغيرات محتواة بشكل حصري ضمن الصدفة الذي تم تعريفها ضمنه وتستخدم عادة لتعقب بعض المعطيات التجريبية مثل طباعة مسار العمل الحالي. نميز اصطلاحًا بين هذين النوعين أن متغيرات الجلسة تكون مكتوبة بأحرف كبيرة وذلك لتمييزها عن متغيرات البيئة التي تكتب بحروف صغيرة. طباعة متغيرات الصدفة والبيئة ترتبط كل جلسة صدفة بمتغيرات البيئة والصدفة المرتبطة بها. يمكن النفاذ إلى هذه المتغيرات بعدة طرق. نستعرض متغيرات البيئة المتاحة بتنفيذ الأمر env أو printenv وفي حال عدم إجراء أية تعديلات على طريقة العمل فالأمرين السابقين يعملان دون اختلاف. printenv يظهر عندها خرج مشابه لما يلي مع الأخذ بعين الاعتبار أن عدد المتغيرات يختلف من جهاز لآخر: SHELL=/bin/bash TERM=xterm USER=demouser LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca:... MAIL=/var/mail/demouser PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games PWD=/home/demouser LANG=en_US.UTF-8 SHLVL=1 HOME=/home/demouser LOGNAME=demouser LESSOPEN=| /usr/bin/lesspipe %s LESSCLOSE=/usr/bin/lesspipe %s %s _=/usr/bin/printenv لا يوجد اختلاف أي من الأمرين السابقين يتم تنفيذه فيجب أن يبقى الخرج ذاته بالحالتين أما عن الاختلاف بين الأمرين فيظهر عند تخصيص الأمر printenv إذ يمكن أن يطبع المسارات الخاصة بالمتغيرات مثلا بتنفيذ الأمر التالي: printenv PATH فيظهر عندها خرج مشابه لما يلي: /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games بينما يسمح الأمر env بتعديل البيئة التي تستخدمها البرامج عبر تمرير مجموعة من المتغيرات بالشكل التالي: env VAR1="value" command_to_run command_options ترث العمليات الناشئة متغيرات البيئة من العملية الأب مما يسمح بإعادة تحميل بعض القيم أو إضافة متغيرات لبيئة العملية الابن. نستعرض المتغيرات الخاصة بالصدفة باستخدام الأمر set ولكن تجدر الإشارة إلى أنه في حال تنفيذ هذا الأمر بدون أية إضافات فيتم عرض قائمة بجميع متغيرات الصدفة والبيئة وحتى المتغيرات المحلية والتوابع الخاصة بالصدفة ويتم ذلك بتنفيذ الأمر: set يظهر خرج مشابه لما يلي: BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() . . . نظرًا لأن هذه القائمة تكون كبيرة فمن الأفضل تقليل عدد الأسطر البرمجية التي سيتم عرضها ويتم ذلك بتنفيذ الأمر التالي: set | less تبقى كمية المعلومات كبيرة وبعضها ليس مفيدًا مثل بعض التوابع لهذا يمكن تنظيف هذا الخرج بتوجيه الأمر set ليعمل ضمن نمط POSIX بحيث لن تطبع توابع الصدفة ويتم ذلك بتنفيذ الأمر التالي: (set -o posix; set) تظهر قائمة بمتغيرات البيئة والصدفة التي تم تعريفها بشكل مسبق، يمكن تنفيذ مقارنة بين خرج الأمر env و printenv لمحاولة استخلاص متغيرات الصدفة فقط ولكن ذلك لن يكون عمليًا نظرًا لتعدد الطرق التي يعرض فيها كل من الأوامر السابقة نتائجه، تتم عملية المقارنة بتنفيذ الأمر التالي: comm -23 <(set -o posix; set | sort) <(env | sort) يمكن أن يظهر في الخرج بعض متغيرات البيئة نظرًا لأنّ الأمر set يضيف قيم محاطة بإشارات تنصيص بينما لا يستخدم الأمران envو printenv هذه الطريقة مما قد يسبب بعض الاختلافات ولكن يعطي ذلك المستخدم فكرة جيدة عن المتغيرات المستخدمة ضمن البيئة. يعد الاستخدام الأهم لهذه المتغيرات أنها تسمح بإتاحة قيم دائمة تستخدم بين العمليات دون الحاجة إلى كتابتها ضمن ملفات. متغيرات الصدفة والبيئة الشائعة توجد مجموعة كبيرة من متغيرات البيئة والصدفة التي يتم استخدامها بشكل متكرر من قبل المستخدمين، نذكر منها: المتغير SHELL: يصف هذا المتغير الصدفة الذي سيقوم بتفسير الأوامر التي يدخلها المستخدم وتمريرها لنواة نظام التشغيل، يشير المتغير إلى الصدفة bash بشكل افتراضي ولكن يمكن تغيير هذه القيمة إذا اقتضت الحاجة ذلك. المتغير TERM: يحدد هذا المتغير نوع موجه الأوامر الذي سيستخدم عند تنفيذ أمر ما عن طريق الصدفة، تختلف هذه الأنواع تبعًا لمتطلبات التشغيل ولا يتم تغيير قيمة هذا المتغير عادة. المتغير USER: يحدد المستخدم الحالي الذي سجل دخول إلى نظام التشغيل. المتغير PWD: يحدد مسار العمل الحالي. المتغير OLDPWD: يحدد مسار العمل السابق، ويتم استخدام هذا المتغير لإمكانية العودة إلى المسار السابق باستخدام الأمر cd -. *المتغير LS_COLORS:يحدد نمط الألوان المستخدم والذي تتم إضافته -بشكل خياري- إلى خرج الأمر ls بيحث يتم التمييز بين أنواع الملفات عن طريق اللون مما يسهل العمل على المستخدم بشكل كبير. المتغير MAIL: يحدد المسار إلى صندوق البريد الخاص بالمستخدم. المتغير PATH: يتضمن هذا المتغير قائمة المجلدات التي سيفحصها نظام التشغيل بالترتيب للبحث عن الملفات التنفيذية الخاصة بالأوامر التي يدخلها المستخدم. المتغير LANG: يشير هذا المتغير إلى اللغة الحالية والخيارات المحلية إضافة إلى نوع ترميز المحارف المستخدم. المتغير HOME: تشير إلى مسار المجلد الافتراضي الخاص بالمستخدم الحالي. المتغير _: يشير إلى أحدث أمر قد تم تنفيذه. بالإضافة إلى متغيرات الصدفة التالية التي يصادفها معظم المستخدمون في أعمالهم: المتغير BASHOPTS: يتضمن قائمة بالخيارات المستخدمة عندما تنفيذ الأمر الخاص بالصدفة Bash ويفيد ذلك في التأكد من أنّ بيئة الصدفة ستعمل وفق ما هو متوقع أم لا. المتغير BASH_VERSION: يشير إلى رقم الإصدار الخاص بالصدفة Bash بشكل مقروء بالنسبة للمستخدم. المتغير BASHVERSINFO: يشير إلى رقم الإصدار الخاص بالصدفة Bash بشكل خاص بالآلة. المتغير COLUMNS: يشير إلى عدد الأعمدة الذي يمكن استخدامه لعرض خرج الأوامر بما يناسب الشاشة. المتغير DIRSTACK: يتضمن قائمة بالمجلدات المخصصة للمكدسات stacks والتي يتم استخدامها مع أوامر pushd وpopd. المتغير HISTFILESIZE: يشير إلى عدد الأوامر السابقة التي يتم حفظها ضمن الملف الخاص بحفظ الأوامر السابقة. المتغير HOSTNAME: يتضمن اسم المضيف الخاص بالحاسب المستخدم. المتغير IFS: يشير هذا المتغير إلى الفاصل المستخدم بين الكلمات التي يدخلها المستخدم وهي فراغ space بشكل افتراضي. المتغير PS1: يحدد هذا المتغير المؤشر الخاص بموجه الأوامر الرئيسي فنلاحظ بشكل افتراضي أنه يطبع اسم المستخدم الحالي واسم الحاسب بشكل افتراضي إلا أنه يمكن تخصيص هذه الطباعة بتعديل قيمة هذا المتغير، بينما يشير المتغير PS2 إلى تعريف المؤشرات الثانوية عندما يمتد الأمر لأكثر من سطر واحد. المتغير SHELLOPTS: يشير إلى خيارات الصدفة التي يمكن إعدادها باستخدام الأمر set. المتغير UID: يشير إلى رقم التعريف الخاص بالمستخدم UID الخاص بالمستخدم الحالي. إعداد متغيرات البيئة والصدفة تبين الفقرات التالية خطوات إنشاء النوعين السابقين من المتغيرات ويفيد ذلك في التمييز بين هذين النوعين: إنشاء متغيرات الصدفة يمكن تعريف متغير الصدفة للجلسة الحالية بسهولة عبر كتابة اسم المتغير والقيمة التي يتم إسنادها له، يتم ذلك بتنفيذ الأمر التالي: TEST_VAR='Hello World~' نلاحظ استخدام علامة التنصيص بسبب وجود فراغ ضمن قيمة المتغير أما سبب استخدام علامة التنصيص المفردة بدلًا عن المزدوجة كما وضحنا في الفقرة السابقة هو وجود إشارة التعجب والتي تعد محرفًا خاصًا ويستدعي استخدام علامة التنصيص الإفرادية معه أو استخدام محرف الهروب (/) وإلا فإنه سيتم تنفيذ الأمر الخاص بالمحرف المميز وهو في حالة إشارة التعجب استدعاء أمر تم تنفيذه مسبقًا من قائمة الأوامر. أصبح هذا المتغير متاحًا ضمن الجلسة الحالية ولكنه لن يمرر إلى الجلسات التي تنتج عنها، نستعرض هذا المتغير بتنفيذ الأمر: set | grep TEST_VAR يظهر عندها الخرج التالي: TEST_VAR='Hello World!' نتحقق من أنّ هذا المتغير ليس من ضمن متغيرات البيئة بتنفيذ الأمر التالي: printenv | grep TEST_VAR لن تظهر قيمة المتغير في هذه الحالة، نستعرض قيمة المتغير بتنفيذ الأمر echo كما في الشكل: echo $TEST_VAR يظهر عندها الخرج التالي: Hello World! يدرك الصدفة بمجرد وجود رمز $ أن النص التالي يمثل اسم متغير وليس قيمة ثابتة ليقوم بطباعتها كما هي، لنتحقق أنّ هذا المتغير لن يمرر إلى العمليات الناتجة من العملية التي قامت بإنشائه ونبدأ ذلك بإنشاء جلسة صدفة جديدة باستخدام الأمر bash كما يلي" bash echo $TEST_VAR لن تظهر قيمة المتغير في هذه الحالة، نغادر الجلسة الجديدة بتنفيذ الأمر exit الذي يعيدنا إلى جلستنا الأصلية: exit إنشاء متغيرات البيئة نستطيع تحويل متغير الصدفة إلى متغير بيئة عبر تنفيذ ما يعرف بالتصدير export وذلك بتنفيذ الأمر: export TEST_VAR يصبح عندها هذا المتغير خاصًا بالبيئة ونتحقق من ذلك بتنفيذ الأمر التالي: printenv | grep TEST_VAR ليظهر عندها الخرج التالي: TEST_VAR=Hello World! نعيد التجربة السابقة ونتأكد من تمرير المتغير إلى الجلسات الناتجة عن هذه الجلسة بتنفيذ الأوامر التالية: bash echo $TEST_VAR يظهر عندها الخرج التالي: Hello World! أي أنّ العملية الابن استطاعت الحصول على قيمة المتغير. نتأكد أيضًا من قدرتها على إنشاء متغيرات البيئة بتنفيذ الأمر: export NEW_VAR="Testing export" نتحقق من قيمة المتغير بتنفيذ الأمر: printenv | grep NEW_VAR ليظهر الخرج التالي: NEW_VAR=Testing export نعود إلى جلسة الصدفة الأصلية بتنفيذ الأمر التالي: exit ونتحقق من قيمة المتغير الذي تم إنشاؤه بتنفيذ الأمر: echo $NEW_VAR لن يظهر شيء على خرج الشاشة. يعود سبب ذلك إلى أنّ متغيرات البيئة يتم تمريرها من العملية الأب تمرر إلى العملية الابن فقط وليس بالعكس ويعد ذلك مفيدًا في منع البرامج من التأثير على بيئة التشغيل الأساسية التي تحويهم. بعد أن تم الخروج من صدفة الابن تم هدم البيئة وبالتالي إزالة المتغير ولهذا لم تظهر قيمته. إزالة وتخفيض مستوى المتغيرات يمكن للمستخدم إعادة متغير البيئة ليصبح متغير صدفة عبر عملية تعرف باسم تخفيض المستوى demote والتي تُنفّذ بالشكل التالي: export -n TEST_VAR ننفذ الأمر التالي للتحقق بأن هذا المتغير لم يعد خاصًا بالبيئة: printenv | grep TEST_VAR ولكن يجب أن يظهر ضمن قائمة متغيرات الصدفة ونتحقق من ذلك بتنفيذ الأمر: set | grep TEST_VAR ليظهر عندها الخرج التالي: TEST_VAR='Hello World!' نستطيع إزالة المتغير سواء كان متغير بيئة أم متغير صدفة باستخدام الأمر unset بالشكل التالي: unset TEST_VAR ونتأكد من أنّ المتغير لم يعد موجودًا بتنفيذ الأمر التالي: echo $TEST_VAR لن يظهر أي خرج على الشاشة لأن المتغير تمت إزالته. إعداد متغيرات البيئة عند تسجيل الدخول تستخدم العديد من البرامج متغيرات البيئة لتحدد بعض خصائص عملها، وبما أنّ بعض القيم مهمة فلا داعي إلى إعدادها في كل مرة يتم فيها تأسيس جلسة عمل كما أنّ بعض قيم هذه المتغيرات ترتبط بالمستخدم والذي يتم تحديده بعد تسجيل الدخول. الاختلاف بين جلسات الصدفة التفاعلية وغير التفاعلية وذات تسجيل الدخول وبدون تسجيل الدخول يقرأ صدفة bash العديد من ملفات الإعداد المتعلّقة ببدء الجلسة، ومن أهم الاختلافات بين الجلسات أن عملية إنشاء الصدفة تمت بتسجيل دخول login أو بدون تسجيل دخول non-login. تبدأ جلسة الصدفة مع تسجيل الدخول بمصادقة المستخدم user authentication كما يتم عند تسجيل الدخول إلى مخدم باستخدام بروتوكول الاتصال الآمن SSH حيث يتم طلب اسم المستخدم وكلمة المرور أما إذا أنشأ المستخدم جلسة صدفة جديدة باستخدام الأمر bash كما تم في المثال السابق فإنه في هذه الحالة أنشأ جلسة صدفة دون تسجيل دخول حيث لن يُسأل المستخدم عن اسم المستخدم وكلمة المرور. يتم التمييز أيضًا بين الجلسات فيما إذا كانت تفاعلية Interactive أو غير تفاعلية Non-Interactive حيث أنّ الجلسة التفاعلية تتصل بموجه أوامر محدد أما جلسة الصدفة غير التفاعلية فلا تحقق ذلك. إذا تصنف كل جلسة صدفة بأنها تفاعلية أم لا وأنها تمت بتسجيل دخول أم بدونه. تعد جلسة الصدفة التي تبدأ عند استخدام بروتوكول SSH مثالًا على جلسة الصدفة التفاعلية التي تتم بتسجيل دخول بينما يعد تشغيل نص برمجي ما عن طريق موجه الأوامر مثالًا على جلسة صدفة غير تفاعلية بدون تسجيل دخول علمًا أن جلسة موجه الأوامر يمكن أن تكون مزيجًا من الخصائص السابقة. يتم في حالة جلسة الصدفة التي تتطلب تسجيل دخول قراءة الإعدادات والتفاصيل من الملف /etc/profile ومن ثم تبحث عن أول ملف خاص بالصدفة ضمن المجلد الأساسي الخاص بالمستخدم للحصول على أية إعدادات إضافية خاصة بالمستخدم حيث تقرأ الملف الموجود في المسار‎~/.bash_profile أو ضمن المسار ‎~/.bash_login أو ضمن المسار ‎~/.profile وفي حال لم تعثر على ملف فلن تبحث في أية مجلدات أخرى. أما في حالة جلسة الصدفة التي تتم دون تسجيل دخول فتتم قراءة الملف ‎/etc/bash.bashrc ومن ثم قراءة الملف ‎~/.bashrc الخاص بالمستخدم لبناء البيئة. أما الصدفة غير التفاعلي فيقرأ متغير البيئة BASH_ENV الذي يحوي مسار إلى ملف إعدادات والذي يستخدمه من أجل تعريف البيئة الجديدة. صياغة متغيرات البيئة يتيح عدد الملفات الكبير المتعلق بمكان تعريف متغيرات البيئة المرونة في العمل حيث يمكن ضبط بعض الإعدادات لحالات معينة عند تسجيل الدخول مثلًا وعدم إتاحتها في حال عدم تسجيل الدخول ولكن عمليًا تظهر الحاجة إلى تعريف بعض المتغيرات التي تكون مشتركة ضمن جميع أنواع الصدفة المتاحة. يتيح نظام التشغيل لينكس هذا الخيار، فعندما يحتاج المستخدم إلى تعريف متغيرات بيئة خاصة بالمستخدم بحيث تكون متاحة سواء سجل المستخدم الدخول أم لا فيمكن استخدام الملف ‎~/.bashrc والذي يمكن تعديله باستخدام محرر النصوص المتاح كما يلي: nano ~/.bashrc يتضمن هذا الملف عددًا كبيرًا من المتغيرات ومعظمها يكون متعلقًا بإعدادات الصدفة bash والتي ليست متعلقة فعليًا بمتغيرات البيئة. يمكن إعداد المتغيرات كما تم إعدادها بموجه الأوامر بالشكل التالي: export VARNAME=value يمكن إضافة أي متغير بيئة ضمن أي سطر في الملف ‎~/.bashrc بشرط عدم دمجه بمتغير آخر أو كتابته ضمن حلقة تكرار موجودة مسبقًا.نحفظ الملف ونغلقه وعند بدء جلسة صدفة جديدة يتم التصريح عن متغير البيئة الجديد وقراءته وتمريره لبيئة الصدفة أما إذا رغب المستخدم بإجبار الجلسة الحالية على قراءة هذا الملف فيتم ذلك بتنفيذ الأمر التالي: source ~/.bashrc يمكن عند الحاجة لاستخدام متغيرات يمكن استخدامها ضمن نظام التشغيل كاملًا إضافتها إلى الملف ‎/etc/profile أو ‎/etc/bash.bashrc أو ‎/etc/environment. الخاتمة توجد متغيرات الصدفة والبيئة دومًا ضمن جلسات الصدفة حيث تعد هذه المتغيرات ذات فائدة كبيرة بالنسبة للمستخدمين. يعد الاستخدام الأساسي لهذه المتغيرات أن تتحكم العملية الأب بكامل تفاصيل العمليات الأبناء لها سواء تم ذلك عن طريق الملفات أو بدونها. توجد العديد من الحالات التي يعد استخدام متغيرات البيئة ضروريًا فعلى سبيل المثال، تعتمد بعض آليات نشر وتوزيع التطبيقات على متغيرات البيئة لإعداد المصادقة authentication والاحتفاظ ببعض المعلومات الهامة حيث لا يمكن الاحتفاظ بهذه المعلومات ضمن ملفات نظرًا لحساسيتها حيث أنها قد تصبح قابلة للقراءة من قبل جهات غير مخولة بالاطلاع على المحتوى. ترجمة وبتصرف للمقال How To Read and Set Environmental and Shell Variables on Linux لصاحبه Justin Ellingwood. اقرأ أيضًا مدخل إلى كتابة سكربتات الصدفة Shell Scripts؟ ما هو سطر الأوامر؟ أهم 20 أمرا في نظام التشغيل لينكس لجميع المستخدمين
  7. تعرفنا في المقال ما هو محمل الإقلاع GRUB في لينكس وفيما يستخدم على أداة Grub فهي أول قائمة تظهر عند بدء عمل نظام التشغيل لينكس لتعرض الخيارات المتعلّقة بالإقلاع. تتضمن هذه الخيارات أنظمة التشغيل المثبتة على الحاسب إضافة إلى خيارات الوصول إلى إعدادات UEFI وقائمة الاسترداد recovery عند حدوث خطأ ما. يمكن تخصيص العديد من قوائم الأداة Grub، كما يمكن تغيير ترتيب الإقلاع الخاص بأنظمة التشغيل وتغيير المهلة التي يتم بعدها انتقاء الاختيار الافتراضي للإقلاع وإخفاء أنظمة تشغيل محددة وحتى إخفاء شاشة الأداة Grub بالكامل وتغيير صورة الخلفية ضمن الأداة وحتى تبديل الواجهة والألوان والعديد من الخيارات الأخرى. يمكن تخصيص وضبط كل ما سبق بتغيير ملفات إعداد الأداة Grub الموجودة في المسار ‎/etc/default/grub و ‎/boot/grub2 في سطر الأوامر. لكن ذلك ليس سهلًا بالنسبة للعديد من مستخدمي نظام لينكس، لذلك يمكن استخدام أداة ذات واجهة رسومية مثل Grub Customizer وتغيير إعدادات الأداة Grub بسهولة. تثبيت الأداة Grub Customizer ضمن نظام لينكس تتوفر الأداة Grub Customizer في المخازن الرسمية للعديد من توزيعات لينكس الشهيرة. أي أنه يمكن تثبيتها بسهولة من مركز البرامج كما في الشكل التالي: يمكن استخدام مدير الحزم الخاص بالتوزيعة المستخدمة لتثبيت هذه الأداة أيضًا. كما يمكن استخدام الأمر apt لتثبيت الأداة Grub Customizer ضمن أي نظام لينكس معتمد على توزيعة أوبنتو وديبيان: sudo apt install grub-customizer أما في حال تم استخدام توزيعة فيدورا Fedora فيتم استخدام الأمر التالي: sudo dnf install grub-customizer وفي حال توزيعتي آرتش Arch ومانجارو Manjaro فيتم استخدام الأمر التالي: sudo pacman -Sy grub-customizer أما بالنسبة لتوزيعة أوبنتو Ubuntu إصدار 18.04 ومينت Mint إصدار 19، يجب استخدام الأداة PPA. نبدأ بتشغيل موجه الأوامر وتنفيذ ما يلي: sudo add-apt-repository ppa:danielrichter2007/grub-customizer sudo apt update sudo apt install grub-customizer تخصيص الأداة Grub باستخدام أداة الواجهات الرسومية Grub Customizer نبحث عن الأداة Grub Customizer بعد الانتهاء من تثبيتها ونشغّلها. تحتاج الأداة إلى كلمة مرور لمستخدم ذي صلاحيات عالية لأنها تعدّل إعدادات مهمة خاصة بالإقلاع والتي تستدعي وجود صلاحيات مستخدم الجذر root. تظهر الواجهة الرئيسية للأداة بعد إدخال كلمة السر المناسبة. تغيير ترتيب الإقلاع تستخدم الأداة Grub Customizer بشكل أساسي من أجل تغيير ترتيب الإقلاع. ففي حال وجود أكثر من نظام تشغيل على الحاسب كامتلاك نسخة من نظام ويندوز Windows وتوزيعة لينكس بحيث يختار المستخدم النظام الذي يريد العمل معه عند الإقلاع أو حتى في حال وجود أكثر من توزيعة لينكس على نفس الحاسب، فقد يرغب المستخدم في تغيير نظام التشغيل الافتراضي. نختار نظام التشغيل الذي نرغب بجعله افتراضيًا وننقله إلى أعلى القائمة،ننقر على زر الحفظ لتطبيق التعديلات. يبين الشكل التالي تحديد نظام تشغيل ويندوز ليصبح افتراضيًا عند الإقلاع. إصلاح مشكلة إعادة التشغيل المتعددة بعد تحديث نواة نظام التشغيل لا تثبت الأجهزة متعددة الإقلاع التي تستخدم نظام التشغيل ويندوز غالبًا التحديثات بشكل صحيح ما لم تتم إعادة التشغيل مباشرة في هذا النظام. يعني ذلك أنه قد يحتاج المستخدم الإقلاع وإعادة الإقلاع عدة مرات قبل أن يعود كل شيء إلى طبيعته. يمكن أن تظهر هذه المشكلة أيضًا عند استخدام نظام لينكس، عندما يبدأ الجهاز بالإقلاع بواسطة نظام تشغيل خاطئ بعد عملية إعادة التشغيل، لا يتم تثبيت أحدث إصدار من نواة نظام التشغيل لينكس بشكل صحيح في بعض الأحيان. تقدّم الأداة Grub Customizer حلًا لهذا المشكلة. ننتقل إلى النافذة الخاصة بالإعدادات العامة "general settings" ونبحث عن خيار الإدخال الافتراضي "default entry" نبدل الخيار "predefined" إلى "previously booted entry". يتم اختيار آخر نظام تشغيل تم استخدمه دومًا عند الإقلاع بعد إتمام هذا التعديل بغض النظر عن ترتيب الإقلاع المحدد ضمن الأداة Grub. لذلك بعد الانتهاء من تحديث نواة نظام التشغيل، وعند تنفيذ إعادة التشغيل سيتم دائمًا إعادة تشغيل الجهاز إلى نظام التشغيل الصحيح ولن يتلف ملف الإقلاع بسبب هذه المشكلة. تغيير صورة خلفية واجهة الإقلاع Grub تكون عادةً صورة الخلفية لأداة Grub عبارة عن لون أسود أو برتقالي، يستطيع المستخدم تغيير هذه الصورة بواسطة الأداة Grub Customizer. ننتقل إلى التبويب "Appearance Settings" في الشريط الجانبي الأيسر، نجد ضمنه الخيار الخاص بصورة الخلفية "background image". نضغط على هذا الخيار ومن ثم نختار الصورة التي نرغب باستخدامها. نلاحظ أن الأداة تبدأ البحث انطلاقًا من مجلد الجذر، ننقل إلى الدليل الرئيسي ومن ثم إلى مكان وجود الصورة: تحذير: قبل إجراء أي تغييرات أخرى هنا، يجب على المستخدم أن يلتقط صورة للشاشة للون النص إذا تم تغييره، فلا توجد طريقة لمعرفة لون النص الأصلي بعد الآن. هناك أيضًا خيار لتغيير الخط ولكن الأداة Grub Customizer تحذّر من استخدام هذا الخيار لهذا السبب لا يوصي أحد باستخدامه. يمكن أن يضطر المستخدم إلى تغيير النص ولون الخلفية لأنه قد يصبح من الصعب قراءة أسطر قائمة الأداة Grub على صورة الخلفية التي تم تغييرها. يمكن العثور على خيار تغيير النص والخلفية من أجل جميع الخيارات ضمن نفس الشريط الجانبي الذي استخدمناه قبل قليل. نستطيع معاينة التغييرات أثناء تحديد ألوان النص، وبعد أن يختار المستخدم اللون المناسب ننقر فوق زر الحفظ save ونعيد تشغيل الحاسب. يجب أن تظهر الصورة التي تم اختيارها ضمن خلفية قائمة Grub الآن. إزالة صورة خلفية واجهة الإقلاع Grub يستطيع المستخدم في حالة عدم الرضا عن صورة الخلفية التي خصصها مسبقًا أن يستعيد الخلفية القديمة الخاصة بقائمة Grub عن طريق خيار مخفي ضمن قوائم الأداة. ننتقل إلى تبويب إعدادات المظهر "Appearance Settings" ومن ثم ننقر على خيار الإعدادات المتقدّمة "advanced settings" الكائن في الركن الأيمن السفلي. نلغي تحديد الخيار "GRUBMENUPICTURE" ومن ثم نحفظ التغييرات كما في الشكل التالي. تغيير سمة الأداة Grub وإضفاء مظهر جذاب عليها تحذير: تشترط الأداة Grub نوع محدد للصورة وحجم الخط والدقة وما إلى ذلك. يؤدي تغيير سمة الأداة Grub والإعدادات المتعلقة بها كثيرًا إلى الحصول على نظام تشغيل ذي ملفات إقلاع يمكن أن تتلف بسهولة، لهذا يجب أخذ نسخة احتياطية لنظام التشغيل كاملًا أو استخدام أدوات مخصصة لأخذ نسخة احتياطية لإعدادات النظام فقط وتعد الأداة Timeshift مناسبة لذلك، كما يجب أن يحتفظ المستخدم بنسخة من نظام التشغيل بحيث تكون جاهزة للإقلاع مباشرة على قرص USB خارجي لاستخدامها عند الطوارئ. نجد خيار السمة ضمن النافذة "Appearance Settings" في واجهة الأداة Grub Customizer، يمكن تصفح السمات القابلة للاستخدام وتفعيلها من هناك كما في الشكل التالي. يمكن الحصول على سمات خاصة بالأداة Grub من موقع Pling الذي يتضمن قسمًا كاملًا مخصصًا لسمات الأداة Grub: يمكن اتباع النصائح التالية من أجل اختيار سمات Grub مناسبة: التأكد من أنه قد تم تحديث سمة Grub مؤخرًا ونجد هذه المعلومات على صفحة السمة. تقبل الأداة Grub Customizer السمات بتنسيق ‎.tar.gz فقط لذا يجب التحقق أنّ السمة متاحة بهذه اللاحقة أم لا. الانتباه إلى تقييم السمة حيث يشير التقييم السيء لسمة ما أن العديد من المستخدمين واجهوا مشكلة ما بسببه. قراءة الوصف المرفق بالسمة للحصول على معلومات وإرشادات إضافية. قراءة التعليقات الأخيرة المتعلقة بالسمة لمعرفة ما إذا صادف مستخدم ما أخطاء أو مشاكل عند استخدامها. انتبه، يتم إنشاء بعض السمات لتوزيعات محددة، ولن تعمل بعض السمات على بعض التوزيعات حتى لو لم يظهر أي خطأ أو تحذير. عند الانتقال إلى مكان حفظ ملفات سمة الأداة Grub التي تم تنزيلها، نجد محتوياتها ضمن نافذة الأداة Grub Customizer والتي تتيح للمستخدم تعديل إعدادات الأداة Grub وذلك بالطبع إن كان المستخدم متمكنًا من ذلك، مما يتيح له تعديل الملفات وتخصيصها بشكل أكبر ولكن عادة لا يحتاج المستخدم إلى مثل هذا التعديل. يوجد خيار حذف السمة في نفس المكان الذي أضفتها فيه في حال رغبة المستخدم بالتخلص من السمة لسبب ما. هل يجب تخصيص الأداة Grub؟ شخصيًا لا نفضل تخصيص مظهر شاشة Grub ومع ذلك يمكن تغيير المهلة الافتراضية لانتقاء نظام التشغيل من 10 ثوانٍ إلى ثانيتين أو 3 ثوانٍ في حال وجود أكثر من نظام تشغيل مما يسرّع عملية الإقلاع وخصوصًا عندما لا يكون المستخدم قريبًا للضغط على مفتاح لاختيار نظام التشغيل. ترجمة وبتصرف للمقال Customize Grub to Get a Better Experience With Linux لصاحبه Abhishek Prakash. اقرأ أيضًا الدليل النهائي لاختيار توزيعة لينكس تثبيت لينكس مع نظام ويندوز كيفية تثبيت توزيعة أوبنتو من لينكس بأبسط طريقة
  8. لا بدّ أنّ أي مستخدم لنظام التشغيل لينكس قد شاهد مثل هذه الشاشة عند بدء عمل حاسبه، فهذه الشاشة هي شاشة GRUB الأساسية في نظام لينكس. نتعرف في هذا المقال على ماهية هذه الأداة واستخداماتها إضافة إلى الحديث عن إعدادها وتخصيصها بما يناسب المستخدم. ما هي الأداة GRUB؟ تعد الأداة GRUB برنامجًا متكاملًا لتحميل وإدارة عملية الإقلاع وتعد هذه الأداة شائعة الاستخدام مع توزيعات لينكس المختلفة. نعرّف برنامج محمل الإقلاع bootloader على أنّه أول برنامج يعمل عند إقلاع الحاسب، إذ يحمّل نواة نظام التشغيل في الذاكرة ومن ثم تهيئ النواة مكونات نظام التشغيل للعمل مثل: الصدفة Shell ومدير الإظهار وبيئة سطح المكتب وغيرها. محمل الإقلاع أم مدير الإقلاع يحصل الكثير من اللغط عند الحديث عن محمل الإقلاع ومدير الإقلاع boot manager، فالأول قد تم تعريفه في الفقرة السابقة أما الثاني فهو برمجية تسمح لك باختيار واحد من أنظمة التشغيل المتاحة ضمن حاسبك عند الإقلاع. يمكن للمستخدم أن يمتلك نسخة من نظام التشغيل Windows ونسخة أخرى من نظام التشغيل لينكس وهنا يأتي دور مدير الإقلاع لإعطاء الخيار للمستخدم حول نظام التشغيل الذي يرغب بإقلاعه. تتضمن جميع توزيعات لينكس انطلاقًا من إصدار النواة رقم 3.3 محمل إقلاع EFI مدمج وفي الحقيقة يجب أن يتضمن أي نظام تشغيل قادر على العمل مع نظام EFI محمل إقلاع مناسب، حيث تتم قراءة جزء نظام EFI والتي يرمز لها بـ ESP اختصارًا إلى EFI System Partition لتحديد موقع ملفات EFI والتي تتضمن معلومات الإقلاع. فالأداة GRUB تنفذ الوظيفتين السابقتين معًا على الرغم مما يوحي اسمها فهذه الأحرف هي اختصار لـ GRand Unified Bootloader. ما الذي تعنيه الأسطر الظاهرة ضمن شاشة GRUB؟ تختلف الأسطر الظاهرة ضمن الشاشة بين توزيعات لينكس وبين طرق الإعداد المختلفة التي يمكن استخدامها، نجد عادة اسم توزيعة لينكس ضمن السطر الأول كما يمكن أن نجد قائمة الخيارات المتقدمة وعند الدخول إليها نلاحظ مجموعة من الأسطر والتي تبدأ بعبارة مشابهة لـ linux-generic-x-y-z. من المزايا المفيدة أنّ نظام لينكس يحتفظ بإصدار واحد أقدم عندما يُحدَّث إصدار نواة نظام التشغيل. لهذا نستطيع اختيار أي نسخة نريد الإقلاع منها. ينقذ هذا الإجراء المستخدمين عندما تظهر مشاكل في النسخة الحديثة حيث يستطيعون متابعة أعمالهم دون انقطاع. يمكن أن نشاهد في نهاية القائمة سطرًا خاصا بإعداد النظام أو إعدادات UEFI وذلك للوصول إلى نظام BIOS الخاص بالحاسوب. برامج أخرى تدير عملية الإقلاع تعد أداة GRUB الأكثر شيوعًا ضمن توزيعات لينكس ولكنها ليست الوحيدة. إذ تعد الأداة rEFInd إحدى الأدوات المعروفة بين مستخدمي أنظمة لينكس. تتميز هذه الأداة بأنها قابلة للتخصيص بشكل كبير كما أنها تمتلك واجهات أجمل من تلك المستخدمة ضمن الأداة GRUB. توجد العديد من الميزات الأخرى منها ما يتعلق بالأمان والأداء ولكن تبقى الأداة GRUB متفوقة بالعديد من النواحي وأهمها أنها متاحة بشكل مباشر ضمن توزيعات لينكس بينما تحتاج الأداة rEDInd إلى دعم من جهة ثالثة Third-Party Support لتعمل بشكل صحيح. يوجد أيضًا مدير إقلاع نصي اسمه systemd-boot المعد خصيصًا لنظام تشغيل لينكس، نجد مدير الإقلاع هذا ضمن بعض توزيعات لينكس مثل Pop OS. التعديل المباشر على عناصر GRUB تتضمن الشاشة الرئيسية للأداة قائمة بنظم التشغيل التي يمكن استخدامها في عملية الإقلاع وذلك في حال وجود أكثر من نظام واحد ضمن الحاسب، يمكن أن يختار المستخدم إصدار محدد من نواة نظام تشغيل لينكس على سبيل المثال من أجل تنفيذ عملية الإقلاع. توجد العديد من الخيارات إضافة إلى تحديد نظام التشغيل الذي نريد الإقلاع منه، فعلى سبيل المثال يمكن أن نختار تعديل بعض المتغيرات الخاصة بنواة نظام التشغيل قبل بدء الإقلاع. من الممكن أن نعطّل التعريفات الخاصة بالإظهار في حال سببت مشكلة ما لنستطيع النفاذ إلى الحاسب وحل هذه المشكلة. يتم تحرير القائمة بالضغط على الحرف "e". كما يمكن الضغط على الحرف "c" للدخول إلى قائمة موجّه الأوامر الخاصة بالأداة GRUB من القائمة السابقة. ملف الإعداد الخاص بالأداة GRUB تكون التعديلات على قوائم الأداة GRUB مؤقتة فإذا أردنا أن تصبح دائمة فيجب تعديل ملف الإعداد الخاص بالأداة وذلك بعد إقلاع نظام التشغيل. نجد في نظام لينكس ملف الإعداد الخاص بالأداة GRUB ضمن المسار ‎/etc/default/grub وتجدر الإشارة إلى وجود مجلد أيضًا خاص بالأداة ضمن المسار ‎/etc/default/grub.d. يمكن التعديل على الملف مباشرة إلا أن ما ينصح به المختصون أن ننشئ ملفات إعداد إضافية ضمن المجلد والتي يكون لها اللاحقة ‎.cfg وتعديلها. يجب بعد إتمام التعديلات أن نطلب من محمل الإقلاع أن يقرأ الملف الجديد، لكن هذا يحدث تلقائيًا بعد عملية تثبيت نظام تشغيل لينكس جديد إلى جانب نظام موجود حيث سيحدث محتوى الملف بشكل تلقائي بمعلومات النظام الجديد. أداة تخصيص الأداة GRUB يتخوف الكثير من المستخدمين وتحديدًا غير المختصين منهم من استخدام الأدوات النصية في تعديل الملفات الحساسة مثل تلك الخاصة بالإقلاع. تحل هذه المشكلة باستخدام الأداة الرسومية GRUB Customizer والتي تتيح تغيير ترتيب الإقلاع والعديد من المتغيرات المهمة وحتى يمكنها تغيير صورة الخلفية الخاصة بالأداة GRUB إذا رغب المستخدم بذلك. الخاتمة تضمن هذا المقال تعريفًا عامًا للأداة GRUB وعملية تحميل الإقلاع وإدارته، في الحقيقة تحتوي هذه الأداة العديد من الخيارات المعقدة والتي نتركها إلى مقالة تفصيلية أخرى. يمكن عند الرغبة باكتساب معلومات تفصيلية عن هذه الأداة مراجعة التوثيق الرسمي لها ضمن موجه الأوامر الخاص بنظام لينكس عبر تنفيذ الأمر info grub ليظهر خرج مشابه للشكل التالي ترجمة وبتصرف للمقال ?Linux Jargon Buster: What is Grub in Linux? What is it Used for لصاحبه Abhishek Prakash. اقرأ أيضًا تخصيص محمل الإقلاع Grub للحصول على تجربة أفضل مع نظام لينكس ما هو نظام التشغيل لينكس؟ كيفية تثبيت توزيعة آرتش Arch من لينكس
  9. تُبسّط أداة دوكر Docker إدارة إجراءات التطبيق في الحاويات؛ إذ تشبه الحاويات الأجهزة الافتراضية Virtual Machines بالكثير من الجوانب، إلا أنها تتميز بخفة الوزن كما أنها أفضل من ناحية استخدام الموارد. يتيح ذلك للمطورين تجزئة بيئة التطبيق إلى خدمات معزولة متعددة. يصبح تنظيم جميع الحاويات التي تعود للخدمات المختلفة التي يعتمد تطبيق ما عليها أمرًا صعبًا، إذ أنّ تشغيلها معًا والاتصال فيما بينها وحتى إيقافها عن العمل يدويًا ليس عمليًا. تسمح أداة دوكر كومبوز Docker Compose بتشغيل بيئات التطبيق متعددة الحاويات اعتمادًا على مجموعة تعريفات مُخزّنة في ملف YAML، كما تبني هذه الأداة بيئات كاملة قابلة للتخصيص حسب الحاجة متضمنة العديد من الحاويات التي تتشارك الشبكات وأقراص التخزين فيما بينها. نوضح فيما يلي طريقة تثبيت الأداة دوكر كومبوز على خادم ذي نظام تشغيل لينكس أوبونتو Ubuntu إصدار 20.04 وكيفية استخدام هذه الأداة. المتطلبات الأساسية يجب توفير ما يلي: الوصول إلى حاسب يعمل بنظام التشغيل أوبنتو (استعملنا الإصدار 20.04 في هذا المقال) أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo، ولا يُفضّل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم، كما يُفضل وجود جدار حماية نشط في حال العمل على خادم بعيد. تثبيت أداة دوكر على الخادم أو الجهاز المحلي. ملاحظة: نعمل على تثبيت Docker Compose v1، والذي يستخدم "docker-compose"، ولكن بدءًا من Docker Compose v2، انتقل Docker نحو استخدام أمر الإضافة "compose" كما هو موثّق في أحدث إصدار Ubuntu 22.04، بعيدًا عن "docker-compose" الأصلي. وعلى الرغم من اختلاف طريقة التثبيت إلا أن الاستخدام الفعلي قد لا يتعدى لدى كثيرٍ من المستخدمين التخلص من الرمز "-" بين الكلمتين ليتحول الاستدعاء "docker-compose" إلى "docker compose". نجد ضمن وثائق Docker الرسمية مزيدًا من المعلومات حول توافق الأوامر بين "compose" الجديد و "Docker-compose" القديم. الخطوة 1 - تثبيت الأداة دوكر كومبوز نرغب بتثبيت أحدث إصدار مستقر من الأداة دوكر كومبوز، لذلك سنستخدم المستودع الرسمي GitHub من أجل ذلك. نبدأ بالتحقق من توفر أحدث إصدار ضمن صفحة الإصدارات الخاصة بهم. تجدر الإشارة إلى أن أحدث إصدار مستقر في وقت كتابة هذا المقال هو "1.29.2". نبدأ تحميل الإصدار "1.29.2" وحفظ الملف القابل للتنفيذ في "/usr/local/bin/docker-compose/"، مما سيجعل هذا البرنامج متاحًا للاستخدام عند الحاجة باستدعاء الأمر docker-compose. ننفذ الأمر التالي لتحقيق ذلك: $ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose نعرّف الأذونات الصحيحة ليصبح الأمر docker-compose قابلاً للتنفيذ كما يلي: $ sudo chmod +x /usr/local/bin/docker-compose نتحقق من نجاح عملية التثبيت، بتنفيذ الأمر التالي: $ docker-compose --version يظهر على الشاشة خرجٌ مشابهٌ لما يلي: docker-compose version 1.29.2, build 5becea4c انتهت عند هذه المرحلة عملية تثبيت الأداة دوكر كومبوز بنجاح. نبدأ الآن بإعداد ملف "docker-compose.yml" للحصول على بيئة محتواة وتشغيلها باستخدام هذه الأداة. الخطوة 2 - إعداد ملف docker-compose.yml نستطيع إنشاء أية بيئة نرغب بها عبر إعداد ملف "docker-compose.yml" ولتوضيح كيفية إعداد هذا الملف والعمل مع دوكر كومبوز، سننشئ بيئة خادم ويب باستخدام صورة Nginx الرسمية من Docker-Hub ، الذي يعرّف بأنه سجل دوكر العام. ستخدّم هذه البيئة المحتواة ملف HTML واحد ساكن static، أي لا يتضمن محتويات متغيرة. أنشئ مجلّدًا جديدًا في مجلدك الافتراضي، ثم انتقل إليه: $ mkdir ~/compose-demo $ cd ~/compose-demo ثم اضبط مجلد التطبيق ليكون المجلد الجذر لبيئة خادم Nginx على النحو التالي: $ mkdir app أنشئ الملف "index.html" باستخدام محرر النصوص المفضل عن طريق إنشاء ملف جديد داخل مجلد "app" على النحو التالي: $ nano app/index.html نضيف المحتوى التالي إلى هذا الملف: <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Docker Compose Demo</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css"> </head> <body> <h1>This is a Docker Compose Demo Page.</h1> <p>This content is being served by an Nginx container.</p> </body> </html> نحفظ ونغلق الملف عند الانتهاء ويكون ذلك عند استخدام محرر النصوص نانو nano، بالضغط على الاختصار "CTRL + X"، ثم الزر "Y" ثم زر الإدخال "ENTER" للتأكيد. أنشئ بعد ذلك الملف "docker-compose.yml" بتنفيذ الأمر التالي: $ nano docker-compose.yml أضف المحتوى التالي إلى ملف "docker-compose.yml": version: '3.7' services: web: image: nginx:alpine ports: - "8000:80" volumes: - ./app:/usr/share/nginx/html يبدأ ملف "docker-compose.yml" عادةً بتحديد رقم الإصدار "version". إذ يُعلم هذا الرقم الأداة دوكر كومبوز أي إصدار من الإعدادات سيُستخدم. نجد بعد رقم الإصدار جزء الخدمات "services"، إذ تُعد هنا الخدمات التي تشكّل هذه البيئة. يتضمن تطبيقنا الحالي خدمةً واحدةً فقط نسميها "web"، وتستخدم هذه الخدمة صورة "nginx: alpine" وتضبط إعادة توجيه المنفذ باستخدام الموجّه "ports"، ويعني ذلك إعادة توجيه جميع الطلبات الواردة إلى المنفذ "8000" من الجهاز المضيف (النظام الذي يُشغِّل أداة دوكر كومبوز) إلى حاوية "web" عبر المنفذ "80" حيث يعمل خادم Nginx. ينشئ الموجّه "volumes" وحدة تخزين مشتركة بين الجهاز المضيف والحاوية. نختار مشاركة المجلد "app" الموجود محليًا مع الحاوية، إذ أنّ مسار تخزين المجلد داخل الحاوية هو "usr/share/nginx/html/" والذي يصبح الصفحة الافتراضية لخادم Nginx. احفظ الملف واغلقه. انتهى إعداد صفحة توضيحية وملف "docker-compose.yml" لإنشاء بيئة خادم ويب محتواة. نحتاج لاختبار هذه البيئة وتشغيلها باستخدام أداة دوكر كومبوز. الخطوة 3 - تشغيل أداة دوكر كومبوز نستدعي أداة دوكر كومبوز بعد الانتهاء من إعداد الملف "docker-compose.yml"، وعندها يمكن إرسال الطلب إلى الخادم. يبدأ الأمر بتحميل صور دوكر الضرورية وإنشاء حاوية لخدمة "web"، وفي النهاية تشغيل البيئة الحاوية بالنمط المخفي، وذلك بتنفيذ الأمر التالي: $ docker-compose up –d تبحث أداة دوكر كومبوز أولاً عن النسخة المحددة ضمن حاسبك المحلي، وإذا لم يعثر عليها، يُحمّل الصورة من مخزن Docker Hub ويحتفظ بها في حال الحاجة لها لاحقًا، يظهر الخرج على نحوٍ مشابهٍ لما يلي: Creating network "compose-demo_default" with the default driver Pulling web (nginx:alpine)... alpine: Pulling from library/nginx cbdbe7a5bc2a: Pull complete 10c113fb0c77: Pull complete 9ba64393807b: Pull complete c829a9c40ab2: Pull complete 61d685417b2f: Pull complete Digest: sha256:57254039c6313fe8c53f1acbf15657ec9616a813397b74b063e32443427c5502 Status: Downloaded newer image for nginx:alpine Creating compose-demo_web_1 ... done ملاحظة: في حال طباعة ما يدل على أنه توجد مشكلة في الأذونات، فهذا يعني أنّ أداة دوكر غير قادرة على العمل دون صلاحية sudo ويجب حل هذه المشكلة أولًا قبل متابعة العمل. أصبحت البيئة جاهزة وتعمل في الخلفية، نتحقق من أن الحاوية نشطة عبر تنفيذ الأمر: $ docker-compose ps تظهر معلومات حول الحاويات قيد التشغيل وحالتها، إضافةً إلى عمليات إعادة توجيه المنافذ المستخدمة حاليًا: Name Command State Ports ---------------------------------------------------------------------------------- compose-demo_web_1 /docker-entrypoint.sh ngin ... Up 0.0.0.0:8000->80/tcp نستطيع الوصول إلى التطبيق التوضيحي من خلال طلب الرابط "localhost:8000" ضمن متصفح الويب في حال كان تشغيل العرض التوضيحي على الجهاز المحلي، أو "yourserverdomainorIP: 8000" في حال كان تشغيل العرض التوضيحي على خادم بعيد. يظهر ضمن المتصفح محتوى كما يلي: تحافظ وحدة التخزين المشتركة التي اعددناها داخل ملف "docker-compose.yml" على مزامنة ملفات مجلد "app" الموجود محليًا مع المجلّد الموجود ضمن الحاوية، أي أنّ أية تغييرات على ملف "index.html" ستنعكس تلقائيًا على المتصفح عند إعادة تحميل الصفحة. الخطوة 4 - التعرف على أوامر الأداة دوكر كومبوز تستخدم أوامر الأداة دوكر كومبوز لإدارة البيئة المحتوية والتفاعل معها. نتحقق من السجلات المُتشأة عن عمل حاوية خادم Nginx، باستخدام الأمر logs: $ docker-compose logs يظهر محتوًى مشابه لما يلي: Attaching to compose-demo_web_1 web_1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration web_1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ web_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh web_1 | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf web_1 | 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf web_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh web_1 | /docker-entrypoint.sh: Configuration complete; ready for start up web_1 | 172.22.0.1 - - [02/Jun/2020:10:47:13 +0000] "GET / HTTP/1.1" 200 353 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" "-" نستطيع إيقاف تنفيذ البيئة مؤقتًا دون تغيير الحالة الراهنة للحاويات بتنفيذ الأمر: $ docker-compose pause ليكون الخرج على النحو التالي: Pausing compose-demo_web_1 ... done نستأنف تنفيذ البيئة بتنفيذ الأمر التالي: $ docker-compose unpause ويكون الخرج على النحو التالي: Unpausing compose-demo_web_1 ... done ينهي الأمر stop تنفيذ الحاوية، لكنه لن يزيل البيانات المرتبطة بالحاويات: $ docker-compose stop ويكون الخرج على النحو التالي: Stopping compose-demo_web_1 ... done نستخدم الأمر down من أجل إزالة الحاويات والشبكات ووحدات التخزين المرتبطة بالبيئة الحاوية بتنفيذ الأمر التالي: $ docker-compose down يظهر الخرج على النحو التالي: Removing compose-demo_web_1 ... done Removing network compose-demo_default لن يزيل تنفيذ هذا الأمر الصورة الأساسية التي تستخدمها أداة دوكر كومبوز لإنشاء البيئة وهي "nginx:alpine"، وعند تطبيق الأمر docker-compose up فتُنجز العملية بسرعة لأن هذه الصورة موجودة على الجهاز المحلي ولا داعي لتحميلها من الموقع الرسمي مجددًا. نزيل الصورة الأساسية عند الحاجة إلى ذلك بتنفيذ الأمر التالي: $ docker image rm nginx:alpine وتكون المخرجات على النحو التالي: Untagged: nginx:alpine Untagged: nginx@sha256:b89a6ccbda39576ad23fd079978c967cecc6b170db6e7ff8a769bf2259a71912 Deleted: sha256:7d0cdcc60a96a5124763fddf5d534d058ad7d0d8d4c3b8be2aefedf4267d0270 Deleted: sha256:05a0eaca15d731e0029a7604ef54f0dda3b736d4e987e6ac87b91ac7aac03ab1 Deleted: sha256:c6bbc4bdac396583641cb44cd35126b2c195be8fe1ac5e6c577c14752bbe9157 Deleted: sha256:35789b1e1a362b0da8392ca7d5759ef08b9a6b7141cc1521570f984dc7905eb6 Deleted: sha256:a3efaa65ec344c882fe5d543a392a54c4ceacd1efd91662d06964211b1be4c08 Deleted: sha256:3e207b409db364b595ba862cdc12be96dcdad8e36c59a03b7b3b61c946a5741a الخاتمة تضمن هذا المقال خطوات تثبيت الأداة دوكر كومبوز وإعداد بيئة حاوية بالاعتماد على صورة خادم الويب Nginx، كما تضمن بعض الأوامر الأساسية لإدارة هذه البيئة. ترجمة -وبتصرف- للمقال How To Install and Use Docker Compose on Ubuntu 20.04 لصاحبيه Tony Tran و Erika Heidi. اقرأ أيضًا إعداد حاوية لتطبيق لارافيل باستخدام دوكر كومبوز Docker Compose تثبيت وإعداد لارافيل Laravel على دوكر كومبوز Docker Compose كيفية تثبيت Docker Compose على دبيان نقل سير عمل Docker Compose إلى Kubernetes إعداد لارافيل مع خادم Nginx وقاعدة بيانات MySQL باستخدام دوكر كومبوز Docker Compose
  10. يُعد Helm مدير حزم ضمن كوبيرنتس Kubernetes، وهو يسمح للمطورين و المشغلين إعداد وتطوير التطبيقات ضمن عناقيد Kubernetes. يُطلق على حزم Helm اسم المخططات Charts، وهي تتضمن قوالبًا لتعريف الموارد التي تضبط وتركب التطبيقات بأقل جهد ممكن. يستطيع المستخدم باستخدام القولبة templating إدارة المخططات وضبطها والتحكم بسلوكها بتمرير تعريفات متنوعة دون تعديل المخططات الأساسية. ويدير Helm تعريفات الموارد المخصصة إضافةً الى التعديلات على التعريفات المستخدمة مسبقًا. تسمى المخططات المنفذة مع المُخصصة من قبل المستخدم باسم الإصدار Release. سنعمل في هذا المقال على إعداد Helm وتوضيح كيفية تثبيت وترقية والتراجع عن الترقية، إضافةً إلى إدارة المخططات والإصدارات، كما سننشئ المخططات الخاصة بنا مع إعداد مخازن المخططات التي تحتضن هذه المخططات. المتطلبات الأساسية عنقود Kubernetes يدعم التحكم بالوصول على أساس الدور role-based access control -أو اختصارًا RBAC- كما هو متاح في المخزن الرسمي. أداة موجه الأوامر"kubectl" ضمن الحاسب المحلي قادرة على الاتصال بالعنقود، والتي تُعد وفقًا للتوثيق الرسمي. نتحقق من الاتصال بالعنقود بتنفيذ الأمر التالي: $ kubectl cluster-info يكون الاتصال بالعنقود ناجحًا ما لم تظهر أخطاء نتيجةً للأمر السابق، أما في حالة وجود عدة عناقيد، نحدد سياق context العنقود المطلوب عبر تنفيذ الأمر التالي: $ kubectl config get-contexts يظهر الخرج لائحةً بالإعدادات المتوفر ة كما يلي: CURRENT NAME CLUSTER AUTHINFO NAMESPACE * do-fra1-helm3-example do-fra1-helm3-example do-fra1-helm3-example-admin تشير النجمة * إلى أن الاتصال الحالي خاص بالعنقود do-fra1-helm3-example؛ وللتبديل إلى عنقود آخر ننفذ الأمر التالي: $ kubectl config use-context context-name ننتقل إلى الخطوة التالية بعد التأكد من اختيار العنقود الذي نرغب باستخدامه لتثبيت مدير الحزم Helm عليه. الخطوة 1- تثبيت مدير الحزم Helm 3 نعتمد طريقة تثبيت مدير الحزم Helm 3 باستخدام السكربت script المُتاح على الموقع الرسمي. نبدأ بالتنقل إلى المجلد "tmp/"حيث نخزّن البرنامج النصي الخاص بالتثبيت. نحقق التنقل بتنفيذ الأمر: $ cd /tmp نحمّل السكربت بتنفيذ الأمر التالي: $ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 يُعد التحقق من محتوى السكربت قبل تثبيته من الممارسات الجيدة المتعلّقة بالأمان، ونستخدم محرر النصوص المفضل من أجل ذلك، إذ نستعرض محتوى الملف "get_helm.sh" قبل تثبيته. نضيف قابلية التنفيذ إلى السكربت بعد التأكد من سلامته بتنفيذ الأمر التالي: $ chmod u+x get_helm.sh ننفذ السكربت لتبدأ عندها عملية تثبيت مدير الحزم Helm 3 عبر تنفيذ الأمر: $ ./get_helm.sh يظهر خرجٌ مشابهٌ لما يلي: Downloading https://get.helm.sh/helm-v3.5.2-linux-amd64.tar.gz Verifying checksum... Done. Preparing to install helm into /usr/local/bin helm installed into /usr/local/bin/helm وبهذا ينتهي تثبيت مدير الحزم Helm 3 على الجهاز المحلي. الخطوة 2- إعداد مخازن المخططات تُخزّن مخططات مدير الحزم Helm ضمن مخازن مخططات قابلة للاستضافة من أي مستخدم وضمن أي جهاز. لا يترافق مدير الحزم Helm 3 عادةً مع أي مخزن مُعد مسبقًا. وعلى الرغم من أن النسخ السابقة من مدير الحزم Helm تضمنت مخزن مخططات مركزي منسق، إلا أنّ تصميم مدير الحزم Helm 3 يحُث المطورين على إدارة مخازنهم الخاصة، إذ يسمح ذلك بحرية أكبر وكذلك الحصول على إصدارات بصورةٍ أسرع، ومعنى ذلك أننا نحتاج إضافة مخزن مستضيف لكل مخطط نستخدمه ضمن مدير الحزم Helm. نستخدم الموقع ArtifactHub.io لإيجاد المخزن المناسب، وهو موقع مفتوح المصدر مُدار من قبل CNCF التي تدير مخططات مدير الحزم Helm ومخازنها، كما تتعقب أكثر المخططات شعبيةً وفائدةً والتي تستخدمها مشاريع CNCF الأخرى. ولذلك تختلف عن المخازن المستقرة "stable" التي استخدمتها الإصدارات السابقة من مدير الحزم Helm. يتضمن الموقع كثيرًا من المخططات المهمة للمشاريع الشائعة، مثل مشاريع Nginx، ومشاريع أدوات المراقبة. نبحث عن المخططات الواجب تثبيتها عبر الصفحة الرئيسية، إذ نبدأ بالبحث عن "nginx" مثلًا لتظهر المخططات المتعلّقة به. نثبت النسخة المجانية Community edition المدارة من قبل فريق Kubernetes، كما نبحث عن "ingress-nginx" ونختاره من بين النتائج كما في الشكل التالي: يمتلك المخطط توصيفًا يبين المهام التي ينفذها مع الأوامر اللازمة لإضافة مخازنه الى الحاسب وتثبيت المخطط، ويمكن الحصول على الأوامر الضرورية عبر النقر على زر INSTALL في يمين الصفحة. ننقر على الزر الازرق الموجود إلى جانب الأمر لنسخه، ونبدأ بنسخ وتنفيذ الأمر الأول: $ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx ننفذ الأمر helm repo add لاضافة المخزن إلى مدير الحزم Helm، إذ يتطلب هذا الأمر تمرير متغيرين، هما: اسم المخزن ورابطه، ويظهر خرجٌ مشابهٌ لما يلي: "ingress-nginx" has been added to your repositories ننفذ الأمر التالي لإعلام مدير الحزم Helm بوجود مخزن جديد يجب عليه التعرّف على محتواه: $ helm repo update يظهر الخرج التالي ليشير إلى نجاح التحديث: Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "ingress-nginx" chart repository Update Complete. ⎈Happy Helming!⎈ تعرفنا في هذه الخطوة على موقع ArtifactHub وما يقدمه، كما أضفنا أيضًا مخزنًا جديدًا إلى تثبيت مدير حزم Helm. وسنثبّت في الخطوة التالية مخطط Helm. الخطوة 3- تثبيت مخطط Helm يملك كل مخطط متغيرات خاصة بالإعداد تحدد سلوكه، إذ تُخزَّن هذه المتغيرات ضمن الملف "values.yaml" الموجود ضمن المخطط، ونستطيع التعرّف على هذه المتغيرات بتنفيذ الأمر التالي مع ضرورة استبدال chart_name باسم المخطط الذي نريد معرفة متغيراته كما يلي: $ helm show values chart_name نتعرّف على المتغيرات الخاصة بمخطط "ingress-nginx" بتنفيذ الأمر التالي: $ helm show values ingress-nginx/ingress-nginx يظهر خرج طويل جدًا يمثل محتويات "values.yaml" الخاص بمخطط "ingress-nginx". نثبت المخطط باستخدام الأمرhelm install على النحو التالي: $ helm install release_name repository/chart_name عرّفنا الإصدار بأنه عينة من المخطط والتي ندعوها بالأمر السابق باسم "ingress-nginx". يثبّت الأمر السابق المخطط ضمن العنقود اعتمادًا على القيم الافتراضية للمتغيرات والتي تُعدّل عند الحاجة باستخدام set-- يتلوها اسم المتغير والقيمة الجديدة كما يلي: $ helm install ingress-nginx/ingress-nginx --set variable_name=variable_value يمكننا تكرار الإضافة set-- لجميع المتغيرات التي تحتاج للتعديل، وطالما أننا لن نخصّص المخطط الآن سنستخدم القيم الافتراضية في عملية التثبيت ونتابع بتنفيذ الأمر التالي: $ helm install ingress-nginx ingress-nginx/ingress-nginx يظهر الخرج التالي بعد نجاح العملية: NAME: ingress-nginx LAST DEPLOYED: Wed Feb 24 10:12:37 2021 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: The ingress-nginx controller has been installed. It may take a few minutes for the LoadBalancer IP to be available. You can watch the status by running 'kubectl --namespace default get services -o wide -w ingress-nginx-controller' … يجب الانتباه إلى أن المتغير NAME يقابل اسم الإصدار الذي حددناه سابقًا. يُدرج مدير الحزم Helm المعلومات العامة، مثل حالة الإصدار ونطاق الاسم namespace التي نُشرت ضمنه. يختلف قسم الملاحظات NOTES بين المخططات وغالبًا ما يحتوي دليلًا مختصرًا أو تحذيرات من بعض المشاكل الشائعة عند استخدام موارد المخطط. يتضمن جزء الملاحظات تحذيرًا بأن إعداد موازن الحمل Load Balancer قيد الإنشاء وأن هذه العملية تستغرق وقتًا كي تنتهي. نتحقق من المخططات باستخدام الأمر التالي: $ helm list نجد أن المخطط "ingress-nginx" هو المخطط الوحيد المُتاح في الوقت الحالي: NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION ingress-nginx default 1 2021-02-24 10:12:37.281049711 +0000 UTC deployed ingress-nginx-3.23.0 0.44.0 ونجد الخدمات الخاصة بهذا المخطط ضمن العنقود عن طريق تنفيذ الأمر التالي: $ kubectl get services ليظهر خرجٌ مُشابهٌ لما يلي: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx-controller LoadBalancer 10.245.211.81 46.101.68.67 80:30704/TCP,443:30700/TCP 7m19s ingress-nginx-controller-admission ClusterIP 10.245.50.17 <none> 443/TCP 7m19s kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 83m الآن، بعد أن نشرنا إصدارًا في العنقود، سنعدل ضبطه أثناء عملية النشر. الخطوة 4 - ترقية الإصدار لا نحتاج إلى إزالة الإصدار كليًا عند الحاجة إلى إجراء تعديلات في ضبطه، إذ نستخدم الأمرhelm upgrade لترقية الإصدار بنسخة جديدة من المخطط أو تطبيق الإعدادات الجديدة. يعرض المخطط "ingress-nginx" متغيرًا اسمه controller.replicaCount يتحكم بعدد حجيرات التحكم controller pods المنشورة، ويمكن التأكد من عددها باستخدام الأمر التالي وعادةً ما تكون القيمة الافتراضية لهذا المتغير تساوي الواحد: $ kubectl get pods يظهر الخرج بوجود حجيرة واحدة فقط على النحو التالي: NAME READY STATUS RESTARTS AGE ingress-nginx-controller-7fc74cf778-kjtst 1/1 Running 0 12m نستطيع إضافة مزيدٍ من الحجيرات من أجل التكرارية Redundancy (ثلاثة على سبيل المثال) عبر ترقية الإصدار وتعديل قيمة المتغير الى 4 من خلال الأمر التالي: $ helm upgrade ingress-nginx ingress-nginx/ingress-nginx --set controller.replicaCount=3 --reuse-values يمكن استخدام values -reuse--، الذي يوجّه مدير الحزم Helm ببناء التعديلات على أساس الإصدار المنشور مع الحفاظ على الإصدار السابق. نلاحظ في الخرج أنّ مدير الحزم Helm يزيد من رقم الاشعار لهذه المراجعة للإشارة إلى ترقية الإصدار: NAME: ingress-nginx LAST DEPLOYED: Wed Feb 24 12:07:54 2021 NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None NOTES: … يمكن الحصول على قائمة بالحجيرات المتاحة بتنفيذ الأمر التالي: $ kubectl get pods نلاحظ وجود ثلاث حجيرات عوضًا عن حجيرة واحدة: NAME READY STATUS RESTARTS AGE ingress-nginx-controller-7fc74cf778-4hk9g 1/1 Running 0 18s ingress-nginx-controller-7fc74cf778-kjtst 1/1 Running 0 22m ingress-nginx-controller-7fc74cf778-wz595 1/1 Running 0 18s سنتراجع في الخطوة التالية عن التغييرات ونحذف الإصدارات تمامًا. الخطوة 5 - التراجع و حذف الإصدار يخزّن مدير الحزم Helm رقم المراجعة لكل إصدار داخليًا، بحيث يزداد هذا الرقم عند ترقية الإصدار، ويسمح ذلك بالعودة الى المراجعة السابقة عند الحاجة. نستطيع إعادة عدد الحجيرات إلى واحد وهي القيمة الافتراضية التي عدلناها في الخطوة السابقة، ننفذ الأمر helm upgrade مرةً أخرى ونحدد العدد يدويًا لأنه تغيير بسيط. تصبح هذه العلمية في حالة المخططات الكبيرة التي تمتلك عددًا كبيرًا من المتغيرات دون جدوى ويجب أتمتة عملية تعديل هذه المتغيرات. نتراجع عن الإصدار بتنفيذ الأمر helm rollback: $ helm rollback release_name release_revision ويمكننا التراجع مثلًا عن التعديلات السابقة الخاصة بالمخطط "ingress-nginx" بالعودة الى المراجعة رقم 1 من خلال تنفيذ الأمر التالي: $ helm rollback ingress-nginx 1 يظهر الخرج التالي الذي يشير إلى نجاح العملية: Rollback was a success! Happy Helming! نتحقق من رقم المراجعة الحالية عن طريق طلب قائمة الإصدارات بتنفيذ الأمر التالي: $ helm list نجد أن المراجعة أصبحت 3 بدلًا من 1: NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION ingress-nginx default 3 2021-02-24 12:43:21.523664768 +0000 UTC deployed ingress-nginx-3.23.0 0.44.0 ينظر مدير الحزم Helm لأي تغيير ومن ضمنها التراجع على أنه مراجعة جديدة للإصدار. نتحقق من أن المراجعة رقم 3 مماثلةٌ للأولى عن طريق التحقق من عدد الحجيرات المنشورة بتنفيذ الأمر التالي: $ kubectl get pods نلاحظ وجود حجيرةٍ واحدةٍ فقط في الخرج: NAME READY STATUS RESTARTS AGE ingress-nginx-controller-7fc74cf778-kjtst 1/1 Running 0 41m نستطيع حذف إصدار ما وكل المراجعات المتعلقة به بتنفيذ الأمر helm delete: $ helm delete release_name لم نعد بحاجة لمخطط "ingress-nginx"، لذالك نحذفه بتنفيذ الأمر التالي: $ helm delete ingress-nginx يظهر خرجٌ مشابهٌ لما يلي: release "ingress-nginx" uninstalled نتحقق من قائمة الإصدارات والتي يجب أن تكون فارغة بعد نجاح تنفيذ العملية بتنفيذ الأمر: $ helm list يظهر الخرج التالي ليشير إلى نجاح العملية: NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION نستطيع إعادة استخدام اسم الإصدار في المستقبل لأنه أصبح متاحًا. الخطوة 6- إنشاء مخططات مخصصة -خطوة اختيارية نعمل على إنشاء مخطط مخصص يتضمن تعريف الموارد وكيفية تحزيم هذه المخططات من أجل إعادة استخدامها لاحقًا. ننشئ مخططًا جديدًا يُدعى "example-chart" بتنفيذ الأمر التالي: $ helm create example-chart ينشئ ذلك مجلّدًا جديدًا يدعى "example-chart" يحتوي المجلدات ضمن البنية التالية: charts/ templates/ ├─ tests/ │ ├─ test-connection.yaml ├─ deployment.yaml ├─ hpa.yaml ├─ ingress.yaml ├─ NOTES.txt ├─ service.yaml ├─ serviceaccount.yaml ├─ _helpers.tpl Chart.yaml values.yaml توجد تعريفات الموارد التي ثبتّها المخطط على العنقود الهدف في المجلد "templates"، إذ ينشئ مدير الحزم Helm مجموعة من التعريفات الافتراضية مثل نقطة بداية لتنشر متحكم "Nginx ingress". نستخدم هنا صيغة قولبة Go على الرغم من أنّ لاحقة الملف هي "YAML"، لتبقى قابلة للتخصيص عبر المتغيرات التي يمكن تمريرها عند تنفيذ الأمر. نتحقق من ذلك بإظهار محتوى الملف "service.yaml" بتنفيذ الأمر التالي: $ cat example-chart/templates/service.yaml نلاحظ وجود أوامر قولية تولّد قيم محاطة بأقواس مضاعفة كما في الخرج التالي: apiVersion: v1 kind: Service metadata: name: {{ include "mychart.fullname" . }} labels: {{- include "mychart.labels" . | nindent 4 }} spec: type: {{ .Values.service.type }} ports: - port: {{ .Values.service.port }} targetPort: http protocol: TCP name: http selector: {{- include "mychart.selectorLabels" . | nindent 4 }} تُعرض المتغيرات المرجعية للمستخدم وتُعرّف ضمن الملف "values.yaml"؛ وتُخزن نصوص "NOTES" التي يظهرها مدير الحزم Helm ضمن الملف "NOTES.txt" ويجري قولبتها؛ كما تُعرّف بيانات التعريف للمخطط، مثل الاسم و النسخة ونسخة البرمجيات المنشورة ضمن الملف "Chart.yaml"، الذي يتضمن المحتوى التالي: apiVersion: v2 name: mychart description: A Helm chart for Kubernetes … type: application … version: 0.1.0 … appVersion: "1.16.0" نتحقق مما سينشره Helm بتمرير dry-run-- و debug-- للأمر helm install مع الإشارة إلى المجلّد الذي يحتوي المخطط: $ helm install example-chart --dry-run --debug ./example-chart يظهر خرج طويل يتضمن جميع تعريفات الموارد التي تطبق على العنقود أثناء العمل على المخطط، كما يمكن استخدام upgrade helm لدفع النسخة الجديدة الى Kubernetes. $ helm package ./example-chart يظهر خرجٌ مشابهٌ لما يلي: Successfully packaged chart and saved it to: …/example-chart-0.1.0.tgz نستطيع تثبيت المخطط المحزّم كما نثبّت أي مخطط من المخازن المضافة إلى مدير الحزم Helm: $ helm install example-chart example-chart-0.1.0.tgz الخاتمة قدم هذا المقال طريقة استخدام مدير الحزم Helm لتثبيت وترقية البرمجيات المنشورة إلى عنقود Kubernetes، كما أضفنا مخازن المخططات واستخدمنا موقع ArtifactHub للمساعدة في إيجادها، وأنشأنا مخططا مخصصًا جديدًا وتحكمنا بمراجعات الإصدار وبيّنا طريقة التراجع عن الإصدار إذا اقتضى الأمر. ترجمة وبتصرف للمقال How To Install Software on Kubernetes Clusters with the Helm 3 Package Manager لمؤلفيه Savic و Brian Boucheron. اقرأ أيضًا مدخل إلى Helm: مدير حزم Kubernetes ما الفرق بين دوكر Docker وكوبيرنيتيس Kubernetes؟ تعلم أساسيات Kubernetes نظام كوبيرنتس Kubernetes وكيفية عمله
  11. نعرّف الاحتواء ضمن حاوية Containerization على أنه عملية تكييف التطبيق ومكوناته لتصبح قادرة على العمل ضمن بيئة بسيطة أساسية المقومات ندعوها الحاوية لتشكّل بيئة معزولة يمكن التخلص منها بسهولة عند الرغبة بذلك، كما يمكن الاستفادة منها لتطوير واختبار ونشر التطبيقات ضمن بيئات الإنتاج. نعمل في هذا المقال على استخدام أداة Docker Compose لاحتواء تطبيق لارافيل بهدف تطويره ضمن بيئة مستقلة خاصة به. نحصل على تطبيق لارافيل توضيحي موزّع على ثلاث حاويات خدمة منفصلة كما يلي: خدمة تطبيق "app" تعمل على PHP7.4-FPM. خدمة قاعدة بيانات "db" تحتوي خادم MySQL 5.7. خدمة "nginx" تستخدم خدمة "app" من أجل تحليل شيفرة برمجية بلغة PHP قبل تقديم تطبيق لارافيل للمستخدم النهائي. نستخدم وحدات التخزين المشتركة Shared Volumes من أجل مزامنة ملفات التطبيق وذلك لتطوير تطبيق بسيط وتصحيح الأخطاء بسهولة، كما نستخدم أوامر "docker-compose exec" لتشغيل تعليمات "Composer" و "Artisan" في حاوية التطبيق. المتطلبات الأساسية الوصول إلى حاسب يعمل بنظام التشغيل أوبنتو Ubuntu (استعملنا الإصدار 18.04 في هذا المقال) أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo، ولا يُفضّل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم، كما يُفضّل وجود جدار حماية نشط في حال العمل على خادم بعيد. تثبيت الأداة دوكر على الخادم أو الجهاز المحلي. تثبيت أداة دوكر كومبوز "Docker Compose" على الخادم أو الجهاز المحلي. الخطوة 1- الحصول على التطبيق التوضيحي نبدأ بتحميل تطبيق لارافيل التوضيحي من مخزن Github وننتقل إلى الفرع tutorial-01 والذي يتضمن تطبيقًا بسيطًا مبنيًا باستخدام لارافيل. نعتمد في هذا العمل على الإصدار tutorial-1.0.1 والذي نحملّه ضمن المجلد الأساسي للمستخدم بتنفيذ الأمر: cd ~ curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip يبدأ تحميل الملف المضغوط بصيغة "zip" لذلك يجب عند انتهاء التحميل فك الضغط بعد التأكد من تحديث الحزم الخاصة بنظام التشغيل ما لم تكن محدّثة مؤخرًا كما يجب تثبيت الأداة "unzip" لتحقيق ذلك. ننفذ الأمر التالي: sudo apt update sudo apt install unzip ننفذ الأمر التالي لفك الضغط وتسمية المجلد ليصبح باسم "travellist-demo" بهدف السهولة: unzip travellist.zip mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo ننتقل إلى المجلد "travellist-demo" من خلال الأمر التالي: cd travellist-demo الخطوة 2- إعداد ملف الضبط الخاص بالتطبيق تتواجد ملفات ضبط لارافيل في مجلد يُدعى "config" ضمن مجلد الجذر للتطبيق، إذ يُستخدم الملف "env." لعمليات الضبط المتعلقة بالبيئة، مثل بيانات الاعتماد وأية معلومات تختلف بين عمليات نشر التطبيقات لذلك لا يُضمّن هذا الملف ضمن ملفات التحكم بالإصدارات لكي لا تنتشر هذه المعلومات لجميع المستخدمين الذين يستخدمون صورة التطبيق لاحقًا. تحذير: يحتوي ملف تهيئة البيئة على معلومات حساسة حول الخادم، بما في ذلك بيانات اعتماد قاعدة البيانات ومفاتيح الأمان، لهذا السبب لا يجب أبدًا مشاركة هذا الملف علنًا. توجد أولوية للقيم الموجودة في الملف "env." على القيم الموجودة في ملفات التهيئة الأخرى الموجودة في المجلد "config". تتطلب كل عملية تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف معلومات جديدة، مثل إعدادات الاتصال في قاعدة البيانات، وخيارات التصحيح، ورابط URL للتطبيق، إضافةً لبقية العناصر او المعلومات التي تختلف تبعًا للبيئة التي يعمل بها التطبيق. ننشئ ملف "env." جديد لضبط خيارات التهيئة لبيئة التطوير التي نُعدها. ويمكننا نسخ الملف "example.env" المتاح افتراضيًا مع أي تطبيق لارافيل بتنفيذ الأمر: cp .env.example .env نحرر الملف باستخدام محرر النصوص نانو "nano" أو باختيار محرر النصوص المفضّل: nano .env يحتوي ملف "env." الحالي من تطبيق "travellist" التوضيحي على إعدادات لاستخدام التطبيق المُحتَوى المتصل بقاعدة بيانات محلية من نوع MySQL أي أنها متاحة على المضيف المحلي"127.0.0.1"، نحتاج لتعديل قيمة المتغير DB_HOST لكي يشير إلى قاعدة البيانات التي ننشئها ضمن بيئة دوكر. نعتمد في عملنا على أنّ إسم خدمة قواعد البيانات هو "db". نعدّل محتوى الملف لضبط قيم المتغيرات على النحو التالي: APP_NAME=Travellist APP_ENV=dev APP_KEY= APP_DEBUG=true APP_URL=http://localhost:8000 LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=travellist DB_USERNAME=travellist_user DB_PASSWORD=password ... نستطيع تغيير القيم الخاصة ببقية المتغيرات مثل اسم قاعدة البيانات وكلمة المرور واسم المستخدم عند إعداد الملف "docker-compose.yml" من أجل تهيئة الخدمات. نضغط على الاختصار "CTRL + X" ثم الحرف "Y" وأخيرًا زر الإدخال "Enter" بعد الانتهاء من تعديل الملف. الخطوة 3- إعداد Dockerfile للتطبيق تستند خدمتا MySQL و Nginx إلى الصور الافتراضية التي يمكن الحصول عليها من Docker Hub، ونحتاج في مثالنا إلى إنشاء صورة مخصصة لحاوية التطبيق وسننشئ ملف Dockerfile جديد لذلك. تعتمد صورة التطبيق travillist على صورة PHP الرسمية ذات الاسم "php:7.4-fpm" والمتاحة ضمن مخزن Docker Hub. نحتاج تثبيت بعض حزم PHP الإضافية باستخدام أداة إدارة الاعتمادية Composer. ننشئ مستخدم نظام جديد لتنفيذ الأوامر المختلفة مثل أوامر "composer" و "artisan" أثناء تطوير التطبيق. يضمن إعداد "uid" امتلاك المستخدم الموجود داخل الحاوية نفس معرف المستخدم الخاص بمستخدم النظام على الجهاز المضيف أثناء تشغيل دوكر. تتزامن الملفات التي تُنشأ من الأوامر في جهاز المضيف باستخدام الأذونات الصحيحة، نستطيع استخدام أي محرر نصوص لتطوير الشيفرة البرمجية للتطبيق داخل الحاويات. ننشئ ملف Dockerfile جديد بتنفيذ الأمر: nano Dockerfile ننسخ المحتوى التالي إلى ملف Dockerfile: FROM php:7.4-fpm # Arguments defined in docker-compose.yml ARG user ARG uid # Install system dependencies RUN apt-get update && apt-get install -y \ git \ curl \ libpng-dev \ libonig-dev \ libxml2-dev \ zip \ unzip # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install PHP extensions RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Create system user to run Composer and Artisan Commands RUN useradd -G www-data,root -u $uid -d /home/$user $user RUN mkdir -p /home/$user/.composer && \ chown -R $user:$user /home/$user # Set working directory WORKDIR /var/www USER $user نحفظ الملف بعد الانتهاء من التعديل عليه. يبدأ الملف بتحديد الصورة الأساس التي نستخدمها وهي في حالة الملف السابق php:7.4-fpm. نثبت كومبوزر بنسخ الملف التنفيذي الخاص بـ composer والمتاح ضمن أحدث صورة رسمية إلى صورة التطبيق الخاص بنا. ننشئ مستخدم نظام جديد ونبدأ بإعداد المتغيرين user و uid الذين عرّفناهما في بداية الملف Dockerfile إذ تُمرر هذه المتغيرات إلى الحاوية باستخدام الأداة دوكر كومبوز في وقت الإنشاء. نحدد مسار العمل الافتراضي "www/var/" ونسجل الدخول بواسطة المستخدم الذي أنشأناه مؤخرًا، للتأكد من الاتصال بقاعدة البيانات مثل مستخدم عادي وأننا في المسار الصحيح عند استخدام الأوامر مثل أوامر "composer" و "artisan" في حاوية التطبيق. الخطوة 4- إعداد بنية خادم Nginx وملفات تفريغ قاعدة البيانات يجب مشاركة ملفات الضبط أو التهيئة مع حاويات الخدمة عند إنشاء بيئة تطوير باستخدام الأداة دوكر كومبوز مما يسهّل إجراء التعديلات على ملفات الضبط وضبط البيئة أثناء تطوير التطبيق. ننشئ مجلد ونضع به الملفات التي تُستخدم في تهيئة وضبط حاويات الخدمة. ننشئ مجلد "docker-compose/nginx" ونضع به ملف "travellist.conf" الذي يهيئ آلية تقديم التطبيق وذلك بتنفيذ الأمر: mkdir -p docker-compose/nginx نعدل محتوى الملف "travellist.conf" باستخدام محرر النصوص المفضل عن طريق تنفيذ الأمر التالي: nano docker-compose/nginx/travellist.conf نضيف الشيفرة البرمجية التالية داخله: server { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } } يضبط الملف السابق خادم Nginx ويجبره على الاستماع للمنفذ "80" ويستخدم الصفحة index.php لتكون صفحة الدليل الأساسية للتطبيق. نضبط المسار الجذر Root للمستند ليصبح var/www/public/ ونضبط Nginx ونجبره على استخدام المنفذ "9000" لمعالجة الملفات ذات اللاحقة "php.*". سنشارك تفريغ قاعدة البيانات database dumpfile التي تستورد عند تهيئة الحاوية لإعداد قاعدة البيانات MySQL، إذ تتوفر هذه الميزة في MySQL 5.7 التي سنستخدمها في حاوية التطبيق. ننشئ مجلدًا جديدًا لتهيئة ملفات MySQL داخل المجلد "docker-compose" بتنفيذ الأمر التالي: mkdir docker-compose/mysql ننشئ ملف "sql." جديد بتنفيذ الأمر: nano docker-compose/mysql/init_db.sql يعتمد ملف قاعدة البيانات MySQL dump التالي على قاعدة البيانات المُنشأة في مقال لارافيل بالاعتماد على LEMP من ديجيتال أوشن، إذ يُنشئ جدولًا اسمه places في قاعدة البيانات ثم سيملأ محتوياته بمجموعة من العينات. ولضبط بنية هذا الجدول ومحتوياته، نكتب الشيفرة البرمجية التالية في الملف "init_db.sql" ليصبح كما يلي: DROP TABLE IF EXISTS `places`; CREATE TABLE `places` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `visited` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0); يتضمن الجدول places ثلاثة حقول id و name و visited وهي على الترتيب معرّف خاص بكل مكان واسم المكان ومتغير يشير إلى زيارة المكان مسبقًا أم لا، ويمكن تعديل أسماء الحقول وإضافة حقول جديدة عند الحاجة. الخطوة 5- إنشاء بيئة متعددة الحاويات باستخدام أداة دوكر كومبوز تٌنشئ أداة دوكر كومبوز بيئات متعددة الحاويات للتطبيقات التي تعمل على دوكر، كما يستخدم تعريفات الخدمة لبناء بيئات قابلة للتخصيص بالكامل مع حاويات متعددة يمكنها مشاركة الشبكات وأحجام البيانات، مما يتيح التكامل السلس بين مكونات التطبيق المختلفة. ننشئ ملفًا جديدًا يسمى "docker-compose.yml"، والذي يمكن أن يكون موجودًا مسبقًا ضمن مجلد الجذر Root للتطبيق، ويحدد هذا الملف بيئة الحاويات بما في ذلك الصور الأساسية لبناء التطبيق وكيفية تفاعل الخدمات ضمنه. نحدد ثلاث خدمات مختلفة ضمن ملف "docker-compose.yml" وهي "app" و "db" و "nginx"؛ إذ تُنشئ خدمة "app" صورةً تسمى "travellist" بناءً على ملف Dockerfile الذي أنشأناه مسبقًا، وتُشغّل الحاوية التي تحددها هذه الخدمة خادم "php-fpm" لتحليل شيفرات PHP وتُرسل النتائج مرةً أخرى إلى خدمة "nginx"، التي تعمل على حاوية منفصلة؛ بينما تحدد خدمة "mysql" حاويةً تُشغل خادم MySQL 5.7. تتصل هذه الخدمات فيما بينها باستخدام شبكة جسر أسميناها "travellist". تُزامن ملفات التطبيق على كل من الخدمتين "app" و "nginx" عبر حوامل الربط ؛ إذ تُعد حوامل الربط مفيدةً في بيئات التطوير لأنها تتيح مزامنةً ثنائية الاتجاه بين الجهاز المضيف والحاويات. نُنشئ ملفًا جديدًا باسم "docker-compose.yml" في مجلد الجذر Root للتطبيق بتنفيذ الأمر التالي: nano docker-compose.yml يبدأ ملف "docker-compose.yml" التقليدي برقم الإصدار يليه تعريف الخدمات "services" الخاصة بالتطبيق، كما يُضاف تعريف الشبكات التي يشاركها التطبيق في نهاية الملف، ويكون بالتالي محتوى هذا الملف على النحو التالي: version: "3.7" services: networks: travellist: driver: bridge خدمة التطبيق app تُعِد الخدمة "app" حاويةً باسم "travellist-app" وتبني صورة دوكر جديدة بناءً على Dockerfile الموجود في نفس مسار الملف "docker-compose.yml" وتُحفظ الصورة محليًا باسم "travellist". نحتاج تواجد ملفات التطبيق ضمن حاوية التطبيق "app" حتى ولو كانت هذه الملفات موجودةً في جذر المستند الذي قد جرى تقديمه على أنه تطبيق موجود في حاوية "nginx"، ونحتاج ذلك من أجل تنفيذ أوامر أداة "Artisan" الخاصة بإطار عمل لارافيل على هذه الملفات. نضيف تعريف الخدمة التالي إلى الملف "docker-compose.yml": app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: travellist container_name: travellist-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - travellist تحقق هذه الإعدادات ما يلي: build: تُعلِم هذه البنية الأداة دوكر كومبوز ببناء صورة محلية لخدمة التطبيق، باستخدام المسار المحدد context وملف Dockerfile للحصول على الإرشادات. تُحقن المتغيرات user و uid في Dockerfile لتخصيص أوامر إنشاء المستخدم في وقت الإنشاء. image: تُعد الاسم الذي يستخدم للصورة قيد الإنشاء. container_name: تُعِد اسم الحاوية لهذه الخدمة. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقاف الخدمة. working_dir: يعيّن المجلّد الافتراضي لهذه الخدمة مثل var/www/. volumes: يُنشئ وحدة تخزين مشتركة تُزامِن المحتويات من المسار الحالي إلى var/www/ داخل الحاوية، ويبقى موجودًا في حاوية "nginx". networks: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. خدمة قاعدة البيانات db تستخدم خدمة "db" صورة MySQL 5.7 من Docker Hub. نظرًا لأن دوكر كومبوز يحمّل الملفات المتغيرة "env." الموجودة في نفس المسار الذي يحتوي الملف "docker-compose.yml"، نحصل على إعدادات قاعدة البيانات ملف "env." الذي قد ولّدناه عند إنشاء تطبيق لارافيل. نضع البيانات التالية بعد البيانات التي وضعناها للخدمة "app": db: image: mysql:5.7 container_name: travellist-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - travellist تحقق هذه الإعدادات ما يلي: image: تحدد صورة دوكر التي ستُستخدم في هذه الحاوية. نستخدم صورة MySQL 5.7 من Docker Hub. container_name: اسم الحاوية travellist-db. restart: يعيد التشغيل دائمًا ، ما لم يحدث إيقاف الخدمة. environment: تُحدد متغيرات البيئة في الحاوية الجديدة. نستخدم القيم التي حصلنا عليها من ملف "env." لإعداد خدمة قاعدة البيانات MySQL والتي تُنشِئ تلقائيًا قاعدة بيانات ومستخدمًا جديدًا بناءً على متغيرات البيئة المتوفرة. volumes: ينشئ وحدة تخزين لتهيئة قاعدة بيانات التطبيق. تستورد صورة قاعدة البيانات MySQL ملفات"sql." تلقائيًا والتي توجد في المسار ‎/docker-entrypoint-initdb.d داخل الحاوية. network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. خدمة nginx تستخدم خدمة "nginx" صورة Nginx مبنية مسبقًا على توزيعة لينكس اسمها Alpine، إذ تنشئ حاويةً باسم "travellist-nginx" وتُعيد التوجيه من المنفذ "8000" الى المنفذ "80" داخل الحاوية. نضع البيانات التالية بعد بيانات خدمة "db": nginx: image: nginx:1.17-alpine container_name: travellist-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d networks: - travellist تحقق هذه الإعدادات ما يلي: image: اسم صورة دوكر التي تستخدم في هذه الحاوية وهي في هذه الحالة الصورة Alpine Nginx 1.17 . container_name: اسم الحاوية travellist-nginx. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقاف الخدمة. ports: تعيد توجيه المنفذ الذي يسمح بالوصول الخارجي عبر المنفذ "8000" إلى خادم الويب الذي يعمل على المنفذ 80 داخل الحاوية. volumes: تنشئ وحدتي تخزين مشتركتين، بحيث تزامن الوحدة الأولى المحتويات من نقطة العمل إلى المسار var/www/ داخل الحاوية ويفيد ذلك بنقل التعديلات المحلية إلى التطبيق الذي يقدّمه Nginx تلقائيًا، وتنسخ الوحدة الثانية ملفات الإعداد الخاصة بخادم nginx الموجودة في الملف "docker-compose/nginx/travellist.conf" الى ملفات الضبط الخاصة بـ nginx ضمن الحاوية. network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. وعليه يصبح ملف "docker-compose.yml" على النحو التالي: version: "3.7" services: app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: travellist container_name: travellist-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - travellist db: image: mysql:5.7 container_name: travellist-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - travellist nginx: image: nginx:alpine container_name: travellist-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d/ networks: - travellist networks: travellist: driver: bridge الخطوة 6- تشغيل التطبيق باستخدام أداة دوكر كومبوز ننشئ صورة تطبيق جديد ونشغّل الخدمات التي حددناها ضمن الإعدادات باستخدام الأمر التالي: docker-compose build app يستغرق الأمر بضعة دقائق ومن ثم يظهر الخرج التالي: Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in f71eb33b7459 Removing intermediate container f71eb33b7459 ---> 533c30216f34 Step 3/11 : ARG uid ---> Running in 60d2d2a84cda Removing intermediate container 60d2d2a84cda ---> 497fbf904605 Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev ... Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> e499f74896e3 Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user ---> Running in 232ef9c7dbd1 Removing intermediate container 232ef9c7dbd1 ---> 870fa3220ffa Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user ---> Running in 7ca8c0cb7f09 Removing intermediate container 7ca8c0cb7f09 ---> 3d2ef9519a8e Step 10/11 : WORKDIR /var/www ---> Running in 4a964f91edfa Removing intermediate container 4a964f91edfa ---> 00ada639da21 Step 11/11 : USER $user ---> Running in 9f8e874fede9 Removing intermediate container 9f8e874fede9 ---> fe176ff4702b Successfully built fe176ff4702b Successfully tagged travellist:latest نُشغّل البيئة بالخلفية بعد الانتهاء من مرحلة الإنشاء بتنفيذ الأمر: docker-compose up -d ويكون الخرج على النحو التالي: Creating travellist-db ... done Creating travellist-app ... done Creating travellist-nginx ... done نستعرض معلومات حالة الخدمة النشطة حاليًا بتنفيذ الأمر: docker-compose ps ويكون الخرج على النحو التالي: Name Command State Ports ------------------------------------------------------------------------------- travellist-app docker-php-entrypoint php-fpm Up 9000/tcp travellist-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp travellist-nginx nginx -g daemon off; Up 0.0.0.0:8000->80/tcp بيئتنا الآن قيد التشغيل، لكننا ما زلنا بحاجة إلى تنفيذ أمرين لإنهاء إعداد التطبيق، إذ نستخدم الأمر docker-compose exec لتنفيذ جميع الأوامر ضمن الحاويات، فلو رغبنا بتنفيذ الأمر ls –l الذي يظهر معلومات تفصيلية حول الملفات في مسار التطبيق، ننفذ الأمر التالي وتظهر النتائج كما يلي: docker-compose exec app ls -l ويكون الخرج على النحو التالي: total 256 -rw-rw-r-- 1 sammy 1001 738 Jan 15 16:46 Dockerfile -rw-rw-r-- 1 sammy 1001 101 Jan 7 08:05 README.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 app -rwxr-xr-x 1 sammy 1001 1686 Jan 7 08:05 artisan drwxrwxr-x 3 sammy 1001 4096 Jan 7 08:05 bootstrap -rw-rw-r-- 1 sammy 1001 1501 Jan 7 08:05 composer.json -rw-rw-r-- 1 sammy 1001 179071 Jan 7 08:05 composer.lock drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 config drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 database drwxrwxr-x 4 sammy 1001 4096 Jan 15 16:46 docker-compose -rw-rw-r-- 1 sammy 1001 1015 Jan 15 16:45 docker-compose.yml -rw-rw-r-- 1 sammy 1001 1013 Jan 7 08:05 package.json -rw-rw-r-- 1 sammy 1001 1405 Jan 7 08:05 phpunit.xml drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 public -rw-rw-r-- 1 sammy 1001 273 Jan 7 08:05 readme.md drwxrwxr-x 6 sammy 1001 4096 Jan 7 08:05 resources drwxrwxr-x 2 sammy 1001 4096 Jan 7 08:05 routes -rw-rw-r-- 1 sammy 1001 563 Jan 7 08:05 server.php drwxrwxr-x 5 sammy 1001 4096 Jan 7 08:05 storage drwxrwxr-x 4 sammy 1001 4096 Jan 7 08:05 tests -rw-rw-r-- 1 sammy 1001 538 Jan 7 08:05 webpack.mix.js تُثبّت اعتماديات التطبيق باستخدام الأداة composer install كما يلي: docker-compose exec app composer install يظهر الخرج التالي بعد إتمام العملية: Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) - Installing erusev/parsedown (1.7.4): Downloading (100%) - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%) - Installing phpoption/phpoption (1.7.2): Downloading (100%) - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%) - Installing symfony/css-selector (v5.0.2): Downloading (100%) … Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. نولّد مفتاح التطبيق الخاص باستخدام أداة artisan الخاصة بلارافيل، إذ يشفّر هذا المفتاح جلسات المستخدم والبيانات الحساسة: docker-compose exec app php artisan key:generate ويكون الخرج على النحو التالي: Application key set successfully. نطلب الرابط التالي من المتصفح: http://server_domain_or_IP:8000 يظهر عندها الخرج التالي: نستطيع استخدام الأمرlogs لفحص السجلات التي تولّدها الخدمة بتنفيذ الأمر التالي: docker-compose logs nginx ويكون الخرج على النحو التالي: Attaching to travellist-nginx travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:25 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:26 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" travellist-nginx | 192.168.160.1 - - [23/Jan/2020:13:57:42 +0000] "GET / HTTP/1.1" 200 626 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" … نستطيع إيقاف العمل مؤقتًا لبيئة دوكر كومبوز مع الحفاظ على حالة الخدمات بتشغيل الأمر: Docker-compose puse ويكون الخرج على النحو التالي: Pausing travellist-db ... done Pausing travellist-nginx ... done Pausing travellist-app ... done نستطيع استئناف العمل بتنفيذ الأمر: docker-compose unpause ويكون الخرج على النحو التالي: Unpausing travellist-app ... done Unpausing travellist-nginx ... done Unpausing travellist-db ... done نستطيع إيقاف عمل بيئة كومبوز ونزيل جميع حاوياتها وشبكاتها ووحدات تخزينها بتنفيذ الأمر: docker-compose down ويكون الخرج على النحو التالي: Stopping travellist-nginx ... done Stopping travellist-db ... done Stopping travellist-app ... done Removing travellist-nginx ... done Removing travellist-db ... done Removing travellist-app ... done Removing network travellist-laravel-demo_travellist الخاتمة أعددنا بيئة دوكر مكونة من ثلاث حاويات باستخدام الأداة دوكر كومبوز وحددنا بنيته الأساسية في ملف YAML. يمكن العمل على تطبيق لارافيل دون الحاجة إلى تثبيت خادم ويب محلي وإعداده للتطوير والاختبار، ويتحقق كل ذلك باستخدام بيئة معزولة يمكن تكرارها وإعادة إنشائها بسهولة حتى الوصول إلى التطبيق المطلوب تثبيته ضمن بيئات الإنتاج. ترجمة -وبتصرّف- للمقال How To Containerize a Laravel Application for Development with Docker Compose on Ubuntu 18.04 لصاحبه Erika Heidi. اقرأ أيضًا تثبيت وإعداد لارافيل Laravel على دوكر كومبوز Docker Compose كيفية تثبيت Docker Compose على دبيان نقل سير عمل Docker Compose إلى Kubernetes إعداد لارافيل مع خادم Nginx وقاعدة بيانات MySQL باستخدام دوكر كومبوز Docker Compose
  12. تتضمن العديد من تطبيقات الويب نظام إشعارات مبني ضمن التطبيق والذي يُعلِم المستخدم فورًا عندما يحاول شخص ما تنفيذ فعل ما مرتبط به، إذ يتلقى المستخدم في شبكة التواصل الاجتماعي فيسبوك مثلًا إشعارًا عندما يُعجَبُ أحدهم بحالة ما قد نشرها المستخدم أو عندما يضع أحدهم تعليقًا على صفحة المستخدم الشخصية. ننشئ في هذه المقالة آليةً شبيهةً بذلك عن طريق تطوير منظومة إشعارات معتمدة على الويب باستخدام بيئة لارافيل ومكتبة Pusher. المتطلبات الأساسية يجب التأكد من تثبيت خادم PHP ولارافيل Laravel على الحاسوب لإكمال المشروع كما يجب امتلاك حساب على منصة بوشر Pusher. ما الذي سنبنيه؟ يتضمن العمل إنشاء تطبيق ويب بسيط يعرض الإشعارات باستخدام لارافيل وقنوات بوشر Pusher. يبين العرض التالي ما الذي نريد بناءه: إعداد تطبيق Pusher ننشئ بدايةً حسابًا على منصة Pusher ومن ثم نضبط التطبيق كما هو موضح بالصورة أدناه: إعداد تطبيق لارافيل ننشئ تطبيق لارافيل جديد بإجراء الأمر التالي في موجه الأوامر: laravel new laravel-web-notifications نثبت حزمة التطوير البرمجي الخاصة بمنصة بوشر Pusher والمعتمدة على لغة PHP بتنفيذ الأمر التالي: composer require pusher/pusher-php-server نوجّه لارافيل لاستخدام منصة بوشر على أنها وسيلة لإرسال رسائل بث broadcast تُستخدم لإعلام أجزاء البرنامج بوقوع حدثٍ ما، ولتحقيق ذلك نفتح الملف "‎.env" الموجود في المجلد الجذر Root الخاص بلارافيل، ثم نحدّث محتواه ليوافق الضبط التالي مع ضرورة استبدال الرموز X بالقيم الخاصة بالحساب الخاص بك: PUSHER_APP_ID=322700 BROADCAST_DRIVER=pusher // ‫نضيف المعلومات المتعلقة بالحساب الخاص بنا من منصة بوشر PUSHER_APP_ID=XXXXX PUSHER_APP_KEY=XXXXXXX PUSHER_APP_SECRET=XXXXXXX ملاحظة مهمة: يتصل لارافيل افتراضيًا بخوادم الولايات المتحدة الأمريكية، وعند الحاجة لاستخدام خوادم أخرى، يجب تحديث مصفوفة الخيارات الموجودة ضمن الملف "config/broadcasting.php"، كما يُعدّل الملف "config/app.php" ويحذف التعليق الموجود في الجزء: App\Providers\BroadcastServiceProvider::class إنشاء التطبيق الذي يدمج لارافيل مع Pusher ننشئ التطبيق بعد الانتهاء من العمليات السابقة، حيث نبدأ بإنشاء صنف الحدث Event، الذي يبث الرسائل إلى قنوات بوشر Pusher انطلاقًا من تطبيق لارافيل. تُستدعى الأحداث من أي مكان نرغب به ضمن التطبيق. php artisan make:event StatusLiked ينشئ هذا السطر صنفًا باسم StatusLiked ضمن مجلد "app/Events". نفتح هذا الملف ونحدّث محتواه كما يلي: <?php namespace App\Events; use Illuminate\Queue\SerializesModels; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class StatusLiked implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public $username; public $message; /** * إنشاء عينة جديدة من الحدث * * @return void */ public function __construct($username) { $this->username = $username; $this->message = "{$username} liked your status"; } /** * تحديد القنوات التي سيُبث الحدث عليها * * @return Channel|array */ public function broadcastOn() { return ['status-liked']; } } تخبر الواجهة ShouldBroadcast لارافيل أن الحدث الحالي يجب أن يُرسل وفقًا للطريقة المحدّدة في ملف الضبط الذي أعددناه مسبقًا. يوجد تابع باني يأخذ وسيطين، هما: اسم المستخدم وفعل verb، إذ تُسند قيم المتغيرات إلى خصائص الصنف التي تأخذ نفس الأسماء، ويجب أن تكون هذه الخصائص عامة public وإلا فسيجري تجاهلها. إنشاء واجهة عرض التطبيق نستخدم واجهة عرض وحيدة تحتوي شريط تنقّل وأيقونة للإشعارات، إذ تُحدّث الأيقونة عند وجود إشعارات جديدة دون الحاجة لإعادة تحميل الصفحة. لن تستمر الإشعارات طويلًا في التجربة الحالية ولكن يمكن زيادة المدة الزمنية لاستمرار الإشعار حسب الحاجة. نفتح الملف "welcome.blade.php" ونستبدل محتواه بما يلي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Demo Application</title> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <link rel="stylesheet" type="text/css" href="/css/bootstrap-notifications.min.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-9" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Demo App</a> </div> <div class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="dropdown dropdown-notifications"> <a href="#notifications-panel" class="dropdown-toggle" data-toggle="dropdown"> <i data-count="0" class="glyphicon glyphicon-bell notification-icon"></i> </a> <div class="dropdown-container"> <div class="dropdown-toolbar"> <div class="dropdown-toolbar-actions"> <a href="#">Mark all as read</a> </div> <h3 class="dropdown-toolbar-title">Notifications (<span class="notif-count">0</span>)</h3> </div> <ul class="dropdown-menu"> </ul> <div class="dropdown-footer text-center"> <a href="#">View All</a> </div> </div> </li> <li><a href="#">Timeline</a></li> <li><a href="#">Friends</a></li> </ul> </div> </div> </nav> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script src="//js.pusher.com/3.1/pusher.min.js"></script> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script type="text/javascript"> var notificationsWrapper = $('.dropdown-notifications'); var notificationsToggle = notificationsWrapper.find('a[data-toggle]'); var notificationsCountElem = notificationsToggle.find('i[data-count]'); var notificationsCount = parseInt(notificationsCountElem.data('count')); var notifications = notificationsWrapper.find('ul.dropdown-menu'); if (notificationsCount <= 0) { notificationsWrapper.hide(); } // ‫تأهيل وظيفة السجلات الخاصة بمكتبة بوشر Pusher // لا نستخدم هذه الوظيفة في بيئة الإنتاج الفعلية // Pusher.logToConsole = true; var pusher = new Pusher('API_KEY_HERE', { encrypted: true }); // الإشتراك بالقناة التي حددناها في صنف الحدث المعرّف في لارافيل var channel = pusher.subscribe('status-liked'); // ربط تابع ما بالحدث الذي عرّفناه في الصنف channel.bind('App\\Events\\StatusLiked', function(data) { var existingNotifications = notifications.html(); var avatar = Math.floor(Math.random() * (71 - 20 + 1)) + 20; var newNotificationHtml = ` <li class="notification active"> <div class="media"> <div class="media-left"> <div class="media-object"> <img src="https://api.adorable.io/avatars/71/`+avatar+`.png" class="img-circle" alt="50x50" style="width: 50px; height: 50px;"> </div> </div> <div class="media-body"> <strong class="notification-title">`+data.message+`</strong> <!--p class="notification-desc">Extra description can go here</p--> <div class="notification-meta"> <small class="timestamp">about a minute ago</small> </div> </div> </div> </li> `; notifications.html(newNotificationHtml + existingNotifications); notificationsCount += 1; notificationsCountElem.attr('data-count', notificationsCount); notificationsWrapper.find('.notif-count').text(notificationsCount); notificationsWrapper.show(); }); </script> </body> </html> نركّز على الجزء الخاص بلغة جافا سكريبت JavaScript، الذي يتضمن الأجزاء الخاصة بمكتبة Pusher التي ترسل الإشعارات. وفيما يلي الجزء المهم من الكتلة البرمجية الخاصة بعملية الإرسال: // ‫تأهيل وظيفة السجلات الخاصة بمكتبة بوشر //لا نستخدم هذه الوظيفة في بيئة الإنتاج الفعلية // Pusher.logToConsole = true; // نهيئ مكتبة جافا سكريبت الخاصة بقنوات بوشر var pusher = new Pusher('API_KEY_HERE', { encrypted: true }); // الإشتراك بالقناة التي حددناها في صنف الحدث المعرّف في لارافيل var channel = pusher.subscribe('status-liked'); // ربط تابع ما بالحدث الذي عرّفناه في الصنف channel.bind('App\\Events\\StatusLiked', function(data) { // يُستدْعى هذا التابع عند استلام إشعار بالحدث }); ملاحظة: ستبث لارافيل الحدث افتراضيًا تحت اسم الصنف الخاص بالحدث ولكن يمكن تخصيص هذا الاسم عن طريق تعريف طريقة خاصة للبث الخاص بالحدث: public function broadcastAs() { return 'event-name'; } تهيئ الشيفرة السابقة مكتبة الجافا سكريبت الخاصة بالتعامل مع بوشر Pusher وتؤسس قناة اتصال لإرسال واستقبال الأحداث المختلفة، وتتضمن أيضًا طريقةً خاصةً تُستَدعى عند استلام عملية بث تخص حدث ما عن طريق القناة. اختبار التطبيق ننشئ الاتجاه Route اللازم لتنفيذ الحدث والذي يسبب وصول الإشعار إلى المستخدم، إذ يظهر الإشعار عند الوصول إلى هذا الاتجاه ما لم يوجد خطأ ما في الخطوات السابقة. نضيف الاتجاه الجديد كما يلي: Route::get('test', function () { event(new App\Events\StatusLiked('Someone')); return "Event has been sent!"; }); نشغّل خادم PHP عن طريق لارافيل لاختبار نجاح عمل البرنامج الذي كتبناه: php artisan serve الخاتمة أنشأنا نظام إشعارات خاص بالويب باستخدام عددٍ قليل نسبيًا من السطور البرمجية بالاعتماد على قنوات بوشر Pusher، وما أنجزناه يُعد مثالًا بسيطًا على قدرات هذه المكتبة وأداةً يمكن تضمينها في عدة مشاريع، ولا شك أنه يمكن الاعتماد على مكتبة بوشر Pusher في تطوير كثيرٍ من الأدوات المفيدة أيضًا والتي يمكن تضمينها ضمن مختلف المشاريع البرمجية. ترجمة -وبتصرف- للمقال How To Create Web Notifications Using Laravel and Pusher Channels لصاحبه Neo Ighodaro. اقرأ أيضًا أساسيات بناء التطبيقات في إطار العمل Laravel 5 إنشاء تطبيق Todo List بسيط باستخدام Laravel 5 - الجزء الأول
  13. يُعد دوكر الحل الأكثر شيوعًا لنشر التطبيقات بسبب ما يقدمه من تبسيط لعملية تشغيل التطبيقات ونشرها في حاويات مؤقتة. يمكن استخدام دوكر لإنشاء حاويات تشكل حزمة تطبيقات LEMP مع خوادم PHP و Nginx و MySQL وإطار عمل لارافيل من أجل تسهيل عملية إنشاء التطبيقات. يسمح Docker Compose للمطورين بتعريف البنية التحتية بما فيها من خدمات وشبكات ووحدات تخزين في ملف واحد ويوفر بديلًا فعالًا لتشغيل الأمرين التاليين: docker container create docker container run سننشئ تطبيقًا باستخدام إطار عمل لارافيل، مع خادم ويب Nginx وقاعدة بيانات MySQL، إذ تتواجد هذه المكونات ضمن حاويات دوكر، وسنحدد تكوين المكدس كاملًا ضمن ملف "docker-compose"، جنبًا إلى جنب مع ملفات التهيئة للغة PHP وقاعدة بيانات MySQL وخادم Nginx. المتطلبات الأساسية الوصول إلى خادم يعمل بنظام التشغيل أوبنتو Ubuntu ذي رقم إصدار 18.04 أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo ولا يفضل استخدام حساب الجذر root لأسباب تتعلق بأمان الخادم، كما يُفضّل وجود جدار حماية نشط في حال العمل على خادم بعيد. تثبيت الأداة دوكر على الخادم. تثبيت الأداة دوكر كومبوز Docker Compose على الخادم. الخطوة 1- تنزيل لارافيل وتثبيت اعتمادياتها لا بُد من تنزيل أحدث إصدار متاح من لارافيل وتثبيت الاعتماديات اللازمة للمشروع البرمجي بما فيها Composer، مدير الحزم الخاص بلغة PHP في دوكر. نثبّت أحدث إصدار من لارافيل داخل مجلد laravel-app ضمن المسار الرئيسي للنظام كما يلي: cd ~ git clone https://github.com/laravel/laravel.git laravel-app ننتقل إلى المجلّد الجديد: cd ~/laravel-app نستخدم صورة composer لمشاركة المجلدات التي نحتاجها ضمن مشروع لارافيل ويفيدنا ذلك أيضًا بتجنب أعباء تثبيت الأداة Composer عمومًا ضمن الخادم. ننفذ الأمر التالي لتحقيق ذلك: docker run --rm -v $(pwd):/app composer install تُنشئ التعليمة السابقة باستخدام الرايات v- و rm– حاويةً تزول تلقائيًا عند الانتهاء من عملها أي عندما ينفذ المستخدم الأمرexit، وتُربط بالمسار الحالي قبل إزالتها، وسينسخ هذا محتويات مسار التطبيق "laravel-app/~" إلى الحاوية، ويضمن نسخ المجلد "vendor" الذي أنشأه Composer داخل الحاوية إلى المسار الحالي. نضبط أذونات التطبيق على أنه مستخدم غير جذر non-root: sudo chown -R $USER:$USER ~/laravel-app سيكون هذا مهمًا عند كتابة Dockerfile لصورة التطبيق الخاص بك في الخطوة 4، إذ سيسمح لك بالعمل مع شيفرة التطبيق الخاصة بك وتشغيل العمليات في الحاوية الخاصة بك مثل مستخدم غير جذر. بعد الانتهاء من كتابة شيفرة التطبيق الخاص بك، يمكنك الانتقال إلى تحديد خدماتك باستخدام دوكر كومبوز. الخطوة 2- إنشاء ملف دوكر كومبوز تُبسّط الأداة دوكر كومبوز عملية إعداد التهيئة الأساسية للبنية التحتية المستخدمة في مشروع تطوير معين مع الاحتفاظ بالتعديلات المختلفة المُطبقة والتي ندعو كل منها إصدارًا. ننشئ ملف "docker-compose" لإعداد تطبيق لارافيل يتضمن إنشاء البيئة اللازمة للتطبيق من خادم الويب وقاعدة البيانات والخدمات الأخرى. nano ~/laravel-app/docker-compose.yml نضبط الخدمات الثلاثة "db" و "webserver" و "app"بإضافة الشيفرة البرمجية التالية الى الملف "laravel-app/docker-compose.yml/~" مع الأخذ بالحسبان ضبط كلمات المرور جيدًا. نتأكد من وضع كلمة المرورMYSQL_ROOT_PASSWORD، بحيث تصبح هذه القيمة متغيرًا خاصًا بكامل البيئة أي ضمن خادم الويب وقاعدة البيانات وخدمات التطبيق المختلفة. نضيف المحتوى التالي إلى الملف "laravel-app/docker-compose.yml/~": version: '3' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: digitalocean.com/php container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www networks: - app-network #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" networks: - app-network #MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: your_mysql_root_password SERVICE_TAGS: dev SERVICE_NAME: mysql networks: - app-network #Docker Networks networks: app-network: driver: bridge يتضمن هذا الملف تعريف الخدمات التالية: "app": تحدد هذه الخدمة صورة دوكر التي ستُستخدم وتضبط مجلد العمل working_dir في الحاوية ليصبح var/www/. "webserver": تحدد صورة nginx:alpine وتعيّن المنفذين 80 و 443. "db": تنشئ حاوية انطلاقًا من صورة mysql:5.7.22 وتعرّف بعض متغيرات البيئة الأخرى، مثل اسم قاعدة البيانات وكلمة المرور المستخدمة والتي يجب أن تكون مناسبة. تحدد هذه الخدمة أيضًا المنافذ المستخدمة، إذ تربط المنفذ 3306 للمضيف إلى المنفذ 3306 للحاوية. تحدد خاصية container_name اسمًا للحاوية يتوافق مع اسم الخدمة، وإذا لم تحدد هذه الخاصية، يعين دوكر اسمًا لكل حاوية من خلال الجمع بين اسم شخص مشهور تاريخيًا وكلمة عشوائية مفصولة بشرطة سفلية. لتسهيل الاتصال بين الحاويات، تُوصل الخدمات بشبكة جسرية تسمى app-network، إذ تستخدم هذه الشبكة جسرًا برمجيًا Software Bridge يسمح للحاويات المتصلة بنفس الشبكة التواصل مع بعضها بعضًا. يثبّت برنامج تشغيل الجسر Bridge driver آليًا قواعد الاتصال الشبكي على الجهاز المضيف بحيث يضمن عزل الحاويات الموجودة على الشبكات الجسرية المختلفة عن بعضها بعضًا ما لم يرغب المستخدم بربطها معًا. يزيد ذلك من أمان التطبيق ويضمن تواصل الخدمات ذات الصلة فقط مع بعضها بعضًا، وبذلك تستخدم خدمات التطبيقات الأمامية شبكة "frontend" وتستخدم خدمات الواجهة الخلفية شبكة "backend". الخطوة 3- ديمومة البيانات يتضمن دوكر عدة مزايا تضمن احتفاظ أو ديمومة البيانات Data Persistence، ففي تطبيقنا نستخدم وحدات التخزين Volumes وحوامل الربط bind mounts لضمان احتفاظ البيانات ضمن قاعدة البيانات وملفات التطبيق والتهيئة العامة؛ إذ توفر وحدات التخزين المرونة للنسخ الاحتياطي والاستمرار الى ما بعد دورة حياة الحاوية؛ وتسهل حوامل الربط تغيير التعليمات البرمجية أثناء التطوير، مما يزامن إجراء التغييرات على ملفات المضيف والمجلدات في الحاوية لتنعكس هذه التغييرات فور اعتمادها على التطبيق. تحذير: تتيح حوامل الربط إمكانية تغيير نظام ملفات المضيف من خلال العمليات التي تعمل في الحاوية، بما في ذلك إنشاء أو تعديل أو حذف ملفات النظام أو المجلدات المهمة. على الرغم من الفائدة الكبيرة لهذه الميزة إلا أنّ لها انعكاسات أمنية يمكن أن تؤثر على العمليات التي لا تتعلق بدوكر على النظام المضيف لذلك يتوجب استخدام حوامل الربط بعناية. ننشئ وحدة تخزين تدعى dbdata في خدمة db من أجل احتفاظ قاعدة البيانات MySQL بوضع البيانات التالية ضمن ملف docker-compose.yml ... #MySQL Service db: ... volumes: - dbdata:/var/lib/mysql networks: - app-network ... تضمن وحدة التخزين dbdata الاحتفاظ بالمحتوى في المجلد ‎/var/lib/mysql وبذلك يمكن إيقاف وإعادة تشغيل خدمة db دون فقدان البيانات. نضيف في نهاية ملف التعريف التالي لوحدة التخزين dbdata: ... #Volumes volumes: dbdata: driver: local نضيف حامل الربط إلى خدمة db لملفات تهيئة قاعدة البيانات MySQL التي ننشئها لاحقًا: ... #MySQL Service db: ... volumes: - dbdata:/var/lib/mysql - ./mysql/my.cnf:/etc/mysql/my.cnf ... يربط حامل الربط الملف "‎~/laravel-app/mysql/my.cnf" بالملف "‎/etc/mysql/my.cnf" داخل الحاوية، ومن ثم نضيف حوامل الربط إلى خدمة webserver، إذ توجد خدمتان، تعود الأولى للشيفرة البرمجية للتطبيق والأخرى لتعريف تهيئة خادم Nginx الذي سننشئه في الخطوة 6: #Nginx Service webserver: ... volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network يربط حامل الربط الأول الشيفرة البرمجية للتطبيق في مجلد التطبيق "‎~/laravel-app" بالمجلد "‎/var/www" داخل الحاوية، ويحمّل ملف التهيئة الذي نضيفه إلى المجلد "‎~/laravel-app/nginx/conf.d/‎" إلى المجلد "/etc/nginx/conf.d/" في الحاوية، وبذلك نضيف أو نعدل محتويات مجلد التهيئة حسب الحاجة. نضيف حوامل الربط إلى الخدمة app على النحو التالي: #PHP Service app: ... volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network تربط الخدمة appمجلد التطبيق "laravel-app/~" الذي يحتوي على الشيفرة البرمجية للتطبيق بالمجلد "var/www" في الحاوية لتسريع عملية التطوير، نظرًا لأن أية تغييرات تحصل على مجلد التطبيق المحلي تنعكس على الفور داخل الحاوية. تربط الخدمة أيضًا ملف تهيئة خادم PHP الموجود في المسار "laravel-app/php/local.ini/~" بالملف "usr/local/etc/php/conf.d/local.ini/" داخل الحاوية. يصبح محتوى الملف "docker-compose.yml"على النحو التالي: version: '3' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: digitalocean.com/php container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www volumes: - ./:/var/www - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks: - app-network #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network #MySQL Service db: image: mysql:5.7.22 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: your_mysql_root_password SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf networks: - app-network #Docker Networks networks: app-network: driver: bridge #Volumes volumes: dbdata: driver: local نحفظ الملف بعد الانتهاء من إجراء التعديلات السابقة. نستطيع الآن باستخدام الأداة دوكر كومبوز بناء الصورة المخصًصة التي أنشأناها لتطبيقنا الخطوة 4- إنشاء ملف Dockerfile يسمح دوكر لك بتخصيص البيئة داخل الحاويات الفردية باستخدام ملف Dockerfile، الذي يمكّننا من إنشاء صور مخصصة يمكننا استخدامها لتثبيت البرنامج الذي يتطلبه التطبيق وضبط الإعدادات بناءً على المتطلبات. يمكن دفع الصور المخصصة التي ننشئها إلى Docker Hub أو أي سجل خاص آخر. نضع الملف Dockerfile ضمن "laravel-app/~"، ولإنشائه ننفّذ الأمر التالي: nano ~/laravel-app/Dockerfile يحدد ملف دوكر هذا الصورة الأساسية ويحدد الأوامر والإرشادات اللازمة لبناء صورة تطبيق لارافيل. نضيف الشيفرة البرمجية التالية إلى الملف: FROM php:7.2-fpm # Copy composer.lock and composer.json COPY composer.lock composer.json /var/www/ # Set working directory WORKDIR /var/www # Install dependencies RUN apt-get update && apt-get install -y \ build-essential \ libpng-dev \ libjpeg62-turbo-dev \ libfreetype6-dev \ locales \ zip \ jpegoptim optipng pngquant gifsicle \ vim \ unzip \ git \ curl # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install extensions RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ RUN docker-php-ext-install gd # Install composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Add user for laravel application RUN groupadd -g 1000 www RUN useradd -u 1000 -ms /bin/bash -g www www # Copy existing application directory contents COPY . /var/www # Copy existing application directory permissions COPY --chown=www:www . /var/www # Change current user to www USER www # Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"] ينشئ ملف Dockerfile صورةً جديدةً على أساس صورة دوكر php:7.2-fpm المبنية على نظام دبيان Debian، ويثبّت أداة الإدارة PHP-FPM من أجل التحكم بتطبيق PHP FastCGI، كما يثبت حزم لارافيل التالية: mcrypt و pdo_mysql و mbstring و imagick مع composer. يوجه أمر التوجيه RUN الأوامر لتحديث الإعدادات وتثبيتها وتكوينها داخل الحاوية، بما في ذلك إنشاء مستخدم مخصص ومجموعة تسمّى www. تحدد تعليمة WORKDIR المجلد "‎/var/www" على أنه مجلد العمل الأساسي للتطبيق. يخفف إنشاء مستخدم ومجموعة بأذونات مقيدة الخطر الذي ينتج عن الثغرات الأمنية الناتجة عن تشغيل حاويات دوكر. عندما تبدأ الحاوية للعمل فإنها تستخدم حساب الجذر افتراضيًا ما لم يُحدّد مستخدم آخر في ملف الإعداد الخاص بالصورة. يمتلك هذا الحساب الأذونات المطلقة على الجهاز المضيف والحاويات معًا. بدلاً من تشغيل هذه الحاوية باستخدام المستخدم الجذر، ننشئ مستخدمwww يمتلك أذونات القراءة والكتابة على المجلد "var/www/" بفضل تعليمات COPYالتي نستخدمها مع العلامة chown-- لنسخ أذونات مجلد التطبيق. يعرض الأمر EXPOSE المنفذ 9000 في الحاوية لخادم "php-fpm" ويحددCMD الأمر الذي يجب تشغيله بمجرد إنشاء الحاوية، وهو هنا "php-fpm"، الذي سيشغّل الخادم. الخطوة 5- إعداد خادم PHP نُعد خدمة PHP لتعمل مثل معالج PHP للطلبات الواردة من Nginx. ولضبط ذلك ننشئ ملف "local.ini" داخل مجلد "php" الذي ربطناه بالملف "usr/local/etc/php/conf.d/local.ini/" داخل الحاوية في خطوة سابقة، إذ يسمح هذا الملف بتجاوز ملف "php.ini" الافتراضي الذي يفحصه خادم PHP عندما نبدأ بالعمل. ننشئ مجلد php بالأمر التالي: mkdir ~/laravel-app/php نحرر الملف"local.ini" باستخدام محرر النصوص المفضل وبحالة المحرر نانو nano ننفذ الأمر التالي: nano ~/laravel-app/php/local.ini نلصق داخل الملف الأوامر التالية لتحديد أقصى حجم لتحميل الملفات: upload_max_filesize=40M post_max_size=40M تعيّن كل من الخاصتين upload_max_filesize و post_max_size الحجم الأقصى المسموح به لرفع الملفات إلى الخادم، ويوضح تعديل هاتين الخاصتين إمكانية إعداد الملف"php.ini" انطلاقًا من تعديل الملف "local.ini"، ويمكن إضافة أية إعدادات خاصة بخادم PHP نرغب بتطبيقها ضمن هذا الملف. نحفظ الملف بعد إجراء التعديلات السابقة ومن ثم نغلق محرر النصوص، وبهذا ينتهي إعداد خادم PHP وننتقل لإعداد خادم Nginx. الخطوة 6- إعداد خادم Nginx يسمح إعداد خدمة PHP بتعديل خدمة Nginx لاستخدام PHP-FPM مثل خادم FastCGI لتقديم خدمة المحتوى الديناميكي، إذ يعتمد خادم FastCGI على بروتوكول ثنائي binary protocol لربط البرامج التفاعلية بخادم الويب. ننشئ ملف "app.conf" مع ضبط الخدمة في المجلد /laravel-app/nginx/conf.d/~ من أجل إعداد Nginx. ننشئ المجلد "‎/nginx/conf.d" بتنفيذ الأمر التالي: mkdir -p ~/laravel-app/nginx/conf.d ننشئ بعدها الملف "app.conf" بتنفيذ الأمر: nano ~/laravel-app/nginx/conf.d/app.conf نضيف المحتوى التالي لإعداد خادم Nginx: server { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } } يتضمن إعداد كتلة الخادم الموجهات directives الضرورية لإعداد خادم الويب Nginx إذ تدل هذه الموجهات إلى ما يلي: listen: يحدد هذا الموجه المنفذ الذي يستمع الخادم إليه من أجل استقبال الطلبات. error_log و access_log: تحدد هذه الموجّهات الملفات لكتابة السجلات المتعلقة بالنفاذ للخادم والأخطاء التي تحدث. root: يعيّن هذا الموجه مسار المجلد الجذر root، ويشكّل المسار الكامل لأي ملف مطلوب على نظام الملفات المحلي. يحدد الموجه fastcgi_pass أن الخدمة app تستمع إلى مقبس TCP على المنفذ "9000" وهذا يجعل خادم PHP-FPM يستمع عبر الشبكة بدلاً من مقبس Unix. على الرغم من تفوق مقبس Unix من حيث السرعة بصورةٍ طفيفة على مقبس TCP، إلا أنه لا يحتوي على بروتوكول شبكة وبالتالي يتخطى مكدس الشبكة. يناسب مقبس Unix الحالات التي يتواجد فيها أكثر من مضيف على جهاز واحد، ولكن في الحالات التي يكون لدينا خدمات تعمل على مجموعة موزعة من المضيفات، فيوفّر مقبس TCP ميزة السماح لك بالاتصال بالخدمات الموزعة. نظرًا لأن حاوية التطبيق app الخاصة تعمل على مضيف مختلف من حاوية webserver، يكون مقبس TCP أكثر ملاءمةً للضبط الذي نستخدمه. الخطوة 7- إعداد قاعدة بيانات MYSQL ننشئ ملف "my.cnf" في المجلد "mysql" الذي ربطناه بالملف "‎/etc/mysql/my.cnf" داخل الحاوية بالخطوة 2. يسمح حامل الربط هذا بتجاوز ملف "my.cnf" الأساسي عند الطلب واستخدام الملف الذي نجري التعديلات عليه. نضيف الإعدادات التالية إلى ملف "my.cnf" لتفعيل سجل الاستعلام العام وتحديد ملف السجل. ننشئ أولًا المجلد "mysql" بتنفيذ الأمر التالي: mkdir ~/laravel-app/mysql ومن ثم ننشئ الملف "my.cnf" بتنفيذ الأمر التالي: nano ~/laravel-app/mysql/my.cnf نضيف المحتوى التالي إلى الملف: [mysqld] general_log = 1 general_log_file = /var/lib/mysql/general.log نفعّل سجل الاستعلام بوضع القيمة 1 للخيار general_log ونحدد المكان الذي نريد حفظ السجل به بتحديد قيمة الخيار general_log_file. الخطوة 8- تعديل إعدادات البيئة وتشغيل الحاويات حددنا جميع الخدمات في ملف "docker-compose" وأنشأنا ملفات الضبط لهذه الخدمات وحان الوقت لتشغيل التطبيق. ننشئ نسخةً من الملف "env.example." الذي يولّده لارافيل افتراضيًا ونسمّي النسخة التي نعمل عليها حاليًا "env." بتنفيذ الأمر التالي: cp .env.example .env نعدل على الملف الذي جرى نسخه لنضع البيانات الخاصة بحاوية تطبيقنا باستخدام محرر النصوص المفضل: nano .env نبحث عن الكتلة التي تحدد الاتصال مع قاعدة البيانات DB_CONNECTION ونعدل ضمنها الحقول التالية: DB_HOST: عنوان حاوية قاعدة بيانات db. DB_DATABASE: اسم قاعدة بيانات لارافيل. DB_USERNAME: اسم المستخدم الذي نستخدمه لقاعدة البيانات، نستخدم "laraveluser" ويمكن استخدام أي اسم آخر نرغب به. DB_PASSWORD كلمة المرور للاتصال بقاعدة البيانات. ويكون ملف "env." بالشكل التالي: DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=laraveluser DB_PASSWORD=your_laravel_db_password احفظ التغييرات وأغلق المحرر. ننفذ الآن أمر بدء تشغيل جميع الحاويات وإنشاء وحدات التخزين وإعداد الشبكات وتوصيلها: docker-compose up -d تُحمّل جميع صور دوكر الضرورية عند تشغيل الأمر السابق لأول مرة، وتستغرق بعض الوقت إذا لم تكن موجودة مسبقًا على الجهاز المحلي، وبمجرد تحميل الصور وتخزينها يُنشئ compose الحاويات اللازمة. تضفي الراية d- الطابع الخفي على العملية وتشغّلها في الخلفية. نستعرض الحاويات التي تعمل في هذه اللحظة بتنفيذ الأمر: docker ps يظهر خرجٌ مشابه للخرج التالي ما لم توجد حاويات أخرى إضافية غير "app" و "webserver" و "db" ضمن البيئة: CONTAINER ID NAMES IMAGE STATUS PORTS c31b7b3251e0 db mysql:5.7.22 Up 2 seconds 0.0.0.0:3306->3306/tcp ed5a69704580 app digitalocean.com/php Up 2 seconds 9000/tcp 5ce4ee31d7c0 webserver nginx:alpine Up 2 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tc يُعد CONTAINER ID معرفًا فريدًا لكل حاوية ويعرض NAMES اسم الحاوية ويعرض IMAGE اسم الصورة ويوفر الحقل STATUS معلومات حول الحاوية فيما إذا كانت تعمل أو يُعاد تشغيلها أو متوقفة نهائيًا عن العمل. نستخدم الأمر docker-compose exec لتوليد مفتاح التطبيق لتطبيق لارافيل وننسخه للملف "env." ليضمن حماية جلسات المستخدم وتأمين البيانات المشفرة بتنفيذ ما يلي: docker-compose exec app php artisan key:generate نشغّل الأمر التالي: docker-compose exec app php artisan config:cache تُحمّل إعدادات الضبط إلى الملف "‎/var/www/bootstrap/cache/config.php" ضمن الحاوية، وبزيارة الرابط التالي "http://yourserverip" في المتصفح نرى الصفحة التالية: مع تشغيل الحاويات الخاصة بك ومعلومات الضبط في مكانها الصحيح، يمكننا الانتقال إلى تكوين معلومات المستخدم الخاصة بك لقاعدة بيانات "laravel" على حاوية "db". الخطوة 9- إنشاء مستخدم لقاعدة البيانات MySQL يُنشئ MySQL افتراضيًا حساب الجذر root لأغراض إدارية، إذ يتمتع هذا المستخدم بصلاحيات غير محدودة على خادم قاعدة البيانات. نتجنّب استخدام هذا الحساب عند التعامل مع قاعدة البيانات وبدلاً من ذلك ننشئ مستخدم قاعدة بيانات مخصص لقاعدة بيانات تطبيق لارافيل. ننفذ الأمر التالي في حاوية "db": docker-compose exec db bash نسجّل دخول الى حساب الجذر الخاص بقاعدة البيانات MySQL داخل الحاوية: root@c31b7b3251e0:/# mysql -u root -p نُدخل كلمة المرور المُعينة لحساب الجذر الخاص بقاعدة البيانات MySQL أثناء التثبيت في الملف "docker-compose". نتحقق من قاعدة البيانات "laravel" التي حددناها في الملف "docker-compose" بتنفيذ الأمر التالي: mysql> show databases; يظهر خرج يشابه الخرج التالي: +--------------------+ | Database | +--------------------+ | information_schema | | laravel | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) ننشئ حساب المستخدم الذي يُسمح له بالوصول إلى قاعدة البيانات ونسميه "laraveluser". نتأكد من تطابق الاسم وكلمة المرور مع الاسم وكلمة المرور الموجودين في الملف "env.": mysql> GRANT ALL ON laravel.* TO 'laraveluser'@'%' IDENTIFIED BY 'your_laravel_db_password'; نمسح الصلاحيات لنُعلم خادم MySQL بالتعديلات التي أجريناها: mysql> FLUSH PRIVILEGES; نخرج من واجهة الأوامر التفاعلية الخاصة بقاعدة البيانات MySQL والحاوية: mysql> EXIT; root@c31b7b3251e0:/# exit الخطوة 10- تهجير البيانات والعمل باستخدام طرفية Tinker نجح إعداد التطبيق إلا أنّ قاعدة البيانات لا تتضمن أية محتوى حتى الآن. نستطيع إدخال بعض المحتوى يدويًا أو الاستفادة من تهجير قواعد البيانات لملئها بمعلومات بصورةٍ سريعة. تُهجّر البيانات باستخدام طرفية tinker، التي تُشغّل الطرفية PsySH عند تحميل تطبيق لارافيل الأولي. تُستخدم الطرفية PsySH مثل واجهة تطوير في وقت التشغيل كما أنها تعمل مثل مصحح أخطاء تفاعلي للغة PHP. تُعد طرفية Tinker بيئة اختبار REPL خاصة لإطار العمل لارافيل. يسمح استخدام الأمر tinker بالتفاعل مع تطبيق لارافيل باستخدام سطر الأوامر في صدفة تفاعلية وتنفيذ الأوامر عليها مباشرةً. نختبر الاتصال بقاعدة البيانات MySQL عن طريق تشغيل أمر artisan migrate، الذي يُنشئ جدول تهجير في قاعدة البيانات داخل الحاوية ويتحقق ذلك بتنفيذ الأمر: docker-compose exec app php artisan migrate ويظهر الخرج الذي يؤكد نجاح التهجير بالشكل التالي: Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table ننفذ الاستعلام التالي للتحقق من وجود اتصال بقاعدة البيانات على نحوٍ صحيح باستخدام الأمر tinker: docker-compose exec app php artisan tinker اختبر اتصال MySQL عن طريق الحصول على البيانات التي هجّرناها للتو: \DB::table('migrations')->get(); يظهر خرج مشابه للخرج التالي مع نجاح العملية: => Illuminate\Support\Collection {#2856 all: [ {#2862 +"id": 1, +"migration": "2014_10_12_000000_create_users_table", +"batch": 1, }, {#2865 +"id": 2, +"migration": "2014_10_12_100000_create_password_resets_table", +"batch": 1, }, ], } تُستخدم tinker للتفاعل مع قواعد البيانات المختلفة وتنفيذ التجارب على النماذج والخدمات المرتبطة بها. الخاتمة أنشأنا في هذا المقال تطبيقًا برمجيًا باستخدام مكدس LEMP يعمل على الخادم المحلي واختبرناه من خلال الوصول إلى صفحة الترحيب في لارافيل وأنشأنا عملية تهجير لقاعدة بيانات MySQL. يمكن استخدام هذه الخطوات العملية في إنشاء تطبيق حقيقي يعتمد على المكونات السابقة. ترجمة وبتصرف للمقال How To Set Up Laravel, Nginx, and MySQL with Docker Compose لصاحبه Faizan Bashir. اقرأ أيضًا تثبيت وإعداد لارافيل Laravel على دوكر كومبوز Docker Compose كيفية تثبيت Docker Compose على دبيان تنصيب، إعداد واستخدام nginx كخادوم ويب
  14. نستطيع استخدام البوتات الآلية (يُطلق عليها اسم بوتات bots عندما تكون في الويب) لتقديم بيانات مخصصة للمستخدمين بناءً على طلباتهم، إذ يتيح إطارا عمل لارافيل Laravel وبوتمان Potman الأدوات اللازمة لإنشاء بوتات قادرة على تنفيذ هذه المهمة بسهولة. نعمل في هذا المقال على إنشاء بوت تلغرام لمحبي الكلاب باستخدام DOG API، ويمكن اختيار أي نوعٍ مختلفٍ من البيانات عند الرغبة. يظهر البوت عند الانتهاء من العمل كما في الشكل التالي: تثبيت لارافيل وبوتمان يُعد إطار عمل بوتمان مكتبةً خاصةً بلغة البرمجة PHP، وصُمِّمَت لتبسيط عملية تطوير بوتات مبتكرة لمنصات المراسلة المتعددة، مثل منصة سلاك Slack، وتلغرام، وإطار عمل مايكروسوفت بوت وNixmo وفيسبوك وغيرها. $botman->hears('Bot, What’s the best Web Development training website?', function (BotMan $bot) { $bot->reply('DigitalOcean for sure. Give me a harder question!!'); }); تثبيت بوتمان استوديو وفّر المطور مارسيل بوكيوت Marcel Pociot كثيرًا من الوقت على المطورين من خلال تطويره برنامج بوتمان استوديو Botman Studio بالاعتماد على لارافيل مع بوتمان لنحصل على برنامج سهل الاستخدام محدّث باستمرار. ننشئ مشروعًا جديدًا ضمن بوتمان استوديو بتنفيذ التعليمة التالية في موجه الأوامر: composer create-project --prefer-dist botman/studio ilovedogs نتحقق من نجاح عملية التثبيت بتنفيذ التعليمة التالية في موجه الأوامر: php artisan botman:tinker يمكن إدخال الكلمة "Hi" في موجه الأوامر ليظهر الرد بعبارة "Hello" في حالة العمل الصحيح كما هو موضح بالشكل التالي: إنشاء الأوامر يتميز البوت الذي ننشئه بالقدرة على الرد على أنواع مختلفة من الرسائل والأوامر التي تصله، أي أنه يستطيع التعامل مع هذه الحالات: إرسال صورة عشوائية للكلاب من جميع السلالات. إرسال صورة عشوائية للكلب حسب سلالته. إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية. إجراء محادثة وتقديم المساعدة. الاستجابة للأوامر غير المعروفة. لتحقيق هذه الوظائف، نفرغ محتوى الملف "routes/botman.php" لأننا سنضيف له محتوى جديد كليًا ويجب إزالة المحتوى القديم لعدم حصول تعارض. إرسال صورة عشوائية للكلاب من جميع السلالات نحصل على صورة كلب عشوائي من البوت بإرسال الأمر "random/" ونعدل على النص البرمجي في ملف "routes/botman.php" ليصبح كما يلي: <?php use App\Conversations\StartConversation; $botman = resolve('botman'); $botman->hears('/random', 'App\Http\Controllers\AllBreedsController@random'); ننشئ المتحكم باستخدام التعليمة التالية: php artisan make:controller AllBreedsController نكتب الشيفرة البرمجية التالية في المتحكم الذي أنشأناه: <?php namespace App\Http\Controllers; use App\Services\DogService; use App\Http\Controllers\Controller; class AllBreedsController extends Controller { /** * الباني الخاص بالمتحكم * * @return void */ public function __construct() { $this->photos = new DogService; } /** * إعادة صورة عشوائية لكلب من إحدى السلالات * * @return void */ public function random($bot) { // $this->photos->random() يمثل رابط الصورة ‫URL التي تعيدها هذه الخدمة‫‪ // $bot->reply تمثل ما نستخدمه لإرسال الصورة إلى المستخدم $bot->reply($this->photos->random()); } } ننشئ عينةً من الصنف DogService الموجود ضمن الملف "app//services/DogService.php" ليكون مسؤولاً عن الاستجابة لاستدعاءات الواجهة البرمجية API الخاصة بجلب الصور ونضع به الشيفرة البرمجية التالية: <?php namespace App\Services; use Exception; use GuzzleHttp\Client; class DogService { // عنوان الوجهة التي سنحصل منها على صورة الكلاب const RANDOM_ENDPOINT = 'https://dog.ceo/api/breeds/image/random'; /** * Guzzle client. * * @var GuzzleHttp\Client */ protected $client; /** * DogService constructor * * @return void */ public function __construct() { $this->client = new Client; } /** * إحضار وإعادة صورة كلب عشوائية من إحدى السلالات * * @return string */ public function random() { try { // التي استلمناها JSON فك ترميز استجابة $response = json_decode( // التي تعيد الجسم الخاص بالاستجابة API استدعاء $this->client->get(self::RANDOM_ENDPOINT)->getBody() ); // إعادة رابط الصورة return $response->message; } catch (Exception $e) { // نستخدم هذا السطر لإعادة رسالة الخطأ للمستخدم في حال وقوع مشكلة ما. return 'An unexpected error occurred. Please try again later.'; } } } إرسال صورة عشوائية للكلب حسب سلالته نكرر العملية السابقة ولكن نضيف الأمر ‎/b {breed}‎، ونعدل الملف "routes/botman.php" بإضافة السطر البرمجي التالي: botman->hears('/b {breed}', 'App\Http\Controllers\AllBreedsController@byBreed'); نضيف ما يلي على المتحكم AllBreedsController الذي أنشأناه مسبقًا: /** * إعادة صورة كلب من سلالة محددة * * @return void */ public function byBreed($bot, $name) { // نترك أمر معالجة استدعاء الواجهة البرمجية إلى صنف الخدمة ونرد على الطلب القادم بالنتيجة فور وصولها إلينا $bot->reply($this->photos->byBreed($name)); } نضيف التابع byBreed إلى الصنف DogService الذي أنشأناه على النحو التالي: /** * جلب وإعادة صورة عشوائية من سلالة محددة * * @param string $breed * @return string */ public function byBreed($breed) { try { // لدى الطرف الآخر باسم الصنف المحدد %s نستبدل $endpoint = sprintf(self::BREED_ENDPOINT, $breed); $response = json_decode( $this->client->get($endpoint)->getBody() ); return $response->message; } catch (Exception $e) { return "Sorry I couldn\"t get you any photos from $breed. Please try with a different breed."; } } يجب إضافة نقطة النهاية const المُستخدمة أعلاه إلى نفس الملف على النحو التالي: // نقطة النهاية التي سنصل إليها للحصول على صورة عشوائية باسم سلالة معطى const BREED_ENDPOINT = 'https://dog.ceo/api/breed/%s/images/random'; إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية نضيف الأمر ‎/s {breed}:{subBreed}‎ من أجل السلالات الفرعية على النحو التالي: botman->hears('/s {breed}:{subBreed}', 'App\Http\Controllers\SubBreedController@random'); ننشئ متحكمًا جديدًا : php artisan make:controller SubBreedController نعرّف التابع random على النحو التالي: <?php namespace App\Conversations; use App\Services\DogService; use App\Http\Controllers\Controller; class SubBreedController extends Controller { /** * التابع الباني للمتحكم * * @return void */ public function __construct() { $this->photos = new DogService; } /** * إعادة صورة عشوائية لكلب من إحدى السلالات * * @return void */ public function random($bot, $breed, $subBreed) { $bot->reply($this->photos->bySubBreed($breed, $subBreed)); } } يجب إضافة نقطة الاتصال النهائية والتابع الذي حدثنا محتواه إلى الصنف DogService: // تعيد نقطة الاتصال النهائية صورة عشوائية لكلب من سلالة محددة وسلالة فرعية محددة const SUB_BREED_ENDPOINT = 'https://dog.ceo/api/breed/%s/%s/images/random'; /** * جلب وإعادة صورة عشوائية لصورة عشوائية من سلالة معينة وسلالة فرعية * * @param string $breed * @param string $subBreed * @return string */ public function bySubBreed($breed, $subBreed) { try { $endpoint = sprintf(self::SUB_BREED_ENDPOINT, $breed, $subBreed); $response = json_decode( $this->client->get($endpoint)->getBody() ); return $response->message; } catch (Exception $e) { return "Sorry I couldn\"t get you any photos from $breed. Please try with a different breed."; } } إجراء محادثة وتقديم المساعدة لا نحبّذ الرد على كلمات رئيسية مفردة عند برمجة بوت الدردشة، وإنما نجمع معلومات المستخدمين من خلال المحادثة، بحيث يتعامل بوت الدردشة مع كل مستخدم بصورةٍ مناسبة تتوافق مع بياناته. لتحقيق ذلك نضيف الى الملف "routes/botman.php" ما يلي: botman->hears('Start conversation', 'App\Http\Controllers\ConversationController@index'); ننشئ متحكمًا جديدًا: php artisan make:controller ConversationController نعرّف التابع index ضمن الصنف على النحو التالي: <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Conversations\DefaultConversation; class ConversationController extends Controller { /** * إنشاء محادثة جديدة * * @return void */ public function index($bot) { // التي يوفرها إطار العمل بوتمان لبدء محادثة جديدة startConversation نستخدم التابع $bot->startConversation(new DefaultConversation); } } إذا كنا نستخدم بوتمان ستوديو، نجد مجلد باسم "Conversations" ضمن مجلد التطبيق، لذلك ننشئ داخل هذا المجلد ملفًا جديدًا ونسميه "DefaultConversation.php" ونضع فيه المحتوى التالي: <?php namespace App\Conversations; use BotMan\BotMan\Messages\Incoming\Answer; use BotMan\BotMan\Messages\Outgoing\Question; use BotMan\BotMan\Messages\Outgoing\Actions\Button; use BotMan\BotMan\Messages\Conversations\Conversation; class DefaultConversation extends Conversation { /** * بدء المحادثة بالسؤال الاول * * @return void */ public function defaultQuestion() { // نبدأ المحادثة بإضافة السؤال الأول ونضبط الخيارات المتاحة للإجابة على هذا السؤال $question = Question::create('Huh - you woke me up. What do you need?') ->addButtons([ Button::create('Random dog photo')->value('random'), Button::create('A photo by breed')->value('breed'), Button::create('A photo by sub-breed')->value('sub-breed'), ]); // نسأل المستخدم السؤال الذي أعددناه return $this->ask($question, function (Answer $answer) { // نفحص إذا كان المستخدم قد كتب عبارة ما أم ضغط على أحد الخيارات if ($answer->isInteractiveMessageReply()) { // نقارن جواب المستخدم مع الإجابات المعدة مسبقًا switch ($answer->getValue()) { case 'random': $this->say((new App\Services\DogService)->random()); break; case 'breed': $this->askForBreedName(); break; case 'sub-breed': $this->askForSubBreed(); break; } } }); } /** * السؤال عن سلالة الكلب وسلالته الفرعية * * @return void */ public function askForBreedName() { $this->ask('What\'s the breed name?', function (Answer $answer) { $name = $answer->getText(); $this->say((new App\Services\DogService)->byBreed($name)); }); } /** *طلب اسم السلالة وإرسال الصورة * * @return void */ public function askForSubBreed() { $this->ask('What\'s the breed and sub-breed names? ex:hound:afghan', function (Answer $answer) { $answer = explode(':', $answer->getText()); $this->say((new App\Services\DogService)->bySubBreed($answer[0], $answer[1])); }); } /** * بدء المحادثة * * @return void */ public function run() { // يُعد هذه التابع إقلاعي فهو ما سيجري تنفيذه أولًا $this->defaultQuestion(); } } الاستجابة للأوامر غير المعروفة تُستخدم هذه الحالة عندما يرسل المستخدم رسالةً لا يتعرف عليها البوت فلا بد من إعلامه بإعادة طلبه على نحوٍ صحيح. نضيف إلى الملف "routes/botman.php" السطر البرمجي التالي: botman->fallback('App\Http\Controllers\FallbackController@index'); ننشئ متحكمًا جديدًا على النحو التالي: php artisan make:controller FallbackController نضيف الرسالة التي يراها المستخدم عند إرساله لأمر غير معروف: <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; class FallbackController extends Controller { /** * الإجابة برسالة عامة * * @param Botman $bot * @return void */ public function index($bot) { $bot->reply('Sorry, I did not understand these commands. Try: \'Start Conversation\''); } } اختبار البوت إرسال صورة عشوائية للكلاب من جميع السلالات. إرسال صورة عشوائية للكلب حسب سلالته. إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية. إجراء محادثة وتقديم المساعدة. الاستجابة للأوامر غير المعروفة. تثبيت برنامج تشغيل تلغرام بعد الانتهاء من تطوير التطبيق يجب دمجه مع برنامج تلغرام، ولتحقيق ذلك نحتاج برنامج تشغيل التلغرام Telegram driver الذي يقدمه بوتمان والذي نحصل عليه بتنفيذ الأمر: composer require botman/driver-telegram إنشاء بوت تلغرام نفتح تطبيق تلغرام ونبحث عن BotFather ونكتب "‎/newbot" وندخل اسم مستخدم البوت كما في الشكل: نضيف الرمز إلى ملف "env." ونستبدل YOUR_TOKEN بالرمز المميز Token الذي يقدمه تلغرام: TELEGRAM_TOKEN=YOUR_TOKEN تثبيت وتشغيل الأداة ngrok يتطلّب التلغرام استخدام رابط URL صالح وآمن لإعداد الخطافات webhooks وتلقي الرسائل من المستخدمين، ولتحقيق ذلك نستخدم ngrok أو نضع التطبيق على خادم ونُعِد له شهادة SSL، ولكن لسهولة التنفيذ سنستخدم ngrok. نستطيع الحصول عليه من الموقع الرسمي باختيار النسخة المناسبة لنظام التشغيل الذي سنعمل عليه. ننتقل إلى مجلد التطبيق وننفّذ التعليمة: php artisan serve ننتقل إلى المجلد الذي ثبتنا البرنامج ضمنه ونشغل الأداة ngrok بتنفيذ الأمر التالي: /ngrok http 8000 ربط البوت بالتلغرام نربط تطبيقنا ببوت التلغرام الذي أنشأناه مسبقاً بإرسال طلب من نوع POST إلى عنوان الرابط هذا وتمرير عنوان الرابط الذي ولّده ngrok: https://api.telegram.org/bot{TOKEN}/setWebhook نستخدم برنامج بوستمان أو أداة "CURL" لتحقيق ذلك على النحو التالي: curl -X POST -F 'url=https://{YOU_URL}/botman' https://api.telegram.org/bot{TOKEN}/setWebhook يصل الرد التالي بصيغة JSON في حال نجاح العملية: { "ok": true, "result": true, "description": "Webhook was set" } الاختبار باستخدام تلغرام إرسال صورة عشوائية للكلاب من جميع السلالات. إرسال صورة عشوائية للكلب حسب سلالته. إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية. إجراء محادثة وتقديم المساعدة. الاستجابة للأوامر غير المعروفة. الخاتمة قدم هذا المقال طريقةً لتطوير بوت وربطه بإحدى وسائل التواصل الاجتماعي الشهيرة وهي التلغرام، إذ يمكن الاعتماد على إطار العمل بوتمان للربط مع العديد من وسائل التواصل الاجتماعي لتطوير بوت قادر على الاتصال بشريحة واسعة من المستخدمين، كما تضمن المقال خطوات تحديد الأوامر المتاحة للبوت ليتخاطب بها مع المستخدمين وطريقة التعامل مع الحالات الخاصة. ترجمة -وبتصرف- للمقال How To Build a Telegram Bot with Laravel and BotMan لصاحبه Rachid Laasri. اقرأ أيضًا استخدام قوالب Blade لإنشاء عروض Laravel تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder
  15. يُعرّف الاحتواء ضمن حاوية على أنها عملية تكييف التطبيق ومكوناته لتصبح قادرةً على العمل ضمن بيئة بسيطة أساسية المقومات ندعوها الحاوية لتشكّل بيئةً معزولةً يمكن للمستخدم إزالتها بسهولة وسرعة عندما تنتهي حاجته منها أو عندما يرغب بتعديل بعضًا من أجزائها، كما يمكن الاستفادة منها لتطوير واختبار ونشر التطبيقات ضمن بيئات الإنتاج. نعمل في هذا المقال على استخدام الأداة دوكر كومبوز Docker Compose لاحتواء تطبيق لارافيل لتطويره ضمن بيئة مستقلة خاصة به. نحصل على تطبيق لارافيل توضيحي موزّع على ثلاث حاويات خدمة معزولة عن بعضها يعضًا على النحو التالي: خدمة تطبيق "app" تعمل على PHP7.4-FPM. خدمة قاعدة بيانات "db" تحتوي خادم MySQL 5.7. خدمة "nginx" تستخدم خدمة "app" من أجل تحليل شيفرة برمجية بلغة PHP قبل تقديم تطبيق لارافيل للمستخدم النهائي. تُستخدم وحدات التخزين المشتركة Shared Volumes من أجل مزامنة ملفات التطبيق وذلك لتطوير تطبيق بسيط وتصحيح الأخطاء بسهولة؛ كما تُستخدم أوامر docker-compose exec لتشغيل تعليمات Composer و artisan في حاوية التطبيق. المتطلبات الأساسية الوصول إلى حاسب يعمل بنظام التشغيل لينكس أوبنتو Ubuntu ذي رقم إصدار 20.04 أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo ولا يفضل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم، كما يُفضل وجود جدار حماية firewall مثبت ونشط في حال استخدام خادم بعيد. تثبيت الأداة دوكر على الخادم أو الجهاز المحلي. تثبيت الأداة دوكر كومبوز Docker Compose على الخادم أو الجهاز المحلي. الخطوة 1- الحصول على التطبيق التوضيحي نبدأ بتنزيل تطبيق لارافيل التوضيحي من مخزن غيت هب Github وننتقل إلى الفرع tutorial-01، الذي يتضمن تطبيقًا بسيطًا مبنيًا باستخدام لارافيل. نعتمد في هذا العمل على الإصدار tutorial-1.0.1 والذي نحملّه ضمن المجلد الأساسي للمستخدم بتنفيذ الأمر: cd ~ curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip يبدأ تنزيل الملف المضغوط بصيغة "zip" لذلك يجب عند انتهاء التحميل فك الضغط باستخدام الأمر unzip بعد التأكد من تحديث الحزم الخاصة بنظام التشغيل ما لم تكن محدّثة مؤخرًا. ننفذ الأمر التالي: sudo apt update sudo apt install unzip ننفذ الأوامر التالي لفك ضغط الملف الذي حملناه ونعيد تسمية المجلد لاسم مناسب لسهولة الوصول إليه: unzip travellist.zip mv travellist-laravel-demo-tutorial-1.0.1 travellist-demo ننتقل إلى المجلّد "travellist-demo" بتنفيذ الأمر: cd travellist-demo الخطوة 2- إعداد ملف الضبط الخاص بالتطبيق نجد عادةً ملفات الضبط الخاصة بلارافيل ضمن المجلد "config" داخل المجلد الجذر للتطبيق. يحتوي الملف "env." معلومات الضبط المتعلقة بالبيئة، مثل بيانات الاعتماد وكلمات المرور وأية معلومات تختلف بين عمليات نشر التطبيقات، لذلك لا يُضمّن هذا الملف ضمن ملفات التحكم بالإصدارات لكي لا تنتشر هذه المعلومات لجميع المستخدمين الذين يستخدمون صورة التطبيق لاحقًا. تحذير: يحتوي ملف تهيئة البيئة على معلومات حساسة حول الخادم، بما في ذلك بيانات اعتماد قاعدة البيانات ومفاتيح الأمان، لهذا السبب لا يجب أبدًا مشاركة هذا الملف علنًا. توجد أولويةٌ للقيم الموجودة في الملف "env." على القيم الموجودة في ملفات التهيئة الأخرى الموجودة في المجلد "config". تتطلب كل عملية تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف معلومات جديدة، مثل إعدادات الاتصال في قاعدة البيانات وخيارات التصحيح ورابط للتطبيق، إضافةً إلى بقية العناصر أو المعلومات التي تختلف تبعًا للبيئة التي يعمل بها التطبيق. ننشئ ملف "env." جديد لضبط خيارات التهيئة لبيئة التطوير التي نُعدها، ويمكننا نسخ الملف "example.env" المتاح افتراضيًا مع أي تطبيق لارافيل بتنفيذ الأمر: cp .env.example .env نحرر الملف باستخدام محرر النصوص نانو nano أو باختيار محرر النصوص المفضّل: nano .env يحتوي ملف "env." الحالي من تطبيق "travellist" التوضيحي على إعدادات لاستخدام التطبيق المُحتَوى المتصل بقاعدة بيانات MySQL محلية أي أنها متاحة على المضيف المحلي "127.0.0.1". نحتاج لتعديل قيمة المتغير DB_HOST لكي يشير إلى قاعدة البيانات التي ننشئها ضمن بيئة دوكر. نعتمد في عملنا على أنّ اسم خدمة قواعد البيانات هو db. نعدّل محتوى الملف لضبط قيم المتغيرات على النحو التالي: APP_NAME=Travellist APP_ENV=dev APP_KEY= APP_DEBUG=true APP_URL=http://localhost:8000 LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=travellist DB_USERNAME=travellist_user DB_PASSWORD=password ... نستطيع تغيير القيم الخاصة ببقية المتغيرات، مثل اسم قاعدة البيانات وكلمة المرور واسم المستخدم الذين سيُستخدمان عند إعداد الملف "docker-compose.yml" من أجل تهيئة الخدمات. نضغط على الاختصار "CTRL+X" ثم الحرف "Y" وأخيرًا زر الإدخال "Enter" بعد الانتهاء من تعديل الملف. الخطوة 3 - إعداد ملف دوكر الخاص بالتطبيق تستند خدمتا MySQL و Nginx على الصور الافتراضية التي يمكن الحصول عليها من Docker Hub، لكن سنحتاج في مثالنا إلى إنشاء صورة مخصصة لحاوية التطبيق وسننشئ ملف Dockerfile جديد لذلك. تعتمد صورة التطبيق travillist على صورة PHP الرسمية ذات الاسم php:7.4-fpm والمتاحة ضمن مخزن دوكر هب Docker Hub. نحتاج تثبيت بعض حزم PHP الإضافية باستخدام أداة إدارة الاعتمادية Composer. ننشئ مستخدم نظام جديد لتنفيذ الأوامر المختلفة مثل أوامر"Composer" و "artisan" أثناء تطوير التطبيق. يضمن إعداد "uid" امتلاك المستخدم الموجود داخل الحاوية نفس معرف المستخدم الخاص بمستخدم النظام على الجهاز المضيف أثناء تشغيل دوكر. تتزامن الملفات التي تُنشأ من الأوامر في جهاز المضيف باستخدام الأذونات الصحيحة، ونستطيع استخدام أي محرر نصوص لتطوير الشيفرة البرمجية للتطبيق داخل الحاويات. ننشئ ملف Dockerfile جديد بتنفيذ الأمر: nano Dockerfile ننسخ المحتوى التالي إلى ملف Dockerfile: FROM php:7.4-fpm # Arguments defined in docker-compose.yml ARG user ARG uid # Install system dependencies RUN apt-get update && apt-get install -y \ git \ curl \ libpng-dev \ libonig-dev \ libxml2-dev \ zip \ unzip # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install PHP extensions RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Create system user to run Composer and Artisan Commands RUN useradd -G www-data,root -u $uid -d /home/$user $user RUN mkdir -p /home/$user/.composer && \ chown -R $user:$user /home/$user # Set working directory WORKDIR /var/www USER $user نحفظ الملف بعد الانتهاء من التعديل عليه. يبدأ الملف بتحديد الصورة الأساس التي نستخدمها وهي في حالة الملف السابق php:7.4-fpm. نثبت أداة Composer بنسخ الشكل التنفيذي الخاص بالأمر "composer" والمتاح ضمن أحدث صورة رسمية إلى صورة التطبيق الخاص بنا. ننشئ مستخدم نظام جديد ونبدأ بإعداد المتغيرينuser و uid الذين عرّفناهما في بداية الملف Dockerfile، إذ تُمرَّر هذه المتغيرات إلى الحاوية باستخدام الأداة دوكر كومبوز في وقت البناء. نحدد مسار العمل الافتراضي "var/www/" ونسجّل الدخول بواسطة المستخدم الذي أنشأناه مؤخرًا للتأكد من الاتصال بقاعدة البيانات بصفة مستخدم عادي وأننا في المسار الصحيح عند استخدام الأوامر المختلفة، مثل أوامر"composer" و "artisan" في حاوية التطبيق. الخطوة 4 - إعداد ضبط Nginx وملفات إفراغ قاعدة البيانات يجب مشاركة ملفات الضبط والتهيئة مع حاويات الخدمة عند إنشاء بيئة تطوير باستخدام أداة دوكر كومبوزلإعداد أو التمهيد لهذه الخدمات، إذ يسهّل ذلك إجراء التعديلات على ملفات الضبط وضبط البيئة أثناء تطوير التطبيق. ننشئ مجلد ونضع به الملفات التي تستخدم في تهيئة وبناء حاويات الخدمة. ننشئ مجلد "docker-compose/nginx" ونضع به ملف "travellist.conf" الذي يهيئ آلية تقديم التطبيق وذلك بتنفيذ الأمر التالي: mkdir -p docker-compose/nginx نعدّل محتوى الملف "travellist.conf" باستخدام محرر النصوص المفضل عبر تنفيذ الأمر التالي: nano docker-compose/nginx/travellist.conf نضيف الشيفرة البرمجية التالية داخله: server { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } } يضبط الملف السابق خادم Nginx ويجبره على الاستماع للمنفذ 80 ويستخدم الصفحة index.php لتكون صفحة الدليل الأساسية للتطبيق. نضبط المسار الجذر Root للمستند ليصبح "‎/var/www/public" ونضبط خادم Nginx ونجبره على استخدام المنفذ "9000" لمعالجة الملفات ذات اللاحقة "php.*". احفظ الملف وأغلقه عند الانتهاء من التعديل. سنشارك من أجل إكمال إعداد قاعدة البيانات MYSQL ملفًا يتضمن محتوى قاعدة البيانات database dump، الذي سيُستورد محتواه إلى قاعدة البيانات عندما نهيئ الحاوية لأول مرة، وتتوفر هذه الميزة في MySQL 5.7 التي نستخدمها في حاوية التطبيق. ننشئ مجلدًا جديدًا لتهيئة ملفات قاعدة البيانات MySQL داخل المجلد "docker-compose" بتنفيذ الأمر التالي: mkdir docker-compose/mysql ننشئ ملف "sql." جديد بتنفيذ الأمر: nano docker-compose/mysql/init_db.sql يعتمد ملف قاعدة البيانات MySQL dump التالي على قاعدة البيانات المُنشأة في دليل لارافيل بالاعتماد على LEMP، إذ يُنشئ جدولًا اسمه places في قاعدة البيانات ثم سيملأ محتوياته بمجموعة من العينات. اكتب الشيفرة البرمجية التالية في الملف "db_init.sql" ليصبح بالشكل التالي: DROP TABLE IF EXISTS `places`; CREATE TABLE `places` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `visited` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0); يتضمن الجدول places ثلاثة حقول id و name و visited وهي على الترتيب معرّف خاص بكل مكان واسم المكان ومتغير يشير إلى زيارة المكان مسبقًا أم لا، ويمكن تعديل أسماء الحقول وإضافة حقول جديدة عند الحاجة. الخطوة 5 - إنشاء بيئة متعددة الحاويات بواسطة دوكر كومبوز تُنشئ الأداة دوكر كومبوز بيئات متعددة الحاويات للتطبيقات التي تعمل على دوكر، كما تستخدم تعريفات الخدمة لبناء بيئات قابلة للتخصيص بالكامل مع حاويات متعددة يمكنها مشاركة الشبكات وأحجام البيانات، مما يتيح التكامل السلس بين مكونات التطبيق المختلفة. ننشئ ملفًا جديدًا يسمى "docker-compose.yml"، والذي يمكن أن يكون موجودًا مسبقًا في مجلد الجذر للتطبيق، إذ يحدد هذا الملف بيئة الحاويات بما في ذلك الصور الأساسية لبناء التطبيق وكيفية تفاعل الخدمات ضمنه. نحدد ثلاث خدمات مختلفة ضمن ملف "docker-compose.yml"، هي: "app" و "db" و "nginx"؛ إذ تُنشئ خدمة "app" صورةً تسمى "travellist" بناءً على ملف Dockerfile الذي أنشأناه سابقًا، وتُشغّل الحاوية التي تحددها هذه الخدمة خادم "php-fpm" لتحليل شيفرات PHP وتُرسل النتائج مرةً أخرى إلى خدمة "nginx، التي تعمل على حاوية منفصلة. تحدد خدمة "mysql" حاويةً تُشغل خادم MySQL 5.7. تتصل هذه الخدمات فيما بينها باستخدام شبكة جسر أسميناها "travellist". تُزامن ملفات التطبيق على كل من الخدمتين "app" و "nginx" عبر حوامل الربط، التي تُعد مفيدةً في بيئات التطوير لأنها تتيح مزامنةً ثنائية الاتجاه بين الجهاز المضيف والحاويات. نُنشئ ملفًا جديدًا باسم "docker-compose.yml" في مجلد الجذر للتطبيق بتنفيذ الأمر: nano docker-compose.yml يبدأ ملف "docker-compose.yml" التقليدي برقم الإصدار يليها تعريف الخدمات "services" الخاصة بالتطبيق، كما تُعرَّف الشبكات التي يشاركها التطبيق في نهاية الملف. إذًا، يكون محتوى هذا الملف كما يلي: version: "3.7" services: networks: travellist: driver: bridge سنعدّل الآن عقدة "services" لتتضمن خدمات "app" و "db" و "nginx". خدمة التطبيق app تُعِد خدمة "app" حاويةً باسم "travellist-app" وتبني صورة دوكر جديدة بناءً على Dockerfile الموجود في نفس مسار الملف "docker-compose.yml" وتُحفظ الصورة محليًا باسم "travellist". نحتاج تواجد ملفات التطبيق ضمن حاوية التطبيق "app" حتى ولو كانت هذه الملفات موجودةً في جذر المستند الذي جرى تقديمه على أنه تطبيق موجود في حاوية "nginx"، ونحتاج ذلك من أجل تنفيذ أوامر "artisan" الخاصة بإطار عمل لارافيل على هذه الملفات. نضيف البيانات التالية إلى الملف "docker-compose.yml": app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: travellist container_name: travellist-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - travellist تحقق هذه الإعدادات ما يلي: build: يعلِم هذا الضبط أداة دوكر كومبوز ببناء صورة محلية لخدمة التطبيق، باستخدام المسار المحدد context وملف Dockerfile للحصول على التعليمات. تُحقن المتغيرات user و uid في ملف Dockerfile لتخصيص أوامر إنشاء المستخدم في وقت الإنشاء. image: تُعدّ الاسم الذي يستخدم الصورة قيد الإنشاء. container_name: تُعِدّ اسم الحاوية لهذه الخدمة. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقافٌ الخدمة. working_dir: يعيّن المجلّد الافتراضي لهذه الخدمة، مثل "‎/var/www". volumes: يُنشئ وحدة تخزين مشتركة تُزامِن المحتويات من المسار الحالي إلى "‎/var/www" داخل الحاوية، ويبقى موجودًا في حاوية "nginx". networks: تُعِدّ هذه الخدمة لاستخدام شبكة باسم "travellist". خدمة قاعدة البيانات db تستخدم خدمة "db" صورة MySQL 5.7 من مخزن دوكر هب. تحمّل الأداة دوكر كومبوز الملفات المتغيرة "env." الموجودة في نفس المسار الذي يحتوي الملف "docker-compose.yml"، ونحصل على إعدادات قاعدة البيانات ملف "env." الذي قد ولّدناه عند إنشاء تطبيق لارافيل. نضع البيانات التالية بعد البيانات التي وضعناها للخدمة "app": db: image: mysql:5.7 container_name: travellist-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - travellist تحقق هذه الإعدادات ما يلي: image: تحدد صورة دوكر التي ستستخدم في هذه الحاوية. نستخدم صورة MySQL 5.7 من دوكر هب Docker Hub. container_name: اسم الحاوية travellist-db. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقاف للخدمة. environment: تُحدد متغيرات البيئة في الحاوية الجديدة. نستخدم القيم التي حصلنا عليها من ملف "env." لإعداد خدمة قاعدة البيانات MySQL والتي تنشئ تلقائيًا قاعدة بيانات ومستخدمًا جديدًا بناءً على متغيرات البيئة المتوفرة. volumes: ينشئ وحدة تخزين لتهيئة قاعدة بيانات التطبيق. تستورد صورة MySQL ملفات"sql." تلقائيًا والتي توجد في المسار ‎/docker-entrypoint-initdb.d داخل الحاوية. network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. الخدمة nginx تستخدم خدمة "nginx" صورة Nginx مبنية مسبقًا على توزيعة لينكس اسمها Alpine. تنشئ حاوية باسم "travellist-nginx" وتُعيد التوجيه من المنفذ "8000" الى المنفذ "80" داخل الحاوية. نضع البيانات التالية بعد بيانات خدمة "db": nginx: image: nginx:1.17-alpine container_name: travellist-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d networks: - travellist تحقق هذه الإعدادات ما يلي: image: اسم صورة دوكر التي تستخدم في هذه الحاوية وهي في هذه الحالة الصورة Alpine Nginx 1.17 . container_name: اسم الحاوية travellist-nginx. restart: يعيد التشغيل دائمًا، ما لم يحدث إيقافٌ للخدمة. ports: تعيد توجيه المنفذ الذي يسمح بالوصول الخارجي عبر المنفذ 8000 إلى خادم الويب الذي يعمل على المنفذ 80 داخل الحاوية. volumes: تنشئ وحدتي تخزين مشتركتين، بحيث تزامن الوحدة الأولى المحتويات من نقطة العمل إلى المسار ‎/var/www داخل الحاوية ويفيد ذلك بنقل التعديلات المحلية إلى التطبيق الذي يقدّمه Nginx تلقائيًا. تنسخ الوحدة الثانية ملفات الإعداد الخاصة بخدمة nginx الموجودة في الملف "docker-compose/nginx/travellist.conf" الى ملفات الإعداد الخاصة بخدمة nginx ضمن الحاوية. network: تُعِد هذه الخدمة لاستخدام شبكة باسم travellist. وعليه يصبح ملف "docker-compose.yml" على الشكل التالي: version: "3.7" services: app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: travellist container_name: travellist-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - travellist db: image: mysql:5.7 container_name: travellist-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - travellist nginx: image: nginx:alpine container_name: travellist-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d/ networks: - travellist networks: travellist: driver: bridge نتأكد من حفظ الملف بعد الانتهاء من إجراء التعديلات السابقة. الخطوة 6 - تشغيل التطبيق عبر أداة دوكر كومبوز ننشئ صورة تطبيق جديد ونشغّل الخدمات التي حددناها ضمن الإعدادات باستخدام الأمر التالي: docker-compose build app يستغرق الأمر بضعة دقائق، ثم يظهر الخرج التالي: Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in f71eb33b7459 Removing intermediate container f71eb33b7459 ---> 533c30216f34 Step 3/11 : ARG uid ---> Running in 60d2d2a84cda Removing intermediate container 60d2d2a84cda ---> 497fbf904605 Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev ... Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> e499f74896e3 Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user ---> Running in 232ef9c7dbd1 Removing intermediate container 232ef9c7dbd1 ---> 870fa3220ffa Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user ---> Running in 7ca8c0cb7f09 Removing intermediate container 7ca8c0cb7f09 ---> 3d2ef9519a8e Step 10/11 : WORKDIR /var/www ---> Running in 4a964f91edfa Removing intermediate container 4a964f91edfa ---> 00ada639da21 Step 11/11 : USER $user ---> Running in 9f8e874fede9 Removing intermediate container 9f8e874fede9 ---> fe176ff4702b Successfully built fe176ff4702b Successfully tagged travellist:latest نُشغّل البيئة بالخلفية بعد الانتهاء من مرحلة الإنشاء بتنفيذ الأمر: docker-compose up -d ويكون الخرج على النحو التالي: Creating travellist-db ... done Creating travellist-app ... done Creating travellist-nginx ... done نستعرض معلومات حالة الخدمة النشطة حاليًا بتنفيذ الأمر: docker-compose ps ويكون الخرج على النحو التالي: Name Command State Ports -------------------------------------------------------------------------------- travellist-app docker-php-entrypoint php-fpm Up 9000/tcp travellist-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp travellist-nginx /docker-entrypoint.sh ngin ... Up 0.0.0.0:8000->80/tcp أصبحت البيئة الآن جاهزة للعمل، ولكن يجب تنفيذ بعض الأوامر قبل انتهاء إعداد التطبيق كاملًا. نستخدم الأمر docker-compose exec لتنفيذ جميع الأوامر ضمن الحاويات، فلو رغبنا بتنفيذ الأمر ls –l الذي يظهر معلومات مفصلة حول الملفات في مسار التطبيق، ننفذ الأمر التالي: docker-compose exec app ls -l وسيكون خرج شبيهًا بالخرج التالي: total 260 -rw-rw-r-- 1 sammy sammy 737 Jun 9 11:19 Dockerfile -rw-rw-r-- 1 sammy sammy 101 Jan 7 08:05 README.md drwxrwxr-x 6 sammy sammy 4096 Jan 7 08:05 app -rwxr-xr-x 1 sammy sammy 1686 Jan 7 08:05 artisan drwxrwxr-x 3 sammy sammy 4096 Jan 7 08:05 bootstrap -rw-rw-r-- 1 sammy sammy 1501 Jan 7 08:05 composer.json -rw-rw-r-- 1 sammy sammy 179071 Jan 7 08:05 composer.lock drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 config drwxrwxr-x 5 sammy sammy 4096 Jan 7 08:05 database drwxrwxr-x 4 sammy sammy 4096 Jun 9 11:19 docker-compose -rw-rw-r-- 1 sammy sammy 965 Jun 9 11:27 docker-compose.yml -rw-rw-r-- 1 sammy sammy 1013 Jan 7 08:05 package.json -rw-rw-r-- 1 sammy sammy 1405 Jan 7 08:05 phpunit.xml drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 public -rw-rw-r-- 1 sammy sammy 273 Jan 7 08:05 readme.md drwxrwxr-x 6 sammy sammy 4096 Jan 7 08:05 resources drwxrwxr-x 2 sammy sammy 4096 Jan 7 08:05 routes -rw-rw-r-- 1 sammy sammy 563 Jan 7 08:05 server.php drwxrwxr-x 5 sammy sammy 4096 Jan 7 08:05 storage drwxrwxr-x 4 sammy sammy 4096 Jan 7 08:05 tests drwxrwxr-x 41 sammy sammy 4096 Jun 9 11:32 vendor -rw-rw-r-- 1 sammy sammy 538 Jan 7 08:05 webpack.mix.js نشغّل الأداة composer install لتثبيت اعتماديات التطبيق كما يلي: docker-compose exec app composer install يظهر الخرج التالي بعد إتمام العملية: Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) - Installing erusev/parsedown (1.7.4): Downloading (100%) - Installing symfony/polyfill-ctype (v1.13.1): Downloading (100%) - Installing phpoption/phpoption (1.7.2): Downloading (100%) - Installing vlucas/phpdotenv (v3.6.0): Downloading (100%) - Installing symfony/css-selector (v5.0.2): Downloading (100%) … Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. يجب أن نولد مفتاح التطبيق الفريد باستخدام الأداة artisan الخاصة بلارافيل قبل أن نختبر التطبيق الذي طورناه، إذ يشفّر هذا المفتاح جلسات المستخدم والبيانات الحساسة الأخرى. ننفذ الأمر التالي: docker-compose exec app php artisan key:generate ويكون الخرج على النحو التالي: Application key set successfully. نطلب الرابط التالي من المتصفح: http://server_domain_or_IP:8000 ملاحظة: نطلب العنوان المحلي "http://localhost:8000" في حالة العمل على حاسب محلي ضمن المتصفح لتشغيل التطبيق التوضيحي الذي نطوّره. يظهر عندها الخرج التالي: نستطيع استخدام الأمر logs لفحص السجلات التي تولّدها الخدمة بتنفيذ الأمر التالي: docker-compose logs nginx Attaching to travellist-nginx … travellist-nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh travellist-nginx | /docker-entrypoint.sh: Configuration complete; ready for start up travellist-nginx | 192.168.0.1 - - [09/Jun/2020:11:46:34 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" travellist-nginx | 192.168.0.1 - - [09/Jun/2020:11:46:35 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" … نستطيع إيقاف العمل مؤقتًا لبيئة دوكر كومبوز مع الحفاظ على حالة الخدمات بتشغيل الأمر: docker-compose pause ليكون الخرج على النحو التالي: Pausing travellist-db ... done Pausing travellist-nginx ... done Pausing travellist-app ... done نستطيع استئناف العمل بتنفيذ الأمر: docker-compose unpause ويكون الخرج على النحو التالي: Unpausing travellist-app ... done Unpausing travellist-nginx ... done Unpausing travellist-db ... done نستطيع إيقاف عمل بيئة دوكر كومبوز ونزيل جميع حاوياتها وشبكاتها ووحدات تخزينها بتنفيذ الأمر التالي: docker-compose down ويكون الخرج على النحو التالي: Stopping travellist-nginx ... done Stopping travellist-db ... done Stopping travellist-app ... done Removing travellist-nginx ... done Removing travellist-db ... done Removing travellist-app ... done Removing network travellist-laravel-demo_travellist الخاتمة أعددنا بيئة دوكر بثلاث حاويات باستخدام أداة دوكر كومبوز Docker Compose وحددنا بنيته الأساسية في ملف YAML. يمكن العمل على تطبيق لارافيل Laravel دون الحاجة إلى تثبيت خادم ويب محلي وإعداده للتطوير والاختبار، ويتحقق كل ذلك باستخدام بيئة معزولة يمكن تكرارها وإعادة إنشائها بسهولة حتى الوصول إلى التطبيق المطلوب تثبيته ضمن بيئات الإنتاج. ترجمة وبتصرف للمقال How To Install and Set Up Laravel with Docker Compose on Ubuntu 20.04 لصاحبه Erika Heidi. اقرأ أيضًا مدخل إلى دوكر Docker نشر تطبيقات Laravel على منصة Heroku تثبيت Laravel 5 وإعداده على Windows وUbuntu
  16. يتيح إطار العمل لارافيل Laravel المعتمد على لغة PHP عدة أدوات مُستخدمة مع قواعد البيانات ومن أهمها أداتي التهجير وتوليد البيانات أو البذر seeder اللتان تساعدان المطور على تهيئة قاعدة البيانات أو التخلص منها أو إعادة إنشائها بسرعة عالية، إذ تقلل هذه الأدوات من مشاكل عدم الاتساق الخاصة بقاعدة البيانات، والتي تظهر عند تشارك عدة مطورين باستخدام نفس قاعدة البيانات أو نفس التطبيق في الوقت ذاته. ينفذ المطوّر الذي يحتاج للعمل مع قواعد البيانات المشتركة مجموعةً بسيطةً من أوامر "artisan" لإعداد قاعدة البيانات لتصبح جاهزة للاستخدام. نستخدم في عملنا هذا عدة عمليات تهجير لقواعد البيانات وتوليد بيانات نموذجية لملء قاعدة بيانات خاصة بتطبيق لارافيل توضيحي، وسنحذف الجداول ونعيد إنشائها عدة مرات باستخدام أوامر "artisan" فقط. المتطلبات الأساسية لاتباع خطوات هذا المقال ستحتاج ما يلي: الوصول إلى حاسب يعمل بنظام التشغيل أوبنتو Ubuntu ذي رقم إصدار 18.04 أو إلى خادم تطوير يعمل بنفس نظام التشغيل المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo ولا يفضل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم كما يفضّل وجود جدار حماية نشط في حال العمل على خادم بعيد. تثبيت الأداة دوكر Docker على الخادم. تثبيت الأداة دوكر كومبوز Docker Compose على الخادم. ملاحظة: نستخدم بيئة تطوير حاويات تديرها الأداة دوكر كومبوز لتشغيل التطبيق كما يمكن اختيار حزمة التخديم LEMP لتشغيله. الخطوة 1- الحصول على التطبيق التوضيحي نبدأ بتحميل تطبيق لارافيل التوضيحي من مخزن Github وننتقل إلى الفرع tutorial-02، الذي يحتوي إعداد الأداة دوكر كومبوز لتشغيل التطبيق على الحاويات، نحمّل التطبيق التوضيحي في المجلد الافتراضي ولكن يمكن اختيار أي مجلد آخر إذا دعت الحاجة لذلك، ومن ثم ننفذ الأوامر التالية: cd ~ curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip يبدأ تحميل الملف المضغوط بصيغة "zip." لذلك يجب عند انتهاء التحميل فك الضغط بعد التأكد من تحديث الحزم الخاصة بنظام التشغيل ما لم تكن محدّثة مؤخرًا، وذلك بتنفيذ الأوامر التالية: sudo apt update نثبت الحزمة "unzip" بتنفيذ الأمر: sudo apt install unzip مع إتمام عملية التثبيت نفك ضغط الملف بتنفيذ الأمر: unzip travellist.zip نعيد تسمية المجلد ليصبح باسم "travellist-demo" لسهولة الوصول إليه بتنفيذ الأمر: mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo الخطوة 2- إعداد ملف "env." الخاص بالتطبيق يتضمن الملف "env." عمليات الضبط الخاصة بالبيئة، مثل بيانات الاعتماد Credentials وأية معلومات تختلف بين عمليات نشر التطبيقات، لذلك لا يُضمّن هذا الملف ضمن ملفات التحكم بالإصدارات لكي لا تنتشر هذه المعلومات لجميع المستخدمين الذين يستخدمون صورة التطبيق لاحقًا. تحذير: يحتوي ملف ضبط البيئة على معلومات حساسة حول الخادم، بما في ذلك بيانات اعتماد قاعدة البيانات ومفاتيح الأمان، لهذا السبب لا يجب مشاركة هذا الملف علنًا. توجد أولوية للقيم الموجودة في الملف "env." على القيم الموجودة في ملفات التهيئة الأخرى الموجودة في المجلد "config"، وتتطلب كل عملية تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف معلومات خاصة، مثل إعدادات الاتصال بقاعدة البيانات، خيارات التصحيح debug والرابط الخاص بالتطبيق URL، إضافةً لبقية العناصر التي تختلف تبعاً للبيئة التي يعمل بها التطبيق. ننتقل إلى المجلّد "travellist-demo" بتنفيذ الأمر: cd travellist-demo ننشئ ملف "env." جديد لتخصيص خيارات الإعداد لبيئة التطوير التي نعدها. ويمكننا نسخ الملف "example.env" الذي الموجود افتراضيًا ضمن أي تطبيق لارافيل بتنفيذ الأمر: cp .env.example .env نستخدم محرر نانو nano لتعديل محتوى الملف بتنفيذ الأمر: nano .env يبدو هذا الملف بالشكل التالي: APP_NAME=Travellist APP_ENV=dev APP_KEY= APP_DEBUG=true APP_URL=http://localhost:8000 LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=travellist DB_USERNAME=travellist_user DB_PASSWORD=password … يحتوي ملف "env." الحالي الخاص بتطبيق "travellist" التوضيحي إعدادات لاستخدام بيئة الحاويات التي أنشأناها باستخدام أداة دوكر كومبوز. لا نحتاج إلى تغيير أي من هذه القيم، ولكن يمكن تعديل DB_DATABASE و DB_USERNAME و DB_PASSWORD عند الحاجة، حيث أنّ هذه القيم تُسحب بالاعتماد على الملف docker-compose.yml تلقائيًا لإعداد قاعدة البيانات. نتأكد من بقاء المتغير DB_HOST دون تغيير، لأنه يشير إلى اسم خادم قاعدة البيانات داخل بيئة دوكر كومبوز. نضغط على الاختصار "CTRL + X" ثم زر "Y" وأخيرًا زر الإدخال "Enter" عند الانتهاء من تعديل الملف. ملاحظة: نحتاج عند تشغيل التطبيق على خادم LEMP إلى تغيير القيم المشار إليها لتتوافق مع إعدادات قاعدة البيانات بما في ذلك المتغير "DB_HOST". الخطوة 3- تثبيت اعتماديات التطبيق مع كومبوزر نستخدم الأداة كومبوزر لإدارة الاعتمادية الخاصة ببرامج PHP، إذ تُستخدم لتثبيت جميع اعتماديات التطبيق والتأكد من إمكانية استخدام أوامر "artisan". نُظهر بيئة دوكر كومبوز حيث نبني صورة "travellist" لتشغيل التطبيق مثل خدمة "app" كما تُحمَّل جميع صور دوكر المتعلقة بالتطبيق مثل "nginx" و "db" لتشكيل بيئة التطبيق الكاملة. ننفذ الأمر التالي لتحقيق ذلك: docker-compose up -d وسيكون الخرج على النحو التالي: Creating network "travellist-demo_travellist" with driver "bridge" Building app Step 1/11 : FROM php:7.4-fpm ---> fa37bd6db22a Step 2/11 : ARG user ---> Running in 9259bb2ac034 … Creating travellist-app ... done Creating travellist-nginx ... done Creating travellist-db ... done تستغرق هذه العملية بضع دقائق حتى تكتمل ومن ثم نشغّل كومبوزر لتثبيت اعتماديات التطبيق. نستخدم الأمر docker-compose exec لتنفيذ أوامر كومبوزر وجميع الأوامر الأخرى ضمن حاوية خدمة التطبيق، إذ يسمح الأمرexec بتنفيذ أي أمر على الحاويات التي يديرها دوكر كومبوز، ويُكتب هذا الأمر وفقًا للصيغة التالية: docker-compose exec service_name command إذ يُستبدل المتغير service_name باسم الخدمة التي نرغب بتنفيذ الأمر عليها ويُستبدل المتغيرcommand بالأمر الذي نريد تطبيقه. ملاحظة: نتجاهل عمليات الأمر docker-compose exec في حال استخدام خادم LEMP لتشغيل التطبيق التجريبي ونستخدم الأمر composer installعوضًا عنه. ننفذ الأمر composer install ضمن الحاوية app بتطبيق الأمر: docker-compose exec app composer install يظهر الخرج التالي بعد انتهاء التنفيذ: Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Package operations: 85 installs, 0 updates, 0 removals - Installing doctrine/inflector (1.3.1): Downloading (100%) - Installing doctrine/lexer (1.2.0): Downloading (100%) - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%) … ننتظر إلى أن ينتهي كومبوزر من تثبيت اعتماديات التطبيق ومن ثم نستطيع تنفيذ أوامر "artisan". نختبر قدرة التطبيق على الاتصال بقاعدة البيانات بتنفيذ الأمر التالي الذي يفرّغ محتوى الجداول الموجودة مسبقًا: docker-compose exec app php artisan db:wipe يظهر الخرج التالي ما لم توجد مشكلة ما وعندها يكون التطبيق قادرًا على الاتصال بقاعدة البيانات: Dropped all tables successfully. نستخدم أداة "artisan" في تهجير وتوليد المعطيات بعد التأكد من قدرة التطبيق على الاتصال بقاعدة البيانات. الخطوة 4- تهجير قاعدة البيانات يتضمن الأمر "artisan" المُتاح افتراضيًا ضمن لارافيل عدة أوامر مساعدة تُستخدم في إدارة التطبيقات وتهيئة الأصناف الجديدة، نستخدم الأمر make:migration لتوليد صنف تهجير بيانات جديد بالشكل التالي: docker-compose exec app php artisan make:migration create_places_table تستنتج لارافيل من الأمر السابق أن العملية المطلوبة هي عملية إنشاء create وأنّ اسم الجدول المطلوب places. تحدد لارافيل إذا ما كانت عملية التهجير تنشئ جدولًا جديدًا أم لا بناءً على الاسم الوصفي الموجود في الأمر make:migration. يظهر الخرج التالي بعد تنفيذ الأمر: Created Migration: 2020_02_03_143622_create_places_table يولَّد ملف جديد في المجلد "database/migrations" ضمن التطبيق ويُستخدم الطابع الزمني المضمّن في الملف المُنشأ تلقائيًا بوساطة لارافيل لتحديد الترتيب الذي تُنفّذ عمليات التهجير وفقًا له. نحرر الملف الذي ولّدناه باستخدام محرر النصوص المفضّل مع التركيز على استبدال اسم الملف أدناه باسم الملف الفعلي في حال وجود اختلاف بينهما. nano database/migrations/2020_02_03_143622_create_places_table.php يحتوي هذا الملف على صنفٍ يدعى CreatePlacesTable كما هو مبين فيما يلي: <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreatePlacesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('places', function (Blueprint $table) { $table->bigIncrements('id'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('places'); } } يتضمن هذا الصنف تابعين هما up و down، اللتان تحتويان على شيفرة تهيئة التشغيل التي تحدد ما يحدث عند تنفيذ عملية التهجير وعند التراجع عنها. نعدّل التابع up بحيث يعكس الجدول places البنية التي نستخدمها في تطبيقنا الحالي: id: حقل المفتاح الأساسي. name: حقل اسم المكان. visited: حقل يشير إذا ما حدثت زيارة لهذا المكان مسبقًا أم لا. يقدِّم مُنشِئ المخططات schema في لارافيل طرقًا لإنشاء وتعديل وحذف الجداول في قاعدة البيانات، إذ يعرّف الصنف Blueprint بنية الجدول ويقدم مجموعة توابع تحدّد حقول الجدول على نحوٍ مجرّد. تُعد الشيفرة البرمجية المولّدة تلقائيًا حقلًا للمعرف الأساسي id كما ينشئ التابع timestamps حقلين من نوع معطيات timestamps يُعدَلان آليًا عند إضافة قيم إلى الجدول أو عند تعديل القيم الموجودة مسبقًا ضمن الجدول، ويُضاف إلى هذه الحقول حقلين إضافيين هما name و visited. يُضبط نوع الحقل name ليكون سلسلة نصية "string" والحقل visited من النوع "boolean" وتوضع القيمة "0" في الحقل visited على أنها قيمة افتراضية لتمثّل عدم زيارة المكان مسبقًا ليصبح التابع الذي نعدّله على الشكل التالي: … public function up() { Schema::create('places', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name', 100); $table->boolean('visited')->default(0); $table->timestamps(); }); } … ملاحظة: توجد قائمة بجميع أنواع الأعمدة المتاحة ضمن التوثيق الخاص بلارافيل. نحفظ الملف بعد التأكد من إضافة كامل المحتوى السابق، ثم نغلقه فتصبح قاعدة البيانات جاهزة للتهجير بتنفيذ الأمر: artisan migrate تُنشأ حاليًا جداول فارغة بالبنية التي اعتمدناها ولملء هذه الجداول ببيانات من اختيارنا لا بُد من استخدام مولّدات قواعد البيانات. الخطوة 5- إنشاء مولدات قواعد البيانات يستخدم الصنف الخاص Seeder لتوليد وإدخال البيانات إلى قاعدة البيانات، وتساعد هذه الميزة المطورين على إعادة إنشاء قاعدة البيانات وإدخال البيانات إليها بسرعة عالية دون الحاجة إلى عمليات يدوية لتحقيق ذلك. يولَّد صنف توليد بيانات آليًا باستخدام الأمر artisan ويحمل هذا الصنف الاسم PlacesTableSeeder بتنفيذ الأمر التالي: docker-compose exec app php artisan make:seeder PlacesTableSeeder يظهر ملف جديد اسمه "PlacesTableSeeder.php" ضمن المجلد "database/seeds". نحرّر محتوى الملف باستخدام محرر النصوص المفضّل: nano database/seeds/PlacesTableSeeder.php يتضمن الملف "PlacesTableSeeder.php" المُولّد تلقائيًا المحتوى التالي: <?php use Illuminate\Database\Seeder; class PlacesTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // } } يحتوي الصنف على تابع فارغ run والذي يبدأ عمله عند تنفيذ الأمر db:seed. نعدّل محتوى هذا التابع ليتضمن التعليمات التي تُدخِل عينةً من البيانات إلى قاعدة البيانات، ونستخدم مُنشئ استعلامات لارافيل لتنفيذ ذلك. يتيح منشئ استعلام لارافيل واجهة سلسة لعمليات قاعدة البيانات، مثل إدراج البيانات وتحديثها وحذفها واسترجاعها، كما أنّه يحمي قاعدة البيانات من هجمات حقن SQL. يمكن الوصول إلى باني الاستعلامات بالاعتماد على واجهة خاصة تدعى facade وهي وكيل Proxy ساكن إلى الأصناف الخاصة بقاعدة البيانات ضمن حاوية التطبيق. ننشئ متغير ساكن من نوع مصفوفة ضمن الصنف والذي يحتوي على جميع الأماكن التي نرغب بإدخالها إلى قاعدة البيانات مثل مصفوفة. نستخدم حلقة foreach للتجوال على جميع القيم وإدخال كل منها بالاعتماد على باني الاستعلامات وسندعو هذا المتغير بالاسم places$كما في الشكل التالي: <?php use Illuminate\Database\Seeder; class PlacesTableSeeder extends Seeder { static $places = [ 'Berlin', 'Budapest', 'Cincinnati', 'Denver', 'Helsinki', 'Lisbon', 'Moscow', 'Nairobi', 'Oslo', 'Rio', 'Tokyo' ]; … نستخدم عبارة use ضمن الصنف PlacesTableSeeder للمساعدة في الإشارة إلى واجهات قاعدة البيانات ضمن الشيفرة البرمجية كما يلي: <?php use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; class PlacesTableSeeder extends Seeder … نستخدم حلقة foreach للتجوال ضمن قيم المصفوفة places$ وإدخال كل من هذه القيم ضمن الجدول places باستخدام باني الاستعلامات كما يلي: … public function run() { foreach (self::$places as $place) { DB::table('places')->insert([ 'name' => $place, 'visited' => rand(0,1) == 1 ]); } } تتكرر تعليمات حلقة foreachعلى قيم المصفوفة الساكنة places$ واحدةً تلو الأخرى، ومع كل تكرار تُدخِل واجهة قاعدة البيانات سطرًا جديدًا ضمن الجدول places، بحيث يُضاف قيمة اسم المدينة الموجود في الجدول ضمن قاعدة البيانات من القيمة الموافقة في المصفوفة places$، كما توضع قيمة عشوائية إما أن تكون 0 أو 1 ضمن الحقل visited. يصبح محتوى الشيفرة البرمجية الكاملة للصف PlacesTableSeeder بعد تجميع الأجزاء البرمجية السابقة على النحو التالي: <?php use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; class PlacesTableSeeder extends Seeder { static $places = [ 'Berlin', 'Budapest', 'Cincinnati', 'Denver', 'Helsinki', 'Lisbon', 'Moscow', 'Nairobi', 'Oslo', 'Rio', 'Tokyo' ]; /** * Run the database seeds. * * @return void */ public function run() { foreach (self::$places as $place) { DB::table('places')->insert([ 'name' => $place, 'visited' => rand(0,1) == 1 ]); } } } لا تُحمّل أصناف توليد البيانات آليًا ضمن التطبيق، أي أنّه يجب تعديل الصنف DatabaseSeeder الرئيسي لتضمينها استدعاءً للصنف الذي أنشأناه. نحرر الملف "database/seeds/DatabaseSeeder.php" باستخدام محرر نانو أو أي محرر مفضل لديك بتنفيذ الأمر التالي: nano database/seeds/DatabaseSeeder.php لا يختلف الصنف "DatabaseSeeder" عن أية صنف آخر لتوليد البيانات، إذ أنّه يرث الصنف "Seeder" ويمتلك التابع "run" الذي نُحدّث محتواه ليتضمن استدعاءً للصنف "PlacesTableSeeder". نحدّث محتوى التابع run ضمن الصنف DatabaseSeeder بإزالة التعليق الموجود ضمنه وإضافة ما يلي: … public function run() { $this->call(PlacesTableSeeder::class); } … يصبح محتوى الشيفرة البرمجية للصنف DatabaseSeeder بعد التحديث كما يلي: <?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(PlacesTableSeeder::class); } } نحفظ الملف السابق وبهذا يكون قد انتهى إعداد كل من وظيفتي التهجير وتوليد البيانات الخاصتين بالجدول places ويبقى تنفيذ هذه الإجراءات. الخطوة 6- ترحيل قواعد البيانات وتوليد البيانات نتأكد من أنّ التطبيق الذي أعددناه جاهز للعمل، ومن ثم نُعدّ مفاتيح التشفير الخاصة بالتطبيق وعندها نستطيع اختبار التطبيق بطلبه ضمن المتصفح ومراقبة استجابة الخادم للطلب. نولّد مفاتيح التشفير الضرورية لعمل لارافيل وذلك باستخدام الأمر التالي: docker-compose exec app php artisan key:generate نطلب من المتصفح رابط التطبيق على المنفذ 8000 كما يلي: http://server_host_or_ip:8000 نرى الاستجابة التالية على المتصفح: نستنتج أن التطبيق يستطيع الاتصال بقاعدة البيانات لكنه لم يعثر على جدول باسم places ولذا ننشئ هذا الجدول بأمر التهجير التالي: docker-compose exec app php artisan migrate يظهر الخرج التالي: Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.06 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds) نلاحظ تنفيذ عمليات تهجير إضافية إلى جانب التهجير create_places_table الذي أعددناه، إذ يجري إعداد هذه العمليات الإضافية عند تثبيت لارافيل. لا تفيد هذه الجداول ضمن نطاق العمل الحالي إلا أنها أساسيةٌ عند توسيع عمل التطبيق لتشمل المهام المجدولة والتعامل مع المستخدمين المسجّلين ولهذا لا نعدل في محتواها الآن. تخلو الجداول السابقة من البيانات ومن أجل توليد بيانات في الجدول places نستخدم الأمر db:seed بالمحتوى الذي أنشأناه مسبقًا: docker-compose exec app php artisan db:seed يشغّل الأمر السابق المُولد الذي أنشأناه ضمن الصنف PlacesTableSeeder، ويظهر خرجٌ مشابهٌ لما يلي: Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully. نعيد تحميل صفحة المتصفح لتظهر بالشكل التالي: يمكن إفراغ الجداول من بياناتها بتنفيذ الأمر: docker-compose exec app php artisan db:wipe ويكون الخرج على النحو التالي: Dropped all tables successfully. ويمكن تنفيذ عمليتي التهجير والتوليد بأمر برمجي واحد بتنفيذ الأمر: docker-compose exec app php artisan migrate --seed ويكون الخرج على النحو التالي: Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.06 seconds) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (0.07 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.03 seconds) Migrating: 2020_02_10_144134_create_places_table Migrated: 2020_02_10_144134_create_places_table (0.03 seconds) Seeding: PlacesTableSeeder Seeded: PlacesTableSeeder (0.06 seconds) Database seeding completed successfully. يمكن التراجع عن عملية التهجير بتنفيذ الأمر: docker-compose exec app php artisan migrate:rollback حيث يُستدعى التابع down من أجل كل عملية تهجير معرّفة ضمن الصنف وتكون هذه الأصناف مجمّعةً في مجلد "migrations" حيث تجري إزالة جميع الجداول التي أنشأتها أصناف التهجير باستثناء تلك التي أنشأها المستخدم يدويًا. يظهر لدينا خرج مشابهٌ لما يلي: Rolling back: 2020_02_10_144134_create_places_table Rolled back: 2020_02_10_144134_create_places_table (0.02 seconds) Rolling back: 2019_08_19_000000_create_failed_jobs_table Rolled back: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds) Rolling back: 2014_10_12_100000_create_password_resets_table Rolled back: 2014_10_12_100000_create_password_resets_table (0.02 seconds) Rolling back: 2014_10_12_000000_create_users_table Rolled back: 2014_10_12_000000_create_users_table (0.02 seconds) يفيد أمر التراجع بصورةٍ خاصة عندما نعدّل النماذج الخاصة بالتطبيق علمًا أنّ الأمر "db:wipe" لا يكون متاحًا للاستخدام كما في حالة اعتماد أكثر من نظام على قاعدة بيانات مشتركة. الخاتمة تضمنّت هذه المقالة توضيحًا بمدى أهمية عمليات تهجير وتوليد البيانات ضمن قاعدة البيانات من أجل إعداد واختبار قواعد البيانات الخاصة بتطبيقات لارافيل من الإصدار 6. ترجمة –وبتصرف- للمقال How To Use Database Migrations and Seeders to Abstract Database Setup in Laravel لصاحبه Erika Heidi. اقرأ أيضًا مقدمة عن قواعد البيانات تهجير قواعد البيانات في Laravel 5 تهجير قواعد البيانات (migrations) على Laravel
  17. نعم يمكن ذلك وأفترض أنك تقصدين أن كل شبكة مبدل لها عناوين خاصة بها. أما اذا كانت المبدلات تأتي من نفس مجال العنونة فيجب الحذر من مثل هذه البنية وتقسيمها بشكل وظيفي أفضل والاعتماد على استخدام الشبكات الافتراضية VLAN في العمل.
  18. لقد اقتضى التعرّف على مشكلة اختناق العتاد hardware bottlenecks، ضرورة امتلاك خبرات عالية في العديد من المجالات التقنية، وقد أصبح من السهل مؤخرًا كشف هذه المشاكل باستخدام أدوات مراقبة الأداء مفتوحة المصدر ذات الواجهات الرسومية التي تسمح لأي مستخدم بتشخيص المشكلة التي يعاني منها، دون شراء أدوات مكلفة، ودون الحاجة إلى تعلّم الأوامر المعقدة. تُعَد الحواسيب أنظمةً متكاملةً تقدم أداءً بسرعة تتناسب مع أبطأ المكونات العتادية الموجودة فيها، فعندما تكون إحدى المكونات أقلّ قدرةً من المكونات الأخرى، فإنه حتمًا سيسبب تأخير عمل كامل النظام. ويُعرف ما سبق باسم "اختناق الأداء"، حيث تتيح إزالة الاختناقات الحادة إمكانية تحسين أداء النظام، بحيث يشعر المستخدم بأنّ الحاسب يعمل بسرعة عالية. ستشرح هذه المقالة كيفية التعرف على الاختناقات الخاصة بالعتاد في أنظمة لينكس، حيث تنطبق التقنيات المذكورة على كل من الحواسب الشخصية والمخدّمات، حيث ستركز المقالة على الحواسب الشخصية ولن تتضمن اختناقات خاصة بالخوادم مثل تلك الناتجة عن إدارة الشبكة المحلية LAN، أو أنظمة قواعد البيانات التي تحتاج عادةً أدوات خاصة لكشف الاختناق. ستتضمن المقالة أيضًا تعريفًا بمشكلة اختناق الأداء، كما ستتناول بعضًا من الأدوات التي يمكن استخدامها في كشف حدوث الاختناقات، إلى جانب تقديمها لبعض الإرشادات لكشف الاختناق أينما حدث ضمن الحاسوب، ومحاولة حل المشاكل المرتبطة به. ستركز هذه المقالة تحديدًا على الأدوات مفتوحة المصدر ذات الواجهات الرسومية لكشف ومعالجة مشاكل الاختناقات المختلفة، حيث نجد أن معظم المقالات حول اختناقات الأداء في نظام لينكس تكون معقدة، نظرًا لاستخدام هذه المقالات لأوامر مخصصة، تحتاج إلى مختصين إلى استخدامها؛ إلا أنّ المشاكل الأكثر شيوعًا تُكشف ببساطة من قِبل المستخدم دون الحاجة إلى مثل هذا التعقيد. تجعل الأدوات ذات الواجهات الرسومية التي تتيحها منصة Open Source لكشف اختناق الأداء أمرًا بسيطًا، فالهدف من هذه المقالة أن تقدّم للقارئ مقاربةً بسيطةً يمكن استخدامها في أية حالة تواجه المستخدم. من أين نبدأ يتألف الحاسوب من ستة موارد عتادية أساسية وهي: المعالجات الذاكرة التخزين منافذ اتصال USB الاتصال بالانترنت المعالج الرسومي يمكن لأيٍ من الموارد السابقة في حال أصبح أداؤه سيئًا، أن يسبب اختناقًا في الأداء، ويجب عند تشخيص الاختناق أن نراقب الموارد الستة سابقة الذكر. توجد العديد من الأدوات مفتوحة المصدر التي يمكن استخدامها لمراقبة الموارد المختلفة في الحاسوب، حيث سنستخدم أداة GNOME System Monitor لأن مخرجاتها سهلة الفهم. ويمكن الحصول على هذه الأداة بسهولة من مستودعات توزيعات لينكس، حيث سيكون علينا فقط تشغيل الأداة ومن ثم نضغط على تبويب الموارد Resources، ويمكن التعرف على العديد من مشاكل الأداء مباشرةً. الشكل 1: تكتشف الأداة System Monitor العديد من المشاكل. تُظهر لوحة Resources ثلاثة أقسام رئيسية هي تاريخ وحدة المعالجة المركزية CPU History، وتاريخ الذاكرة والذاكرة المبدلة Memory and Swap History، وتاريخ الشبكة Network History، حيث يمكن بمجرد إلقاء نظرة سريعة أن نلاحظ إذا كانت المعالجات غارقةً في العمل، أو إذا كان الحاسب قد نفّذ من الذاكرة، أو أنه يستهلك كامل عرض المجال الخاص بالانترنت يجب تفقد هذه الأداة عند الشعور بأن أداء الحاسب قد أصبح سيئًا لأنها تبين بسهولة بعض الأدلة على مشاكل الأداء الأكثر شيوعًا. التعرف على اختناقات المعالج يجب أن نتعرف على العتاد المتاح لدينا عند تشخيص الاختناق، حيث تتوفر العديد من الأدوات للتعرف على مواصفات الحاسوب المستخدم وتفاصيل العتاد الكاملة، وتُعَد الأداة HardInfo من أفضل الأدوات، وذلك لأنها شائعة وتمتلك واجهات رسومية سهلة القراءة. بعد تشغيل الأداة HardInfo يحصل اختيار التبويب Computer -‏> Summary، فتظهر لوحة تتضمن معلومات وحدة المعالجة المركزية مثل عدد الأنوية cores والنياسب أو الخيوط threads، والسرعات speeds، كما أنها تتضمن معلومات عن اللوحة الأم وبقية مكونات الحاسب. الشكل 2: تُظهر واجهة أداة HardInfo التفاصيل عن العتاد المتوفر في الجهاز. تبيّن الأداة HardInfo أن الحاسب المستخدم في المثال يمتلك وحدة معالجة مركزية فيزيائية واحدة، والتي تتضمن معالجين أو نواتين. حيث تدعم كل نواة استخدام خيطين أو ما يعرف بالمعالجات المنطقية، مما يجعل العدد الكلي المتاح أربع معالجات منطقية، وهذا بالضبط ما أظهره الجزء الخاص بتاريخ المعالج من أداة System Monitor في الشكل 1. يحدث اختناق المعالج عندما يعجز المعالج عن تلبية الطلبات الواردة، إليه لأنه يكون بحالة انشغال كامل. يمكن التعرف على هذه الحالة عندما تُظهِر أداة System Monitor أن استخدام المعالج المنطقي تجاوز 80% أو 90% لفترة زمنية مستمرة. حيث نجد في المثال التالي أن ثلاثة من المعالجات المنطقية الأربعة قد استُهلِكت استهلاكًا كاملًا، وهذا ما يُعَد اختناقًا لأنقدرة وحدة المعالجة المركزية المتاحة لم تعد كافيةً لتنفيذ أي من الأعمال الأخرى في حال ورودها. الشكل 3: اختناق في عمل المعالج معرفة أي تطبيق هو سبب المشكلة؟ يجب أن نعرف أي تطبيق أو مجموعة التطبيقات التي تستهلك وحدة المعالجة المركزية، حيث يمكن أن نشاهد العمليات مرتّبةً وفقًا إلى نسبة استهلاكها لوحدة المعالجة المركزية عند الضغط على تبويب Processes في أداة System Monitor ومن ثم بالضغط على ترويسة ‎% CPU، كما يمكن عندها معرفة أي من التطبيقات يخنق النظام. الشكل 4: التعرف على العمليات المسيئة. تستهلك كل من العمليات الثلاثة الأولى نسبة 24% من موارد وحدة المعالجة المركزية الإجمالي، حيث نلاحظ وجود أربعة معالجات منطقية في النظام، مما يعني أنّ كل عملية تستهلك معالجًا كاملًا كما يُظهر الشكل 3. تبيّن لوحة العمليات Processes أنّ برنامجًا اسمه analytical_AI هو سبب المشكلة، حيث يمكن الضغط بالزر اليميني عليه ضمن اللوحة لنجد المزيد من التفاصيل حول استهلاكه لموارد الحاسوب، متضمنةً نسبة استهلاك الذاكرة وعدد الملفات المفتوحة وتفاصيل عمليات الإدخال والإخراج، والمزيد من التفاصيل الأخرى. يمكن في حال كان المستخدم يتمتع بصلاحيات المدير Administrator إدارة هذه العملية، إذ يمكن تغيير أولويتها وإيقافها، أو إعادتها للعمل، أو إنهائها أو قتلها، مما يؤدي إلى حل مشكلة الاختناق مباشرةً. الشكل 5: الضغط بالزر اليميني على العملية لإدارتها. كيف يمكن أن نحل مشاكل اختناق المعالجة؟ يمكن في البدائة إدارة العملية التي تكون سبب المشكلة فور حدوثها، حيث يمكن منع الاختناق من الحدوث باستبدال هذا التطبيق بآخر، أو من خلال محاولة تجنب استخدامه أو تغيير سلوك المستخدم عند استخدام هذا التطبيق، إضافةً إلى إمكانية جدولة التطبيق في ساعات عدم استخدام الحاسب من قِبل المستخدم. يمكن أن تُعالَج مشكلة مخفية في الذاكرة الرئيسية والتي يكون لها تأثير مباشر على عمل وحدة المعالجة المركزية، كما يمكن العمل على إجراء تحسينات في أداء التطبيق أو النظام البرمجي، أو قد تحتاج إلى ترقية العتاد آنذاك لأنه لم يَعُد كافيًا بالنسبة للتطبيقات التي تشغلّها. اختناقات المعالج الشائعة يمكن أن نصادف العديد من الاختناقات الشائعة عند مراقبة وحدات المعالجة المركزية باستخدام أداة System Monitor، حيث يمكن في بعض الأحيان حدوث حالة اختناق في أداء أحد المعالجات المنطقية، بينما تكون المعالجات المتبقية ذات مستوى استخدام منخفض، وذلك يعني أنّ أحد التطبيقات المستخدمة لم يُطوّر بذكاء بحيث يستفيد من ميزة وجود أكثر من معالج منطقي في الحاسوب، مما سبب الوصول إلى أقصى أداء ممكن على المعالج المستخدم. ولكن من وجهة نظر مختلفة، نجد أنّ المعالجات المتبقية حرة ومتاحة لتنفيذ أي من الأعمال الأخرى، أي أنّه لم تُشَغَّل كامل موارد الحاسب بما يعيق تنفيذ أعمال جديدة. يمكن أن نجد معالجًا منطقيًا عالقًا دائمًا بنسبة استخدام 100، وقد يعني ذلك أنه إما مشغول جدًا أو أنه توجد عملية ما قد أصبحت بحالة جمود، كما يمكن أن نتأكد بأن العملية قد أصبحت جامدةً عندما لا تمارس العملية أي نشاط متعلق بـ قرص التخزين (مثلما ستُظهِر لوحة العمليات Processes في أداة System Monitor). وفي الختام يمكن ملاحظة أنه عندما تصبح جميع المعالجات المنطقية في حالة اختناق، فإن الذاكرة تصبح مستخدمةً كليًا أيضًا. يمكن أن تسبب حالات نفاد الذاكرة Out-of-memory اختناقات في المعالج، وفي هذه الحالة يجب العمل على حل مشاكل الذاكرة المخفية والابتعاد عن التركيز الكثيف على حل مشكلة المعالج، والتي تُعَد عارضًا من أعراض المشكلة الحقيقية. التعرف على اختناقات الذاكرة تمتلك الحواسب الشخصية الحديثة اليوم كميةً وافرةً من الذاكرة، لذا نجد أن اختناقات الذاكرة قد أصبحت أقل شيوعًا موازنةً بالسنين الماضية، ومع ذلك يمكن أن نصادف هذه المشكلة عند تشغيل برامج ذات استهلاك ذاكرة كثيف، وخصوصًا إذا لم يكن الحاسب يمتلك حجمًا كافيًا من الذاكرة العشوائية RAM. يستخدم نظام لينكس الذاكرة من أجل البرامج ومن أجل تخبئة المعطيات المخزّنة على القرص، حيث تفيد الثانية في تسريع الوصول إلى المعطيات الموجودة على القرص، ويمكن لنظام لينكس أن يقرأ المعطيات الذي خزنها على جزء القرص الصلب المستخدم كذاكرة في أي وقت، وتقديم هذه المعطيات للبرامج التي تحتاجها. تُظهر لوحة الموارد Resources ضمن أداة System Monitor؛ إجمالي الذاكرة والكمية المستخدمة منها، ويمكن في لوحة العمليات Processes مشاهدة استخدام الذاكرة لكل عملية على حدى. يظهر الشكل الجزء من لوحة الموارد Resources ضمن أداة System Monitor التي تتعقب تراكم استخدام الذاكرة. الشكل 6: اختناق الذاكرة. نلاحظ إلى يمين الذاكرة وجود جزء التبادل، وهو مساحة القرص التي يستخدمها نظام لينكس عندما تصبح نسبة الذاكرة المتاحة منخفضة، حيث تُكتَب محتويات الذاكرة إلى القرص من أجل متابعة العمليات، مما يحقق استخدام جزء التبادل مثل توسعة بطيئة بعض الشيء لذاكرة الوصول العشوائي. يمكن أن نبحث بصورة رئيسية عن مشكلتين في أداء الذاكرة وهي: تظهر الذاكرة وكأنها مستخدمة كثيرًا، ويمكن مشاهدة نشاط متكرر أو متزايد على جزء التبادل. أصبح كل من جزئي الذاكرة والتبادل مستخدمين كليًا. تشير الحالة الأولى إلى وجود بطء في الأداء لأن جزء التبادل أبطأ من الذاكرة، وذلك نظرًا لتواجده على القرص الصلب. ويمكن أن يتعايش بعض المستخدمين مع مستوى الأداء بحيث لا يَعُدونه بطيئًا. تُعَد مسألة اختيار حجم التبادل أمرًا هامًا، حيث يرتبط تحديده بخيارات المستخدم، لذا فعليه أن يقرر على سبيل المثال معدل نشاط جزء التبادل وسرعته والتوقعات منه وغيرها من القضايا التي تؤثر إجمالًا على أداء الحاسب، إذ يرتبط تحديد حجم جزء التبادل المستخدم بحجم الذاكرة الإجمالي الموجود وعادةً لا يتجاوز نسبة 20% من إجمالي الذاكرة. أما الحالة الثانية التي تحدث عندما تكون كلٍ من الذاكرة وجزء التبادل، فهما مُستخدمان كليًا فهي حالة اختناق الذاكرة، أين يبدو الحاسب وكأنه لا يستجيب، ومن الممكن أن يصل إلى حالة تجمد thrashing والتي لا يكون فيها الحاسب قادرًا على تنفيذ الكثير من العمليات إضافةً إلى عمليات إدارة الذاكرة. يظهر الشكل 6 أعلاه حاسوبًا قديمًا يمتلك ذاكرة نفاذ عشوائي ذات حجم 2 غيغابايت، وبما أنّ استهلاك الذاكرة تجاوز 80%، فقد بدأ النظام بالكتابة في جزء التبادل، وهو ما سبب انحسارًا في مدى استجابة الحاسب. تُظهر هذه الصورة بأن استهلاك الذاكرة قد تجاوز 90% وأن الحاسب قد دخل في حالة الجمود. يُعَد الحل النهائي لمشاكل الذاكرة، إما باستخدام ذاكرة أقل إن أمكن ذلك عبر إغلاق التطبيقات غير المستخدمة ومعرفة التطبيقات التي تعمل باستمرار في الخلفيّة مع إيقاف التطبيقات غير الضرورية منها، أو وبدراسة مواصفات الحاسوب ومعرفة حجم الذاكرة الأعظمي المسموح به، حيث يمكن استبدال الذواكر الموجودة ضمن الجهاز بأكبر منها أو توسعة الذاكرة الإجمالية عبر إضافة ذواكر إضافية بشرط دراسة التوافق بين الذواكر الجديدة والقديمة. التعرف على اختناقات التخزين توجد اليوم العديد من الأشكال لوسائط التخزين فبعض منها يكون أقراص HDD أو أقراص SSD. يمكن أن تكون واجهات الربط مع هذه الأقراص منافذ PCIe وSATA وThunderbolt وUSB.مهما كان نوع وسيط التخزين الذي تمتلكه فيمكن اتباع نفس الإجرائية للتعرف على اختناقات الأقراص. نقوم بتشغيل أداة System Monitor ثم من لوحة العمليات Processes نراقب معدلات الإدخال والإخراج من أجل العمليات بشكل إفرادي مما يتيح التعرف على العمليات التي تقوم بمعظم عمليات الإدخال والإخراج من وإلى القرص. لا تُظهر هذه الأداة معدل النقل التراكمي للقرص، لذا يجب مراقبة الاستهلاك الإجمالي على أحد الأقراص لكشف حدوث اختناق في التخزين، ويمكن تحقيق ذلك باستخدام الأمر atop، وهو متاح في معظم منصات تنزيل البرمجيات. يمكن أن نكتب الأمر atop ضمن موجه الأوامر، حيث يُظهر الخرج أدناه بأن الجهاز sdb مشغول بنسبة 101%، ويعني ذلك بوضوح أنّه قد وصل الجهاز إلى حد استخدامه الأعظمي وأنه يُقيِّد سرعة النظام على تنفيذ الأعمال. الشكل 7: يتعرف الأمر atop على اختناق القرص. يمكن أن نلاحظ أن أحد المعالجات ينتظر القرص الصلب بنسبة 85% من وقته لكي يؤدي مهامه، ويحدث ذلك عندما يصبح جهاز التخزين بحالة اختناق. عمليًا، سيراقب العديد من المستخدمين حدوث انتظار المعالج لوحدات الإدخال والإخراج لكشف حدوث اختناقات التخزين، حيث يمكن استخدام الأمر atop لكشف حدوث اختناق القرص الصلب بسهولة، ومن ثم يمكن استخدام لوحة العمليات Processes من أداة System Monitor للتعرف على العمليات الإفرادية التي تسبب مشكلة الاختناق. كيفية التعرف على اختناقات منفذ USB يستخدِم العديد من الناس منافذ USB باستمرار طوال اليوم، ومع ذلك لا يتأكدون مما إذا كان استخدام هذه المنافذ مثاليًا، وذلك مهما كان نوع الجهاز الذي توصله عبر منفذ USB، لهذا يجب التأكد من الحصول على أفضل أداء ممكن من هذه الجهاز. الشكل 8: تتفاوت سرعة منافذ USB كثيرًا (Howard Fosdick, بناءً على شكل قدمه Tripplite و Wikipedia, منشورة برخصة CC BY-SA 4.0). يظهر التبويب USB Devices ضمن أداة HardInfo المعايير الخاصة بمنافذ USB التي يدعمها الحاسوب، حيث تتيح معظم الحواسيب إمكانية استخدام منافذ USB بسرعات مختلفة، كما يمكن أن نعرف السرعة لأحد منافذ الـ USB بالاعتماد على لون المنفذ. يمكن أيضًا معرفة سرعة المنفذ الموجود في الحاسب عن طريق موازنة لونه مع الألوان المستخدمة في الشكل السابق، كما يمكن العودة إلى الدليل الورقي أو الإلكتروني المُرفق بالحاسب الشخصي، والذي يتضمن عدد المنافذ الموجودة على الحاسب وسرعة كل منها. إذا أردنا مشاهدة السرعات الحقيقية التي نحصل عليها، فيمكننا اختبارها باستخدام الأداة GNOME Disks مفتوحة المصدر، حيث سنشغّل الأداة ومن ثم اختيار Benchmark Disk، وعند تشغيل عملية الاختبار، ستظهر السرعة الحقيقية الأعظمية التي يمكن الحصول عليها من أحد المنافذ الذي أوصِل إليه جهاز ما. يمكن أن نحصل على سرعات نقل متفاوتة من أجل أحد المنافذ، وذلك تبعًا لنوع الجهاز الموصول بالمنفذ، حيث يعتمد تحديد معدل المعطيات على تشكيلة مكونة من المنفذ والجهاز الموصول به. فعلى سبيل المثال، عند وصل جهاز ما يمكن أن يعمل بسرعة 3.1 وقد وُصل بمنفذ ذي سرعة 2.0، فإن الجهاز سيعمل بسرعة 2.0 دون مشاكل ولن يظهر أي إنذار بأن الجهاز يعمل بسرعة أقل من سرعته الأعظمية؛ بينما إذا وُصِل جهاز يعمل بسرعة 2.0 إلى منفذ 3.1، فسيعمل ولكن بسرعة 2.0. لذا فمن أجل الحصول على عمل USB سريع، يجب أن نضمن أن كلًا من المنفذ والجهاز يدعمان السرعة. وتوفر الأداة GNOME Disks الوسائل اللازمة للتحقق من ذلك. إذا أردنا كشف حدوث اختناقات خاصة بمنافذ USB، فيمكن استخدام نفس الإجراء الذي نفذناه عند التعامل مع أقراص الحالة الصلبة والأقراص الصلبة، حيث نشغّل الأمر atop لكشف وجود اختناق خاص بوسيط التخزين الموصول عن طريق USB، ومن ثم نستخدم برنامج System Monitor من أجل الحصول على تفاصيل فيما يخص العملية التي سببت المشكلة. كيفية التعرف على اختناقات اتصال الإنترنت تُظهر لوحة الموارد Resources ضمن أداة System Monitor، سرعة الاتصال بالإنترنت في الزمن الحقيقي كما هو ظاهر في الشكل 1. توجد العديد من الأدوات المبنية بلغة بايثون لاختبار سرعة الانترنت الأعظمية، ولكن يمكننا اختبار السرعة باستخدام المواقع على الانترنت مثل Speedtest وFast.com وSpeakeasy، حيث يجب علينا إغلاق كل شيء وتشغيل عملية اختبار السرعة فقط، وذلك للحصول على أفضل نتيجة ممكنة، إضافةً إلى إطفاء اتصال VPN وتشغيل الاختبارات في أوقات متفرقة من اليوم، وموازنة النتائج من عدة مواقع اختبار سرعة. يمكن عندها موازنة النتائج لديك مع سرعة التنزيل والرفع، والتي يدعي مزود الخدمة تقديمها لك، وبهذا الشكل يمكن التأكد من أن مزود خدمة الإنترنت يقدم السرعة الحقيقية التي ادّعى توفيرها للمستخدم. يمكن في حال وجود موجه Router مستقل أن يتم الاختبار بوجوده وبغيابه، وبهذا يمكن أن نحكم فيما إذا كان الموجه يمثل نقطة الاختناق أم لا. وفي حال وجود خدمات اللاسلكي WiFi، فيجب أن يَجري الاختبار بوجودها وبغيابها، أي بوصل الكابل مباشرةً بين الجهاز المحمول وجهاز المودم)، ففي الحقيقة توجد عدة حالات اشتكى فيها المستخدمون من مزود الخدمة الخاص بهم علمًا أنّ مشكلتهم الحقيقية كانت الاختناق في خدمات الاتصال اللاسلكي والذي كان بإمكانهم حلها بأنفسهم، ففي حال كان أحد البرامج يستهلك كامل اتصال الانترنت، فيجب معرفته باستخدام الأمر nethogs، وهو متاح لدى أغلب منصات تنزيل البرمجيات. لقد أظهرت أداة System Monitor في أحد الأيام فجأةً وجود استهلاك إنترنت مفاجئ، وعند كتابة الأمر nethogs في موجه الأوامر، حدث التعرف فورًا على سبب استهلاك عرض المجال بأنه عملية تحديث لمضاد الفايروسات Clamav الشكل 9: تتعرف الأداة Nethogs على البرامج التي تستهلك عرض المجال. التعرف على اختناقات معالج الرسوم يجب معرفة نوع معالج الرسوم الموجود في الحاسب، فإذا كان يحدث توصيل الشاشة إلى اللوحة الأم من الخلف في الحاسب الشخصي، فهذا يدل على وجود معالج رسومي مدمج؛ أما إذا كان توصيل الشاشة إلى اللوحة الأم عن طريق بطاقة إضافية تُركّب على اللوحة الأم، فهذا يعني وجود نظام فرعي مستقل لمعالجة الرسوم، والتي تُعرف بإسم بطاقة الفيديو Video Card، أو بطاقة الرسوميات Graphics Card. تكون البطاقات هذه أكثر قوةً وكلفةً من المعالجات الرسومية المدمجة باللوحة الأم، علمًا أن الحواسيب المحمولة تستخدم المعالجات الرسومية المدمجة دومًا ولا يمكن إضافة بطاقة رسومية إليها. تُظهر لوحة PCI Devices ضمن أداة HardInfo، معلومات حول وحدة معالجة الرسوميات لديك، كما يمكن أن تُظهر كمية الذاكرة المخصصة للفيديو (عن طريق البحث عن الذاكرة المعنونة باسم قابلة للجلب المسبق Prefetchable). الشكل 10: توفر الأداة HardInfo معلومات عن المعالجة الرسومية. تعمل وِحدتَي المعالجة المركزية و معالجة الرسوميات بتكامل، حيث يمكن ببساطة أن نقول أن وحدة المعالجة المركزية تحضر الإطارات Frames لوحدة معالجة الرسوميات لتُظهِرها، ويحدث الاختناق في معالج الرسوم عندما تنتظر وحدة المعالجة المركزية العمل من وحدة معالجة الرسوميات، والتي تكون مشغولةً كليًا، حيث يمكن كشف ذلك عن طريق مراقبة معدلات استخدام كلا الوحدتين، إذ تتيح الأدوات مفتوحة المصدر Conky وGlances ذلك بسهولة. فيما يلي مثال تم الحصول عليه باستخدام الأداة Conky، ويمكن ملاحظة أن النظام يمتلك كميةً وافرةً من قدرة المعالجة في وحدة المعالجة المركزية؛ أما وحدة معالجات الرسوميات، فهي مستهلكة بنسبة 25%، فلو تخيلنا أنّ هذا الرقم قارب الـ 100%، فعندها نعلم أنّ وحدة المعالجة المركزية تنتظر وحدة معالجة الرسوميات، وأنه توجد حالة اختناق في وحدة معالجة الرسوميات. الشكل 11: تظهر أداة Conky استخدام وحدة المعالجة المركزية ووحدة معالجة الرسوميات (صورة مقتبسة من منتدى AskUbuntu). يمكن في بعض الحواسيب أن نضطر إلى استخدام أدوات مصنّعة خصيصًا من قِبل الشركة المصنعة لبطاقة الفيديو، وتتوفر هذه الأدوات للتنزيل من موقع GitHub. الخلاصة تتألف الحواسيب من مجموعة من الموارد العتادية المتكاملة، حيث يمكن أن تسبب أي منها في حال تأخرها عن تنفيذ الأعمال المسندة إليها؛ اختناقًا في الأداء قد يُسبب بطء أداء النظام كاملًا، لهذا يجب أن نكون قادرين على التعرف على الاختناقات وتصحيحها للحصول على الأداء المثالي. اقتضى التعرّف على مشكلة اختناق العتاد hardware bottlenecks امتلاك خبرات عالية في العديد من المجالات التقنية، وحديثًا أصبح من السهل كشف هذه المشاكل باستخدام أدوات مراقبة الأداء مفتوحة المصدر ذات الواجهات الرسومية التي تسمح لأي مستخدم بتشخيص المشكلة التي يعاني منها، دون شراء أدوات مكلفة، ودون الحاجة إلى تعلّم الأوامر المعقدة. جميع الصورة منشورة برخصة CC BY-SA 4.0 لصاحبها Howard Fosdick إلا إن ذكر خلاف ذلك. ترجمة -وبتصرف- للمقال Identify Linux performance bottlenecks using open source tools لصاحبه Howard Fosdick. اقرأ أيضًا 4 أدوات مفتوحة المصدر من أجل مراقبة نظام لينكس ما هو نظام التشغيل لينكس؟ دليل المستخدم للروابط في نظام ملفات لينكس عشرون أمرا في لينكس يفترض أن يعرفها كل مدير نظم 4 أدوات مفتوحة المصدر من أجل مراقبة نظام لينكس
  19. يُعد دمج الأمن ضمن دورة حياة تطوير النظام أمرًا هامًا، ولكنه لا يكون دومًا أمرًا سهلًا، ويُعَد اتباع نهج DevOps ضمن أية مؤسسة أمرًا هامًا لأنه يساعد المؤسسة في تحسين سرعة تطوير واختبار وتركيب البرمجيات التي تعمل على تطويرها لتصبح جاهزةً للعمل. توجد العديد من التجارب الناجحة المتعلّقة بتطبيق نهج DevOps ضمن المؤسسات، حيث أصبحت هذه المؤسسات تقدّم أفكارًا مبتكرةً وقادرةً على تسليم منتجاتها البرمجية بصورة رشيقة دون مشاكل، إلا أنّ بعض التجارب لاتباع هذا النهج قد انتهت بالفشل الذريع، فقد سببت عددًا كبيرًا من المشاكل يفوق الفوائد الناتجة عن نجاحها. توجد العديد من العوامل التي قد تسبب فشل اتباع نهج DevOps ضمن مؤسسة ما، وأهم هذه العوامل هو الأمن. يُعَد غياب ثقافة الأمن في المؤسسة أمرًا خطيرًا، وغالبًا ما يحدث ذلك عندما لا تهتم المؤسسة بمسائل الأمن حتى نهاية مرحلة تبني سياسة DevOps، مما قد يسبب تطبيق الإجراءات الأمنية المتبعة في المؤسسة بطريقة تتسبب في تأخير المشروع من جهة، كما تساهم في إحباط فريق التطوير والعديد من المشاكل المالية التي يمكن أن تضر بالمشروع كثيرًا. لحل هذه المشاكل وُضِع نهج DevSecOps، حيث أنّ غايته الأساسية هي تأكيد فكرة أن الجميع في الفريق مسؤولون عن أمن المشروع، بحيث يكون التفكير بالقضايا المتعلقة بالأمن في كل مراحل حياة المشروع. إجرائية DevSecOps يبين الشكل 1 الآلية التي كانت متّبعةً في تطبيق مفاهيم الأمن ضمن عملية التطوير قبل ظهور نهجي DevOps و DevSecOps، فمن الواضح أن التفكير بالأمن لم يكن من أولويات فريق التطوير لأنّه يحدث في المراحل النهائية، أي عند البدء بتسليم المشروع، أينما تكون البرمجيات قد قُبِلت للدخول في مرحلة الإنتاج Production. Michael Calizo يمكن تبعًا للإجراءات المتّبعة ضمن المؤسسة أن يحدث في بعض الأحيان تجاوزُ للمراجعات الخاصة بالأمن أثناء قبول المشروع، وعندها يمكن عدّ هذه المراجعة على أنها فقط شكل من أشكال التدقيق، وذلك من أجل ضمان عدم تأخير المشروع. Michael Calizo, CC BY-SA 4.0 يعدّ الهدف الأساسي من اتباع نهج DevSecOps هو دمج الأمن بكل من عملية التطوير وعملية التشغيل، وذلك لضمان عدم إغفال أي من متطلبات الأمن أو خصوصية المعطيات، لذا ينصح الخبراء بأن يغير المطورون طريقة عملهم وسلوكهم وثقافتهم باكرًا. لا تُعَد هذه المهمة سهلةً خصوصًا في البيئات الضخمة، ويُعَد المبدأ الرئيسي لنهج DevSecOps هو بناء ثقافة الأمن في عمليتي التطوير والتشغيل، مما يجعلها أكثر رشاقةً ومرونة، ويجب أن يعمل المطورين بحيث يصبح الأمن والتوافقية متاحةً من قِبل الأجزاء البرمجية لكي تُستهلَك وكأنها خدمة. يعمل نهج DevSecOps على تضمين الأمن ضمن دورة حياة تطوير النظام ويُعاد تطوير المفاهيم الخاصة بالأمن مع كل دورة من دورات تطوير المنتج Michael Calizo, CC BY-SA 4.0 عوائق تبني نهج DevSecOps يعمل الناس بطبيعتهم على محاربة التغيير، بحيث يميلون إلى إيجاد العيوب والأخطاء في العملية الجديدة التي ستُتبنّى. بطبيعة الحال لا يمكن تغيير ذلك لأنها من الطبيعة البشرية، إذ يفضّل البشر دومًا اتباع عادةٍ ما عوضًا عن إجراء التغيير المستمر؛ أما أهم العوائق التي تواجه تبنّي نهج DevSecOps فهي: استخدام عملية DevOps أو DevSecOps من مزود خارجي: يعني ذلك أنّ المفاهيم والعمليات المستخدمة تدور حول منتج ما يقدّمه المزود الخارجي ولن تستطيع المؤسسة لبناء المقاربة لأنها محدودة بما يقدمه المزود. توتر المدراء: يعاني المدراء من التخوف المستمر وخصوصًا عند تبني أي تقنية أو نهج جديد، بحيث يؤثر هذا الخوف والتوتر على قدرة المدير على اتخاذ القرار الصحيح. تجنّب محاولة إصلاح أي شيء ليس معطّلًا بالكامل: يميل معظم مدراء تقنيات المعلومات إلى تجنّب إجراء أية تغييرات في الخدمات التي تعمل حتى ولو وُجدت فيها عدة مشاكل طالما أن بعض نتائجها صحيحة. وفي بعض الأحيان، حتى مع نجاح النهج الجديد يميل مدراء تقنيات المعلومات إلى المحافظة على المنتج القديم والإجراءات التي أنتجته. تأثير نتفليكس Netflix وأوبر Uber: نجحت كل من شركتي نتفليكس ةأوبر بتطبيق نهج DevSecOps بنجاح، وتعمل العديد من الشركات على تقليدهم، ومع ذلك تفشل معظم هذه الشركات بسبب الاختلاف بين ثقافة هذه الشركات وثقافة بقية الشركات. قلة القياس: يجب أن تتم عملية قياس التحول ضمن المؤسسة أثناء تنبي نهج DevOps أو DevOpsSec، فهي من أهم المقاييس التي ينظُر إليها الأداء في عملية تسليم البرمجية أو الأداء العام للمؤسسة. الأمن المقاس بقوائم التحقق: يتبع فريق الأمن ما يعرف بقائمة التحقق، وهي تتضمن الخطوات التقليدية ذاتها في كل مرة. وانطلاقًا من ذلك ظهرت مقاربة "as code"، والتي تتطلب أن يتعلّم مختصو الأمن البرمجة وأن يتجنبوا الطرائق التقليدية لتطبيق الأمن ضمن المؤسسة. اعتبار فريق الأمن كفريق خاص: تظهر هذه المشكلة عندما يكون فريق الأمن مفصولًا عن فريق التطوير والتشغيل، مما يدفعهم إلى صرف الكثير من وقت فريق أمن المعلومات في مراجعة ومحاولة تحسين عمل الفريقين عوضًا عن تواجدهم إلى جانبهم أثناء عملية التطوير. كيفية تبني نهج DevSecOps بنجاح يُعَد تبني نهج DevSecOps أمرًا صعبًا، ولكن نظرًا للفوائد الكبيرة، يمكن العمل على تجنب العوائق التي أصبحت معروفةً جيدًا، وتُعَد ثقافة الأمن العائق الأكبر، فلكي تنجح هذه الثقافة ضمن المؤسسة يجب أن يكون تبنيها من أعلى هرم المؤسسة، ومن ثم تعميم هذه الثقافة على الموظفين. يفيد وجود القادة وبعض المتحمسين للنهج الجديد؛ في تسريع عملية تبني الثقافة الجديدة ضمن المؤسسة، حيث يجب تضمين فرق التطوير والتشغيل والأمن بعضًا من هؤلاء الأشخاص ليكونوا مناصرين للنهج الجديد، مما يؤسِّس لظهور فرق متعددة الوظائف تتشارك فيما بينها الخبرة والنجاحات مع بقية الفرق، مما يسرّع عملية تبني النهج الجديد. تحتاج المؤسسة بعد نجاح هذه الخطوة إلى وجود حالة استخدام للنهج الجديد للبدء بها، ولا داعي لكي تكون كبيرةً أو تتضمن الكثير من المخاطرة، بل يجب أن تكون مضمونة النجاح، إذ يفيد ذلك في دفع الفريق إلى التعلم والفشل ومن ثم النجاح دون تأثير وظائف النظام الجوهرية. يجب أن يكون تبني النهج الجديد قابلًا للقياس، كما يجب الاتفاق على تعريف النجاح ضمن المشروع. ولتحقيق كل ما سبق يجب أن تتوفر لوحة إظهار تعرض القيم التي تُعَد مقاييس يجب مراقبتها وهي: مهلة التغيير. وتيرة تركيب النظام. الزمن الوسطي للاستعادة. معدل فشل التغييرات. تُعَد هذه المعايير أساسيةً عند التعرف على عملية ما ومحاولة تحديد جوانبها التي تحتاج تحسينًا. تسمى هذه المنهجية بالتحول المقاد بالأحداث Event-Driven Transformation، وتفيد في تحديد ما إذا كانت عملية تبني النهج الجديد ناجحةً أم فاشلة. الاستنتاجات يسمح تبني نهج DevOps - عندما يُتبنّى بطريقة صحيحة - للمؤسسة بتسليم المنتجات البرمجية بسرعة عالية، مما يُكسبها العديد من المزايا موازنةً بمنافسيها، حيث يحتاج تبني نهج DevOps وDevSecOps ما يأتي: تغيير الثقافات في المؤسسة. اقتناع الإدارة التنفيذية بالتغيير. مشاركة القادة والمتحمسين للنهج الجديد في عملية التبني. فرق متعددة الوظائف. بعض المؤشرات القابلة للقياس. وبالتالي يُعَد تبني الثقافة السليمة الخطوة الأساسية لتبني نهج DevSecOps بطريقة صحيحة. ترجمة -وبتصرف- للمقال How to adopt DevSecOps successfully لصاحبه Mike Calizo. اقرأ أيضًا ما هي DevSecOps؟ خمس طرق يغيّر بها مفهوم DevSecOps منظومتك الأمنية ثلاث خطوات لتأمين DevOps مفتوح المصدر ما المقصود بـ DevOps؟ سلسلة تعرف على DevOps
  20. يُعَد امتلاك المعلومات المناسبة هو الخطوة الأولى لحل أي مشكلة حاسوبية، سواءً كانت هذه المشكلة مرتبطةً بنظام التشغيل لينكس أو بالعتاد الذي يشغّله النظام. توجد العديد من الأدوات المتاحة منها ما يكون مضمّنًا في معظم توزيعات لينكس، ومنها لا يكون مثبّتًا افتراضيًا، ويجب على المستخدم أن يثبتها في حال رغبته باستخدام الأداة. تقدّم هذه الأدوات الكثير من المعلومات المفيدة في تشخيص المشاكل الخاصة بالحاسوب. تناقش هذه المقالة بعض الأدوات التفاعلية التي تعمل بالأوامر CLI، والتي يمكن تثبيتها بسهولة على توزيعات لينكس ريد هات Red Hat وفيدورا Fedora وسينتوس CentOs وكل التوزيعات المشتقّة منها، حيث تتوفر العديد من الأدوات ذات الواجهات الرسومية التي يمكن استخدامها لنفس الغرض إلا أنها لا تكون قابلةً للاستخدام في جميع الأحيان، نظرًا لعدم امتلاك بعض الخوادم القدرة على العرض رسوميًا. تقدّم المقالة أربع أدوات أساسية ضمن بيئة نظام لينكس لمراقبة النظام وتشخيص المشاكل فيه وهي top وatop وhtop وglances، حيث تراقب هذه الأدوات نسبة استخدام الذاكرة ووحدة المعالجة المركزية CPU، كما تتيح معظمها معلومات عن العمليات قيد التشغيل، إضافةً إلى العديد من الجوانب الأخرى، وتظهر هذه المعلومات تقريبًا بالزمن الحقيقي لنشاط النظام. متوسط الحمل يمثّل متوسط الحمل Load average متوسط عدد التعليمات التي تنتظر أن ينفذها المعالج، فهو مقياس حقيقي لأداء وحدة المعالجة المركزية خلافًا لنسبة استهلاك وحدة المعالجة المركزية، والتي تُعَد مقياسًا غير دقيق كونها تتضمّن زمن انتظار متعلّق بعملية الإدخال والإخراج حيث يكون عندها المعالج خاملًا. نفترض أنّ النظام يمتلك معالجًا وحيدًا، وبالتالي عندما يكون متوسط الحمل مساويًا للواحد، فهذا يعني أنّ المعالج ينفذ الطلبات الواردة إليه دون تأخير وأن نسبة استخدامه ممتازة؛ أما عندما يصبح متوسط الحمل أقل من واحد، فيعني ذلك أنّ المعالج غير مستخدم حسب المطلوب، وأنّه قادر على تنفيذ المزيد من العمل، وعندما يصبح متوسط الحمل أكبر من واحد، فالمعالج هنا يكون قد أصبح مشغولًا مع وجود بعض التعليمات بحالة انتظار لفترة زمنية قبل أن ينفّذها المعالج. في نظام أحادي المعالج وعندما يكون متوسط الحمل مساويًا 1.5 فإنّ ثلث التعليمات الواردة تنتظر لفترة زمنية قبل أن يبدأ تنفيذها، أما في حال النظم متعددة المعالجات، فلو فرضنا أنه يوجد نظام متعدد المعالجات يمتلك أربع معالجات، فإن متوسط الحمل المثالي يساوي أربعة. فإذا كان هذا المتوسط مساويًا 3.24 فسيعني ذلك أنّ ثلاثة معالجات منها مستخدمة كليًا وقد بلغت نسبة استخدام المعالج الرابع 76%. تكون قيمة متوسط الحمل المثالية مساويةً لعدد المعالجات في النظام، ويعني ذلك أنّ جميع المعالجات مستخدَمة بطاقتها القصوى، ولا تضطر أية تعليمة للانتظار حتى تُنفّّذ. تعطي هذه القيمة على المدى الطويل نظرةً عامّةّ للاستخدام العام للموارد في الحاسوب. الإشارات تسمح جميع أدوات المراقبة المذكورة سابقًا بإرسال إشارات Signals للعمليات قيد التشغيل، وتكون لكل إشارة وظيفة محددة مرتبطة بها، كما يمكن أن يعرّف البرنامج الذي يستقبل هذه الإشارة، الوظيفة التي تحدث عند استلامه للإشارة. يسمح الأمر Kill بإرسال الإشارات إلى العمليات أيضًا دون الحاجة لاستخدام برامج المراقبة، ويمكن تنفيذ الأمر kill -l لاستعراض جميع الإشارات التي يمكن استخدامها مع العمليات المختلفة، وتُستخدَم ثلاث من هذه الإشارات من أجل إيقاف العمليات والتي تسمى أحيانًا بقتل العملية kill a process. SIGTERM (15)‎: ترسَل هذه الإشارة افتراضيًا من قِبل الأداة top وبقية أدوات المراقبة عند الضغط على المحرف k، وتُعَد هذه الإشارة هي الأقل فعاليةً، لأنها تشترط امتلاك البرنامج المستقبل لها على جزء برمجي للتعامل مع هذه الإشارة Signal Handler. يجب أن يعترض الجزء البرمجي المذكور الإشارة الواردة إلى العملية والتصرف بطريقة صحيحة، وعند غياب هذا الجزء البرمجي، فستتجاهل العملية الإشارة الواردة إليها؛ أما الغاية من وجود إشارة SIGTERM، فهي إخبار البرنامج أنّ المستخدم يرغب بإنهاء البرنامج لوجوده، مما يجب أن يدفعه لتحرير الموارد التي استخدمها هذا البرنامج وإغلاق الملفات المفتوحة، وذلك دون اتخاذ أية إجراءات قسرية من قِبل المستخدم. SIGKILL (9)‎: تُستخدم هذه الإشارة لقتل أي من العمليات التي يرغب المستخدم بإيقافها، حيث لا تهتم هذه الإشارة لوجود جزء برمجي مخصص ينشط عند استلام الإشارة، إذ تُقتل العملية أولًا، ومن ثم تُقتل جلسة الصدفة shell التي يعمل ضمنها البرنامج. لا تُعد هذه الطريقة لطيفةً عند الحاجة للتخلص من عملية ما ويجب الأخذ بالحسبان أنً قتل العملية قسريًا باستخدام هذه الإشارة يمكن أن يؤثر على العمليات المرتبطة بها. SIGINT (2)‎: تُستخدم هذه الإشارة عند فشل الإشارة SIGTERM في التخلّص من العملية المطلوبة، مع عدم رغبة المستخدم بقتل العملية قسريًا، ولسبب ما لا يرغب المستخدم في إيقاف جلسة الصدفة shell الخاصة بالعملية، وإنما يريد قتل العملية فقط ومقاطعة الجلسة فقط دون إزالتها. تكافئ هذه الإشارة إرسال الأمر CTRL-C للبرنامج أو السكريبت وهو قيد العمل مما يسبب توقفه بصورة دائمة. يمكن تجربة الأوامر السابقة بإنشاء جلسة موجه أوامر جديدة ومن ثم إنشاء ملف ضمن المجلد"‎"/tmp باسم cpuHog، ثم تحويله لبرنامج تنفيذي وإعطائه الأذونات "rwxrxrx" وكتابة المحتوى التالي ضمن الملف: #!/bin/bash # This Little program is a cpu hog X=0; while[1]; do echo $X;X=$(X+1);done نفتح موجه أوامر في نافذة مختلفة ونضع النافذتين متجاورتين لكي نشاهد النتائج، ومن ثم نشغل الأمر top، وبعدها نشغل برنامج cpuHog الذي كتبناه باستخدام الأمر التالي: /tmp/cpuHog يعمل البرنامج بطريقة عدّاد، مع طباعة القيمة التي وصل إليها إلى المخرج الذي نختاره، وهو افتراضيًا الشاشة. يستهلك هذا البرنامج دورات المعالجة الخاصة بالمعالج، لذا سنشاهد ارتفاعًا ملحوظًا في نسبة استخدام المعالج ضمن نتائج الأمر top. يزداد متوسط الحمل أيضًا مع مرور الزمن، ويمكن فتح نوافذ جديدة وتشغيل البرنامج فيها وملاحظة التغير الذي يحصل على استهلاك المعالج. يمكن عند الحاجة لقتل العملية ضمن الأداة top بالضغط على الحرف K، وستظهر رسالة تطلب رقم التعريف الخاص بالعملية PID التي يريد المستخدم قتلها. وبعد إدخال هذا الرقم نضغط على "Enter"، وعندها ستسأل الأداة المستخدِم عن الإشارة التي يرغب بإرسالها، والتي تكون افتراضيًا "15". يمكن في هذه المرحلة تجربة الإشارات المختلفة وملاحظة الاختلافات فيما بينها. أداة top تُعَد هذه الأداة من أهم الأدوات المستخدمة عند تشخيص المشاكل، وتتميز بأنها متاحة دومًا وموجودة في جميع توزيعات لينكس افتراضيًا دون الحاجة الى تنصيبها. تقدّم هذه الأداة الكثير من المعلومات حول النظام قيد العمل، فنجد فيها معطيات حول استهلاك الذاكرة وأحمال المعالج، وقائمة بالعمليات قيد التشغيل، وإلى جانب كل عملية نجد نسبة استهلاكها لموارد الحاسوب. تُحدّث هذه المعلومات كل ثلاثة ثواني، أي أننا قد نَعُد الأداة وكأنها تعمل في الزمن الحقيقي. تسمح هذه الأداة باستخدام أجزاء الثواني إذا احتاج المستخدِم لاستعمالها، ولكن من النادر أن تؤثر القيم الضئيلة على الأداء الكلي للحاسوب، كما تتميز الأداة بأنها تفاعلية ويمكن للمستخدم أن يرتّب النتائج الظاهرة حسب اهتمامه. يظهر الشكل (1) عينةً من نتائج عمل الأداة top، ويقسم هذا الخرج إلى جزأين أساسيين وهما جزء الملخص "Summary" وجزء العملية "Process" بالترتيب. حيث يمكن الاستفادة من الأوامر التفاعلية الخاصة بالأداة من قِبل المستخدِم لتغيير طريقة العرض الخاصة بالأداة لتناسب المستخدِم، إضافةً إلى التحكم بالعمليات كليًا، إذ تعرض الأداة كل الأوامر المتاحة بالضغط على h لاستعراض المساعدة الخاصة بالأداة والتي تكون موزّعةً على صفحتين، بحيث يحدث الانتقال إلى الصفحة الثانية بالضغط على h مرتين، ويمكن الخروج من الصفحة بالضغط على q. جزء الملخص يقدم هذا الجزء ملخّصًا عامًا عن النظام، حيث يُظهر السطر الأول منه زمن عمل النظام منذ آخر عملية إقلاع له، ومن ثم متوسط الحمل محسوبًا على مدة زمنية تعادل 1، 5، 15 دقيقة على الترتيب، بينما السطر الثاني يظهر عدد العمليات النّشطة في الحاسوب وحالة كل من هذه العمليات. تظهر في السطر الثالث إحصائيات خاصة بالمعالج، بحيث قد تكون هذه الإحصائيات مقتصِرةً على سطر واحد يتضمن الإحصائيات عن جميع المعالجات الموجودة في الحاسوب، ويمكن أن نجد سطرًا لكل معالج على حدة، كما يمكن تبديل طريقة الإظهار بين المعلومات المجمّعة عن المعالج، والمعلومات عن المعالجات إفراديًا بالضغط على الرقم 1، بحيث ستظهر القيم بشكل نسبة مئوية من وقت المعالج المتاح للتنفيذ. نجد في النتائج القيم التالية: us:userspace: تشير إلى وقت المعالج المخصص للتطبيقات والبرامج الي تعمل ضمن مجال المستخدم وليس ضمن نواة نظام التشغيل. sy:system calls: تشير إلى وقت المعالج المخصص لاستدعاءات النظام، وهي الوظائف التي تنفَّذ ضمن نواة نظام التشغيل. تجدر الإشارة إلى أنّ هذه النسبة لا تتضمن الزمن الخاص بعمل النواة نفسها. ni:nice: تشير إلى وقت المعالج المخصص للعمليات التي تعمل بمستوى لطافة إيجابي (*)، ويمكن النظر إلى رقم اللطافة الخاص بالعمليات وكأنه أولوية، لكن توجد اختلافات دقيقة بين المصطلحين ليست من موضوع هذه المقالة. id:idle: تشير إلى وقت المعالج الذي يكون فيها خاملًا. wa:wait: تشير إلى الوقت الذي يكون فيه المعالج بحالة انتظار لإتمام عمليات الإدخال والإخراج، وبالطبع يمثل هذا الوقت هدرًا في عمل المعالج. hi:hardware interrupts: تشير إلى الوقت الذي يصرفه المعالج في معالجة المقاطعات العتادية الواردة إليه. si:software interrupts: تشير إلى الوقت الذي يصرفه المعالج في معالجة المقاطعات البرمجية الوارد إليه. st:steal time: تشير إلى الوقت الذي يقضيه المعالج المنطقي حتى ينهي المعالج الفيزيائي تخديم معالج منطقي آخر والانتقال إليه. يعرض السطرين الأخيرين في هذا الجزء استهلاك الذاكرة حيث يظهر كل من استهلاك الذاكرة العشوائية وذاكرة التبادل. الشكل (1): يُظهر الأمر top المعلومات الكاملة عن معالج رباعي النوى مستخدم كليًا. يمكن الضغط على l لإيقاف عرض متوسط الحمل أو تشغيله، كما يمكن الضغط على t وm من أجل تغيير طرق العرض الخاصة بمعلومات العمليات والذاكرة. جزء العمليات يتضمن هذا الجزء المعلومات عن العمليات قيد التشغيل في النظام، حيث تظهر هذه المعلومات على شكل أعمدة، ويتضمن العرض الافتراضي مجموعةً من الأعمدة، كما يمكن إضافة المزيد منهم من قِبل المستخدِم حسب ما يجده مفيدًا له. فيما يلي المعلومات التي تظهر افتراضيًا: PID: يعبر عن رقم التعريف الخاص بالعملية، وهو رقم فريد خاص بالعملية يميزها عن كل العمليات الأخرى. USER: يعبر عن اسم المستخدم الذي يملك العملية. PR: يعبر عن أولوية العملية. NI: يعبر عن رقم اللطافة الخاص بالعملية. VIRT: يعبر عن إجمالي الذاكرة الافتراضية المخصصة للعملية. RES: يعبر عن الذاكرة الفيزيائية غير القابلة للتبادل المخصصة للعملية، وهي مقاسة بالكيلوبت ما لم يذكر خلاف ذلك. SHR: يعبر عن كمية الذاكرة المشتركة المخصصة للعملية. S: يعبر عن حالة العملية، وقد يكون R إذا كانت العملية قيد التشغيل، أو S إذا دخلت العملية في حالة النوم أو Z إذا تحولت العملية إلى عملية ميتة-حية (زومبي). كما توجد بعض الحالات الأقل شيوعًا مثل T للمتوقفة، أو D لحالة النوم غير القابل للمقاطعة. ‎% CPU: يعبر عن وقت المعالج الذي استهلكته العملية خلال فترة القياس. ‎% MEM: يعبر عن نسبة الذاكرة الفيزيائية المستهلكة من قبل العملية. Time +: يعبر عن وقت المعالج الكلي المخصص للعملية منذ بدء عملها لأول مرة. COMMAND: يعبر عن الأمر الذي استُخِدم لتشغيل العملية. يمكن الضغط على Page Up وPage Down للتنقل بين قائمة العمليات قيد التنفيذ، ويمكن ضبط المدة الزمنية لأخذ القراءات باستخدام d وs، وتكون هذه المدة افتراضيًا ثلاث ثواني، بحيث يمكن تعديلها لتصبح جزءًا من الثانية، لكن ذلك يزيد من استهلاك الأداة لموارد الحاسوب ومن المفضل ضبط هذه القيمة بحيث تعادل ثانيةً واحدةً كي لا تؤثر سلبًا على أداء الحاسب وتعطي معلومات وافرة عن هذا الأداء. يفيد الضغط على < و > في التنقل بين الأعمدة إلى اليمين أو اليسار، كما يمكن الضغط على k من أجل قتل العملية أو الضغط على r من أجل تعديل مستوى لطافتها، وفي كلتا الحالتين يجب تحديد رقم التعريف الخاص بالعملية، حيث يجب أن نحدد رقم الإشارة عند قتل العملية. عادةً ما تبدأ المحاولات بالإشارة 15 وفي حال عدم نجاحها يمكن استخدام الإشارة 9 لقتل العملية قتلًا مؤكدًا. الضبط يمكن للمستخدِم الذي يعدّل معلومات العرض الخاصة بالأداة، استخدام الأمر W (يجب استخدام الحرف الكبير Uppercase)، وذلك لكتابة التغييرات إلى ملف الضبط، والذي يوجد عادةً في المسار"‎"~/.toprc في المساحة المخصصة للمستخدِم. أداة atop تتيح هذه الأداة معلومات أكثر تفصيلًا موازنةً بالأداة top. ومن أهم المعلومات الإضافية التي يمكن الحصول عليها باستخدام هذه الأداة، هي نشاط الإدخال والإخراج، حيث تتحدث القيم الظاهرة على الشاشة بعد انقضاء عشرة ثواني، ويمكن تغيير هذه المدة بالضغط على i واستخدام قيمة تناسب حاجة المستخدم. لا تستطيع هذه الأداة استخدام أجزاء الثانية مثل سابقتها، لكن يمكن استخدام الأمر h للحصول على المساعدة، وتوجد عدة صفحات ضمن دليل المساعدة يمكن التنقل بينها بالضغط على المسطرة Space. تتميز هذه الأداة بقدرتها على تخزين معلومات الأداء الخام ضمن ملف واستعراض محتوياته لاحقًا من أجل الدراسة المعمقة، مما يفيد في كشف بعض المشاكل الخفية وخصيصًا تلك التي تظهر في الوقت الذي لا يكون فيه النظام خاضعًا للمراقبة. يستخدم البرنامج atopsar لاستعراض محتويات الملفات المخزّنة حسب حاجة المستخدم. الشكل (2): يقدم نظام المراقبة atop المعلومات حول نشاط الأقراص والشبكة إضافة إلى نشاط المعالج. جزء الملخص تقدّم الأداة atop نفس المعلومات التي تقدّمها الأداة top، إلا أنّها تعرض بعض المعلومات الإضافية مثل المعلومات المتعلقة بنشاط الشبكة والأقراص والحجوم المنطقية ضمن الأقراص. يبين الشكل (2) أعلاه بعضًا من هذه المعلومات، تجدر الإشارة إلى أنّ عدد الأعمدة الذي يظهر هو مرتبط بأبعاد الشاشة، بحيث إذا كانت كافيةً فستعرض الأداة كافة الأعمدة بما تتضمنه من معلومات، وإلا فإنها تهمل بعضًا منها. تتميز هذه الأداة موانةً بجميع أنظمة المراقبة الأخرى بنها تعرض تردد المعالج الحالي، إضافةً إلى تبيان معامل توسيع التردد scaling factor، وتظهر هاتين القيمتين في أقصى اليمين ضمن السطر الثاني. جزء العملية تعرض الأداة atop بعضًا من الأعمدة التي تعرضها الأداة top، ولكنها تضيف بعض المعلومات مثل معلومات الإدخال والإخراج الخاصة بالقرص وعدد النياسب (الخيوط threads)، إضافةً إلى إحصائيات عن تغير كل من الذاكرتين الافتراضية والحقيقية لكل عملية. كما هو الحال في جزء الملخص، يمكن إظهار كامل الأعمدة إذا سمحت أبعاد الشاشة بذلك، وإلا فلن تظهر بعض الأعمدة مثل العمود المخصص لعرض رقم التعريف الحقيقي للمستخدم RUID الذي يملك العملية، ورقم التعريف الفعلي للمستخدم EUID، وتكون هاتين المعلومتين هامتين عند تشغيل بعض البرامج مع التلاعب بهوية المستخدم الذي ينفذ أمر التشغيل للبرنامج. تقدّم الأداة معلومات تفصيلية عن القرص والذاكرة والشبكة والجدولة الخاصة بكل عملية. يمكن الضغط على d وm وn وs بالترتيب لمشاهدة أي من التفاصيل السابقة، كما يمكن الضغط على g لإعادة الإظهار إلى وضعه الطبيعي. يمكن للمستخدم ترتيب العرض وفقًا لمعيار محدد، حيث يمكن الضغط على C للترتيب اعتمادًا على استهلاك وحدة المعالجة المركزية، أو الضغط على M للترتيب اعتمادًا على استهلاك الذاكرة، أو الضغط على D للترتيب اعتمادًا على استهلاك القرص، أو الضغط على N للترتيب اعتمادًا على استهلاك الشبكة، أو الضغط على A للترتيب التلقائي، ويعني ذلك الترتيب وفقًا للمورد الأكثر إشغالًا من قبل العملية. لن تعمل عمليات الترتيب الخاصة بالشبكة إلا بوجود مكتبة netatop إلى جانب الأداة atop، ويمكن الضغط على k لقتل أي عملية ولا تمتلك هذه الأداة القدرة على تعديل مستوى اللطافة مثل سابقتها. لا تعرِض هذه الأداة أجهزة الشبكة والتخزين التي لا تكون نشطةً ضمن فترة جلب المعلومات، مما قد يعطي انطباعًا خاطئًا عن ضبط الجهاز المستخدَم، فقد يوهم بعض المستخدمين بأن أحد الأجهزة لا يعمل بطريقة صحيحة، ولتجنب ذلك يمكن الضغط على f لعرض جميع الموارد وحتى الخاملة منها. الضبط يشير الدليل الخاص بالأداة atop الموجود ضمن نظام لينكس إلى ملفات الضبط الخاصة بالمستخدم وملفات الضبط العامة، وذلك باستثناء توزيعتي فيدورا وسينتوس. حيث لا توجد أية طريقة لحفظ تعديلات المستخدِم على ملفات الضبط وبالتالي لا تكون هذه التغييرات دائمة. أداة htop تشبه هذه الأداة إلى حد كبير الأداة top، ولكنها تعرض بعض المعلومات الإضافية التي لا تقدمها تلك الأداة، حيث لا تقدم هذه الأداة المعلومات عن القرص والشبكة والإدخال والإخراج كما في atop. الشكل (3): تمتلك الأداة htop طريقة إظهار جذابة للمستخدمين، كما أنها تعرض شجرة العملية كاملةً. جزء الملخص يتضمن جزء الملخص للأداة htop عمودين أساسيين يتميزان بالمرونة الشديدة وقدرة المستخدم على ضبطهما بالشكل والترتيب الذي يناسبه، حيث يمكن للمستخدم مشاهدة استهلاك المعالج عن طريق الشريط الظاهر أمامه، كما يمكن استخدام شريط واحد لكامل وحدة المعالجة المركزية، إلى جانب إمكانية استعمال شريط لكل معالج موجود، أو تجميع العرض من عدة معالجات معًا ضمن شريط واحد. يُعَد العرض بهذه الطريقة أكثر سهولةً للمستخدم، إلا أنّه يُغفِل العديد من المعلومات الأساسية التي قد تهمّه، ومنها النسبة المستهلكة من المعالج لكل مستخدم، إضافةً إلى وقت الخمول الخاص بالمعالج وغيرها من المعلومات التي تعرضها الأدوات السابقة. يمكن تعديل ضبط هذا الجزء بالضغط على F2 حيث تُعرض الخيارات المتاحة ويضيف المستخدم ما يشاء من هذه الخيارات وترتيبها ضمن العرض كما يشاء. جزء العملية يشبه جزء العملية الخاص بهذه الأداة إلى حد كبير الأدوات السابقة، حيث يمكن ترتيب العمليات اعتمادًا على نسبة استهلاك المعالج، أو الذاكرة، أو المستخدم، أو رقم تعريف العملية، مع ملاحظة أنه لا يمكن استخدام وظيفة الترتيب عندما يختار المستخدم العرض بالشكل الشجري. يختار المستخدم العمود الذي سيكون الترتيب وفقًا له، وذلك بالضغط على F6 لتُعرض مجموعة الأعمدة التي يمكن الترتيب وفقًا لها، وبعد إقدام المستخدم على الاختيار، فسيضغط على Enter لتنفيذ عملية الترتيب. يمكن التنقّل بين العمليات باستخدام الأسهم وذلك لاختيار عمليةٍ ما، وبعد الاختيار يمكن قتل العملية بالضغط على k، ومن ثم تظهر قائمة بالإشارات ليختار المستخدِم واحدةً منها، بحيث تُرسل إلى العملية. يمكن أيضًا الضغط على المفتاحين F7 وF8 لتغيير مستوى اللطافة للعملية المختارة. يمكن الضغط على F5 لأية عملية لتُعرض شجرة العملية كاملةً، وبالتالي يمكن تحديد العملية الأب الذي ولّد هذه العملية، وتُعَد هذه المسألة هامةً جدًا عند تشخيص مشاكل العمليات، وخصيصًا ظهور عمليات "ميتة-حية" في النظام. الضبط يمتلك كل مستخدم ملف ضبط خاص به مخزنًا في المسار"‎~/.config/htop/htoprc"، وتُحفَظ التغييرات التي يجريها المستخدم في هذا الملف تلقائيًا. لا تمتلك هذه الأداة ضبطًا عامًا وإنما يوجد الضبط فقط ضمن ملفات المستخدم. أداة glances تتميز هذه الأداة بقدرتها على عرض الكثير من المعلومات عن الجهاز موازنةً بجميع الأدوات السابقة، كما تعرض الأداة إلى جانب المعلومات التي تعرضها الأدوات السابقة على سبيل المثال: درجات الحرارة الخاصة بمكونات الحاسب، إضافةً إلى سرعة دوران المروحة المستخدمة مع كل مكون، والكثير من المعلومات المفيدة. تُعَد السلبية الوحيدة لهذه الأداة أنها تستهلك نسبةً كبيرةً من الموارد موازنةً بسابقاتها، وتتراوح نسبة استهلاكها للمعالج بين 10% و18% من إجمالي استخدام المعالج، وهذه النسبة كبيرة جدًا خصوصًا في الأنظمة المحدودة بالموارد. جزء الملخص يحتوي جزء الملخص لأداة glances على معظم المعلومات التي تقدّمها أدوات المراقبة الأخرى، حيث تعرض الأداة معلومات استخدام المعالج بشكل شريط و بشكل عددي في حال كانت أبعاد الشاشة تسمح بذلك، وإلا فإنها ستعرض النتائج بالشكل العددي فقط. الشكل (4): يُظهر الشكل واجهة الأداة glances متضمنةً معلومات الشبكة والقرص ونظام الملفات ومعلومات الحساسات. كما في الأدوات السابقة، يمكن الضغط على 1 لتغيير طريقة عرض معلومات المعالج إما لتعرِض المعلومات عن إجمالي استخدام المعالج أو عرض المعلومات الخاصة بكل معالج على حدى. جزء العملية يعرض هذا الجزء المعلومات الاعتيادية عن كل من العمليات قيد التشغيل، حيث يمكن أن تُرتَّب العمليات تلقائيًا بالضغط على a، أو بالاعتماد على استهلاك المعالج c، أو بالاعتماد على استهلاك الذاكرة m، أو بالاعتماد على اسم العملية p، أو بالاعتماد على اسم المستخدم u، أو بالاعتماد على معدل الإدخال والإخراج i، أو بالاعتماد على الوقت t. يعني أن الترتيب التلقائي في الأداة هو اختيار عرض العمليات بالاعتماد على المورد الأكثر استخدامًا، فإذا كان استهلاك المعالج أكبر من 70%، فسيعتمد ترتيب العمليات على استهلاك كل عملية من وقت المعالج، وإذا كان استهلاك الذاكرة أكبر من 70%، فيعتمد الترتيب على استهلاك كل عملية من الذاكرة. تُظهر الأداة الإنذارات والتحذيرات في أسفل الشاشة متضمّنةً تاريخ ومدة بقاء الإنذار. حيث يفيد وجود الإنذارات بإخبار المستخدِم عند وقوع المشكلة، وبالتالي لا يكون مضطرًا لمراقبة الشاشة ومتابعة تغير الأرقام بدقة دائمًا. ويمكن تشغيل وإيقاف الإنذارات بالضغط على l، كما يمكن إزالة الإنذارات الحالية بالضغط على w، ويمكن إزالة الإنذارات والتحذيرات معًا بالضغط على x. لا تقتل هذه الأداة العمليات لأنها مجرد أداة للمراقبة، كما أنها لا تغير من مستوى اللطافة للعملية للسبب ذاته، وإذا رغب المستخدم بذلك فيجب عليه استخدام الأوامر kill أو renice خارج هذه الأداة. الشريط الجانبي تمتلك الأداة glances شريطًا جانبيًا جميلًا والذي يعرِض معلومات غير موجودة في كل من top وhtop. يمكن أن تعرِض atop بعضًا من المعلومات التي تعرضها هذه الأداة، ولكن فقط glances هي القادرة على عرض معلومات حساسات الحرارة من الأدوات السابقة، كما يمكن عرض المعلومات عن الأقراص ونظام الملفات والشبكة والحساسات، بالضغط على d أو f أو n أو s بالترتيب، ويمكن اظهار الشريط الجانبي بالضغط على 2، كما يمكن عرض الإحصائيات في أسفل الشاشة بالضغط على D. الضبط لا تتطلب الأداة glances ملفًا للضبط لكي تعمل بصورة صحيحة، ولكن في حال رغبة المستخدم بوجوده، فيوجد ملف الضبط العام ضمن المجلد الحامل لهذه التسمية "‎"/etc/glances/glances.conf، فعندما ينشئ المستخدم ملف الضبط الخاص به ضمن المسار "‎"~/.config/glances/glances.conf، فإنه سيصبح ملف الضبط الفعال، ويتجاوز ملف الضبط العام. يمكن ضمن هذه الملفات تحديد عتبات الإنذارات والتحذيرات فقط، في حين فيجب إعادة ضبط أية تعديلات أخرى على الأداة مثل تعديل الشريط الجانبي أو غيره في كل مرة بعد تشغيل الأداة. يتضمن توثيق الأداة معلومات كافية عن استخدام الأداة glances، وتكون موجودةً افتراضيًا ضمن المسار التالي: "‎/usr/share/doc/glances/glances-doc.html" وعلى الرغم من أنه قد ذُكِر في الوثيقة أنه يمكن ضبط الأداة كاملةً عن طريق الملف، إلا أنّه لم تُذكر أية طريقة لتحقيق ذلك ضمن الملف. الخلاصة يجب على المستخدم قراءة الدليل الخاص بكل أداة من أدوات المراقبة للتعرف على الطريقة التي تناسب المستخدم في ضبطها والتفاعل معها، ويمكن دومًا الاستعانة بالأمر h ضمن الأدوات للاستفادة من المساعدة التفاعلية الموجودة ضمنها، والتي تقدّم الكثير من المعلومات حول تنفيذ عمليات الاختيار والترتيب في الأداة. يمكن أن تقدّم هذه الأدوات الكثير من المعلومات عن سبب المشاكل التي تصادف المستخدم، كما يمكن أن تحدد أيًا من العمليات هو الأكثر استهلاكًا للمعالج، أو تحديد كمية الذاكرة الحرّة المتاحة، إضافةً إلى معرفة أي من العمليات قد أوقفت مؤقتًا لأنها تنتظر عمليات الإدخال والإخراج، أو لأنها تنتظر الشبكة. يمكن بالمراقبة المستمرة لهذه الأدوات أن يستطيع المستخدِم التمييز بين السلوك الطبيعي للنظام عن السلوك غير الطبيعي الذي يظهر بالنهاية على هيئة مشكلة في الأداء، كما يجب الأخذ بالحسبان أنّ هذه الأدوات تستهلك من موارد الحاسوب الذي تراقبه، حيث تستهلك الأداة glances نسبةً تتراوح بين 10% و20% من وقت المعالج، بينما لا تستهلك الأدوات المتبقية أكثر من 3% من نفس المورد، ويجب التفكير بذلك جيدًا عند اختيار الأداة المناسبة بتقدير نوع المعلومات التي يحتاج المستخدم مراقبته إضافةً إلى معرفة مواصفات الجهاز الذي يُراقَب. ترجمة -وبتصرف- للمقال "‎4 open source tools for Linux system monitoring" لصاحبه David Both. اقرأ أيضًا ما هو نظام التشغيل لينكس؟ مدخل إلى مصطلحات ومفاهيم التخزين في لينكس عشرون أمرا في لينكس يفترض أن يعرفها كل مدير نظم دليل المستخدم للروابط في نظام ملفات لينكس
×
×
  • أضف...