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

Ali Issa

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

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

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

  • عدد الأيام التي تصدر بها

    1

كل منشورات العضو Ali Issa

  1. تعتقد أنّك تعرف كل شيء عن sudo؟ فكّر بذلك مجدّدًا. يعرف الجميع sudo أليس كذلك؟ تُثبَّت هذه الأداة بشكل افتراضي على معظم أنظمة Linux وهي متوفّرة لمعظم توزيعات BSD (اختصارًا إلى Berkeley Software Distributions) ومختلف توزيعات يونكس التجاريّة. ومع ذلك كانت الإجابة الأكثر شيوعًا التي تلقيتها بعد التحدث إلى مئات مستخدمي sudo هي أنّ sudo أداة لتعقيد الحياة. يوجد لديك مستخدم جذر root ولديك أمر su، فلماذا يكون لديك أداة أخرى؟ كان sudo بالنسبة للكثيرين مجرّد بادئة للأوامر الإداريّة. ذكرت قلّة قليلة فقط أنّه يمكنك استخدام سجلات sudo لمعرفة من قام بعملٍ ما عندما يكون لديك العديد من المسؤولين في نفس النظام. ما هو sudo؟ وفقًا لموقع sudo الإلكتروني: يأتي sudo افتراضيًّا بضبط بسيط، حيث أن قاعدة واحدة تسمح للمستخدم أو لمجموعة من المستخدمين بالقيام بأي شيء عمليًا (المزيد حول ملف الضبط لاحقًا ضمن هذه المقالة): %wheel ALL=(ALL) ALL تعني «المعاملات» (parameters) في هذا المثال ما يلي: يحدّد المعامل الأول أعضاء المجموعة. يحدّد المعامل الثاني المُضيف (المضيفين) الذي يمكن لأعضاء المجموعة تشغيل الأوامر عليه. يحدّد المعامل الثالث أسماء المستخدمين التي يمكن بموجبها تنفيذ الأمر. يحدّد المعامل الأخير التطبيقات التي يمكن تشغيلها. لذلك يمكن لأعضاء مجموعة Wheel في هذا المثال تشغيل جميع التطبيقات مثل كافة المستخدمين على جميع المضيفين. حتى هذه القاعدة المتسامحة حقًا مفيدة لأنها تؤدي إلى تسجيل من قام بعملٍ ما على جهازك. الأسماء المستعارة (Aliases) بالطبع بمجرّد كونك لا تقوم أنت وصديقك المفضّل فقط بإدارة صندوق مشترك ما، فسوف تبدأ التفكير في ضبط الأذونات. يمكنك استبدال العناصر الموجودة في الضبط أعلاه بقوائم: قائمة المستخدمين، قائمة الأوامر، وما إلى ذلك. ستَنسخ على الأرجح وتلصق بعض هذه القوائم في الضبط الخاص بك. في مثل هذه الحالة حيث يكون استخدام الأسماء المستعارة في متناول اليد. يكون الحفاظ على نفس القائمة في أماكن متعدّدة عُرضة للخطأ. بالإمكان تعريف اسم مستعار مرّة واحدة وبعد ذلك يمكنك استخدامه مرّات عديدة. لذلك عندما تفقد الثقة في أحد أو بعض المسؤولين لديك، يمكنك إزالتَهم من خلال الاسم المستعار وينتهي الأمر. ولكن مع وجود قوائم متعددة بدلاً من الأسماء المستعارة فإنّه من السهل أن تنسى إزالة مستخدم ما من إحدى القوائم ذات الامتيازات العالية. تمكين الميزات لمجموعة معيّنة من المستخدمين يأتي الأمر sudo مزودًا بمجموعة كبيرة من الإعدادات الافتراضيّة. لا يزال هناك حالات تريد فيها تغيير بعضٍ من هذه الإعدادات. وذلك عند استخدام التعليمة Defaults في الضبط. عادةً ما يتم فرض هذه الإعدادات الافتراضيّة على كل مستخدم، ولكن يمكنك تضييق مجال هذه الإعدادات لتُطبّق فقط على مجموعة فرعيّة من المستخدمين بناءً على المضيف واسم المستخدم وما إلى ذلك. هنا مثال على أن مسؤول النظام الخاص بي (sysadmins) يُحبّ استخدام "التوبيخ" insults. وهي مجرّد بضع رسائل هزليّة تظهر كَتوبيخ عندما يُخطئ المستخدم في كلمة السرّ عند تنفيذ أوامر في sudo: czanik@linux-mewy:~> sudo ls [sudo] password for root: Hold it up to the light --- not a brain in sight! [sudo] password for root: My pet ferret can type better than you! [sudo] password for root: sudo: 3 incorrect password attempts czanik@linux-mewy:~> وبما أنه ليس الجميع معجب بفكاهة مدير النظام، تُعطّل هذه التوبيخات افتراضيًا. يوضّح المثال التالي كيفية تمكين هذا الإعداد فقط لمسؤولي النظام المتمرسين وهم أعضاء في المجموعة wheel: Defaults !insults Defaults:%wheel insults ليس لدي ما يكفي من الأصابع لتعداد الأشخاص الذين شكروني على إعداد هذه الرسائل. مُصادقة القيم المختصرة المشفرة (Digest verification) بالطبع هناك ميزات أكثر أهميّةً في sudo كذلك. إحدى الميزات هي «مُصادقة القيم المختصرة المشفرة» (digest verification). يمكنك تضمين مصادقة القيم المختصرة المشفرة للتطبيقات في الضبط الخاص بك: peter ALL = sha244:11925141bb22866afdf257ce7790bd6275feda80b3b241c108b79c88 /usr/bin/passwd يقوم sudo في هذه الحالة بفحص وموازنة القيمة المتخصرة المشفرة لتطبيق مع القيمة المشفرة المختصرة لتطبيق المخزّن في الضبط قبل تشغيله. فإذا لم يكونا متطابقين عندها يرفض sudo تشغيل التطبيق. على الرغم من صعوبة الحفاظ على هذه المعلومات في الضبط الخاص بك – حيث لا توجد أدوات تلقائية لهذا الغرض - إلا أنّ هذه الملخّصات يمكن أن توفر لك طبقة إضافيّة من الحماية. تسجيل الجلسة تسجيل الجلسة هو أيضًا ميزة أقل شهرةً لـ sudo. بعد عرضي التوضيحي يغادر كثير من الأشخاص محادثتي مع خطط عازمين على تنفيذها على بنيتهم التحتيّة. لماذا؟ لأن تسجيل الجلسة لا يتيح لك رؤية اسم الأمر فقط، بل كل ما يحدث في الجهاز الطرفي أيضًا. فبإمكانك معرفة ما يفعله المسؤولون لديك حتى لو كان لديهم وصول إلى الصدفة (shell) والسجلات تُظهر فقط أن bash بدأ العمل. توجد محدوديّة واحدة حاليًّا وهي أن السجلات تخزّن محليًّا، لذلك يمكن للمستخدمين حذف سجلات التتبع الخاصّة بهم إذا توفرت لهم أذونات كافية. ترقبوا الميزات القادمة. الإضافات تم تغيير sudo إلى بنية معياريّة قائمة على «الإضافات» (plugins) بدءًا من الإصدار 1.8. حيث أصبح بالإمكان استبدال أو توسيع وظائف sudo بسهولة عن طريق كتابة وظائفك الخاصّة، وذلك اعتمادًا على معظم الميزات التي نُفّذت كإضافات. يتوفر حاليًا كلًّا من الإضافات مفتوحة المصدر والإضافات التجاريّة لـ sudo. عَرضتُ في حديثي الإضافة sudo_pair والتي تتوفر على GitHub. طوّرت هذه الإضافة في Rust مما يعني أنه ليس من السهل «ترجمتها» (compile) والأكثر صعوبةً من ذلك هو نشر النتائج. تُوفّر الإضافات من ناحيةٍ أخرى وظائف مثيرة للاهتمام، مُتطلبةً من مسؤولٍ ثانٍ الموافقة (أو الرفض) لتشغيل الأوامر من خلال sudo. ليس ذلك فحسب، بل يمكن أيضًا تتبع الجلسات على الشاشة وإنهاؤها في حال وجود نشاط مشبوه. في عرضٍ توضيحيّ قدمته خلال حديثي مؤخرًا في مؤتمر "All Things Open" شعرت كمن يجلب لنفسه السمعة السيئة. czanik@linux-mewy:~> sudo rm -fr / كان الجميع يحبس أنفاسهم لمعرفة ما إذا كان جهاز الحاسوب المحمول قد دُمّر عند رؤية الأمر المعروض على الشاشة، لكنه نجا. السجلات يُعدّ التسجيل والتنبيه جزءًا مهمًا من sudo كما ذكرت سابقًا في البداية. إذا لم تقم بفحص سجلات sudo الخاصّة بك بانتظام فليس هناك قيمة كبيرة لاستخدام sudo. تُنبّه هذه الأداة عن طريق البريد الإلكتروني عن الأحداث المحدّدة في الضبط وتُسجل جميع الأحداث في syslog. يمكن تشغيل سجلات التنقيح (Debug) واستخدامها لتصحيح القواعد أو الإبلاغ عن «الأخطاء» (bugs). التنبيهات Alerts تعد تنبيهات البريد الإلكتروني من النمط القديم الآن، ولكن إذا كنت تستخدم syslog-ng لتَجميع رسائل السجل الخاصّة بك، فستُنقّح رسائل سجل sudo تلقائيًا. يمكنك بسهولة إنشاء تنبيهات مخصّصة وإرسالها إلى مجموعة واسعة من الوجهات، بما في ذلك Slack أو Telegram أو Splunk أو Elasticsearch. الضبط تحدثنا كثيرًا عن ميزات sudo وحتى شاهدنا بضعة أسطر من «الضبط» (Configuration). دعنا الآن نلقي نظرة أقرب على كيفيّة ضبط sudo. الضبط نفسه متاح في ‎/etc/sudoers وهو ملف نصيّ بسيط. ومع ذلك ما يزال لا يُنصح بتحرير هذا الملف مباشرة، استخدم بدلاً من ذلك visudo حيث تتحقق هذه الأداة من بناء الجملة النحويّ أيضًا. بإمكانك إذا كنت لا تحب vi تغيير المحرّر المُستخدَم عن طريق ضبط متغير البيئةEDITOR إلى الخيار المفضل لديك. تأكّد قبل البدء في تحرير ضبط sudo من معرفة كلمة مرور المستخدم root. (نعم، حتى على Ubuntu حيث الـ root ليس لديه كلمة مرور افتراضيًّا.) بما أنّ visudo يتحقّق من البناء النحويّ للجملة فمن السهل إنشاء ضبط صحيح نحويًّا يمنعك من الولوج إلى نظامك. يمكنك عندما تتوفر لديك كلمة مرور جذر في حالة الطوارئ البدء في تحرير الضبط الخاص بك. هناك شيء واحد مهم يجب تذكره عندما يتعلق الأمر بملف sudoers وهو أنّه: يُقرأ هذا الملف من الأعلى إلى الأسفل وبالتالي يُنفّذ الإعداد الأخير. ما تعنيه هذه الحقيقة بالنسبة لك هو أنّه يجب أن تبدأ بالإعدادات العامّة وتضع الاستثناءات في النهاية، وإلا فإنّ الإعدادات العامة ستُلغي الاستثناءات. يمكنك العثور على ملف sudoers بسيط أدناه اعتمادًا على ذلك الموجود في CentOS وإضافة بضعة أسطر كنا قد ناقشناها سابقًا: Defaults !visiblepw Defaults always_set_home Defaults match_group_by_gid Defaults always_query_group_plugin Defaults env_reset Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE" Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin root ALL=(ALL) ALL %wheel ALL=(ALL) ALL Defaults:%wheel insults Defaults !insults Defaults log_output يبدأ هذا الملف عن طريق تغيير عدد من الإعدادات الافتراضيّة. ثم تأتي القواعد الافتراضيّة المعتادة: المستخدم root وأعضاء مجموعة wheel لديهم أذونات كاملة على الجهاز. نُمكّن بعد ذلك insults لمجموعة wheel ونعطّلها للجميع. يفعّل السطر الأخير تسجيل الجلسة. الضبط أعلاه صحيح نحويًّا، لكن هل يمكنك اكتشاف الخطأ المنطقي؟ نعم، هناك خطأ: تُعطّل insults للجميع عند آخر إعداد عام حيث يُلغي الإعداد السابق الإعداد الأكثر تحديدًا. وبمجرّد تبديل السطرين يعمل الإعداد كما هو متوقع: يتلقى أعضاء مجموعة wheel رسائل هزليّة في حين أنً باقي المستخدمين لن يتلقونها. إدارة الضبط بمجرد أن تضطر إلى الاحتفاظ بملف sudoers على أجهزة متعدّدة فمن المرجح أنك تريد إدارة الضبط الخاص بك مركزيًا. لدينا هنا احتمالان رئيسيان مَفتوحا المصدر. لكلٍ منهما مزايا وعيوب. يمكنك استخدام أحد تطبيقات إدارة الضبط التي تستخدمها أيضًا لضبط بقية البنية التحتيّة الخاصّة بك. تحتوي Red Hat Ansible و Puppet و Chef على وحدات لضبط sudo. المشكلة في هذا النهج هي أنّ تحديث الضبط بعيد عن الوقت الحقيقي. كما أنه لا يزال بإمكان المستخدمين تحرير ملف sudoers محليًا وتغيير الإعدادات. يمكن للأداة sudo أيضًا تخزين ضبطها في خادم LDAP. تكون تغييرات الضبط في هذه الحالة في الوقت الحقيقي ولا يمكن للمستخدمين العبث بملف sudoers. ولكن من ناحية أخرى لهذه الطريقة محدوديّة أيضًا. حيث لا يمكنك على سبيل المثال استخدام الأسماء المستعارة aliases أو استخدام sudo عندما يكون خادم LDAP غير متوفر. ميزات جديدة هناك نسخة جديدة من sudo قاب قوسين أو أدنى. سيتضمن الإصدار 1.9 العديد من الميزات الجديدة المثيرة للاهتمام. فيما يلي أهم الميزات المُخطط لها: خدمة تسجيل لجمع تسجيلات الجلسة مركزيًا والتي توفر العديد من المزايا مقارنة بالتخزين المحلي: أكثر ملاءمة للبحث حيث يتم ذلك في مكان واحد. تتوفر التسجيلات حتى ولو كان جهاز المرسل متوقفا. لا يمكن حذف التسجيلات بواسطة شخص يريد حذف سجلات التتبع الخاصّة به. لا تضيف الإضافة "Audit" ميزات جديدة إلى sudoers، ولكنها توفّر واجهة برمجة تطبيقات API للإضافات للوصول بسهولة إلى أي نوع من سجلات sudo. تمكّن هذه الإضافة إنشاء سجلات مخصّصة من أحداث sudo باستخدام الإضافات. تُمكّن إضافة approval موافقات الجلسة دون استخدام إضافات خارجية (third-party plugins). والميزة المفضّلة لدي شخصيًا: دعم Python للمكونات الإضافيّة والتي تمكّنك من توسيع sudo بسهولة باستخدام شيفرة Python بدلاً من كتابة شيفرة أصليّة في C. الخلاصة آمل أن يكون هذا المقال قد أثبت لك أن sudo أكثر بكثير من مجرّد بادئة بسيطة. هناك الكثير من الاحتمالات لضبط الأذونات على نظامك. فأنت هنا لا تتمكن من ضبط الأذونات فحسب بل تتمكن أيضًا من تحسين الأمان عن طريق التحقق من عمليات مصادقة digests. تُمكّنك تسجيلات الجلسة من التحقّق مما يحدث على أنظمَتك. بإمكانك أيضًا توسيع وظيفة sudo باستخدام الإضافات، إما باستخدام شيء متاح مُسبقًا أو كتابة ما تريد بشكل خاص. أخيرًا وبالنظر إلى قائمة الميزات القادمة يمكنك أن ترى أنه حتى لو كان عمر sudo عقودًا إلاّ أنّه مشروع حيّ يتطور باستمرار. إذا كنت ترغب بمعرفة المزيد عن sudo فإليك بعض الموارد: موقع sudo الإلكتروني مدونة sudo ترجمة وبتصرف للمقال What you probably didn’t know about sudo لصاحبه Peter Czanik
  2. سيُزار موقعك الإلكتروني هذه الأيام من مجموعةٍ واسعةٍ من الأجهزة: أجهزة الحواسيب المكتبيّة ذات الشاشات الكبيرة وأجهزة الحواسيب المحمولة متوسطة الحجم والأجهزة اللوحيّة والهواتف الذكيّة وغيرها. يتوجب على موقعك من أجل تحقيق تجربة المستخدم المثلى كمطوّر واجهة أماميّة (front-end engineer) ضبط تخطيط الصفحة (layout) استجابةً لهذه الأجهزة المختلفة (على سبيل المثال، دقّة الشاشة وأبعادها المتنوعة). يُشار إلى عملية الاستجابة لشكل جهاز المستخدم باسم (ربما توقعت ذلك) تصميم الويب المتجاوب (RWD). لماذا يجدر بك صرف وقتك لدراسة أمثلة تصميم الويب المتجاوب وتحويل تركيزك إليه؟ يعمل بعض مصممي الويب على سبيل المثال على التأكّد من الحصول على تجربة مستخدم مستقرة عبر جميع المتصفحات، حيث يمضون غالبًا أيامًا في معالجة قضايا صغيرة باستخدام المتصفح Internet Explorer. هذا نهج فاشل. يُمضي بعض مصممي الويب أيامًا في معالجة المشكلات الصغيرة لمستخدمي متصفح Internet Explorer ويتركون مستخدمي الأجهزة المحمولة لديهم كزوار درجة ثانية. وهذا نهج فاشل. أطلق Mashable على عام 2013 عام تصميم الويب المتجاوب. لماذا ا؟ لأن أكثر من 30 ٪ من «حركة مرور البيانات» (traffic) الخاصّة بهم تأتي من الأجهزة المحمولة. إنّهم يتوقعون أن يصل هذا العدد إلى 50٪ بحلول نهاية العام. في الويب بشكل عام، جاءت 17.4٪ من حركة مرور بيانات الويب من الهواتف الذكيّة في عام 2013. يمثل استخدام Internet Explorer في الوقت نفسه على سبيل المثال 12٪ فقط من إجمالي حركة مرور بيانات المستعرض، بانخفاض وقدره 4٪ تقريبًا عن مثل هذا الوقت من العام الماضي (وفقًا لـ W3Schools). إذا كنت تعمل على التحسين لمتصفح معين، بدلًا من مستخدمي الهواتف الذكيّة العالميين، فأنت تضيع في التفاصيل. يمكن أن يُشكّل هذا في بعض الحالات الفرق بين النجاح والفشل - التصميم المتجاوب له آثار على معدلات التحويل (conversion rates) وتحسين ظهور الموقع في محركات البحث (SEO) ومعدلات الارتداد (bounce rates) وغيرها. نهج تصميم الويب المتجاوب إنّ الأمر الأكثر أهميّة في RWD عادةً لا يتعلق فقط بضبط مظهر صفحات الويب الخاصّة بك، بل إنّ التركيز يجب أن يكون على تكييف موقعك منطقيًا للاستخدام عبر أجهزة مختلفة. على سبيل المثال: لا يوفّر استخدام الماوس تجربة المستخدم نفسها التي توفّرها شاشة اللمس. ألا توافقني الرأي؟ يجب أن يعكس تخطيط هاتفك المحمول مقابل تخطيطات الأجهزة المكتبيّة هذه الاختلافات. أنت لا تريد في الوقت نفسه إعادة كتابة موقعك بالكامل من أجل كل حجم من عشرات الأحجام المختلفة للشاشة التي قد يُعرض عليها - فهذه الطريقة ببساطة غير مُمكنة. إنّ الحل البديل هو استعمال عناصر تصميم متجاوبة مرنة تستخدم نفس شيفرة الـ HTML للتكيّف مع حجم شاشة المستخدم. يكمن الحل من وجهة نظر تقنيّة في هذا الدليل للتصميم المتجاوب: في استخدام استعلامات وسائط CSS والعناصر الزائفة وضبط تخطيطات الشبكة المرنة، وأدوات أخرى للتكيُّف ديناميكيًا مع دقّة معيّنة. استعلامات الوسائط في التصميم المتجاوب ظهرت أنواع الوسائط للمرة الأولى في HTML4 و CSS2.1، مما أتاح وضع ملف CSS منفصل للشاشة و آخر للطباعة. وبهذه الطريقة، أصبح بالإمكان تعيين أنماط منفصلة لعرض الصفحة على الحاسوب بشكل مقابل للنسخة المطبوعة. <link rel="stylesheet" type="text/css" href="screen.css" media="screen"> <link rel="stylesheet" type="text/css" href="print.css" media="print"> أو @media screen { * { background: silver } } يمكنك في CSS3 تحديد تنسيق الصفحة وتخطيطها اعتمادًا على عرض الصفحة. ولأن عرض الصفحة يرتبط بحجم جهاز المستخدم، فإنّ هذه الإمكانية تتيح لك بالتالي تحديد تخطيطات مختلفة للأجهزة المختلفة. ملاحظة: تُدعم استعلامات الوسائط من قبل جميع المتصفحات الرئيسية إنّ هذا التعريف ممكن من خلال إعداد الخصائص الأساسية: max-widt وdevice-width وorientation وcolor وهناك تعريفات أخرى ممكنة كذلك، ولكن في هذه الحالة فإنّ أهم الأشياء التي يجب وضعها في الحسبان هو الحد الأدنى من الدقّة («العرض» (width)) وإعدادات الاتجاه (أفقي أو عمودي). يوضّح مثال CSS المتجاوب أدناه الإجراء لبدء ملف CSS معين اعتمادًا على عرض الصفحة. ستُطبّق على سبيل المثال الأنماط المحدّدة في الملف main_1.css إذا كان الحد الأقصى لدقّة شاشة الجهاز الحالي هو 480 بكسل. <link rel="stylesheet" media="screen and (max-device-width: 480px)" href="main_1.css" /> يمكننا أيضًا تحديد أنماط مختلفة داخل ورقة أنماط CSS نفسها بحيث تُستخدم فقط في حالة استيفاء قيود محدّدة. لن يُستخدم على سبيل المثال هذا الجزء من ملف CSS المتجاوب إلا إذا كان عرض الجهاز الحالي أكثر من 480 بكسل: @media screen and (min-width: 480px) { div { float: left; background: red; } ....... } التكبير الذكيّ (smart zoom) تَستخدم متصفحات الهاتف المحمول ما يسمى «التكبير الذكي» (smart zoom) لتزويد المستخدمين بتجربة قراءة "ممتازة". يُستخدم التكبير الذكيّ في الأساس لتقليل حجم الصفحة بشكل متناسب. وهذا يمكن أن يظهر بطريقتين: (1) التكبير الذي يبدؤه المستخدم (على سبيل المثال، النقر مرتين على شاشة iPhone للتكبير على موقع الويب الحالي)، و(2) عرض نسخة مكبّرة منذ البداية من صفحة الويب عند التحميل. نظرًا لأنه يمكننا فقط استخدام استعلامات الوسائط المتجاوبة لحل أي من المشكلات التي قد يستهدفها التكبير / التصغير الذكيّ، فمن المستحسن في كثير من الأحيان (أو حتى الضروري) تعطيل التكبير والتأكّد من أنّ محتوى صفحتك يملأ المتصفح دائمًا: <meta name="viewport" content="width=device-width, initial-scale=1" /> إننا نتحكم في مستوى تكبير الصفحة الأولي (أي مقدار التكبير عند تحميل الصفحة) عن طريق ضبط قيمة initial-scale إلى القيمة 1. إذا صُممت صفحة الويب الخاصة بك لتكون متجاوبة، فإنّه عليك أن يملأ التصميم الديناميكي المتكيّف شاشة الهاتف الذكي بطريقة ذكيّة دون الحاجة إلى أي تكبير أولي. يمكننا إضافة إلى ذلك تعطيل التكبير / التصغير بالكامل باستخدام user-scalable=false. عرض الصفحة (page widths) افترض أنك ترغب بتوفير ثلاثة تخطيطات مختلفة للصفحة المتجاوبة: واحدة من أجل أجهزة الحواسب المكتبيّة، وأخرى للأجهزة اللوحيّة (أو أجهزة الحواسيب المحمولة)، وثالثة للهواتف الذكيّة. ما هي أبعاد الصفحة التي يجب أن تستهدفها كقوالب (على سبيل المثال، 480 بكسل)؟ لا يوجد لسوء الحظ معيار محدّد يمكن اعتماده لعرض الصفحة (page width)، ولكن غالبًا ما يتم استخدام قيم التجاوب التالية: 320 بكسل 480 بكسل 600 بكسل 768 بكسل 900 بكسل 1024 بكسل 1200 بكسل يوجد مع ذلك عددًا من تعريفات العرض المختلفة. يحتوي على سبيل المثال عرض 320 وما فوق على خمس زيادات افتراضية لاستعلام الوسائط في CSS3 وهي:480، 600، 768، 992، 1382 بكسل. يمكنني أن أعدّد عشرة أساليب أخرى على الأقل إضافة إلى المثال الوارد في هذا الدليل لتطوير الويب المتجاوب. يمكنك تغطية معظم أجهزة العرض مع أي من هذه المجموعات المنطقية من الزيادات. عمليًا لا توجد حاجة عادةً للتعامل بشكل منفصل مع جميع الأمثلة المذكورة أعلاه لعرض الصفحة- سبعة خيارات دقّة مختلفة تُعدّ مبالغةً نوعًا ما. إنّ 320px و 768px و 1200px هي القيم الأكثر استخدامًا اعتمادًا على تجربتي. يجب أن تكون هذه القيم الثلاثة كافيةً للتعامل مع الهواتف الذكيّة والأجهزة اللوحيّة / أجهزة الحواسيب المحمولة وأجهزة الحواسيب المكتبيّة بالترتيب. العناصر الزائفة (Psuedo-Elements) قد ترغب أيضًا بناءً على أفضل استعلامات الوسائط المتجاوبة لديك في المثال السابق بإظهار أو إخفاء معلومات معيّنة برمجيًّا وفقًا لحجم شاشة جهاز المستخدم. يمكن لحسن الحظ تحقيق ذلك أيضًا باستخدام CSS صرف كما هو موضّح في الدليل أدناه. بالنسبة للمبتدئين، يمكن أن يكون إخفاء بعض العناصر (display: none;‎) حلاً رائعًا عندما يتعلق الأمر بتقليل عدد العناصر التي تظهر على شاشة التخطيط الخاص بالهاتف الذكيّ حيث لا تتوفر دائمًا مساحة كافية. يمكنك من جهة أخرى أيضًا أن تكون مبدعًا باستخدام عناصر CSS الزائفة (محددات (selectors))، مثل ‎:before و‎:aft. ملاحظة: مرّةّ أخرى، تُدعم العناصر الزائفة من قبل جميع المتصفحات الرئيسية. تُستخدم العناصر الزائفة لتطبيق أنماط محدّدة على أجزاء محدّدة لعنصر HTML، أو لتحديد مجموعة فرعيّة معيّنة من العناصر. يتيح لك على سبيل المثال العنصر الزائف :first-line تحديد الأنماط المطبّقة فقط على السطر الأول لمحدّد معين (على سبيل المثال، p:first-line سيُطبّق على السطر الأول من كل عناصر الفقرة p). وبالمثل، فسيُتيح لك العنصر الزائف a:visited تحديد الأنماط المطبّقة على كافة عناصر a مع الروابط التي زارها المستخدم سابقًا. كان هذا مفيدًا صراحةً. فيما يلي مثال بسيط لتصميم متجاوب، حيث نُنشئ ثلاثة تخطيطات مختلفة لزر تسجيل الدخول لكل من أجهزة الحواسيب المكتبيّة والأجهزة اللوحيّة والهواتف الذكيّة. سيكون لدينا على الهاتف الذكيّ فقط أيقونة، بينما سيكون على الحاسوب اللوحيّ الأيقونة نفسها مرفقةً بعبارة "User name"، سنُضيف أخيرًا للأجهزة المكتبيّة أيضًا رسالة توضيحيّة قصيرة ("Insert your user name"). .username:after { content:"Insert your user name"; } @media screen and (max-width: 1024px) { .username:before { content:"User name"; } } @media screen and (max-width: 480px) { .username:before { content:""; } } يمكننا إنجاز ما يلي اعتمادًا فقط على العناصر الزائفة التالية:before و:after:: لمعرفة المزيد عن سحر العناصر الزائفة، يوجد لدى Chris Coyier " وصف تفصيلي جيد عن حيل CSS)(CSS-Tricks. إذًا، من أين أبدأ؟ أنشأنا في هذا الدليل بعضًا من العناصر الأساسيّة لتَصميم ويب متجاوب (أي استعلامات الوسائط والعناصر الزائفة) وقدّمنا بعض الأمثلة لكل منها. ولكن إلى أين سنذهب الآن؟ الخطوة الأولى التي يجب اتخاذها هي تنظيم جميع عناصر صفحة الويب الخاصة بك من أجل أحجام مختلفة للشاشة. ألقِ نظرة على إصدار الأجهزة المكتبيّة للتخطيط المقدّم أعلاه. يمكن في هذه الحالة أن يكون المحتوى على اليسار (المستطيل الأخضر) كنوع من أنواع القائمة الرئيسية. ولكن عند استخدام الأجهزة ذات الدقة المنخفضة (على سبيل المثال، جهاز لوحي أو هاتف ذكي)، فقد يكون من المنطقي إظهار هذه القائمة الرئيسية بالعرض الكامل. يمكنك تطبيق هذا النهج باستخدام استعلامات الوسائط كما يلي: @media screen and (max-width: 1200px) { .menu { width: 100%; } } @media screen and (min-width: 1200px) { .menu { width: 30%; } } لسوء الحظ، غالبًا ما يكون هذا النهج الأساسي غير كافٍ مع زيادة تعقيد الواجهة الأماميّة. ونظرًا لأن تنظيم محتوى الموقع غالبًا ما يختلف اختلافًا كبيرًا بين إصدارات الأجهزة المحمولة والأجهزة المكتبيّة، فإنّ تجربة المستخدم تعتمد في نهاية المطاف ليس فقط على استخدام CSS المتجاوب، ولكن أيضًا على استخدام HTML وJavaScript. هناك عدة عناصر رئيسيّة مهمّة عند تحديدك لتخطيطات متجاوبة للأجهزة المختلفة. يُعد التطوير بالنسبة للهواتف الذكيّة أكثر تطلبًا بخلاف الإصدارات الخاصّة بالحواسيب المكتبيّة حيث تتوفر مساحات كافية لعرض المحتوى. فمن الضروري أكثر من أي وقت مضى تجميع محتويات محدّدة وتحديد أهميّة الأجزاء الفرديّة هرميًّا. إنّه من المهم أكثر من أي وقت مضى بالنسبة للهاتف الذكي تجميع محتويات محدّدة وتحديد أهمية الأجزاء الفرديّة هرميًّا. إنّ الاستخدامات المختلفة لمحتواك مهمة أيضًا. فمثلًا عندما يكون لدى المستخدم إمكانية استخدام الفأرة يمكنه عندها ضبط المؤشر فوق عناصر معيّنة للحصول على معلومات إضافيّة، بحيث يمكنك (كمطوّر ويب) ترك بعض المعلومات لتُجمّع بهذه الطريقة - لكن الحال لن يكون ذاته عند استخدام الهاتف الذكيّ. بالإضافة إلى ذلك، إذا وضعت أزرارًا على موقعك والتي ستظهر على الهواتف الذكيّة بحجم أصغر من الحجم النموذجي للإصبع، فسَتخلق حالةً من عدم اليقين وعدم الارتياح في استخدام موقعك وفي مظهره. لاحظ إنّ عرض الويب القياسي في الصورة أعلاه (على اليسار) يجعل بعض العناصر غير قابلة للاستخدام تمامًا عند عرضها على جهاز أصغر. سيزيد هذا السلوك أيضًا من فرص قيام المستخدم بخطأ ما، مما يؤدي إلى إبطاء تجربته. يمكن أن يتجلى ذلك في الممارسة العمليّة في انخفاض عدد مرات عرض الصفحة، وانخفاض المبيعات، ومشاركة أقل بشكل عام. عناصر تصميم متجاوبة أخرى يتوجب تذكّر سلوك جميع عناصر الصفحة عند استخدام استعلامات الوسائط وليس فقط العناصر المستهدفة -لا سيما عند استخدام «الشبكات المرنة» (fluid grids)- وفي هذه الحالة (وعلى عكس الأبعاد الثابتة) ستُملئ الصفحة بالكامل في أي وقت، وسيكبر ويصغر حجم المحتوى بما يتناسب معها. نظرًا لتعيين قيم العرض بالنسب المئوية، يمكن أن يحدث تشوه للعناصر الرسوميّة (أي الصور) أو تلفها عند استخدام الشبكات المرنة. إنّ أحد الحلول للصور هو كما يلي: img { max-width: 100% } يجب التعامل مع العناصر الأخرى بطرق مماثلة. فمثلًا يُعدّ استخدام IconFontsحلًّا رائعًا للأيقونات في تصميم الويب المتجاوب. نبذة عن أنظمة الشبكات المرنة عندما نناقش عملية التكيّف الكامل للتصميم فإننا غالبًا ما نتطلع إلى تجربة المشاهدة المثلى (من وجهة نظر المستخدم). يجب أن تتضمن مناقشة كهذه الحد الأعلى لسهولة الاستخدام ولأهميّة العناصر (استنادًا إلى مناطق الصفحة المرئية) ولسهولة القراءة وللتنقل السهل. يُعدّ ضبط عرض المحتوى (content width) من أهم المكونات من بين التصنيفات السابقة. حدَّدت على سبيل المثال ما يسمى بأنظمة الشبكات المرنة عناصر تعتمد على العرض النسبي كنسب مئوية من الصفحة الإجمالية. وبهذه الطريقة تُضبط تلقائيًا جميع العناصر في نظام تصميم الويب المتجاوب بما يتناسب مع حجم الصفحة. على الرغم من أن أنظمة fluid grids هذه ترتبط ارتباطًا وثيقًا بما ناقشناه هنا، إلا أنّها في الحقيقة كيان منفصل بالكامل يتطلب تعليمًا إضافيًا للمناقشة التفصيليّة. لذلك سأذكر هنا فقط بعضًا من الأُطر الرئيسيّة التي تدعم مثل هذا النهج: Bootstrap و Unsemantic و Brackets. الخلاصة كان تحسين موقع الويب حتى وقت قريب مصطلحًا مخصّصًا حصريًا لتخصيص الوظائف استنادًا إلى متصفحات الويب المختلفة. يفترض هذا المصطلح الآن إلى جانب الصراع المحتوم مع معايير المتصفح المختلفة التي نواجهها اليوم التكيف مع الأجهزة والأحجام المختلفة الشاشة ومع تصميم الويب المتجاوب أيضًا. ولكي يتناسب مع شبكة الإنترنت الحديثة. يجب أن يعرف موقعك ليس فقط من يتصفحه ولكن كيف يتصفحه. ترجمة وبتصرف للمقال Introduction to Responsive Web Design: Pseudo-Elements, Media Queries, and More لصاحبه Tomislav Krnic.
  3. مع انتقال أدوات المطوّرين إلى «السحابة» (cloud)، يتزايد إنشاء واعتماد منصّات بيئة التطوير المتكاملة (IDE) السحابية. تتيح منصّات Cloud IDE التعاون في الوقت الحقيقي بين فرق المطوّرين من أجل العمل في بيئة تطوير موحّدة ما من شأنه التقليل من حالات عدم التوافق وتحسين الإنتاجية. حيث يمكن الوصول إليها من خلال متصفحات الويب، وتتوفر Cloud IDEs من كل أنواع الأجهزة الحديثة. إن code-server هو نسخة Microsoft Visual Studio Code تعمل على خادم بعيد ويمكن الوصول إليها مباشرة من متصفحك. المحرر Visual Studio Code هو محرّر تعليمات برمجيّة حديث مع دعم متكامل لـ Git ومنقّح شيفرة وإكمال تلقائي ذكي وميزات أخرى قابلة للتخصيص والتوسيع. يعني هذا أنه سيتوفر لديك دائمًا بيئة تطوير متناسقة حتى مع استخدامك لأجهزة متنوعة تعمل بأنظمة تشغيل مختلفة. ستقوم في هذه الدليل بإعداد منصّة code-server cloud IDE على جهاز يعمل بنظام تشغيل أبونتو 18.04 وإتاحتها على «اسم النطاق» (domain) خاصتك، وسيكون محميّ بشهادات TLS Let's Encrypt المجانيّة. وسيكون لديك في النهاية نسخة Microsoft Visual Studio Code تعمل على خادم Ubuntu 18.04 الخاص بك ومتاحةً على اسم نطاقك ومحميّة بكلمة مرور. المتطلبات المُسبقة خادم يعمل بنظام تشغيل Ubuntu 18.04 على الأقل مع ذاكرة وصول عشوائي (RAM) سعة 2 جيجا بايت، وامتيازات «وصول المستخدم الجذر» (root access)، وحساب sudo «عادي» (non-root). يمكنك إعداد ذلك باتباع هذا الدليل للإعداد الأولي للخادم. نسخة Nginx مُثبتة على خادمك. للحصول على دليل حول كيفيّة القيام بذلك، أكمل الخطوات من 1 إلى 4 حول كيفيّة تثبيت Nginx على Ubuntu 18.04. كلًّا من سجلي DNS التاليين المُعدّين لخادمك. يمكنك متابعة هذه المقدمة إلى DigitalOcean DNS للحصول على تفاصيل حول كيفية إضافتها. سجل لـyour-domain يشير إلى عنوان IP العام للخادم الخاص بك. سجل لـwww.your-domain يشير إلى عنوان IP العام لخادمك. اسم نطاق domain مسجّل بالكامل لاستضافة code-server يُشير إلى خادمك الخاص. سيَستخدم هذا الدليل code-server.your-domain في كامل المقال. يمكنك شراء اسم نطاق من Namecheap أو الحصول على واحد مجانًا عبر Freenom أو استخدام أي موقع تسجيل نطاقات تختاره. الخطوة 1: تثبيت code-server ستقوم في هذا القسم بإعداد code-server على خادمك الخاص. سيستلزم ذلك تنزيل أحدث إصدار وإنشاء خدمة systemd والتي من شأنها أن تُبقي code-server يعمل دائمًا في الخلفية. ستحدد أيضًا سياسة إعادة التشغيل للخدمة، بحيث يبقى code-server متاحًا بعد الأعطال أو إعادات التشغيل المحتملة. سنُخزن جميع البيانات المتعلقة بـ code-server في مجلد باسم ‎~/code-server أنشئه عن طريق تنفيذ الأمر التالي: mkdir ~/code-server انتقل إليه: cd ~/code-server ستحتاج إلى الانتقال إلى صفحة إصدارات Github لـ code-server واختيار أحدث إصدار من Linux (سيحتوي اسم الملف على الكلمة "linux"). كان الإصدار الأخير عند كتابة هذا التقرير هو 2.1692. نزّله باستخدامwgetعن طريق تشغيل الأمر التالي: wget https://github.com/cdr/code-server/releases/download/2.1692-vsc1.39.2/code-server2.1692-vsc1.39.2-linux-x86_64.tar.gz فكّ بعد ذلك ضغط الأرشيف من خلال تشغيل الأمر التالي: tar -xzvf code-server2.1692-vsc1.39.2-linux-x86_64.tar.gz ستحصل على مجلد باسم الملف الأصلي الذي قمت بتنزيله والذي يحتوي على ملف الـ code-server القابل للتنفيذ. انتقل إليه: cd code-server2.1692-vsc1.39.2-linux-x86_64 انسخ ملف code-server التنفيذي إلى المسار /usr/local/bin حتى تتمكن من الوصول إليه عبر كامل نطاق النظام عن طريق تشغيل الأمر التالي: sudo cp code-server /usr/local/bin أنشئ بعد ذلك مجلد لـ code-server حيث ستُخزين بيانات المستخدم: sudo mkdir /var/lib/code-server الآن وبعد تنزيلك لـ code-server وجعله متاحًا على مستوى النظام، ستُنشئ خدمة systemd لإبقاء code-server يعمل في الخلفيّة بشكل دائم. ستخزّن ضبط الخدمة في ملف باسم code-server.service، في المسار‎/lib/systemd/system حيث يخزن systemd خدماته. أنشئه باستخدام محرّر نصوصك الخاص: sudo nano /lib/systemd/system/code-server.service أضف الأسطر التالية في الملف ‎/lib/systemd/system/code-server.service: [Unit] Description=code-server After=nginx.service [Service] Type=simple Environment=PASSWORD=your_password ExecStart=/usr/local/bin/code-server --host 127.0.0.1 --user-data-dir /var/lib/code-server --auth password Restart=always [Install] WantedBy=multi-user.target يتوجب عليك هنا أولًا تحديد وصفٍ للخدمة. تذكر بعد ذلك أنّ خدمة nginx يجب أن تُشغّل قبل هذه الخدمة. يمكنك بعد القسم [Unit] تحديد نوع الخدمة (تعني simple أنه يجب تشغيل العملية ببساطة) وتجهيز الأمر الذي سيُنفّذ. يمكنك أيضًا تحديد أنّه يجب تشغيل code-server العموميّ القابل للتنفيذ مع إضافة بعض «الوسائط» (arguments) لـ code-server. الوسيط ‎--host 127.0.0.1 يربطه مع localhost، وبذلك يمكن الوصول إليه مباشرة فقط من داخل خادمك الخاص. يعين الوسيط ‎--user-data-dir /var/lib/code-server مسار بيانات المستخدم الخاص به، - يُحدّد ‎--auth password أنّه يجب مصادقة الزائرين باستخدام كلمة مرور، كما هو محدّد في متغير البيئة PASSWORD المصرّح عنه في السطر الذي يسبقه. لا تنسَ استبدال your_password بكلمة مرورك الخاصّة ثم احفظ وأغلق الملف. يطلب السطر التالي من systemd إعادة تشغيل code-server عند حصول أي خلل (على سبيل المثال عند تعطله أو إنهاء العملية قسريًّا). يطلب القسم [Install] من systemd بدء هذه الخدمة عندما يصبح بالإمكان تسجيل الدخول إلى الخادم الخاص بك. ابدأ خدمة code-server عن طريق تشغيل الأمر التالي: sudo systemctl start code-server تحقّق من أنها بدأت بشكل صحيح من خلال مراقبة حالاتها: sudo systemctl status code-server سترى خرجًا مشابهًا لما يلي: code-server.service - code-server Loaded: loaded (/lib/systemd/system/code-server.service; disabled; vendor preset: enabled) Active: active (running) since Mon 2019-12-09 20:07:28 UTC; 4s ago Main PID: 5216 (code-server) Tasks: 23 (limit: 2362) CGroup: /system.slice/code-server.service ├─5216 /usr/local/bin/code-server --host 127.0.0.1 --user-data-dir /var/lib/code-server --auth password └─5240 /usr/local/bin/code-server --host 127.0.0.1 --user-data-dir /var/lib/code-server --auth password Dec 09 20:07:28 code-server-ubuntu-1804 systemd[1]: Started code-server. Dec 09 20:07:29 code-server-ubuntu-1804 code-server[5216]: info Server listening on http://127.0.0.1:8080 Dec 09 20:07:29 code-server-ubuntu-1804 code-server[5216]: info - Using custom password for authentication Dec 09 20:07:29 code-server-ubuntu-1804 code-server[5216]: info - Not serving HTTPS مكّن خدمة code-server لجعله يعمل تلقائيًا بعد إعادة تشغيل الخادم من خلال تشغيل الأمر التالي: sudo systemctl enable code-server قمتَ في هذه الخطوة بتنزيل code-server وجعله متاحًا على نحوٍ عمومي. وقمت بعدها بإنشاء خدمة systemd له وتمكينها، لذلك سيبدأ code-server بالعمل عند كل إقلاع للخادم. بعد ذلك، ستعرضه في نطاقك الخاص من خلال ضبط Nginx ليكون بمثابة وكيل عكسيّ بين الزائر و code-server. الخطوة 2: عرض code-server على نطاقك الخاص ستقوم في هذا القسم بضبط Nginx كوكيل عكسي لـ code-server. كما تعلمت في خطوة المتطلبات المُسبقة لـ Nginx، تُخزّن ملفات ضبط الموقع الخاصة به ضمن ‎/etc/nginx/sites-available، ويجب ربطها لاحقًا بـ ‎/etc/nginx/sites-enabled لتصبح نشطة. سنُخزين الضبط لعرض خادم الشفرة في نطاقك في ملف باسم code-server.conf تحت المسار ‎/etc/nginx/sites-available. ابدأ بإنشائه باستخدام المحرّر الخاص بك: sudo nano /etc/nginx/sites-available/code-server.conf أضف الأسطر التالية في الملف ‎/etc/nginx/sites-available/code-server.conf: server { listen 80; listen [::]:80; server_name code-server.your-domain; location / { proxy_pass http://localhost:8080/; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Accept-Encoding gzip; } } استبدل code-server.your-domain باسم لنطاق المطلوب ثم احفظ وأغلق الملف. تحدّد في هذا الملف أنه على Nginx أن يتنصت إلى منفذ HTTP رقم 80. ثم يمكنك تحديد server_name والذي يُخبر Nginx عن النطاق الذي يقبل الطلبات ويطبّق هذا الضبط المحدّد. في الكتلة التالية بالنسبة، لموقع الجذر (/) يمكنك تحديد أنّ الطلبات يجب تمريرها ذهابًا وإيابًا إلى code-server يعمل على localhost:8080. تطلب الأسطر الثلاثة التالية (بدءًا من proxy_set_header) من Nginx نقل بعض ترويسات طلبات HTTP اللازمة من أجل التشغيل الصحيح لـ WebSockets، والذي يستخدمه code-server على نطاق واسع. ستحتاج إلى إنشاء رابط له في المجلد ‎/etc/nginx/sites-enableمن أجل تنشيط ضبط هذا الموقع وذلك من خلال تشغيل الأمر الآتي: sudo ln -s /etc/nginx/sites-available/code-server.conf /etc/nginx/sites-enabled/code-server.conf شغّل الأمر التالي لاختبار صحّة الضبط: sudo nginx -t سترى الخرج التالي: Output nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ستحتاج إلى إعادة تشغيل Nginx لكي يُطّبق الضبط: sudo systemctl restart nginx لديك الآن تثبيت code-server قابل للوصول على نطاقك. ستقوم في الخطوة التالية بتأمينه من خلال تطبيق شهادة Let's Encrypt TLS المجانيّة. الخطوة 3: تأمين النطاق ستقوم في هذا القسم بتأمين نطاقك الخاص باستخدام شهادة Let’s Encrypt TLS، والتي ستوفرها باستخدام Certbot. ستحتاج من أجل تثبيت أحدث إصدار من Certbot إلى إضافة مستودع الحزمة الخاص به إلى خادمك عن طريق تشغيل الأمر التالي: sudo add-apt-repository ppa:certbot/certbot ستحتاج إلى الضغط علىENTER للموافقة. ثبّت بعد ذلك Certbot وإضافة Nginx الخاص به: sudo apt install python-certbot-nginx كنت قد مكّنت ufw (جدار حماية غير معقّد) كجزء من المتطلبات المُسبقة وقمت بضبطه للسماح بحركة مرور HTTP غير المشفّرة. وستحتاج إلى ضبطه لقبول حركة المرور المشفّرة حتى تتمكن من الوصول إلى الموقع الآمن عن طريق تشغيل الأمر التالي: sudo ufw allow https سيكون الخرج: Output Rule added Rule added (v6) ستحتاج كما في Nginx إلى إعادة تحميله حتى يصبح الضبط ساري المفعول: sudo ufw reload سيُظهر الخرج ما يلي: Firewall reloaded انتقل بعد ذلك في متصفحك إلى النطاق الذي استخدمته لـ code-server. حيث سيظهر محّث تسجيل الدخول لـ code-server. سيطلب code-server كلمة المرور الخاصّة بك. أدخل الكلمة التي اخترتها في الخطوة السابقة واضغط على** Enter IDE**. ستدخل الآن إلى code-server وسترى محرّر واجهة المستخدم الرسومية GUI مباشرةً. الآن وبعد تأكّدك من أن خادم الشيفرة قد عُرض بشكل صحيح في نطاقك، سنُثبّت شهادات Let’s Encrypt TLS لتأمينه، باستخدام Certbot. شغّل الأمر التالي لطلب شهادات لنطاقك: sudo certbot --nginx -d code-server.your-domain تقوم في هذا الأمر بتشغيل certbot لطلب شهادات لنطاقك — يمكنك تمرير اسم النطاق باستخدام الراية ‎-d تخبر الراية ‎--nginx بتغيير ضبط موقع Nginx تلقائيًا لدعم HTTPS. تذكر استبدال code-server.your-domain باسم نطاقك الخاص. إذا كانت هذه هي المرة الأولى التي تُشغّل فيها Certbot فسيُطلب منك تقديم عنوان بريد إلكتروني للإشعارات العاجلة وقبول شروط خدمة EFF. سيطلب Certbot بعد ذلك شهادات لنطاقك من Let’s Encrypt. كما سيسألك بعدها فيما إذا كنت ترغب في إعادة توجيه جميع زيارات HTTP إلى HTTPS: Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1: No redirect - Make no further changes to the webserver configuration. 2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for new sites, or if you're confident your site works on HTTPS. You can undo this change by editing your web server's configuration. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Select the appropriate number [1-2] then [enter] (press 'c' to cancel): يُوصى بتحديد الخيار الثاني من أجل زيادة الأمان. اضغطENTERبعد إدخال اختيارك. سيكون الخرج مشابهًا لهذا: IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/code-server.your-domain/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/code-server.your-domain/privkey.pem Your cert will expire on ... To obtain a new or tweaked version of this certificate in the future, simply run certbot again with the "certonly" option. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le هذا يعني أن Certbot أنشئ شهادات TLS بنجاح وطبّقها على ضبط Nginx لنطاقك. يمكنك الآن القيام بإعادة تحميل اسم نطاق code-server الخاص بك في متصفحك ورؤية رمز القفل على يسار عنوان الموقع مما يعني أن اتصالك أصبح آمنًا. الآن وبعد أن أصبح لديك code-server يمكن الوصول إليه في نطاقك من خلال وكيل Nginx عكسي آمن، أصبحت على استعداد لاستعراض واجهة المستخدم لـ code-server. الخطوة 4: استخدام واجهة code-server ستستخدم في هذا القسم بعضًا من ميزات واجهة code-server. ولأنّ code-server هو عبارة عن Visual Studio Code يعمل على السحابة، فإنّه يحتوي على نفس واجهة إصدار سطح المكتب المستقلة. يوجد على الجانب الأيسر من الـ IDE صف عمودي مكوّن من ستة أزرار يُتيح استعمال أكثر الميزات استخدامًا في لوحة جانبية تُعرف باسم Activity Bar. هذا الشريط قابل للتخصيص بحيث يمكنك نقل هذه الأزرار إلى ترتيب مختلف أو إزالتها من الشريط. افتراضيًا يفتح الزر الأول القائمة العامة في قائمة منسدلة، بينما يفتح الزر الثاني لوحة Explorer التي توفر التنقل الهرمي الشبيه ببنية المشروع. يمكنك إدارة المجلدات والملفات هنا – من إنشاء وحذف ونقل وإعادة تسمية حسب الضرورة. يُوفّر الزر التالي التالية إمكانية الوصول إلى وظيفة البحث والاستبدال. بعد ذلك، وبالترتيب الافتراضي (أي الزر الرابع) يُتيح معاينة لأنظمة التحكم في المصدر مثل Git. يدعم Visual Studio code أيضًا موفري التحكم بالمصدر الآخرين ويمكنك العثور على مزيد من الإرشادات لتدفقات عمل التحكم بالمصدر مع المحرّر في هذه الوثائق. يوفر خيار المنقّح debugger في Activity Bar جميع الأدوات الشائعة للتنقيح في اللوحة. يأتي Visual Studio Code مع دعم مضمّن لمنقّح وقت التشغيل Node.js وأي لغة تنتمي إلى Javascript. وبالنسبة للغات أخرى يمكنك تثبيت إضافاتextensions للمنقح المطلوب. كما يمكنك حفظ ضبط التنقيح في ملفlaunch.json. يوفر الزر الأخير في Activity Bar قائمة للوصول إلى الملحقات المُتاحة في Marketplace. إنّ الجزء الرئيسي من واجهة المستخدم الرسوميّة هو محرّرك، والذي يمكنك فصله بواسطة علامات تبويب لتحرير شيفرتك. ويمكنك تغيير طريقة العرض الخاصة بك إلى نظام شبكة أو إلى طريقة عرض الملفات جنبًا إلى جنب. بعد إنشاء ملف جديد من خلال قائمة File، سيُفتح ملف فارغ في علامة تبويب جديدة، وبعد حفظه، سيكون اسم الملف معروضًا في اللوحة الجانبيّة لـ Explorer. يمكن إنشاء المجلدات عن طريق النقر بزر الفأرة الأيمن على الشريط الجانبي لـ Explorer والنقر فوق New Folder. يمكنك توسيع أحد المجلدات بالنقر فوق اسمه وكذلك سحب الملفات والمجلدات وإسقاطها في الأجزاء العليا من التسلسل الهرمي لنقلها إلى موقع جديد. بالإمكان الوصول إلى محطة طرفية عن طريق إدخال CTRL ‎+ SHIFT +‎، أو عن طريق النقر على Terminal في القائمة المنسدلة العليا واختيار New Terminal. سيُفتح الجهاز في لوحة أصغر وسيُوضع مجلد العمل الخاص به في مساحة عمل المشروع، والذي يحتوي على الملفات والمجلدات المعروضة في لوحة Explorer الجانبيّة. لقد أخذت نظرةً عامة عالية المستوى على واجهة code-server وراجعت بعضًا من الميزات الأكثر استخدامًا. الخلاصة لديك الآن بيئة التطوير المتكاملة code-server السحابية متعددة الاستخدامات مُثبّتة على خادم Ubuntu 18.04 ومعروضة في نطاقك المؤّمن باستخدام شهادات Let’s Encrypt. يمكنك الآن العمل على المشاريع بشكل فردي، وكذلك في إطار التعاون الجماعي. يحرّر تشغيل Cloud IDE الموارد على جهازك المحلي ويسمح لك بتوسيع نطاق الموارد عند الحاجة. راجع لمزيد من المعلومات توثيق Visual Studio Code للحصول على ميزات إضافيّة وإرشادات مفصّلة حول المكونات الأخرى لـ code-server. ترجمة وبتصرف للمقال How To Set Up the code-server Cloud IDE Platform on Ubuntu 18.04 لصاحبه Savic
  4. غالبًا ما تشكّل الخطوط مشكلةً للعديد من مستخدمي الحاسوب، فهل سبق لك مثلًا وأن صَممت منشورًا رائعًا، وعند أخذك للملف للطباعة في مكان ما وجدت أنّ جميع عناوين تصميمك تحولت إلى خط Arial لأن تلك الطابعة لا تملك الخط المزخرف الجميل الذي استخدمته في التصميم؟ بالطبع هناك طرق للحيلولة دون ذلك: يمكنك مثلًا تحويل الكلمات في خطوط معيّنة إلى «مسارات» ( paths)، أو تجميع الخطوط في PDF، أو تجميع الخطوط مفتوحة المصدر مع ملفات التصميم خاصتك، أو - على الأقل – تسجيل قائمة الخطوط المطلوبة. ومع ذلك لا تزال هذه تُعدّ مشكلة لأننا بشر وننسى. يواجه الويب ذات النوع من المشاكل. حتى وإن كان لديك فهمًا لأساسيات CSS، فمن المحتمل أنك رأيت نوعًا من التصاريح كهذا: h1 { font-family: "Times New Roman", Times, serif; } إنّها محاولة من المصمم لتحديد خط معين، وتوفير خط احتياطي في حال لم يكن لدى المستخدم خط Times New Roman مثبتًا على جهازه، وتقديم خط احتياطي آخر في حال لم يكن خط Times متوفرا لدى المستخدم أيضًا. إنّها أفضل من استخدام رسومٍ بدلًا من النّص، لكنّها لا تزال طريقةً غير مألوفةٍ وغير ملائمةٍ لخطٍ بدون إدراة، ومع ذلك، كان هذا كل ما يمكننا عمله في الأيام الأولى من الويب. خطوط الويب webfonts ثم جاءت خطوط الويب، ونُقلت إدارة الخطوط من العميل إلى الخادم. فبدلًا من مطالبة متصفح الويب بالعثور على الخط المطلوب على نظام المستخدم، أصبحت الخطوط تُوَفَّر للعميل على مواقع الويب من قبل الخادم نفسه. تستضيف Google ومزوّدو الخدمات الأخرى الخطوط المرخّصة ترخيصًا مفتوحًا والتي يمكن للمصمّمين تضمينها على مواقعهم باستخدام قاعدة CSS بسيطة. إن المشكلة في هذه الميزة المجانيّة هي أنّها بالطبع لا تأتي بدون تكلفة تمامًا. إنّها مجانيّة من ناحية الاستخدام، لكن المواقع الرئيسيّة مثل Google تحبّ تتبّع من يشير إلى بياناتهم بما في ذلك الخطوط. إذا لم تجد حاجة لمساعدة Google لبناء سجل لنشاط كل شخص على الويب، فإنّ الأخبار السارة هي أنّه بالإمكان استضافة خطوط الويب الخاصّة بك، والأمر بسيط ببساطة تحميل الخطوط إلى مضيفك واستخدام قاعدة CSS واحدة سهلة. وكميزة جانبيّة، قد يُحمّل موقعك بشكل أسرع حيث ستجري استدعاءات خارجية أقل عند تحميل كل صفحة. خطوط الويب المُستضافة ذاتيًّا إنّ أول شيء تحتاجه هو خط مرخّص ترخيصًا مفتوحًا. قد يكون هذا أمرًا مربكًا بعض الشيء إن لم تكن معتادًا على التفكير في تراخيص البرامج المبهمة أو الاهتمام بها، خاصّة أنه يبدو وكأن كل الخطوط مجانيّة. يُدرك عدد قليل جدًا منّا أنّهم يدفعون مالًا من أجل الخطوط، مع العلم أنّ معظم الناس لديهم خطوط مرتفعة الثمن على حواسيبهم. فقد يكون حاسوبك وبفضل اتفاقيات الترخيص قد شُحِن مع خطوط لا يُسمح لك قانونيًا بنسخها وإعادة توزيعها. إنّ بعض الخطوط مثل Arial و Verdana و Calibri و Georgia و Impact و Lucida و Lucida Grande و Times و Times New Roman و Trebuchet و Geneva والعديد من الخطوط الأخرى مملوكة لشركة Microsoft و Apple و Adobe. إذا اشتريت جهاز حاسوب مُثبّت عليه مسبقًا نظام تشغيل Windows أو MacOS، فأنت إذًا تدفع مقابل استخدام حزمة الخطوط المُضمّنة، لكنك لا تملك هذه الخطوط ولا يُسمح لك بتحميلها إلى خادم الويب (ما لم يُذكر خلاف ذلك). إنّ جنون المصدر المفتوح لحسن الحظ قد وصل إلى عالم الخطوط منذ زمن طويل، وهناك مجموعات ممتازة من الخطوط المرخّصة ترخيصًا مفتوحًا من المنظمات والمشاريع مثل League of Moveable Type وFont Library وOmnibus Type وحتى Google وAdobe. يمكنك استخدام تنسيقات ملفات الخطوط الأكثر شيوعًا، بما في ذلك TTF و OTF و WOFF و EOT وما إلى ذلك. سأستخدم في هذا المثال الخط Sorts Mill Goudy لأنّه يتضمن إصدار WOFF (تنسيق خط Open Web، طٌوِّر جزئيًا من قبل Mozilla). تعمل التنسيقات الأخرى على أيّة حال بنفس الطريقة. لنفترض أنّك تريد استخدام الخط Sorts Mill Goudy على صفحة الويب خاصتك: حمّل ملف GoudyStM-webfont.woff إلى خادم الويب الخاص بك: scp GoudyStM-webfont.woff seth@example.com:~/www/fonts/ قد يوفّر مضيفك أيضًا أداة تحميلٍ رسوميّة من خلال cPanel أو لوحة تحكم ويب مشابهة. أضف قاعدة ‎@font-face مشابهة لما يلي في ملف CSS الخاص بموقعك: @font-face { font-family: "titlefont"; src: url("../fonts/GoudyStM-webfont.woff"); } قيمة الواصفfont-familyهي تسمية تختارها للخط. إنها اسم أو وصف مألوف للإنسان بغض نظر عمّا تمثله قاعدة ‎@font-face للخط. استَخدمتُ القيمة "titlefont" في هذا المثال لأنني أتصوّر أنّ هذا الخط سيُستخدم للعناوين الرئيسية في موقع وهميّ. يمكنك ببساطة استخدام أيّة قيم أخرى مثل "officialfont" أو "myfont". قيمة الواصفsrc تُحدَد المسار إلى ملف الخط. يجب أن يكون هذا المسار موافقا لبنية ملف الخادم الخاص بك، لدي في هذا المثال المجلد fonts بجانب المجلد css. قد لا يكون موقعك منظمًا بهذه الطريقة، لذا اضبط المسارات بما يناسبك مع الآخذ بالحسبان أن نقطة واحدة (.) تعني هذا المجلد ونقطتان (..) تعنيان مجلدًا آخرًا للخلف (المجلد الحاوي [الأب] للمجلد الحالي). الآن وبعد تحديد اسم الخط وموقعه، يمكنك استدعائه في أي صنف class من أصناف CSS أو معرّف ID تريده. على سبيل المثال، إذا كنت ترغب في عرض <h1> بخط Sorts Mill Goudy، فعليك جعل قاعدة CSS الخاصّة به تستخدم اسم خطك المخصّص: h1 { font-family: "titlefont", serif; } أنت الآن تستخدم وتَستضيف خطوطك الخاصّة. ترجمة وبتصرف للمقال How to host your own webfonts لصاحبه Seth Kenlon
  5. إزالة بعض الالتباس حول مفهوم DevOps. يتعرف الكثير من الناس على DevOps للمرّة الأولى عند رؤيتهم لإحدى انتاجاتها وتساؤلهم عن كيفية حدوث ذلك. إذ أنه ليس من الضروري فهم فيما إذا كان شيء ما يشكل جزءًا من DevOps للبدء بتنفيذه، لكن معرفة ذلك – ومعرفة ما الذي يجعل من DevOps استراتيجية مهمة- يمكن أن تشّكل الفارق بين كونك قائدًا أو تابعًا في مجالٍ ما. ربما سمعت عن بعض النتائج المدهشة التي تُنسب إلى DevOps، مثل بيئات الإنتاج عالية المرونة والتي يمكنها التعامل مع الآلاف من الإصدارات يوميًا بينما تدور أداة "Chaos Monkey" (وهي أداة برمجية طُوّرت بواسطة مهندسي Netflix لاختبار مرونة واسترداد خدمات Amazon Web Services [اختصارًا AWS] الخاصة بهم) حول هذه الاصدارات لفصل الأشياء بشكل عشوائي. هذا أمر مثير للإعجاب، ولكنه في حد ذاته يُمثل حالة عمل ضعيفة، مثقلة بشكل أساسي بإثبات سلبي (proving a negative): أن بيئة DevOps مرنة لأنه لم يُلاحظ فشل خطير ... حتى الآن. يوجد الكثير من الالتباس حول مفهوم DevOps ولا يزال الكثير من الناس يحاولون فهم ذلك. إليك مثال عن شخص ما عبر حسابي على موقع التواصل الاجتماعي LinkedIn: يتابع هذا المنشور المتخصصون في المجال التقني على موقع LinkedIn عبر شريحة واسعة من الإجابات. فكيف ترد؟ جذور DevOps في التصميم الرشيق (lean) والتصميم المرن (agile) تُعد DevOps أسهل للفهم إذا بدأنا باستراتيجيات هنري فورد وتحسينات نظام إنتاج تويوتا لنموذج فورد. وضمن هذا التاريخ ظهور منهجية التصميم الرشيق (lean)، والتي دُرست جيدًا. قام جيمس ب. ووماك ودانييل جونز في كتاب Lean Thinking بتلخيصها إلى خمسة مبادئ: تحديد القيمة المرغوبة من قبل العميل. تحديد سلسلة القيم لكل منتج يوفر هذه القيمة ويلغي جميع الخطوات المهدورة اللازمة حاليًا لتوفيره. جعل تدفق المنتج متواصلًا من خلال خطوات القيمة المضافة المتبقية. ادخال السحب بين جميع الخطوات التي يكون فيها التدفق المستمر ممكنًا. إدارة نحو الاكتمال بحيث ينخفض باستمرار عدد الخطوات ومقدار الوقت والمعلومات اللازمة لخدمة العملاء. تسعى منهجية التصميم الرشيق إلى إزالة الهدر باستمرار وزيادة تدفق القيمة إلى العميل. يمكن التعرف عليها بسهولة وفهمها من خلال مبدأ أساسي للتصميم الرشيق وهو مبدأ: تدفق القطعة الواحدة. يمكننا القيام بعدد من الأنشطة لمعرفة السبب في أن تحريك قطعة منفردة في كل مرة أسرع من تحريك قطع متعددة دفعة واحدة؛ إن لعبة Penny Game و لعبة الطائرة Airplane Game أمثلة على ذلك. ففي لعبة Penny، إذا استغرقت دفعة الـ 20 بنس دقيقتين للوصول إلى العميل، فسيحصل على كامل الدُفعة بعد دقيقتين من الانتظار. بينما إذا نقلت بنس واحد في كل مرة، فسيحصل العميل على أول بنس في غضون خمس ثوانٍ ويستمر في الحصول عليهم بنس تلو الآخر حتى يصل البنس العشرين بعد 25 ثانية تقريبًا. وهذا يعتبر فرقًا كبيرًا، ولكن ليس كل شيء في الحياة بسيط ويمكن التنبؤ به كما هو الحال هنا في مثال البنس في لعبة بيني. ومن هنا أتت «المنهجية المرنة» (agile). بالتأكيد نرى مبادئ Lean تنسحب على فرق Agile عالية الأداء، ولكن هذه الفِرق تحتاج إلى ما هو أكثر من مبادئ Lean للقيام بعملها. تركز عملية التصميم المرن Agile من أجل التمكن من التعامل مع عدم القدرة على التنبؤ وتباين مهام تطوير البرامج النموذجية، على المعرفة الصحيحة والتشاور والقرار والعمل على ضبط المسار في مواجهة الوقائع المتغيرة باستمرار. على سبيل المثال، تزيد الأطر الرشيقة (مثل «فريق سكروم» [scrum]) من الوعي بالمهام مثل الجاهزية اليومية والمراجعة الزمنية. فإذا أصبح فريق سكروم مدركًا لحقيقة جديدة، فإن الإطار يسمح له ويشجعه على ضبط المسار إن لزم الأمر. تحتاج الفِرق لاتخاذ هذه الأنواع من القرارات، إلى أن تكون منظمة ذاتيًا في بيئة عالية الثقة. تحقق فرق التصميم المرن عالية الأداء التي تعمل بهذه الطريقة تدفقًا سريعًا للقيمة مع ضبط للمسار بشكل مستمر، مزيلةً بذلك مضيعة الوقت في السير بالاتجاه الخاطئ. حجم الدفعة الأمثل يساعد فهم اقتصاديات حجم الدُفعات على فهم قوة DevOps في تطوير البرمجيات. تأمل الرسم التوضيحي الأمثل لمنحنى U التالي من كتاب دونالد راينترسن مبادئ تدفق تطوير المنتجات Principles of Product Development Flow: يمكن تفسير ذلك بتشبيه حول التسوق في البقالية. افترض أنك بحاجة إلى شراء بعض البيض وتعيش في مكان يبعد 30 دقيقة من المتجر. إن شراء بيضة واحدة (أقصى اليسار على الرسم التوضيحي) في المرة الواحدة يعني رحلة لمدة 30 دقيقة في كل مرة تريد فيها شراءها. هذه هي تكلفة المعاملة (transaction cost). قد تمثل تكلفة الحجز (holding cost) البيض التالف وشغل المساحة في الثلاجة لفترة من الزمن. التكلفة الإجمالية (total cost) هي تكلفة المعاملة مضافًا إليها تكلفة الحجز في الثلاجة. يفسر منحنى U هذا السبب، بالنسبة لمعظم الناس، بإن شراء أكثر من 12 بيضة (دزينة) في وقت واحد هو الحجم الأمثل للدفعة. إذا كنت تعيش بجوار المتجر، فستكلفك القليل من المشي إلى هناك، وربما تشتري كرتونًا أصغر حجمًا في كل مرة لتوفير مساحة في الثلاجة والاستمتاع بالبيض الطازج. يمكن لهذا الرسم التوضيحي لتحسن منحنى U توضيح سبب زيادة الإنتاجية بشكل كبير في تحويلات المنهجية المرنة الناجحة. تأمل في تأثير تحويل agile على صنع القرار في المنظمة. تكون سلطة اتخاذ القرار مركزية في المنظمات الهرمية التقليدية. هذا يؤدي إلى اتخاذ عدد أكبر من القرارات وبتواتر أقل ومن قبل عدد أقل من الأشخاص. حيث ستعمل المنهجية المرنة (agile) على تقليل تكلفة معاملات المؤسسة بشكل فعال لاتخاذ القرارات من خلال تطبيق اللامركزية على القرارات إلى المكان الذي تكون فيه المعرفة والمعلومات متوفرة بشكلها الأمثل: أي إلى فرق agile ذات الوثوقية العالية والتنظيم الذاتي. توضح الرسوم المتحركة التالية كيف يؤدي خفض تكلفة المعاملة إلى تغيير الحجم الأمثل للدُفعة إلى اليسار. لا يمكنك التقليل من قيمة المؤسسة في اتخاذ قرارات أسرع بشكل متكرر. أين تكون DevOps أكثر ملائمة؟ إن الأتمتة هي إحدى الأشياء التي تشتهر بها DevOps. يوضح الرسم التوضيحي السابق قيمة الأتمتة بتفصيل كبير. نقلل من خلال الأتمتة تكاليف معاملاتنا إلى ما يقارب الصفر، ونحصل بشكل أساسي على الاختبارات والنشر مجانًا. يتيح لنا ذلك الاستفادة من أحجام دُفعات العمل الأصغر والأصغر. إن دُفعات العمل الأصغر يسهل فهمها والالتزام بها واختبارها ومراجعتها ومعرفة وقت إنجازها. كما تنطوي أحجام الدُفعات الأصغر هذه أيضًا على تباين وخطر أقل، مما يجعلها أسهل للنشر واستكشاف الأخطاء وإصلاحها واستردادها عند حدوث خطأ ما. يمكننا من خلال الأتمتة المدمجة مع أنشطة agile القوية أن نجعل تدفق تطوير ميزاتنا قريبًا جدًا من تدفق قطعة واحدة، مما يوفر قيمة سريعة للعملاء بشكل متواصل. تُفهم DevOps بشكل أكثر تقليدية كطريقة لهدم جدران الالتباس بين فرق التطوير dev والعمليات ops. تُطوّر فرق التطوير في هذا النموذج ميزات جديدة، بينما تحافظ فرق العمليات على استقرار النظام وتشغيله بسلاسة. يحدث الالتباس لأن الميزات الجديدة من التطوير تُحدث تغييرًا في النظام، مما يزيد من خطر توقف الخدمة والذي لا يشعر فريق العمليات بالمسؤولية عنه -لكن عليه التعامل معه على أي حال. لا تكتفي DevOps فقط بمحاولة جعل الناس يعملون معًا فحسب، بل أيضًا بمحاولة إجراء تغييرات أكثر تكرارًا في بيئة معقدة وبشكل آمن. يمكننا إلقاء نظرة على أبحاث Ron Westrum للبحث في موضوع تحقيق السلامة في المنظمات المعقدة. فقد وجد عند البحث عن سبب كون بعض المنظمات أكثر أمانًا من غيرها أن ثقافة المنظمة هي التي تنبئ بسلامتها. وحدّد ثلاثة أنواع من الثقافة: «المرضيّة أو غير المُتوقعة» (Pathological)، و«البيروقراطية» (Bureaucratic)، و«الابداعية» (Generative). فوجد أن الثقافة المرضيّة كانت تنبئ بسلامة أقل وأن الثقافة الإبداعية كانت تنبئ بمزيد من السلامة (على سبيل المثال، عدد أقل بكثير من حوادث الطيران أو وفيات المستشفى عن طريق الخطأ في مجالات بحثه الرئيسية). تُحقق فرق DevOps الفعالة ثقافة ابداعية باستخدام أنشطة lean و agile، مما يدل على أن السرعة والأمان متكاملان، أو وجهان لعملة واحدة. تحقق DevOps من خلال تقليل الأحجام المثالية لدُفعات القرارات والميزات لتصبح صغيرة جدًا تدفقًا أسرع للمعلومات وللقيمة في الوقت الذي تزيل فيه الهدر وتقلل المخاطر. وفقا لبحث Westrum، يمكن أن يحدث التغيير بسهولة عند تحسين السلامة والموثوقية في نفس الوقت. عندما يتم الوثوق بفريق agile و DevOps لاتخاذ قراراته الخاصة، سنمتلك حينها الأدوات والتقنيات التي تشتهر بها DevOps اليوم: التشغيل الآلي والتسليم المتواصل. تٌقلل من خلال هذه الأتمتة تكاليف المعاملات أكثر من السابق، ويتحقق تدفق هائل على مبدأ القطعة الواحدة مما يخلق إمكانات لآلاف القرارات والإصدارات في اليوم، كما يجري في مؤسسات DevOps عالية الأداء. التدفق وردود الأفعال (التغذية الراجعة) والتعلم لا تتوقف DevOps عند هذا الحد. لقد كنا نتحدث بشكل رئيسي عن تحقيق DevOps لتدفق ثوري، ولكن يتم زيادة تضخيم أنشطة lean و agile من خلال جهود مماثلة تحقق حلقات تغذية راجعة أسرع كما تحقق تعلمًا أسرع. يشرح المؤلفون في كتاب DevOps Handbook بالتفصيل كيف يُنجز DevOps وفوق تدفقه السريع القياس عن بُعد عبر كامل تدفق القيمة لديه للتغذية الراجعة السريعة والمتواصلة. ستستفيد علاوة على ذلك فرق DevOps عالية الأداء باستمرار من التعلم والتحسين المستمر في أسس مؤسساتها، وذلك من خلال الاستفادة من رشقات «كايزن» (kaizen) الرشيقة و«الأثر الرجعي» (retrospectives) لـسكروم، مما سيؤدي إلى تحقيق ثورة في التصنيع في مجال تطوير منتجات البرمجيات. ابدأ بتقييم DevOps تتمثل الخطوة الأولى في الاستفادة من DevOps، إما بعد دراسة طويلة أو بمساعدة مستشار ومدرب من DevOps، في إجراء تقييم عبر مجموعة من الأبعاد الموجودة دائما في فرق DevOps عالية الأداء. يجب أن يحدّد التقييم قواعد الفريق الضعيفة أو غير الموجودة التي تحتاج إلى تحسين. قيّم نتائج التقييم لإيجاد مكاسب سريعة – التركيز على مجالات ذات فرص عالية للنجاح والتي ستؤدي إلى تحسينات شديدة التأثير. المكاسب السريعة مهمة لاكتساب الزخم اللازم لمعالجة المجالات الأكثر تحديًّا. يجب أن تولد الفرق أفكارًا يمكن تجربتها بسرعة والبدء في تحريك البوصلة باتجاه DevOps. يجب على الفريق مع مرور بعض الوقت إعادة تقييم الأبعاد نفسها لقياس التحسينات وتحديد مجالات تركيز جديدة عالية التأثير مجدّدا بأفكار جديدة من الفريق. سنلقي النظر في الجزء الثاني من هذه المقالة على نتائج استبيان DevOps في مجتمع «دروبال» (Drupal) ونرى أين يمكننا إيجاد المكاسب السريعة. ترجمة وبتصرف للمقال: Why DevOps is the most important tech strategy today لصاحبه: Kelly Albrecht. اقرأ أيضًا المقال السابق: رحلة المطور عبر DevOps كامل مقالات السلسلة.
  6. انتهت أيام فرق التطوير وفرق العمليات المنعزلة. ما علاقة المطوًر «بور سوتر» (Burr Sutter وكتابه، The Phoenix Project؟ كما أوضح سوتر في حديثه المقتضب الذي استمر لمدة خمس دقائق في مؤتمر All Things Open 2016، فإنهم يشتركون في شغفهم بالتقنيين العمليين – وهم المطورون الذين يصممون شيفرات رائعة والمشغلون الذين يقومون بتطوير البنية التحتية لتشغيلها. وتابع سوتير قائلًا أن أيام فِرق التطوير وفرق العمليات المنعزلة انتهت، وأن مستقبل البرامج أن يعمل الجميع معا لإنشاء أعمال ذات قيمة أفضل وبشكل أسرع. استشهادًا برواية جين كيم The Phoenix Project حول إطلاق مبادرة تكنولوجيا المعلومات على نطاق واسع باستخدام مبادئ الـ DevOps، فقد شارك سوتر "مشروع Phoenix" الخاص به. حيث أراد أحد العملاء نظامًا جديدًا غير مرئي ينقله من واجهة المستخدم ذات النمط القديم إلى الويب، مما يتيح الخدمة الذاتية للعملاء عبر الويب. أخبر سوتر المدير التنفيذي أنّه وبالنظر إلى نطاق المشروع والقيود الزمنية المفروضة فإن الفريق "لن يكون لديه وقت حتى للنوم." فكان رد رئيسه تقريبًا: «يمكنك النوم عندما تكون ميتًا». بدأ سوتر وفريقه العمل بتطوير مخطط تفصيلي يركز على النواتج الأسبوعية، مع البقاء على اتصال دائم مع العميل، وتقديم نسخ تجريبية أسبوعية، ثم الانتقال مباشرة إلى الإنتاج. لكن "أبواب الجحيم فتحت" بعد خطأ أتلف نقاط بيع العميل وتكاملات الطرف الثالث. قال سوتر: "لقد فهمنا سريعًا أن السبيل الوحيد للخروج من هذا المأزق هو في المتابعة والمضي قدمًا – كلنا معًا– المطورين، وموظفي العمليات، ومديري قواعد البيانات، وموظفينا- الفريق بأكمله". أوجد الفريق التصحيحات سريعًا خلال ليلةٍ واحدة، وتأكّد من أن كل مطوّر عرف كيف كانت تُستخدَم شيفرته، وقام بفحص منتظم مع فريق العمليات، وخصّص أيام السبت بأكملها لإصلاح الأخطاء. استغرق الأمر مع فريق التطوير يومي سبت فقط للبدء في كتابة شيفرة أفضل بكثير وأكثر استقرارًا، وكان مستعدًا للذهاب في صباح اليوم التالي عندما بدأ العمل على الإنترنت. أوصى سوتر في الختام بكتابين من أشهر كتب جين كيم هما: The Phoenix Project و The DevOps Handbook. ترجمة وبتصرف للمقال: A developer's journey through DevOps. اقرأ أيضًا المقال التالي: لماذا تعد DevOps الاستراتيجية التقنية الأكثر أهمية اليوم المقال السابق: أفضل 5 لغات برمجة لـ DevOps كامل مقالات السلسلة.
  7. نجمع هنا خمسًا من أفضل لغات البرمجة لـ DevOps وبعضًا من الموارد التعليمية المفيدة لكلٍ منها. ركزتُ على البنية التحتية لغالب حياتي المهنية، وقد تبدلت المهارات التقنية المحدّدة المطلوبة بمرور الزمن. سأضع في هذه المقالة، خمسًا من أفضل لغات البرمجة في مجال DevOps، والموارد التي كانت مفيدة للغاية بالنسبة لي، حيث كنت أُضيف هذه المهارات التطويرية إلى مجموعة أدوات البنية التحتية خاصتي. لا تُعد معرفة كيفية تجميع الخوادم وتكدسها مهارة في الطلب في هذه المرحلة. فمعظم مشاريع الأعمال لا تبني مراكز بيانات مادية لها. وبدلاً من ذلك، تُصمم وتبني مقدِرات الخدمة التي تُستضاف في البيئات السحابية العامة. تُهيئ البنية التحتية وتُنشر وتُدار من خلال التعليمات البرمجية. وهذا هو جوهر تصميم الـ DevOps - فعندما تتمكن المؤسسة من تحديد بنيتها التحتية في سطور من التعليمات البرمجية، يصبح عندها أتمتة معظم المهام (إن لم تكن جميعها) في مركز البيانات أمرًا ممكنًا. تتيح المستويات المتقدمة للأتمتة تمكين أنشطة «التركيب المتواصل / التسليم المتواصل» (Continuous Integration /Continuous Delivery CI/CD) التي لم تكن متاحة من قبل. تجعل مهام سير عمل CI / CD هذه من التسليم عملية سلسة خالية من الاحتكاك – حيث يستطيع المطور دفع شفرته إلى مستودع مصدري، وتتولى البنية التحتية تلقائيًا نشرها لدعم عمليات الاختبار التي يمكن أن تدفع تطبيق ما حتى مرحلة الإنتاج تلقائيا دون تدخل بشري. فعمل تقني يزحف تحت قبة أرضية مرتفعة لتوصيل كابلات الشبكة الجديدة لم يعد ضمن المسار الحرج لنشر تطبيق الإنتاج. تقوم فرق البنية التحتية الآن بتحويل قدراتها بعيدًا عن خوادم الأرفف والتكديس إلى دعم قنوات CI / CD، مما يعني شيفرة التعلم. تُنشر ملفات القوالب المضمنة في YAML والبرامج النصية لنشر البنية التحتية في بايثون والتطبيقات في جافا سكريبت من خلال القنوات المحددة في Groovy. تقترب شيفرة التطبيق نفسه من البنية التحتية. يمكن الآن لمطوري التطبيقات إنشاء «إجرائيات» (routines) في تطبيقاتهم لتوسيع نطاق ومعالجة حالات الفشل من خلال واجهات برمجة التطبيقات الخاصة بالبنية التحتية. وهذا هو السبب في أنني بدأت في استثمار فترة جيدة من وقتي في تعلم الشيفرة. قررت التركيز على تعلم لغات التطوير المشاركة في DevOps، واخترت خمسًا من أكثر اللغات أهمية وهي: Python و Ruby و Java Script و Go و C. أنا لست في هذه المرحلة مطورًا يعمل بدوام كامل بأي حال من الأحوال، كما أني لست متأكدًا حتى من أنه بإمكاني تسمية نفسي هاويا. لكني وصلت إلى ما هو أكثر من المعرفة الأساسية بفضل الموارد التي أقدمها في هذا المقال. بايثون Python أصبحت بايثون لغة متعددة الأغراض في البنية التحتية. وقد استُخدمت لبناء مشاريع البنية التحتية السحابية مثل OpenStack، وحتى لدعم تطبيقات الويب من خلال أطر عمل مثل Django. إن بايثون هي لغة سلسة لتلبية مجموعة واسعة من الاستخدامات. Codecademy: بدأت تعلم بايثون في موقع Codecademy. الذي يُقدِّم تمهيدًا رائعًا لبايثون. تدريب Safari Books عبر الإنترنت: انتقلتُ منه إلى المقدمة الممتازة لجيسيكا ماكلار في دورة Introduction to Python في مكتبة Safari Books Online. إن خدمة Safari مكلفة، ولكن غالبًا ما تكون هناك حسومات على مبيعات الأعضاء يمكن أن تمنحك خصمًا قد يصل إلى 50٪. تحتوي SafariBooks أيضًا على مقاطع فيديو لمؤتمرات O'Reilly، بما في ذلك المحادثات والمختبرات. حيث توفر المحادثات فرصة لإيجاد مواضيع هامّة في كل لغة. مقاطع الفيديو الخاصة بالمؤتمرات عبر الإنترنت: ابحث عبر الإنترنت وستجد محادثات مثيرة للاهتمام في مؤتمرات مطوّري برامج مختلفة حول كيفية استخدام اللغات بطرق ربما لم تفكر فيها من قبل. تتوفر على سبيل المثال على YouTube مقاطع فيديو مؤتمر PyCon. روبي Ruby تُستخدم روبي في عدد من مشاريع البنية التحتية. على سبيل المثال إن تطبيق ManageIQ، هو تطبيق Ruby on Rails. كثيرا ما كنت أمازح العملاء خلال وظيفتي في Red Hat، بأنه مع ManageIQ (و CloudForms)، يكون المستخدمون على بعد 10 سطور فقط من شيفرة Ruby للقيام بأي شيء. Codecademy: حصلت على معرفتي في روبي بشكل رئيسي من هذا الموقع، كما هو الحال مع بايثون. التوثيق الرسمي: إن المصدر الآخر الذي ساعدني على فهم روبي بشكل عملي أكثر (أي بالنسبة لوظيفتي) هو كتاب بيتر ماكووان Mastering CloudForms Automation (متوفر بتنسيق PDF مجاني). وساعد العمل مع state machines لـ CloudForms وأتمتة سير العمل المتقدمة في تشكيل فهمي للبنى داخل روبي. الحلقات الصوتية: استمعت أيضًا إلى Ruby on Rails Podcast، و Ruby Rogues. جافا سكريبت JavaScript تستمر منصة ومشاريع النظام البيئي لأطر جافا سكربت والمشاريع في النمو بوتيرة مذهلة. حيث تحتل حيزا ضخما من مساحة الاعمال على الإنترنت، سواء تلك المستخدمة من جانب العميل أو من أطر العمل المستخدمة من جانب الخادم. FreeCodeCamp: ما زلت أتعلم لغة جافا سكريبت، خاصة من خلال FreeCodeCamp. الذي يحتوي على برنامج مجاني ممتاز يوفر أمثلة في العالم الحقيقي ويدفع الطلاب إلى ما هو أبعد من تجربة كتابة الكلمات التقليدية. ستتلقى مع تقدمك في البرنامج، إرشادات أقل إلزاميةً وبدلاً من ذلك ستُكلف بمهام لإكمالها. كانت الدروس التي تعلمتها بشكل أكثر اكتمالا في رحلتي كانت من مبدأ "ابدأ من الجزء الأصعب". والذي لا أستطيع أن أوصي به بدرجة كافية. التوثيق الرسمي: إن التوثيق الرسمي هو مرجعي الأول لأي شيء غامض يواجهني أثناء رحلتي في تعلم جافاسكربت. الحلقات الصوتية: أستمع أيضًا إلى الملفات الصوتية التي تركز على جافا سكريبت، مثل JavaScript Jabber و FiveJS. Go طُرحت لغة Go في عام 2009، وحققت نجاحًا كبيرًا في السوق منذ طرحها. كان مصممو اللغة يركزون على عمل لغة مكتوبة ثابتة مقروءة، كما تقدم أيضًا أداءً جيدًا على نطاق واسع. golang.org: لقد بدأت مع Go، بدءًا من الجولة التعليمية الموجودة في golang.org. قناة Google Developers على YouTube: بدأت أيضًا بمشاهدة مقاطع الفيديو على قناة Google Developers channel، بما في ذلك Go for Pythonistas و Get Started with Go و Go Programming. تدريب Safari Books Online: ركزتُ بشكل أكبر على Go في عام 2017 لأنها تدعم عددًا من تقنيات الويب المهمة مثل Docker و Kubernetes وغيرها. يعد مسار التعلم في Safari Books Online مصدرًا رائعًا آخر، بما في ذلك Master Google's Go. السي C حاولت تعلم لغة C مرات عديدة. في كل مرة كنت أقترب فيها من C لم يكن لدي هدف معين في الحسبان. أردت فقط تعلم اللغة لأن الكثير من الشيفرات في العالم مكتوبة بلغة C، والعديد من« البنى» (constructs) في هذه اللغة يُعاد استخدامها في لغات أخرى. تعلمت سريعًا عند انضمامي إلى Red Hat، أن هناك مقولة موجودة في مجتمع «البرمجيات الحرة والمفتوحة المصدر» (FOSS) لفترة طويلة جدًا وهي: أفضل التوثيق هو الشيفرة نفسها. وأدركت أنني بحاجة إلى تعلم لغة C عند محاولتي فهم مشاريع مثل KVM و libvirt و QEMU، وذلك لفهم ما يحدث في المستوى التأسيسي. تعلم C بالطريقة الصعبة: لتعلم C تعلمت طريقة Learn C the Hard Way والتي أثبتت أنها طريقة مميَّزة للغة. أحب أسلوب كتابة المؤلف والنهج المعبر لتمارين كتابة الشيفرة. يمكنك قراءة الكتاب مجانًا عبر الإنترنت، أو شراء الكتاب للحصول على أمثلة التعليمات البرمجية وملفات الفيديوأيضًا. يُركز عملي الحالي على التحدث مع العملاء حول الحلول السحابية، لكنني استثمرت في مجتمع تكنولوجيا المعلومات لفترة طويلة وأشعر بأنني مضطر لتقديم رد. أحد الأشياء التي ركزت عليها في عام 2017 هو المساعدة في تثقيف موظفي تقنية المعلومات الحاليين حول الاتجاهات السائدة في سوق العمل، وكيفية المشاركة في عالم تكنولوجيا المعلومات الجديد الذي بدأ التركيز عليه. آمل أن تكون قادرًا على أخذ بعض الموارد المتوفرة في هذه المقالة وتحويل البند في سيرتك الذاتية الذي يقول "بناء الخوادم" إلى "بناء الشيفرة". ما هي لغات البرمجة التي تركز على تعلمها الآن؟ أخبرنا عن الموارد التي كانت أكثر فائدة لك في رحلتك البرمجية الخاصة. ترجمة وبتصرف للمقال: Top 5 programming languages for DevOps لصاحبه:Chris Saunders. اقرأ أيضًا المقال التالي: رحلة المطور عبر DevOps المقال السابق: ثلاث خطوات لتأمين DevOps مفتوح المصدر كامل مقالات السلسلة.
  8. إنّ المفتاح الرئيسي لتأمين تطوير تطبيق ما هو "الإزاحة نحو اليسار" - انقل اختبار الأمان بعيدًا عن مرحلة الإنتاج المتأخرة وعُد إلى التصميم والتطوير. حقيقةً، لم يعد أحد الآن يكتب شيفرته الخاصّة، أليس كذلك؟ نذهب إلى GitHub (أحد مواقع خدمات استضافة مستودعات المشاريع مفتوحة المصدر يوفر طرائق لتتبع القضايا التي تُنشِئها وتسمح للمستخدمين بإنشائها)، وننزل بعضًا من المكتبات، ونتجنب إعادة اختراع العجلات غير الضرورية، نجمع هذه العجلات بالشكل الذي يناسبنا لإنشاء برامج جديدة. ثم نُنزّل بعضًا من الأطر الأمامية لجعلها تبدو جميلةً وسريعة الاستجابة ونحن خارج السياق. وجدت خلال مراجعتي للتطبيقات، سواء تلك الموجودة في شركتي أو في شركات أخرى، أن أكثر من 90٪ من الشيفرة التي تشكل تطبيقًا هذه الأيام هي عبارة عن أشياء استعرناها، ولم نكتبها بأنفسنا. يفحص معظمنا شيفرته بحثًا عن العيوب مستخدمًا «أدوات التحليل الثابتة» (static analysis tools)، لكن ماذا عن كل المواضيع التي لم نكتبها بأنفسنا؟ كيف يمكننا معرفة ما في داخلها بالفعل؟ وبمجرد معرفتنا لذلك، ما هي الإجراءات التي نتخذها إما لتنظيفها أو لإبقائها محدّثة؟ كيف يمكننا تجنب التعرض للاختراق لأننا ندع شيئا مفتوحًا يعمل في الخلفية باستخدامنا لتلك المكتبة القوية المزدحمة التي تفعل ذاك الشيء الجميل الذي لا يمكننا الاستغناء عنه؟ الطريقة القديمة أُبرمج منذ 20 عامًا تقريبًا، وهي فترة طويلة وكافية لرؤية التطور بدءًا من النماذج التقليدية لتخطيط البرامج كالنماذج الشلالية أو الحلزونية إلى نماذج «البرمجة الفائقة» (Xtreme Programing)، والنماذج المرنة Agile و تطوير العمليات DevOps الآن. في الماضي كانت دورات التطوير الطويلة والافتقار إلى أي تدريب حقيقي وعدم جدوى الأدوات في تحديد العيوب الأمنية حيث تجري تقييمات الأمان بشكل أساسي في المراحل اللاحقة من دورة حياة تطوير البرمجيات وأكثرها يتم على شكل أنشطة يدوية. وعادةً ما يكون الدافع وراء بدء المراجعة يتعلق بتدقيق أو بعميل يطلب تأكيد بياناته في أنظمتك (والتي قليلًا ما تحدث). بالنظر إلى هذا النهج قليل التكرار والمتعلق بالتقييم الأمني، فإنّه غالبًا ما تُخفّض أولوية العيوب القائمة على الأمان والاختبارات للعثور عليها. ركّزت مجموعات أمن المعلومات على "النتائج"، وعلى تشغيل أدوات لإنتاج التقارير عند الطلب لطمئنة المدققين بأن الأمور تجري على ما يرام. أعطيت الميزات والفاعلية الوظيفية الأولوية على حل الخلل الذي لن يراه المستخدمون العاديون أبدًا، ولن يُطلعهم أحد عليه، أليس كذلك؟ أضف إلى هذا السيناريو حقيقة أنه حتى مع إضافة عمال تقنيين جُدد إلى السوق يوميًا، فإن القليل منهم مُدّرب على أنشطة كتابة الشيفرة الدفاعية، ويمكنك أن ترى كيف يمكن أن ينتهي بنا الأمر إلى حدوث مشكلة. إن الخبر الجيد هنا هو أنه الآن يوجد استراتيجيات حقيقية لإيضاح المشكلة وطرق حلها. الطريقة الجديدة عالم اليوم هو عالم الأتمتة و«التكرار المتواصل» (continuous iteration). نسمي هذه العملية بـ "DevOps" لأنها تمزج تطوير البرمجيات وتعريف وأتمتة البنية التحتية لإنشاء نماذج للنشر والعمليات التي تُمكّن ذاتيًا. عندما نضيف أمانًا إلى ذلك، فإننا نطبق نفس التوقعات بأن نؤتمت كل شيء تلقائيًا ونعرّف «الأنماط» (patterns) والعمليات بحيث يمكن تكرارها باستمرار. وبهذا يكون انتهى بنا الأمر إلى ما أحب أن أسميه "DevSecOps". (DevSecOps هي اختصار لمصطلح التطوير والأمن والعمليات. هدفها هو جعل كل شخص مسؤولاً عن الأمان بهدف تنفيذ القرارات والإجراءات الأمنية بنفس المستوى والسرعة كما في قرارات وإجراءات التطوير والعمليات.) إن المفتاح الرئيسي في هذا النهج الجديد هو "الإزاحة نحو اليسار"، ونقل اختبار الأمان وجهود تركيب المصدر المفتوح بعيدًا عن مرحلة الإنتاج المتأخرة والعودة نحو التصميم والتطوير. كما هو الحال في DevOps، التي تُمكّن المطورين من تعريف« بُنى» (architecture) معتمدة على البرمجيات وإصدارها ونشرها باستخدام الأتمتة، تمنح DevSecOps المطورين نفس الأدوات والتقنيات والعمليات للقيام بالشيء نفسه من أجل أمان البرنامج. الخطوة 1: البدء في التصميم إنّ الطريقة الأكبر التي تخرج بها التطبيقات مفتوحة المصدر عن مسارها بسرعة، تتمثل في عدم التفكير في بنيّة التطبيق قبل البدء بكتابة الشيفرة. هل ما زلت تستخدم نسخة "Struts" عمرها سنتين لتطبيقك الجديد فقط لمجرد أنّها مثبّتة على جهازك المحلي مسبقًا، متبقيةً من مشاريعك العشرة السابقة التي أنجزتها؟ تأكّد في كل مرّة تبدأ فيها مشروعًا جديدًا بأنّك تستخدم الإصدار الأحدث والأكثر موثوقية من إطار العمل الذي تعتمده. استخدم أدوات مجانيّة أو أدوات غير مكلفة مثل SourceClear لتحديد «فاتورة المواد» (Bill Of Materials- BOM) في تطبيقك وكن متأكدًا من أنها تفي بالمطلوب قبل بدء العمل. سيوفر عليك لك المتاعب لاحقًا. الخطوة 2: أتمتة كل شيء بالنسبة لي كمطور، إنه من أكثر الأمور إزعاجًا قدوم شخص ما إلى عندما أكون مشغولًا بشيء آخر يتوجب على إنجازه في يومي المثقل بالأعمال. فإذا كنت تتوقع من المطورين استخدام أداة أو البحث في موقع ويب أو طلب إذن من شخص ما في كل مرّة يقومون فيها بالنشر، فسيجدون حتمًا طريقةً لتجنب ذلك. من ناحية أخرى، إذا كنت تستطيع أتمتة عملية تشغيل شيء ما، أو التحقق من قائمة معينة، أو إخطار مجموعة ما، عندها سيواصل المطورين التركيز على ما يجلب للشركة أموالًا أو ما يضيف قيمةً للعميل. يود InfoSec أن يقول: "الأمان هو مهمة الجميع" ولكن غالبًا ما ينسى أن القيمة المضافة تأتي في المرتبة الأولى. إذا لم نتمكن من إضافة قيمة لعملائنا أو المساهمين معنا، فلن يكون هناك أي شيء لحمايته وتأمينه. (InfoSec هي مجموعة من العمليات التي تحافظ على سرية وسلامة وتوافر بيانات الأعمال بأشكالها المختلفة.) تتمثل الفكرة الرئيسية هنا بالقيام بذلك خارج النطاق وجعله شفافًا. يجب أن يكون غير متزامن وغير مرئي أو سيصبح نقطة عناء وإجهاد لشخص ما. الخطوة 3: تطوير "مواطنين جيدين" وليس "بنى جيدة" أخيرًا، لكي يتحقق DevSecOps بالفعل، علينا العمل على تغيير طريقة التفكير حول سياسة أمن المعلومات InfoSec وعمليات النشر المتعلقة بذلك. كانت تبدو معظم نماذج النشر التي تتضمن الأمان في الماضي كالتالي: تصميم -> كتابة شيفرة -> اختبار التكامل -> ضمان الجودة QA -> مراجعة InfoSec -> الإنتاج. ( QA: هي اختصار للكلمتين Quality Assurance) ولكن عندما تكون دورات DevOps مُحتملة خلال ساعات أو حتى دقائق، فكيف يمكنك مراجعة InfoSec قبل مرحلة الإنتاج؟ الجواب: ليس أنت من يفعل ذلك. واسمحوا لي أن أصيغ السؤال على هذا النحو: إذا كان المطورون يحصلون على معلومات جيدة في وقت مبكر لأنك عملت على أتمتة تحليل الشفرة الثابتة، ووفرتَ طريقة تلقائية لإنشاء فاتورة المواد BOM لأطر عمل المصادر المفتوحة لديك، وقدّمت ذلك مبكرًا في دورة حياة تطوير البرمجيات منذ مرحلة التطوير أو حتى التصميم، فما الذي تختبره بالضبط في هذه البنية؟ أنت ببساطة تسأل عما إذا كانوا قد اتخذوا الإجراءات التي يعرفونها أصلًا. اسأل نفسك الآن السؤال التالي، "هل تثق بهم؟" لاحظ، إذا كنت تقدم المعلومات في وقت مبكر بما فيه الكفاية، فبإمكانك إزالة "مراجعة InfoSec" بالفعل عندما يحين وقت النشر. ماذا؟ وهذا صحيح. يمكن ببساطة في هذه المرحلة أن تسأل عملية التحكم في التغيير الخاصة بك الأسئلة التالية: "هل أُكمِلت مراجعات الأمان التلقائية لهذا التطبيق في كل مرحلة من المراحل؟" "هل حلّ المطورون العيوب الحرجة كما هو متوقع على أسس ثابتة؟" "هل كان آخر تقييم مكتمل يصل إلى مستوى توقعاتنا (سياستنا)؟" إذا كان بإمكانك الإجابة بنعم على هذه الأسئلة، فإن ما عليك فعله هو الوثوق في أن فريق التطوير يعمل بشكل نموذجي (مواطنين جيدين)، والحرص على إنتاج نوعية جيدة، والتصرف بطريقة مسؤولة. سيبدو نموذجنا الجديد مشابها لهذا: تصميم مستنير -> مراجعة الشيفرة الآلية -> ضمان الجودة -> IT -> مواطن جيد؟ -> النشر. ترجمة وبتصرف للمقال: 3 steps to secure, open source DevOps لصاحبه: Jet Anderson. اقرأ أيضًا المقال التالي: أفضل 5 لغات برمجة لـ DevOps المقال السابق: ما هي الغاية من DevOps؟ كامل مقالات السلسلة.
  9. يساعدك التغيير الحقيقي في الثقافة التنظيمية على ردم الفجوات التي اعتقدت أنه ليس بالإمكان تجاوزها. فكّر في آخر مرّة حاولت فيها تغيير عادةٍ شخصية. من المحتمل أن تصل إلى نقطة تحتاج فيها إلى تغيير طريقة تفكيرك وجعل هذه العادة أقل جزء من هويتك. هذا صعب — مع أنك تحاول فقط تغيير طرق تفكيرك الخاصة. لذلك، ربما حاولت وضع نفسك في مواقف جديدة. حيث يمكن أن تساعدنا المواقف الجديدة فعليًا في خلق عادات جديدة، والتي بدورها تؤدي إلى طرق جديدة للتفكير. هذا ما يتعلق بالتغيير الناجح: إنه يتعلق بالتوقعات بقدر ما يتعلق بالنتائج. عليك أن تعرف سبب تغييرك وأين تتجه (وليس فقط كيف ستفعل ذلك)، لأن التغيير فقط من أجل التغيير غالبًا ما يكون محدود الأجل وقصير النظر. فكّر الآن في التغييرات التي تحتاجها مؤسسة تعمل في مجال تكنولوجيا المعلومات. ربما فكّرتَ في اعتماد شيء مثل DevOps. يحتوي هذا الشيء الذي نسميه "DevOps" على ثلاثة مكونات: الأشخاص والعملية والأدوات. يمثل الناس والعملية الأساس لأي منظمة. لذلك، يتطلب اعتماد DevOps إجراء تغييرات أساسية في جوهر معظم المنظمات، وليس فقط تعلم أدوات جديدة. ويمكن أن يكون التغيير قصير النظر، كما هو الحال في أي تغيير، إذا كنت تركز على التغيير كحل لنقطة محددة على سبيل المثال - "الحصول على أداة أفضل لعمل تنبيه"، - فمن المحتمل أن تتوصل إلى رؤية محدودة للمشكلة. قد توفر طريقة التفكير هذه أداة تحتوي على مزيد من الأجراس والصفارات وطريقة أفضل للتعامل مع الإدارة عند الطلب. لكن لا يمكنها معالجة حقيقة أن التنبيهات لا تصل إلى الفريق المطلوب، أو أن تلك الإخفاقات لا تزال موجودةً لأن أحدًا لا يعرف كيفية إصلاح الخدمة. تخلق الأداة الجديدة (أو على الأقل فكرة الأداة الجديدة) فرصة لإجراء مناقشة حول المشاكل الأساسية التي شوهت نظرة فريقك في المراقبة. حيث تتيح لك الأداة الجديدة إجراء تغييرات أكبر - تغييرات على معتقداتك وممارساتك - والتي تُعدُّ أكثر أهمية كأساس لمؤسستك. يتطلب إحداث تغيير أعمق أساليب جديدة لمفهوم التغيير المُشترَك. ونحتاج أولًا إلى فهم محرك التغيير بشكل أفضل لاكتشاف هذه الأساليب. إزالة الحواجز لفهم الحاجة إلى DevOps، التي تحاول إعادة تجميع كيانات "الانقسام" التقليدية "للتطوير" و "العمليات"، يجب علينا أولاً أن نفهم كيف حدث الانقسام. بمجرد "معرفة استخدامه"، يمكننا أن نرى الانقسام على حقيقته- ونزيله إذا لزم الأمر. يوجد اليوم أكثر من نظرية للإدارة، ولكن يمكننا تتبع أصول معظم نظريات الإدارة الحديثة لفريدريك وينسلو تايلور. كان تايلور مهندسًا ميكانيكيًا أنشأ نظامًا لقياس كفاءة العمال في مصنع للفولاذ. اعتقد تايلور أنه بالإمكان تطبيق التحليل العلمي على العمال في المصنع، ليس فقط لتحسين المهام الفردية، ولكن أيضًا لإثبات أن هناك طريقة أفضل يمكن اكتشافها لأداء أي مهمة. يمكننا بسهولة رسم شجرة تاريخية اعتمادًا على وضع تايلور في الجذر. ظهرت من جهود تايلور المبكرة في أواخر الثمانينات من القرن الماضي برامج دراسة الحركة الزمنية وغيرها من برامج تحسين الجودة التي امتدت في عشرينيات القرن العشرين حتى يومنا هذا، حيث نرى منهجيات معايير سيجما الستة (Six Sigma) والتصنيع الرشيق (Lean) وما شابه. وتُهيمن على ثقافة الأعمال السائدة اليوم منهجيات: من من الأعلى إلى الأسفل (Top-down)، والإدارة موجَّهة النمط (directive-style management)، والمقترنة بالنهج النظامية لدراسة العملية. إنها تركز في المقام الأول على الفاعلية كمقياس رئيسي لنجاح العمال. إذا كان تايلور هو الأصل لشجرتنا التاريخية، فإن فرعنا الرئيسي التالي في الصندوق سيكون الفريد سلون (Alfred P. Sloan) من جنرال موتورز في العشرينات من القرن الفائت. إن هيكلية Sloan التي أُنشئت في جنرال موتورز، لن تظل قويةً فقط حتى عام الـ 2000، بل أنها أيضًا ستكون النموذج الرئيسي للشركة على مدار الخمسين عامًا القادمة. كانت جنرال موتورز في عام 1920 تعاني من أزمة في الإدارة -أو بالأحرى أزمة بسبب نقص الإدارة. كتب سلون كتابه «"الدراسة التأسيسية"» (Organizational Study) لمجلس الإدارة، مقترحًا هيكلًا جديدًا لعدد وافر من أقسام جينرال موتورز. يركّز هذا الهيكل الجديد على مفهوم "العمليات اللامركزية مع التحكم المركزي". ستعمل الآن الأقسام الفردية، المرتبطة بعلامات تجارية مثل شيفروليه وكاديلاك وبويك بشكل مستقل في حين توفر الإدارة المركزية الوسائل اللازمة لتوجيه الاستراتيجية والتحكم المالي. صعدت جنرال موتورز نتيجة توصيات سلون (وتوجيهات لاحقة كمدير تنفيذي) إلى مركز رائد في صناعة السيارات الأمريكية. حيث خلقت خطة سلون شركة ناجحة للغاية من واحدة على شفا كارثة. من وجهة النظر المركزية، فالوحدات المستقلة عبارة عن صناديق سوداء. يتم تعيين الحوافز والأهداف في المستويات العليا، والفرق في المستوى الأسفل من أجل التنفيذ. لا تزال فكرة تايلور حول "أفضل الممارسات" - السلوكيات القياسية التبادلية والتكرارية - تحتل مكانًا في مُثُل الإدارة الحالية، حيث تقترن بالنموذج الهرمي للهيكل المؤسسي لسلون، الذي يدعو إلى انقسامات صلبة للإدارة وصوامع من أجل السيطرة القصوى. يمكننا الإشارة إلى العديد من الدراسات الإدارية التي تثبت ذلك. لكن ثقافة الأعمال لا تُنشَأ وتُنشَر فقط من خلال قراءة الكتب. الثقافة التنظيمية هي نتاج أناس حقيقيين في مواقف فعلية يقومون بسلوكيات ملموسة تدفع المعايير الثقافية عبر الزمن. هذه هي الطريقة التي تتعزز بها أشياء مثل نظريات Taylorism و Sloanianism وتصبح ثابتة. إن تمويل قطاع التكنولوجيا هو مثال على ذلك. إليك طريقة عمل الحلقة: يستثمر المستثمرون فقط في الشركات التي يعتقدون أنها يمكن أن تحقق رؤيتهم الخاصة للنجاح. لا ينشأ هذا النموذج للنجاح بالضرورة من الشركة نفسها (وأهدافها الخاصة)، إنه يأتي من أفكار مجلس الإدارة حول الصيغة التي يجب أن تبدو عليها الشركة الناجحة. يأتي العديد من المستثمرين من الشركات التي نجت من اختبارات ومتاعب إدارة الأعمال، ونتيجة لذلك لديهم مخططات مختلفة لما يمكنه جعل الشركة ناجحة. إنهم يمولون الشركات التي يمكن تعليمها لتقليد نماذجهم للنجاح. لذا فإن الشركات التي ترغب في الحصول على تمويل تتعلم محاكاتهم. وبهذه الطريقة، فإن حاضنة بدء التشغيل هي وسيلة مباشرة لاستنساخ بنية وثقافة يفترض أنهما مثاليتان. انقسام "Dev" و "Ops" ليس نتيجة الشخصية أو المهارات المتباينة أو القبعة السحرية الموضوعة على رؤوس الموظفين الجدد، إنها نتيجة ثانوية للنظريات للتيلورية والسلانية. وإن الحدود الواضحة والفاصلة بين المسؤوليات والأشخاص هي وظيفة إدارية مقرونة بالتركيز على كفاءة العمال. كان بالإمكان تقسيم الإدارة بسهولة إلى حدود المنتج أو المشروع بدلاً من المهارات، ولكن يخبرنا تاريخ نظرية إدارة الأعمال حتى اليوم أن التجميع القائم على المهارات هو الطريقة "الأفضل" لتحقيق الكفاءة. لسوء الحظ، تخلق تلك الحدود توترات، وهذه التوترات هي نتيجة مباشرة للأهداف المتعارضة التي حددتها حلقات إدارة مختلفة ذات أهداف مختلفة. فمثلًا: الرشاقة ⟷ الاستقرار استقطاب مستخدمين جدد ⟷ خبرة المستخدمين الحاليين الحصول على ميزات التطبيق ⟷ تطبيق متاح للاستخدام النجاح في المنافسة ⟷ حماية الإيرادات إصلاح المشكلات التي تظهر ⟷ منع المشكلات قبل حدوثها يمكننا أن نرى اليوم اعترافًا متزايدًا بين كبار قادة المنظمات بأن ثقافة الأعمال الحالية (وبالتالي مجموعة التوترات التي تنتجها) تمثل مشكلة خطيرة. في تقرير Gartner لعام 2016، قال 57 بالمائة من المشاركين أن التغيير الثقافي كان أحد التحديات الرئيسية التي ستواجه الشركة حتى عام 2020. إن ظهور أساليب جديدة مثل المنهجية المرنة و DevOps كوسيلة للتأثير على التغييرات التنظيمية يعكس هذا الاعتراف. الارتفاع في «"تكنولوجيا معلومات الظل"» (shadow IT) هو الوجه الآخر للعملة. حيث تربط التقديرات الحديثة ما يقرب من 30 في المئة من إنفاق تكنولوجيا المعلومات خارج سيطرة منظمة تكنولوجيا المعلومات. هذه ليست سوى بعضًا من "الاهتمامات الثقافية" التي تواجهها الشركات. فالحاجة إلى التغيير واضحة، لكن الطريق إلى الأمام لا يزال محكومًا بقرارات الماضي. المقاومة ليست عديمة الجدوى عادةً ما يكون التغيير استجابة تنظيمية لخطأ ما. وبهذا المعنى، إذا كان التوتر (حتى الشدائد) هو المحفز الطبيعي للتغيير، فإن مقاومة التغيير هي مؤشر للنجاح. لكن التركيز المفرط على المسارات الناجحة يمكن أن يجعل المنظمات غير مرنة، وبليدة، وجامدة. إن تقييم سياسة التوجيه من خلال النتائج الفعّالة هو أحد أعراض هذه الصلابة المتزايدة. أدى النجاح في أقسام تقنية المعلومات التقليدية إلى زيادة سماكة جدران تقنية المعلومات. الأقسام الأخرى هي الآن "عملاء"، وليست زملاء عمل. تنشئ محاولات إزاحة تكنولوجيا المعلومات بعيدًا عن كونها مركزًا للتكلفة نموذجَ تشغيلٍ جديد يفصل تكنولوجيا المعلومات عن باقي أهداف العمل. وهذا بدوره يخلق المقاومة التي تحدّ من خفة الحركة أو الرشاقة، ويزيد من الاحتكاك، ويقلل من الاستجابة. التعاون يحصل على الرف لصالح "توجيه الخبراء". والنتيجة هي أن النظرة الانعزالية لتكنولوجيا المعلومات لا يمكن إلا أن تضر أكثر مما تنفع. وبما أن "البرمجيات تجتاح العالم"، يصبح تكنولوجيا المعلومات أكثر وأكثر أهمية للنجاح العام للمنظمة. تدرك مؤسسات تكنولوجيا المعلومات ذات التفكير المتقدم هذا وتقوم بالفعل بإجراء تغييرات متعمدة على قواعد العمل، بدلاً من التعامل مع التغيير على أنه شيء تخافه. على سبيل المثال، تشاور موقع Facebook مع عالم الأنثروبولوجيا «روبن دنبار» (Robin Dunbar) حول أسلوب تعامله المجموعات الاجتماعية، ولكنه أدرك مع نمو الشركة تأثير ذلك على المجموعات الداخلية (وليس فقط المستخدمين الخارجيين للموقع). نالت ثقافة زابوس الكثير من الثناء لدرجة أن المنظمة أنشأت قسمًا يركّز على تدريب الآخرين على وجهات نظرهم حول القيم الأساسية وثقافة الشركات. وبالطبع يعد هذا الكتاب مرافقًا لـكتاب The Open Organization، وهو كتاب يوضح كيف يمكن للمبادئ المفتوحة المطبقة على الإدارة - كالشفافية والمشاركة والمجتمع - إعادة إنشاء المنظمة بما يناسب عصرنا المترابط سريع الخطى. حل للتغيير أخبرني أحد الزملاء ذات مرّة أنّه بإمكانه شرح DevOps لمدير المشروع باستخدام مفردات إطار عمل مكتبة البنية التحتية لتكنولوجيا المعلومات فقط. في حين أن هذه الأطر تبدو متعارضة، فإنها في الواقع تركز على إدارة التغيير والمخاطر. أنها ببساطة تقدّم عمليات وأدوات مختلفة لمثل هذا النوع من الإدارة. من المهم ملاحظة هذه النقطة عند التحدث عن DevOps خارج إطار تقنية المعلومات. فبدلاً من التركيز على أعطال العملية وإخفاقاتها، أظهر كيف أن التغييرات الأصغر تقدّم مخاطر أقل وما شابه ذلك. وهذه طريقة قوية لتسليط الضوء على الفوائد التي تغير ثقافة الفريق: إن التركيز على القدرات الجديدة بدلاً من المشاكل القديمة هو عامل فعال للتغيير، خاصة عند تتبنى إطار مرجعي لشخص آخر. لا يتعلق التغيير فقط بإعادة بناء المنظمة؛ إنه يتعلق أيضًا بطرق جديدة لردم الفجوات التي لا يمكن تجاوزها تاريخيًا - حل لتلك التوترات التي حدّدتها سابقًا برفض وضع أشياء مثل "الرشاقة" و "الاستقرار" كقوى متبادلة. إن إنشاء فرق متداخلة تركز على النتائج أكثر من الوظائف يمثل أحد الاستراتيجيات في العمل. ويعد الجمع بين فرق مختلفة يعتمد كل منها على الآخر حول مشروع أو هدف واحد من أكثر الطرق شيوعًا. تسفر إزالة الاحتكاك بين هذه الفرق وتحسين الاتصالات عن تحسينات هائلة - حتى أثناء التمسك بهياكل الإدارة في صومعة الحديد (لا يلزم هدم الصوامع إذا أمكن إتقانها). حيث لا تعد مقاومة التغيير في هذه الحالات مؤشرًا على النجاح. احتضان التغيير هو المؤشر. إن هذه ليست "أفضل الممارسات". هي ببساطة طريقة لفحص الحدود الخاصة بك. كل منظمة لديها حدود فريدة من نوعها أنشأها الأشخاص داخلها. وبمجرد "معرفة استخدامها"، يمكنك أن تقرّر ما إذا كانت تحتاج إلى إزالة أو إلى تخصيص. ترجمة وبتصرف للمقال: What's the point of DevOps لصاحبه: Matt Micene. اقرأ أيضًا المقال التالي: ثلاث خطوات لتأمين DevOps مفتوح المصدر المقال السابق: ما المقصود بـ DevOps؟ كامل مقالات السلسلة.
  10. تُستخدَم كلمة DevOps (اختصارٌ للكلمتين Development و Operations) لوصف مجموعةٍ من أنشطة التكنولوجيا الحديثة التي تسعى إلى تقريب مطوري البرمجيات وموظفي العمليات من بعضهم بعضًا بشكلٍ أوثق بغية العمل بصورة أكثر تعاونية على نفس المشروع. الهدف من ذلك هو خلال كسر الحواجز التقليدية الموجودة بين هذين الفريقين التقنيين، مما يمكِّن المؤسسات من تقليل الوقت وزيادة الانخراط في تقديم ونشر إصدارات جديدة من البرمجيات. سيؤدي هذا الجهد بديهيًا إلى دورات تطوير أقصر مما قد يوفر الوقت والمال بشكل مثالي، ويمنح المؤسسة ميزة تنافسية تُنافِس بها المؤسسات الأخرى التي تعتمد دورات التطوير الطويلة والأكثر تقليديةً. لماذا ينبغي اتباع استراتيجية DevOps؟ لم تعد عملية الابتكار السريع موضوعًا اختياريًا. فبغض النظر عن مجال عمل مؤسستك، أصبح من شبه المؤكّد أنّه مجال يشهد تقلبات في الأنشطة التجارية التقليدية نتيجة الانتقال إلى الاقتصاد القائم على البرمجيات. فبدءًا من النقل إلى التصنيع، ومن التعدين إلى الزراعة، ومن التمويل إلى الرعاية الصحية، تجعل البيانات الضخمة، والحوسبة السحابية، والتطبيقات المحمولة، وعدد كبير من التقنيات الأخرى من البرمجيات هي ما يشكل الفارق الرئيسي بين الأعمال والمؤسسات التي تتقدم إلى الأمام وتلك التي تتراجع وتتخلف عن الركب. حتى وإن لم تكن مؤسستك تنافس في سوق البرمجيات قبل عقد من الزمن، فهي اليوم كذلك، والطريقة للمضي قدمًا هي في استخدام حلول أفضل للتقدم بشكل أسرع. كيف أبدأ؟ تتمثل الخطوات الأولى في مجال DevOps في فحص ثقافتك وممارساتك، وتحديد العوائق التي تحول دون التواصل والتنسيق بين الفريق، واتخاذ الخطوات اللازمة لتوطيد التواصل بين فِرق التطوير والعمليات لديك. إن تحقيق ذلك يمثل تحدّيًا لا يمكنك بلوغه بين عشية وضحاها. ابدأ بإلقاء نظرة على منهجياتك الحالية ثم قم بتنقيحها وتقويمها. على الرغم من أنّ DevOps يتمحور بشكل رئيسي حول الثقافة التنظيمية، فإنّ تحديد أدوات البرامج الصحيحة والمناسبة يعدّ خطوةً مهمةً أيضًا. فهل تستخدم مؤسستك أدوات للتحكم بالإصدار والمراجعة مثل Git لمساعدتك في إدارة الشيفرة البرمجية؟ هل تعتمد أدوات البناء و «التركيب المتواصل» (continuous integration) لجعل التحرك من المصدر وحتى الاختبار سلسًا قدر الإمكان؟ وماذا عن الأدوات المستخدمة لأتمتة الاختبار وتحزيم البرامج تلقائيًا، أو لاختبارات النشر والحماية؟ هل تبحث عن طرق لإدارة البنية الأساسيّة الخاصّة بك مثل الشيفرة البرمجية باستخدام «أدوات إدارة التكوين» (configuration management tools)، لتوسيع نطاق البيئات وتكرارها بسهولة؟ وماذا عن أدوات المراقبة لمتابعة كامل العملية بدءًا من التطوير وحتى الإنتاج؟ تستفيد DevOps من إيجاد الأدوات المناسبة للحفاظ على عمل فِرق التطوير والعمليات الخاصة بك معًا وتحركها بشكل أسرع إذا كنت بحاجةٍ إلى دليل لحماية تقنية «حاويات لينكس» (Linux container)، ألق نظرة على قائمة التحقق المرجعيّة هذه: 4 خطوات لبدء رحلتك مع الحاويات. دورة علوم الحاسوب دورة تدريبية متكاملة تضعك على بوابة الاحتراف في تعلم أساسيات البرمجة وعلوم الحاسوب اشترك الآن أين يمكنني تعلم المزيد؟ سننشر عددًا من المقالات تشرح ماهية DevOps وتُعرِّفك عليها؛ راجع الوسم «تعرف على DevOps» أو بعضًا من المقالات الأكثر شيوعًا أدناه. ما الهدف من DevOps؟: توضح نظرة موجزة لتاريخ DevOps الحاجة إلى التفكير بطريقة مختلفة حول العمل التعاوني في مجال تكنولوجيا المعلومات. 3 خطوات لحماية DevOps مفتوحة المصدر: المفتاح الرئيسي لتأمين تطوير التطبيق هو «الإزاحة نحو اليسار» (shift left) - انقل اختبار الأمان بعيدًا عن مرحلة الإنتاج المتأخرة وعُد إلى التصميم والتطوير. أفضل 5 لغات برمجة لـ DevOps: نجمع هنا خمسًا من أفضل لغات البرمجة لـ DevOps وبعضًا من الموارد التعليمية المفيدة لكل منها. رحلة المطور عبر DevOps: انتهت أيام التطوير المنعزلة لفرق التشغيل والعمليات. لماذا تعد DevOps الاستراتيجية التقنية الأكثر أهمية اليوم: إزالة بعض الالتباس حول مفهوم DevOps. تقنيات DevOps المحميّة «للخدمات المصغرة» (microservices): أحدثت الحاويات والخدمات المصغّرة ثورةً في تطوير التطبيقات وإدارة البنية التحتية. ربما يمكنك أيضًا إيجاد الفائدة في هذه الموارد الخارجية التي توفّر المزيد من المعلومات. التحديث بسرعة تطبيقات المصدر المفتوح باستخدام DevOps 9 عبارات مفتاحية لـ DevOps تحديث أسرع اعتمادا على DevOps كتاب إلكتروني مجاني: كتاب إلكتروني مجاني: DevOps with OpenShi. ترجمة وبتصرف للمقال: What is DevOps اقرأ أيضًا المقال التالي: ما الهدف من DevOps؟
  11. مقدّمة يُعتبر Apache و Nginx اثنين من أشهر خوادم الويب مفتوحة المصدر ويُستخدمان غالباً مع PHP. قد يكون من المفيد تشغيل كل منهما على نفس الجهاز الإفتراضي virtual machine عند استضافة مواقع ويب متعددة ذات متطلباتٍ متنوعة. إنّ الحل العام لتشغيل خوادم الويب على نظام واحد هو استخدام عناوين IP متعددة أو أرقام منافذ مختلفة. بالإمكان ضبط الخوادم التي تملك كلّا من عناوين IPv4 و IPv6 لخدمة مواقع Apache على أحد البروتوكولين ومواقع Nginx على البروتوكول الآخر، ولكن عمليًا هذا غير مُطبّق حاليًا، نظرًا لأن تبنّي مزودي خدمات الإنترنت لـ IPv6 لا يزال غير شائع. حيث يعدّ وجود رقم منفذ مختلف مثل 81 أو 8080 لخادم الويب الثاني حلاً آخر، ولكن مشاركة عناوين URL بأرقام المنافذ (مثل http://example.com:81) ليس منطقيًّا أو مثاليًّا دائمًا. سنتعلّم في هذه الدورة كيفيّة ضبط Nginx كخادم ويب وكذلك كوسيط عكسي Reverse Proxy لـ Apache - كل ذلك على خادم واحد. قد تكون هنالك حاجة اعتمادًا على تطبيق الويب إلى تغييرات في الشفرة ليبقى Apache مُدركًا بالوسيط العكسي، وخاصّة عند ضبط مواقع SSL. سنتجنّب ذلك بتثبيت module وحدة Apache تسمى mod_rpaf والتي تُعيد كتابة متغيرات بيئة معيّنة بحيث يبدو أن Apache يتعامل مباشرة مع الطلبات من عملاء الويب. ستُضاف أربعة أسماء نِطاقات domain names على خادم واحد. وسيُخدَّم اثنين منهما بواسطة Nginx هما:example.com (المُضيف الظاهري الافتراضي) و sample.org. والاثنين المتبقيين، foobar.net و test.io، سيُخدّمان من قبل Apache. سنُعدّ أيضًا Apache لخدمة تطبيقات PHP باستخدام PHP-FPM، والذي يقدّم أداء أفضل عبر mod_php. المتطلبات المُسبقة ستحتاج لإكمال هذه الدورة التعليميّة إلى ما يلي: خادم Ubuntu 18.04 جديد تم إعداده من خلال اتباع خطوات الإعداد الأولي للخادم في Ubuntu 18.4، مع مستخدم sudo عادي (non-root) و جدار ناري. ضبط أربعة أسماء نطاق مؤهلة بالكامل للإشارة لعنوان IP الخاص بخادمك. انظر الخطوة 3 من كيفية إعداد اسم مضيف فيDigitalOcean كمِثال لكيفية القيام بذلك. إذا كنت تستضيف DNS للنطاقات الخاصّة بك في مكان آخر، فعليك إنشاء سجلات A مناسبة هناك بدلاً من ذلك. الخطوة 1 - تثبيت Apache و PHP-FPM لنبدأ بتثبيت Apache و PHP-FPM. سنثبّت أيضًا بالإضافة إلى تثبيت Apache و PHP-FPM، وحدة PHP FastCGI Apache وهيlibapache2-mod-fastcgi، لدعم تطبيقات ويب FastCGI. أولاً، يجب تحديث قائمة الحزم package الخاصّة بك للتأكد من حصولك على أحدث الحزم. $ sudo apt update يجب بعد ذلك تثبيت حزم Apache و PHP-FPM: $ sudo apt install apache2 php-fpm يجب تنزيل وحدة FastCGI Apache من kernel.org وتثبيتها باستخدام الأمر dpkg لأنّها غير متوفرة في مستودع Ubuntu: $ Wget https://mirrors.edge.kernel.org/ubuntu/pool/multiverse/liba/ libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb $ sudo dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb علينا بعد ذلك تغيير الضبط الافتراضي لخادم Apache من أجل استخدام PHP-FPM. الخطوة 2 - ضبط Apache و PHP-FPM سنغيّر في هذه الخطوة رقم منفذ Apache إلى 8080 وضبطه للعمل مع PHP-FPM باستخدام الوحدة mod_fastcgi. أعد تسمية ملف ضبط ports.conf لمخدم Apache: $ sudo mv /etc/apache2/ports.conf /etc/apache2/ports.conf.default أنشئ ملف ports.conf جديد مع تعيين المنفذ إلى 8080: $ echo "Listen 8080" | sudo tee /etc/apache2/ports.conf ملاحظة: تُضبط خوادم الويب بشكل عام للتنصت على المنفذ 127.0.0.1:8080 عند ضبط الوكيل العكسي، ولكن القيام بذلك سيؤدي إلى ضبط قيمة متغير بيئة (PHP (SERVER_ADDR إلى عنوان IP الاسترجاع بدلاً من عنوان الـ IP العام للخادم. هدفنا هو إعداد Apache بطريقة لا ترى مواقعه على الويب الوكيل العكسي أمامها. لذلك، سنضبطه للتنصت على المنفذ 8080 لجميع عناوين IP. سننشئ بعد ذلك ملف مضيف افتراضي لـ Apache. سيعدّ التوجيه في هذا الملف ليخدّم المواقع فقط على المنفذ 8080. عطّل المضيف الظاهري الافتراضي: $ sudo a2dissite 000-default ثم أنشئ ملف مضيف افتراضي جديد، باستخدام الموقع الافتراضي الموجود: $ sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/001-default.conf افتح الآن ملف الضبط الجديد: $ sudo nano /etc/apache2/sites-available/001-default.conf غيّرمنفذ التنصت إلى 8080: /etc/apache2/sites-available/000-default.conf ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined احفظ الملف وقم بتنشيط ملف الضبط الجديد: $ sudo a2ensite 001-default ثم أعد تحميل Apache: $ sudo systemctl reload apache2 تحقّق من أن Apache يتنصت الآن على 8080: $ sudo netstat -tlpn يجب أن يبدو الخرج output كالمثال التالي، حيث يتنصّت apache2 على المنفذ 8080: output Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1086/sshd tcp6 0 0 :::8080 :::* LISTEN 4678/apache2 tcp6 0 0 :::22 :::* LISTEN 1086/sshd يمكنك إعداد دعم PHP و FastCGI بمجرّد التحقق من أن Apache يتنصت على المنفذ الصحيح. الخطوة 3 - ضبط Apache لاستخدام mod_fastcgi يخدّم Apache صفحات PHP باستخدام mod_php افتراضيًا، ولكنه يتطلب إعدادًا إضافيًّا للعمل مع PHP-FPM. ملاحظة: إذا كنت تجرّب هذا الدرس على نسخة موجودة مسبقًا من LAMP مع mod_php، عطّله أولاً باستخدام sudo a2dismod php7.2. سنضيف كتلة ضبط لوحدة mod_fastcgi التي تعتمد على mod_action. يُعطّل mod_action بشكل افتراضي، لذلك نحتاج أولاً إلى تفعيله: $ sudo a2enmod action أعد تسمية ملف ضبط FastCGI الموجود: $ sudo mv /etc/apache2/mods-enabled/fastcgi.conf/etc/apache2/mods -enabled/fastcgi.conf.default أنشئ ملف ضبط جديد: $ sudo nano /etc/apache2/mods-enabled/fastcgi.conf أضف التوجيهات التالية إلى الملف لتمرير طلبات ملفات php. إلى مقبس PHP-FPM UNIX: /etc/apache2/mods-enabled/fastcgi.conf AddHandler fastcgi-script .fcgi FastCgiIpcDir /var/lib/apache2/fastcgi AddType application/x-httpd-fastphp .php Action application/x-httpd-fastphp /php-fcgi Alias /php-fcgi /usr/lib/cgi-bin/php-fcgi FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -socket /run/php/php7.2-fpm.sock -pass-header Authorization Require all granted احفظ التغييرات واختبر الضبط: $ sudo apachectl -t إذا ظهرت عبارة Syntax OK، أعد تحميل Apache: $ sudo systemctl reload apache2 إذا رأيت رسالة التحذير التالية، يمكنك تجاهلها الآن بشكل آمن. سنَضبط أسماء الخادم في وقت لاحق: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message. دعنا نتأكد الآن من أنّه بإمكاننا تخديم PHP من Apache. الخطوة 4 - التحقق من عمل PHP سَنتأكّد من أن PHP يعمل، وذلك من خلال إنشاء ملف ()phpinfo والوصول إليه من متصفح الويب. أنشئ الملف var/www/html/info.php/ والذي يحتوي على استدعاء للدّالة phpinfo: $ echo "" | sudo tee /var/www/html/info.php انتقل في المتصفح إلى http: // your_server_ip: 8080 / info.php لاستعراض هذا الملف. ستظهر لك قائمة إعدادات الضبط التي يستخدمها PHP. كما في الشكل التالي: تحقّق من أن الخيار Server API يأخذ القيمة FPM/FastCGI وذلك في أعلى الصفحة كما في الصورة السابقة. سترى كذلك في أسفل الصفحة تقريبًا في القسم PHP Variables بأنّ قيمة SERVER_SOFTWARE هي Apache على Ubuntu. وهذا يؤكّد أنّ الوحدة mod_fastcgi مُفعّلة وأنّ Apache يستخدم PHP-FPM لمعالجة ملفات PHP. الخطوة 5 - إنشاء مضيفات افتراضيّة لـ Apache دعونا ننشئ ملفات المضيف الافتراضي لـ Apache للنطاقين foobar.net و test.io. سنقوم لعمل ذلك أولاً بإنشاء الأدلّة الجذر للمستند في كِلا الموقعين ووضع بعض الملفات الافتراضيّة في هذه الأدلة حتى نتمكن من اختبار الضبط لدينا بسهولة. أولاً، أنشئ الأدلّة الجذر للمستند: $ sudo mkdir -v /var/www/foobar.net /var/www/test.io أنشئ بعد ذلك ملف index لكل موقع: $ echo "<h1 style='color: green;'>Foo Bar</h1>" | sudo tee /var/www/foobar.net/index.html $ echo "<h1 style='color: red;'>Test IO</h1>" | sudo tee /var/www/test.io/index.html " | sudo tee /var/www/test.io/index.html ثم أنشئ ملف ()phpinfo لكل موقع حتى نتمكن من اختبار فيما إذا ضُبط PHP بشكل صحيح. $ echo "" | sudo tee /var/www/foobar.net/info.php $ echo "" | sudo tee /var/www/test.io/info.php الآن أنشئ ملف المضيف الافتراضي للنطاق foobar.net: $ sudo nano /etc/apache2/sites-available/foobar.net.conf أضف الشفرة التالية إلى الملف لتعريف المضيف: /etc/apache2/sites-available/foobar.net.conf ServerName foobar.net ServerAlias www.foobar.net DocumentRoot /var/www/foobar.net AllowOverride All يتيح السطر AllowOverride All تفعيل دعم htaccess. احفظ وأغلق الملف. ثم أنشئ ملف ضبط مماثل لـ test.io. أولاً أنشئ الملف: $ sudo nano /etc/apache2/sites-available/test.io.conf ثم أضف الضبط إلى الملف: /etc/apache2/sites-available/test.io.conf ServerName test.io ServerAlias www.test.io DocumentRoot /var/www/test.io AllowOverride All احفظ الملف وإغلاق المحرّر. والآن بعد إعداد كل من مضيفي Apache الافتراضيين، فعّل المواقع باستخدام الأمر a2ensite. والذي يُنشئ رابط رمزي لمَلف المضيف الافتراضي في الدليل sites-enabled: $ sudo a2ensite foobar.net $ sudo a2ensite test.io تحقّق من Apache للتأكّد من وجود أخطاء في الضبط مرّة أخرى: $ sudo apachectl –t سترى عبارة Syntax OK إذا لم يكن هناك أخطاء. إذا رأيت أي شيء آخر، فتحقّق من الضبط وحاول مرّة أخرى. قم بإعادة تحميل Apache لتطبيق التغييرات بمجرّد أن يكون الضبط الخاص بك خاليًا من الأخطاء: $ sudo systemctl reload apache2 افتح http://foobar.net:8080 و http://test.io:8080 في متصفحك للتأكّد من عمل المواقع والتحقّق من أنّ كل موقع يعرض ملف index.html الخاص به. سترى النتائج التالية: تأكّد أيضًا من أن PHP تعمل وذلك عن طريق الوصول إلى ملفات info.php لكل موقع. افتح http://foobar.net:8080/info.php و http://test.io:8080/info.php في متصفحك. سترى قائمة مواصفات ضبط PHP نفسها على كل موقع كما رأيت في الخطوة 4. لدينا الآن موقعين مُستضافين على Apache على المنفذ 8080. فلنَضبط بعد ذلك Nginx. الخطوة 6 - تثبيت وضبط Nginx سنقوم في هذه الخطوة بتثبيت Nginx وإعداد ضبط النطاقات example.com و sample.org كمضيفين افتراضيين لـ Nginx. ثبّت Nginx باستخدام مدير الحزم: $ sudo apt install nginx أزل الرابط الرمزي الافتراضي للمضيف الافتراضي حيث أننا لن نستخدمه بعد الآن: $ sudo rm /etc/nginx/sites-enabled/default سنُنشئ الموقع الافتراضي الخاص بنا فيما بعد (example.com). سنُنشئ الآن مضيفين افتراضيين لـ Nginx باستخدام نفس الإجرائيّة التي استخدمناها من أجل Apache. أنشئ أولاً الأدلّة للمستند الجذر لكل من موقعي الويب: $ sudo mkdir -v /usr/share/nginx/example.com /usr/share/nginx/sample.org سنحتفظ بمواقع الويب الخاصّة بـ Nginx في /usr/share/nginx، وهو المسار الافتراضي الذي سيختاره Nginx. يمكنك وضع هذه المواقع في /var/www/html مع مواقع Apache، لكن هذا الفصل بينها قد يساعدك على ربط المواقع بـ Nginx. كما فعلت مع مضيفي Apache الافتراضيين، أنشئ ملفات index و ()phpinfo من أجل الاختبار بعد اكتمال الإعداد: $ echo "<h1 style='color: green;'>Example.com</h1>" | sudo tee /usr/share/nginx/example.com/index.html $ echo "<h1 style='color: red;'>Sample.org</h1>" | sudo tee /usr/share/nginx/sample.org/index.html $ echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/example.com/info.php $ echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/sample.org/info.php الآن أنشئ ملف مضيف افتراضي للنطاق example.com: $ sudo nano /etc/nginx/sites-available/example.com يستدعي Nginx كتل server {. . .} من ملف الضبط server blocks. أنشئ كتلة خادم من أجل المضيف الافتراضي الأساسي example.com. تجعل ضبط التوجيه default_server هذا المضيف كمضيف افتراضي افتراضي لمعالجة طلبات HTTP التي لا تتطابق مع أي مضيف افتراضي آخر. /etc/nginx/sites-available/example.com server { listen 80 default_server; root /usr/share/nginx/example.com; index index.php index.html index.htm; server_name example.com www.example.com; location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { fastcgi_pass unix:/run/php/php7.2-fpm.sock; include snippets/fastcgi-php.conf; } } احفظ وأغلق الملف. أنشئ الآن ملف مضيف Nginx افتراضي للنطاق الثاني، sample.org: $ sudo nano etc/nginx/sites-available/sample.org أضف ما يلي إلى الملف: /etc/nginx/sites-available/sample.org server { root /usr/share/nginx/sample.org; index index.php index.html index.htm; server_name sample.org www.sample.org; location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { fastcgi_pass unix:/run/php/php7.2-fpm.sock; include snippets/fastcgi-php.conf; } } احفظ وأغلق الملف. ثم فعّل كِلا الموقعين من خلال إنشاء روابط رمزيّة للدّليل sites-enabled: $ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com $ sudo ln -s /etc/nginx/sites-available/sample.org /etc/nginx/sites-enabled/sample.org اختبر بعد ذلك ضبط Nginx لضمان عدم وجود أخطاء في الضبط: $ sudo nginx -t ثم أعد تحميل Nginx إذا لم يكن هناك أخطاء: $ sudo systemctl reload nginx الآن قم بالوصول إلى ملف ()phpinfo الخاص بمُضيفي Nginx الافتراضيين من متصفح الويب من خلال زيارة http://sample.org/info.php و http://example.com/info.php. انظر مجدّدًا إلى الصورة في الأسفل إلى قسم المتغيرات PHP Variables. يجب أن يحوي["SERVER_SOFTWARE"] على القيمة Nginx، مشيرًا إلى أنّ الملفات خُدّمت بشكل مباشر بواسطة Nginx. يجب أن يشير["DOCUMENT_ROOT"] إلى الدليل الذي أنشأته مُسبقًا في هذه الخطوة لكل موقع من مواقع Nginx. ثبّتنا في هذه المرحلة Nginx وأنشأنا مضيفين افتراضيين.سنقوم بعد ذلك بضبط Nginx على طلبات الوكيل المخصّصة للنطاقات المستضافة على Apache. الخطوة 7 - ضبط Nginx لمضيفي Apache الافتراضيين لنُنشئ مضيف Nginx افتراضي إضافي مع أسماء نطاقات متعددة في توجيهات server_name. سيتم توكيل طلبات هذه النطاقات إلى Apache. أنشئ ملف مضيف Nginx افتراضي جديد لإعادة توجيه الطلبات إلى Apache: $ sudo nano /etc/nginx/sites-available/apache أضف كتلة الشفرة التالية التي تحدد أسماء نطاقات كلاً من مضيفي Apache الاتراضيين وتوكل طلباتها إلى Apache. تذكّر استخدام عنوان IP العام في proxy_pass: /etc/nginx/sites-available/apache server { listen 80; server_name foobar.net www.foobar.net test.io www.test.io; location / { proxy_pass http://your_server_ip:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } قم بحفظ الملف وتفعيل هذا المضيف الافتراضي الجديد عن طريق إنشاء رابط رمزي: $ sudo ln -s /etc/nginx/sites-available/apache /etc/nginx/sites-enabled/apache اختبر الضبط للتأكد من عدم وجود أخطاء: $ sudo nginx -t إذا لم يكن هنالك أخطاء، أعد تحميل Nginx: $ sudo systemctl reload nginx افتح متصفحك وقم بالوصول إلى العنوان http://foobar.net/info.php. انتقل لأسفل إلى قسم PHP Variables وتحقق من القيم المعروضة كما في الصورة. يؤكّد المتغيران ERVER_SOFTWARE و DOCUMENT_ROOT أنّ هذا الطلب عُولج بواسطة Apache. وأضيفت المتغيرات HTTP_X_REAL_IP و HTTP_X_FORWARDED_FOR بواسطة Nginx ويجب أن تُظهر عنوان IP العام للحاسب الذي تستخدمه للوصول إلى عنوان URL. لقد أعددنا Nginx بنجاح ليوكل بطلبات نطاقات محدّدة إلى Apache. بعد ذلك، لنقم بضبط Apache لضبط المتغير REMOTE_ADDR كما لو أنه يتعامل مع هذه الطلبات مباشرة. الخطوة 8 - تثبيت وضبط mod_rpaf سنُثبّت في هذه الخطوة وحدة Apache تسمى mod\_rpaf والتي تعيد كتابة قيم REMOTE_ADDR، HTTPS و HTTP_PORT استنادًا إلى القيم المقدّمة من قبل وسيط عكسي. وبدون هذه الوحدة، تتطلب بعض تطبيقات PHP تغييرات في الشفرة للعمل بسلاسة من خلفْ الخادم الوكيل. هذه الوحدة موجودة في مستودع Ubuntu باسم libapache2-mod-rpaf ولكنها قديمة ولا تدعم توجيهات ضبط معينة. سنقوم بدلاً من ذلك بتثبيتها من المصدر. تثبيت الحزم اللازمة لبناء الوحدة: $ sudo apt install unzip build-essential apache2-dev نزّل أحدث إصدار مستقر من GitHub: $ wget https://github.com/gnif/mod_rpaf/archive/stable.zip استخراج الملف الذي نزل: $ unzip stable.zip انتقل إلى المجلد الجديد الذي يحتوي على الملفات: $ cd mod_rpaf-stable ترجم Compile الوحدة ثم ثبّتها: $ make $ sudo make install أنشئ بعد ذلك ملف في المجلد mods-available والذي سيُحمّل وحدة rpaf: $ sudo nano /etc/apache2/mods-available/rpaf.load أضف الشفرة التالية إلى الملف لتحميل الوحدة: /etc/apache2/mods-available/rpaf.load LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.so احفظ الملف وأغلق المحرر. أنشئ ملف آخر في نفس الدليل وسمّه rpaf.conf والذي سوف يحتوي على توجيهات الضبط للوحدة mod_rpaf: $ sudo nano /etc/apache2/mods-available/rpaf.conf أضف كتلة الشفرة التالية لضبط mod_rpaf، مع التأكّد من تحديد عنوان IP الخاص بخادمك: /etc/apache2/mods-available/rpaf.conf RPAF_Enable On RPAF_Header X-Real-Ip RPAF_ProxyIPs your_server_ip RPAF_SetHostName On RPAF_SetHTTPS On RPAF_SetPort On فيما يلي وصف موجز لكل توجيه. لمزيد من المعلومات، راجع ملف mod_rpaf README. RPAF_Header - الترويسة المراد استخدامها لعنوان IP الحقيقي للعميل. RPAF_ProxyIPs - عنوان IP للوكيل لضبط طلبات HTTP من أجله. RPAF_SetHostName - يقوم بتحديث اسم المضيف الافتراضي بحيث يعمل كل من ServerName و ServerAlias. RPAF_SetHTTPS - يضبط متغير بيئة HTTPS استنادًا إلى القيمة الموجودة في X-Forwarded-Proto. RPAF_SetPort - يضبط متغير بيئة SERVER_PORT. يكون مفيد عندما يكون Apache يعمل خلف وكيل SSL. احفظ الملف rpaf.conf وقم بتفعيل الوحدة: $ sudo a2enmod rpaf يؤدي هذا إلى إنشاء روابط رمزيّة من الملفات rpaf.load و rpaf.conf في الدليل mods-enabled. الآن قم بإجراء اختبار الضبط: $ sudo apachectl -t أعد تحميل Apache إذا لم يكن هنالك أخطاء: $ sudo systemctl reload apache2 قم بالوصول إلى الملف ()phpinfo في الصفحات http://foobar.net/info.php و http://test.io/info.php من متصفحك وتحقق من قسم PHP Variables. الآن سيكون المتغير REMOTE_ADDR هو أيضًا عنوان IP العام للحاسب المحلي لديك. الآن دعنا نعد تشفير TLS / SSL لكل موقع. الخطوة 9 - إعداد مواقع HTTPS باستخدام Let's Encrypt (اختياري) سنضبط في هذه الخطوة شهادات TLS / SSL لكل من النطاقات المُستضافة على Apache. سوف نحصل على الشهادات بواسطة [Let's Encrypt](https://letsencrypt.org]. يدعم Nginx إنهاء SSL، لذا من الممكن إعداد SSL بدون تعديل ملفات ضبط Apache. تَضمنْ الوحدة mod_rpaf أن يتم تعيين متغيرات البيئة المطلوبة على Apache لجعل التطبيقات تعمل بسلاسة خلفْ وكيل عكسي لـ SSL. أولاً سنفصل كتل الخادم {...}server من كِلا النطاقين بحيث يمكن أن يكون لكلٍ منهما شهادات SSL خاصّة به. افتح الملف etc/nginx/sites-available/apache/ في المحرّر الخاص بك: $ sudo nano /etc/nginx/sites-available/apache عدّل الملف بحيث يبدو مثل هذا، مع foobar.net و test.io في كتل الخادم الخاصّة بهم: /etc/nginx/sites-available/apache server { listen 80; server_name foobar.net www.foobar.net; location / { proxy_pass http://your_server_ip:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } server { listen 80; server_name test.io www.test.io; location / { proxy_pass http://your_server_ip:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } سنستخدم Certbot لإنشاء شهادات TLS/SSL الخاصّة بنا. ستتولى إضافة Nginx plugin" Nginx" مُهمة إعادة ضبط Nginx وإعادة تحميل الضبط عند الضرورة. أولاً، أضف مستودع Certbot المرخّص: $ sudo add-apt-repository ppa:certbot/certbot اضغط على ENTER عند مطالبتك بتأكيد رغبتك في إضافة المستودع الجديد. ثم قم بتحديث قائمة الحزم للحصول على معلومات حزمة المستودع الجديدة: $ sudo apt update ثم ثبّت حزمة Nginx الخاصّة بـ Certbot باستخدام apt: $ sudo apt install python-certbot-nginx وبمجرّد تثبيته، استخدم أمر certbot لإنشاء الشهادات لـ foobar.net و www.foobar.net: $ sudo certbot --nginx -d foobar.net -d www.foobar.net يخبر هذا الأمر Certbot ليستخدم ملحق nginx، وباستخدم –d لتحديد الأسماء التي نودّ أن تكون الشهادة صالحة لها. إذا كانت هذه هي المرة الأولى التي تُشغّل فيها certbot، فسَتتم مطالبتك بإدخال عنوان بريد إلكتروني والموافقة على شروط الخدمة. سيتصل بعد القيام بذلك certbot بخادم Let's Encrypt، ثم يشغّل ردّا للتحقق من أنّك تتحكم في النطاق الذي تطلب الحصول على شهادة له. سَيسألك Certbot بعد ذلك عن الطريقة التي ترغب في ضبط إعدادات HTTPS الخاصّة بك: Output Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access. ------------------------------------------------------------------------------- 1: No redirect - Make no further changes to the webserver configuration. 2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for new sites, or if you're confident your site works on HTTPS. You can undo this change by editing your web server's configuration. ------------------------------------------------------------------------------- Select the appropriate number [1-2] then [enter] (press 'c' to cancel): حدّد خيارك، ثم اضغط على ENTER. سيتم تحديث الضبط، وإعادة تحميل Nginx لتفعيل الإعدادات الجديدة. الآن، نفّذ الأمر للنطاق الثاني: $ sudo certbot --nginx -d test.io -d www.test.io انظر في قسم PHP Variables. تم تعيين المتغير SERVER_PORT على القيمة 443 وضبط HTTPS على القيمة on، كما لو أنّه تم الوصول إلى Apache مباشرةً عبر HTTPS. مع ضبط هذه المتغيرات، لن تحتاج تطبيقات PHP إلى إعداد خاص للعمل خلف وسيط عكسي. سنقوم الآن بتعطيل الوصول المباشر إلى Apache. الخطوة 10 - حظر الوصول المباشر إلى Apache (اختياري) بما أن Apache يستمع على المنفذ 8080 على عنوان IP العام، فإنّه بإمكان الجميع الوصول إليه. ويمكن حظره من خلال عمل الأمر IPtables التالي في مجموعة قواعد الجدار الناري. $ sudo iptables -I INPUT -p tcp --dport 8080 ! -s your_server_ip -j REJECT --reject-with tcp-reset تأكّد من استخدام عنوان IP لخَادمك مكان اللون الأحمر في المثال السابق. بمجرد حظر المنفذ 8080 في الجدار الناري، اختبر عدم إمكانية الوصول إلى Apache. افتح متصفح الويب الخاص بك وحاول الوصول إلى أحد أسماء نطاقات Apache على المنفذ 8080. على سبيل المثال: http://example.com:8080 يجب أن يعرض المتصفح رسالة خطأ "غير قادر على الاتصال" أو "صفحة الويب غير متوفرة". وبضبط خيار IPtables tcp-reset، لن يرى أحد أي اختلاف بين المنفذ 8080 والمنفذ الذي لا يحتوي أيّ خدمةٍ عليه. ملاحظة: عند إعادة تشغيل النظام وبشكل افتراضي لن تبقى قواعد IPtables كما حدّدناها. هناك طرق متعددة للحفاظ على قواعد IPtables، ولكن أسهلها هو استخدام iptables-persistent في مستودع Ubuntu. استكشف هذه المقالة لمعرفة المزيد حول كيفيّة ضبط IPTables. لنضبط الآن Nginx لخدمة ملفات ثابتة لمواقع Apache. الخطوة 11 - تخديم الملفات الثابتة باستخدام Nginx (اختياري) عندما يقدم وسيط Nginx طلبات لنطاقات Apache، فإنّه يرسل كل ملف طلب لهذا النطاق إلى Apache. Nginx أسرع من Apache في خدمة الملفات الثابتة مثل الصور، وجافا سكريبت وأوراق الأنماط. لذلك دعونا نضبط ملف مضيف apache افتراضي خاص بـ Nginx لتخديم الملفات الثابتة مباشرة ولكن مع إرسال طلبات PHP إلى Apache. افتح الملف etc/nginx/sites-available/apache/ في محرّرك الخاص: $ sudo nano /etc/nginx/sites-available/apache ستحتاج إلى إضافة موضعين location إضافيين لكل كتلة خادم، بالإضافة إلى تعديل أقسام location الموجودة. بالإضافة إلى ذلك، ستحتاج إلى إخبار Nginx بمكان تواجد الملفات الثابتة لكل موقع. إذا قرّرت عدم استخدام شهادات SSL و TLS، فعدّل ملفك بحيث يبدو كالتالي: /etc/nginx/sites-available/apache server { listen 80; server_name test.io www.test.io; root /var/www/test.io; index index.php index.htm index.html; location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { proxy_pass http://your_server_ip:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ~ /\.ht { deny all; } } server { listen 80; server_name foobar.net www.foobar.net; root /var/www/foobar.net; index index.php index.htm index.html; location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { proxy_pass http://your_ip_address:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ~ /\.ht { deny all; { { إذا كنت تريد بأن يكون HTTPS متوفرًا أيضًا، فاستخدم الضبط التالي بدلاً من ذلك: server { listen 80; server_name test.io www.test.io; root /var/www/test.io; index index.php index.htm index.html; location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { proxy_pass http://your_server_ip:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ~ /\.ht { deny all; } listen 443 ssl; ssl_certificate /etc/letsencrypt/live/test.io/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/test.io/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; } server { listen 80; server_name foobar.net www.foobar.net; root /var/www/foobar.net; index index.php index.htm index.html; location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { proxy_pass http://your_ip_address:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ~ /\.ht { deny all; } listen 443 ssl; ssl_certificate /etc/letsencrypt/live/foobar.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/foobar.net/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; { إنّ التوجيه try_files يجعل Nginx يبحث عن الملفات في المستند الجذر ويقدّمها مباشرةً. إذا كان الملف له امتداد php.، سيتم تمرير الطلب إلى Apache. حتى إذا لم يُعثر على الملف في المستند الجذر، يُمرّر الطلب إلى Apache لتعمل ميزات التطبيق مثل permalinks بدون أخطاء. تحذير: إنّ التوجيه location ~ /\.ht مهم جداً؛ حيث يمنع Nginx من عرض محتويات ملفات الضبط Apache مثل htaccess. و htpasswd. التي تحتوي على معلومات حساسة. احفظ الملف وقم بإجراء اختبار الضبط: $ sudo nginx -t أعد تحميل Nginx إذا نجح الاختبار: $ sudo service nginx reload يمكنك للتحقّق من أن العمل تم بشكل صحيح فحص ملفات سجل Apache في var/log/apache2/ ومشاهدة طلبات GET لملفات info.php من test.io و foobar.net. استخدم الأمر tail لمشاهدة الأسطر القليلة الأخيرة من الملف، واستخدم رمز التبديل f- لمشاهدة الملف من أجل التغييرات: $ sudo tail -f /var/log/apache2/other_vhosts_access.log قم الآن بزيارة http://test.io/info.php في مستعرض الويب الخاص بك ثم انظر إلى خرج السجل. سترى أن Apache يجيب بالفعل: Output test.io:80 your_server_ip - - [01/Jul/2016:18:18:34 -0400] "GET /info.php HTTP/1.0" 200 20414 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36" ثم قم بزيارة صفحة index.html لكل موقع ولن ترى أي إدخالات للسجّل من قبل Apache. لأن Nginx هو من يخدّمهم. عند الانتهاء من معاينة ملف السجل، اضغط على CTRL + C لإيقاف تعقبّه. باستخدام هذا الإعداد، لن يكون Apache قادرًا على تقييد الوصول إلى الملفّات الثابتة. وللتَحكم في الوصول إلى الملفّات الثابتة تحتاج إلى ضبط في ملف المضيف apache الافتراضي الخاص بـ Nginx، ولكن هذا خارج نطاق هذه الدورة التعليميّة. الخلاصة لديك الآن خادم Ubuntu مع Nginx يُخدّم example.com و sample.org، جنبًا إلى جنب مع Apache والذي يُخدّم foobar.net و test.io. على الرغم من أن Nginx يعمل كوكيل عكسي لـ Apache، إلا أن خدمة الوكيل في Nginx تتسم بالشفافية وتُظهر اتصالها بنطاقات Apache كما لو أنها مخدّمة مباشرةً من Apache. يمكنك استخدام هذه الطريقة لتخديم مواقع آمنة وثابتة. ترجمة بتصرف للمقال How To Configure Nginx as a Web Server and Reverse Proxy for Apache on One Ubuntu 18.04 Server لصاحبه Jesin A.
  12. مقدمة صُممت أنظمة إدارة الضبط لتجعل من التحكم في عددٍ كبيرٍ من الخوادم أمرًا سهلًا للمدراء وفِرق العمليات. فهي تسمح بالتحكم في العديد من الأنظمة المختلفة بطريقةٍ آلية ومن موقع مركزي واحد. وعلى الرغم من وجود العديد من أنظمة إدارة الضبط الشائعة المتوفرة لأنظمة Linux، مثل Chef وPuppet، إلاّ أنّ هذه الأنظمة غالباً ما تكون أكثر تعقيدًا مما يريده أو يحتاجه الكثير من الأشخاص. يُعدّ Ansible بديلاً هامًا لهذه الخيارات نظرًا لأنّه يتطلب عبئا أقل بكثير للبدء. سنناقش في هذا الدليل كيفيّة تثبيت Ansible على خادم Ubuntu 18.04 وسنتحدّث عن بعض الأساسيّات حول كيفيّة استخدام البرنامج. كيف يعمل Ansible؟ يعمل Ansible عن طريق ضبط أجهزة العميل من خلال حاسب يحوي مكوّنات Ansible مُثبّتة ومُهيأة. يتصل عبر قنوات SSH الاعتيادية لاسترداد المعلومات من الأجهزة البعيدة، وإصدار الأوامر، ونسخ الملفات. ولذلك لا يتطلب نظام Ansible تثبيت أيّة برمجيّات إضافيّة على أجهزة حواسب العملاء. هذه هي إحدى الطرق التي يّبسط فيها Ansible إدارة الخوادم. يمكن ضم أي خادم لديه منفذ SSH مكشوف تحت مظلة ضبط Ansible بغض النظر عن الطور الذي يتواجد فيه ضمن دورة حياته. وهذا يعني أن أي حاسب يمكنك إدارته من خلال SSH، يمكنك إدارته أيضًا من خلال Ansible. يتخذ Ansible نهجًا معياريًا، جاعلًا من السهل التوسع لاستخدام وظائف النظام الرئيسي للتعامل مع سيناريوهات محدّدة. يمكن كتابة الوحدات باستخدام أيّة لغة وتتواصل في JSON القياسيّة. إن ملفات الضبط مكتوبة بشكل أساسي بصيغة تسلسل بيانات YAML بسبب طبيعتها الدلاليّة وتشابهها مع لغات الترميز الشائعة. ويمكن أن يتفاعل Ansible مع المضيفات hosts إما عبر أدوات سطر الأوامر أو من خلال سكربتات الضبط ، والتي تُعرف باسم Playbooks. المتطلبات المسبقة ستحتاج لمتابعة هذه الدورة التعليميّة إلى: اثنين أو أكثر من خوادم Ubuntu 18.04. سيُستخدم واحد منها كخادم Ansible الخاص بك، بينما سيُستخدم الباقي كمضيفين Ansible الخاصين بك. يجب أن يكون لكل منهم مستخدم غير جذري non-root بامتيازات sudo وجدار ناري firewall أساسي مُهيئ. يمكنك إعداد ذلك باتباع دليل إعداد الخادم المبدئي لـ Ubuntu 18.04. ويرجى ملاحظة أنّ الأمثلة في هذا الدليل تحدّد ثلاثة مضيفين Ansible، ولكن يمكن ضبط الأوامر لأيّ عدد تريده من العملاء. أُنشئت مفاتيح SSH للمستخدم الغير جذري non-root user على خادم Ansible الخاص بك. وللقيام بذلك، تابع الخطوة 1 من دليلنا حول كيفية إعداد مفاتيح SSH على Ubuntu 18.04. يمكنك من أجل هذه الدورة التعليميّة حفظ زوج المفاتيح إلى الموقع الافتراضي (ssh/id_rsa./~) ولا تحتاج إلى حماية بكلمة المرور. الخطوة 1 - تثبيت Ansible يجب تثبيت برنامج Ansible على جهاز واحد على الأقل لبدء استخدامه كوسيلة لإدارة الخوادم المختلفة. يمكنك إضافة أرشيف الحزمة الشخصيّة للمشروع (PPA (personal package archive إلى النظام الخاص بك للحصول على أحدث إصدار من Ansible على نظام Ubuntu. عليك قبل القيام بذلك أولاً تحديث فهرس الحزمة وتثبيت حزمة software-properties-common. حيث تسهّل هذه البرمجية إدارة هذا المستودع ومستودعات البرمجيات المستقلة الأخرى: $ sudo apt update $ sudo apt install software-properties-common ثم أضف PPA Ansible عن طريق كتابة الأمر التالي: $ sudo apt-add-repository ppa: ansible / ansible اضغط ENTER لقبول إضافة PPA. بعدها، حدّث فهرس حزمة النظام مرّةً أخرى حتى يصبح على معرفةٍ بالحزم المتاحة في PPA: $ sudo apt update يمكنك تثبيت برمجيّة Ansible بعد هذا التحديث: $ sudo apt install ansible يحتوي الآن خادم Ansible على جميع البرمجيّات المطلوبة لإدارة المضيفات hosts. الخطوة 2 - تهيئة الـ SSH للوصول إلى مضيفات Ansible يتصل Ansible كما ذُكر سابقًا بشكل أساسي مع أجهزة الحواسب العميلة من خلال SSH. وعلى الرغم من أن لديها بالتأكيد القدرة على التعامل مع استيثاق SSH المعتمد على كلمة المرور، إلاّ أن استخدام مفاتيح SSH يمكن أن يساعد في إبقاء الأمور بسيطة. استخدم أمر cat على خادم Ansible خاصتك لطباعة محتويات ملف مفتاح SSH العام للمستخدم الغير جذري non-root الخاص بك إلى خرْج الطرفيّة terminal: $ cat ~ / .ssh / id_rsa.pub انسخ الخرج الناتج إلى حافظتك، ثم افتح طرفيّة جديدة terminal واتصل بأحد مضيفي Ansible مُستخدمًا SSH: $ ssh sammy @ ansible_host_ip بدّل إلى المستخدم الجذري root لجهاز العميل: $ su – افتح الدليل authorized_keys ضمن المسار ~/.ssh كمستخدم جذر root : # nano ~/.ssh/authorized_keys الصق مفتاح SSH لمستخدم Ansible server في الملف، ثم احفظ الملف وأغلق المحرر (, اضغط CTRL + X, Y، ثم ENTER). ثم شغِّل الأمر exit للرجوع إلى المستخدم العادي للمضيف: # exit أخيرًا، ونظرًا لأن Ansible يستخدم مُفسّر بايثون python interpreter الموجود في المسار / usr / bin / python لتشغيل وحداته، فستحتاج إلى تثبيت Python 2 على المضيف حتى يتمكن Ansible من الاتصال به. شغّل الأوامر التالية لتحديث فهرس حزمة المضيف وتثبيت حزمة python: $ sudo apt update $sudo apt install python يمكنك بعد ذلك تشغيل أمر exit مرّةً أخرى لإغلاق الاتصال بالعميل: $ exit كرّر هذه العملية من أجل كل خادم تنوي التحكم فيه باستخدام خادم Ansible الخاص بك. بعد ذلك، سنُهيئ خادم Ansible للاتصال بالمضيفات باستخدام ملف (hosts)الخاص بـ Ansible. الخطوة 3 - إعداد مضيفات Ansible يتتبع Ansible كافة الخوادم الذي يتعرف عليها من خلال ملف المضيفات hosts. نحتاج أولًا إلى إعداد هذا الملف قبل أن نتمكن من بدء الاتصال بحواسبنا الأخرى: $ sudo nano /etc/ansible/hosts سترى ملفًا يحوي عددًا من أمثلة "نماذج" الضبط المُعقّب عليها (بإشارة # تسبق كل سطر). لن تعمل هذه الأمثلة فعليًا في حالتنا نظرًا لأن المضيفات المُدرجات في كل منها وهميّة. بكافة الأحوال سنحتفظ بهذه الأمثلة في الملف لمساعدتنا في الضبط في حال أردنا تنفيذ حالات أكثر تعقيدًا في المستقبل. إن ملف hosts مرن إلى حدّ ما ويمكن ضبطته بعدّة بطرق مختلفة. وبناءً عليه، ستبدو الصياغة التي سنستخدمها كما يلي: [group_name] alias ansible_ssh_host=your_server_ip في هذا المثال، إن group_name وسم تنظيمي يتيح لك الإشارة إلى أي خادم مدرج تحته بكلمة واحدة، بينما alias هو مجرد اسم للإشارة إلى خادم معيّن. نعتبر في حالتنا أن لدينا ثلاثة خوادم سنتحكم بهم باستخدام Ansible. يمكن عند هذه النقطة الوصول إلى هذه الخوادم من خادم Ansible بكتابة: $ ssh root@ansible_host_ip إذا أعددت هذا بشكل صحيح فلا يجب أن تُطالب بكلمة مرور. سنفترض هنا لأغراض العرض التوضيحي أن عناوين IP لمضيفاتنا هي 203.0.113.1 و 203.0.113.2 و 203.0.113.3. وسنضبط ذلك بحيث يمكننا الإشارة إليها بشكل فردي كـ host1، و host2، و host3، أو كمجموعة باسم servers. و لإتمام ذلك يتوجب إضافة هذه الكتلة إلى ملف hosts الخاص بنا: [servers] host1 ansible_ssh_host=203.0.113.1 host2 ansible_ssh_host=203.0.113.2 host3 ansible_ssh_host=203.0.113.3 يمكن أن تكون المضيفات في مجموعاتٍ متعددة، ويمكن للمجموعات ضبط المعاملات parameters من أجل جميع أعضائها. فلنجرّب هذا الآن. إن حاولنا باستخدام إعداداتنا الحاليّة الاتصال بأي من هذه الأجهزة المضيفة hosts من خلال Ansible، فسيفشل الأمر (على افتراض أنك لا تعمل كمستخدم جذر root). يحدث هذا لأنّه تم تضمين مفاتيح SSH من أجل المستخدم الجذر على الأنظمة البعيدة وسيحاول Ansible الاتصال بشكل افتراضي بواسطة المستخدم الحالي، ستعطينا محاولة الاتصال هذا الخطأ: [servers] Output host1 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh.", "unreachable": true } نستخدم على خادم Ansible مستخدمًا اسمه sammy. سيحاول Ansible الاتصال بكل مضيف باستخدام ssh sammy @ server. ولن يعمل هذا إذا لم يكن المستخدم sammy موجودًا على النظام البعيد أيضًا. يمكننا إنشاء ملف يخبر جميع الخوادم في مجموعة "servers " للاتصال كمستخدم جذر root. سننشئ لعمل ذلك دليلًا في بنية ضبط Ansible يدعى group_vars. ويمكننا ضمن هذا المجلد إنشاء ملفات بتنسيق YAML لكل مجموعة نريد ضبطها: $ sudo mkdir /etc/ansible/group_vars $sudo nano /etc/ansible/group_vars/servers يمكننا وضع ضبطنا هنا. تبدأ ملفات YAML بـ "---"، لذا تأكد من عدم نسيان هذا الجزء. /etc/ansible/group_vars/servers --- ansible_ssh_user: root احفظ وأغلق هذا الملف عند الانتهاء. إذا كنت تريد تحديد تفاصيل الضبط لكل خادم، بغض النظر عن المجموعة المرتبط بها، فيمكنك وضع هذه التفاصيل في ملف في المسار etc/ansible/group_vars/all/. يمكن ضبط المضيفات بشكل فردي عن طريق إنشاء ملفات مُسماة بالاسم البديل alias تحت الدليل في /etc/ansible/host_vars. الخطوة 4 - استخدام أوامر Ansible بسيطة يمكننا الآن -وبعد أن أعددنا مضيفاتنا و ضبطنا تفاصيل تهيئة كافية للسماح لنا بالاتصال بنجاح مع مضيفاتنا- تجربة الأمر الأول. عمل اختبار ping لجميع خوادمنا المُهيئة وذلك بكتابة: $ anmible -m ping all ستكون المخرجات كالتالي: host1 | SUCCESS => { "changed": false, "ping": "pong" } host3 | SUCCESS => { "changed": false, "ping": "pong" } host2 | SUCCESS => { "changed": false, "ping": "pong" } وهو اختبار بسيط للتأكّد من أنّ Ansible يتصل بجميع مضيفاته. تعني all جميع المضيفات. ويمكننا بسهولة تحديد مجموعة معيّنة كما يلي: $ ansible -m ping servers يمكننا أيضًا تحديد مضيف بشكل فردي: $ anmible -m ping host1 يمكننا تحديد عدّة مضيفات من خلال فصلها باستخدام النقطتين: $ anmible -m ping host1: host2 إنّ المقطع -m ping من الأمر عبارة عن تعليمة لـ Ansible لاستخدام الوحدة "ping". وهي في الأساس أوامر يمكنك تشغيلها على المضيفات عن بعد. تعمل وحدة ping بعدّة طرق مثل أداة ping العادية في Linux، ولكنها بدلاً من ذلك تتحقق من اتصال Ansible. لا تأخذ وحدة ping في الواقع أيّة وسائط arguments، لكن يمكننا تجربة أمر آخر لمعرفة كيفيّة عمل ذلك. نمرّر المعاملات في تدوين نصي "سكريبت" عن طريق كتابة -a. تتيح لنا الوحدة "shell" إرسال أمر طرفيّة terminal command إلى المضيف البعيد واسترداد النتائج. على سبيل المثال، يمكننا استخدام الأمر التالي لمعرفة استخدام الذاكرة على جهاز host1: $ ansible -m shell -a 'free -m' host1 ستكون مخرجات Shell كالتالي: host1 | SUCCESS | rc=0 >> total used free shared buffers cached Mem: 3954 227 3726 0 14 93 -/+ buffers/cache: 119 3834 Swap: 0 0 0 وبذلك أصبح خادم Ansible الخاص بك مُهيئًا ويمكنك الاتصال والتحكم في المضيفات بنجاح. الخلاصة ضبطنا في هذه الدورة التعليميّة Ansible وتأكّدنا من إمكانية اتصاله مع كل مضيف. واستخدمنا أيضًا الأمر ansible لتنفيذ مهام بسيطة عن بُعد. وعلى الرغم من أن هذا مفيد، إلا أنّنا لم نُغطّي أهم ميزة لـ Ansible في هذا المقال وهي الـ Playbooks. تعتبر Ansible Playbooks طريقةً قويّة وبَسيطة لإدارة عمليات تهيئة الخادم وعمليات النشر المتعدّدة الأجهزة. للحصول على تمهيد حول كتب Playbook، راجع هذا الدليل. بالإضافة إلى ذلك، فإننا نشجعك على مراجعة توثيق Ansible الرسميّة لمعرفة المزيد عن الأداة ترجمة وبتصرّف للمقال How to Install and Configure Ansible on Ubuntu 18.04 لصاحبيه Stephen Rees-Carter و Mark Drake
  13. مقدمة تأتي قواعد بيانات SQL مُثبّتة مع جميع الأوامر التي تحتاجها للإضافة، والتعديل، والحذف والاستعلام عن بياناتك. يوفّر هذا الدليل لنمط الورقة المرجعية cheat sheet مرجعًا سريعًا لبعضٍ من أوامر SQL الأكثر شيوعًا. كيفية استخدام هذا الدليل: هذا الدليل على شكل ورقة مرجعيّة فيها أمثلة منفصلة قابلة للاستخدام فرادى. انتقل إلى أي مقطع ذي صلة بالمهمة التي تحاول إكمالها. عندما ترى نصًّا مميّزًا في أوامر هذا الدليل، فضع بالحسبان أن هذا النص يشير إلى الأعمدة، والجداول، والبيانات في قاعدة البيانات الخاصة بك. ضُمّنت قيم البيانات في هذا الدليل في الأمثلة المُعطاة بعلامة ('). من الضروري في SQL تضمين أي قيم بيانات تحتوي على سلاسل نصية في علامات اقتباس أحادية. هذا التضمين غير مطلوب من أجل البيانات الرقمية، ولكنه لن يتسبب بأيّة مشاكل أيضًا. يرجى ملاحظة أنّه على الرغم من كون SQL معياريّة، إلاّ أنّ معظم برامج قواعد بيانات SQL لها إضافاتها الخاصّة. يستخدم هذا الدليل MySQL كنموذج لنظام إدارة قواعد البيانات العلائقية (RDBMS)، ولكن الأوامر المقدّمة ستعمل مع برامج قواعد البيانات العلائقية الأخرى، بما في ذلك PostgreSQL و MariaDB وSQLite. سنُضمّن الأوامر البديلة عند وجود فروق مهمّة بين أنظمة إدارة قواعد البيانات العلائقية RDBMSs. بدء مِحث أوامر قاعدة البيانات (باستخدام استيثاق Socket/Trust) يمكن لمستخدم MySQL الجذر root الاستيثاق بدون كلمة مرور بشكل افتراضي في نظام التشغيل أبونتو Ubuntu 18.04 باستخدام الأمر التالي: $ sudo mysql استخدم الأمر التالي لفتح مِحث أوامر PostgreSQL. سيُسجلك هذا المثال كمستخدم postgres، والذي يتضمن صلاحيات دور المستخدم المميّز superuser role، ولكن يمكنك استبداله بأي دور مُنشئ مُسبقًا: $ sudo -u postgres psql بدء مِحث أوامر قاعدة البيانات (باستخدام استيثاق كلمة المرور) إذا ُضبط مستخدم MySQL الجذر root للاستيثاق باستخدام كلمة مرور، فبإمكانك استخدام الأمر التالي: $ mysql -u root -p إذا أعددت مُسبقًا حساب مستخدم عادي non-root لقاعدة بياناتك، فيمكنك أيضًا استخدام هذه الطريقة لتسجيل الدخول باسم هذا المستخدم: $ mysql -u user -p سيُقاطعك الأمر السابق بعد تشغيله للمطالبة بكلمة المرور الخاصّة بك. إذا كنت ترغب في جعل كلمة المرور كجزء من الأمر، فأَتبعْ الخيار p- مباشرة بكلمة مرورك، بدون ترك فراغ بينهما: $ mysql -u root -ppassword إنشاء قاعدة بيانات يُنشئ الأمر التالي قاعدة بيانات بإعداداتٍ افتراضيّة: mysql> CREATE DATABASE database_name; يمكنك إذا أردت لقاعدة بياناتك أن تستخدم مجموعة محارف وتصنيف مختلفة عن الإعدادات الافتراضيّة تحديد ذلك باستخدام الصياغة التالية: mysql> CREATE DATABASE database_name CHARACTER SET character_set COLLATE collation; إظهار قائمة قواعد البيانات شغّل الأمر التالي لرؤية قواعد البيانات الموجودة في نظام MySQL أو MariaDB: mysql> SHOW DATABASES; يمكنك في PostgreSQL مشاهدة قواعد البيانات المُنشأة باستخدام الأمر التالي: postgres=# \list حذف قاعدة البيانات شغّل الأمر التالي لحذف قاعدة بيانات بما في ذلك ضمنًا أي جداول وبيانات موجودة فيها: mysql> DROP DATABASE IF EXISTS database; إنشاء مستخدم نفّذ الأمر التالي لإنشاء معرّف مستخدِم لقاعدةِ بياناتك من دون تحديد أيّ امتيازاتٍ له: mysql> CREATE USER username IDENTIFIED BY 'password'; تَستخدم PostgreSQL بنية مشابهة، ولكنها مختلفة قليلاً، إليك الصياغة: postgres=# CREATE USER user WITH PASSWORD 'password'; يمكنك إذا أردتَ إنشاء مستخدم جديد ومنحه امتيازات باستخدام أمر واحد عن طريق إصدار عبارة GRANT. ينشئ الأمر التالي مستخدمًا جديدًا ويمنحه امتيازات كاملة لكامل قاعدة البيانات والجداول في نظام إدارة قواعد البيانات العلائقية RDBMS: mysql> GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password'; لاحظ الكلمة المفتاحيّة PRIVILEGES في تعليمة GRANT السابقة. إن هذه الكلمة اختيارية في معظم أنظمة إدارة قواعد البيانات العلائقية، ويمكن كتابة هذه التعليمة بشكل مكافئ على النحو التالي: mysql> GRANT ALL ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password'; كن منتبهًا مع ذلك، أنّ الكلمة المفتاحيّة PRIVILEGES مطلوبة لمنح امتيازات كهذه عندما يكون وضع Strict SQL مُشغّلًا. حذف مستخدم استخدم الصياغة التالية لحذف اسم مستخدم قاعدة البيانات: mysql> DROP USER IF EXISTS username; لاحظ أن هذا الأمر لا يحذف افتراضيًا أيّة جداول أُنشأت بواسطة المستخدم المحذوف، وقد تؤدي محاولات الوصول إلى جداول كهذه إلى حدوث أخطاء. اختيار قاعدة البيانات يجب أولًا إخبار RDBMS بقاعدة البيانات التي ترغب في إنشائها في MySQL و MariaDB قبل أن تتمكن من إنشاء جدول. استخدم الصياغة التالية للقيام بذلك: mysql> USE database; يجب عليك استخدام الأمر التالي في PostgreSQL لاختيار قاعدة بياناتك المرغوبة: postgres=# \connect database إنشاء جدول تنشئ بنية الأمر التالية جدولًا جديدًا باسم table يحوي عمودين لكل منهما نوع بياناته الخاص: mysql> CREATE TABLE table ( column_1 column_1_data_type, column_2 column_2_data_taype ); حذف جدول نفّذ ما يلي لحذف جدول بالكامل، بما في ذلك جميع البيانات الخاصّة به: mysql> DROP TABLE IF EXISTS table إدخال البيانات في جدول استخدم الصياغة التالية لملء جدول بصف واحد من البيانات (row): mysql> INSERT INTO table ( column_A, column_B, column_C ) VALUES ( 'data_A', 'data_B', 'data_C' ); يمكنك أيضًا ملء جدول بعدة صفوف من البيانات باستخدام أمر واحد، على النحو التالي: mysql> INSERT INTO table ( column_A, column_B, column_C ) VALUES ( 'data_1A', 'data_1B', 'data_1C' ), ( 'data_2A', 'data_2B', 'data_2C' ), ( 'data_3A', 'data_3B', 'data_3C' ); حذف بيانات من جدول استخدم بنية الأوامر التالية لحذف صف من البيانات من جدول. لاحظ أن value يجب أن تكون القيمة الموجودة في العمود المحدد column في الصف الذي تريد حذفه: mysql> DELETE FROM table WHERE column='value'; ملاحظة: إذا لم تُضمّن عبارة WHERE في تعليمة DELETE، كما هو موضّح في المثال التالي، فستُحذف جميع البيانات الموجودة في الجدول، ولكن لن تُحذف الأعمدة أو الجدول نفسه: mysql> DELETE FROM table; تغيير البيانات في جدول استخدم الصياغة التالية لتحديث البيانات الموجودة في الصف المُعطى. لاحظ أنّ عبارة WHERE في نهاية الأمر تُخبر SQL بالصف المطلوب تحديثه. إنّ value هي القيمة الموجودة في column_A المحاذية للصفِ الذي تريد تغييره. ملاحظة: إذا أهملتَ تضمين عبارة WHERE في تعليمة UPDATE، فسيَستبدِل الأمر البيانات الموجودة في كل صف من الجدول. mysql> UPDATE table SET column_1 = value_1, column_2 = value_2 WHERE column_A=value; إضافة عمود ستضيف صياغة الأمر التالية عمودًا جديدًا إلى جدول: mysql> ALTER TABLE table ADD COLUMN column data_type; حذف عمود سيؤدي هذا الأمر إلى حذف عمود من جدول: mysql> ALTER TABLE table DROP COLUMN column; تنفيذ الاستعلامات الأساسيّة استخدم الصياغة التالية لعرض جميع البيانات من عمود واحد من جدول: mysql> SELECT column FROM table; افصلْ بين أسماء الأعمدة بفاصلة للاستعلام عن أعمدة متعددة من نفس الجدول: mysql> SELECT column_1, column_2 FROM table; يمكنك أيضًا الاستعلام عن كل الأعمدة في جدول عن طريق استبدال أسماء الأعمدة بعلامة النجمة (*). تعمل علامات النجمة في SQL كبدائل لتمثيل "الكل": mysql> SELECT * FROM table; استخدام عبارات WHERE يمكنك تضييق نطاق نتائج استعلام عن طريق إلحاق تعليمة SELECT بعبارة WHERE، كما يلي: mysql> SELECT column FROM table WHERE conditions_that_apply; يمكنك على سبيل المثال الاستعلام عن جميع البيانات من صف واحد من خلال صياغة مشابهة لما يلي. لاحظ أن value يجب أن تكون قيمة محفوظة في كل من column المحدّد والصف الذي تريد الاستعلام عنه: mysql> SELECT * FROM table WHERE column = value; العمل مع مُعاملات المقارنة يحدّد مُعامل المقارنة في جملة WHERE كيفيّة مقارنة العمود المحدّد بقيمة ما. فيما يلي بعض معاملات المقارنة الشائعة لـ SQL: = : اختبار المساواة != : اختبار عدم المساواة < : اختبار أقل من > : اختبار أكبر من <= : اختبار أقل من أو يساوي >= : اختبار أكبر من أو يساوي BETWEEN : اختبار فيما إذا كانت القيمة ضمن مجال مُعطى IN : اختبار ما إذا كانت قيمة الصّف مُتضَمّنة في مجموعة من القيم المحدّدة EXISTS : اختبار ما إذا كانت صفوف موجودة، تبعاً للشروط المحدّدة LIKE : اختبار فيما إذا كانت قيمة تتطابق مع سلسلة نصيّة محدّدة IS NULL : اختبار القيم الفارغة IS NOT NULL : اختبار كافّة القيم غير الفارغة "NULL" العمل مع محارف البدل Wildcards يسمح SQL باستخدام محارف البدل wildcard. وهي مفيدة عندما تحاول العثور على مُدخل محدّد في جدول، ولكنك لا تكون متأكدًا تماماً من هذا المُدخل. تعتبر علامات النجمة (*) عناصر بديلة لتمثيل "الكل"، حيث تقوم بالاستعلام كل الأعمدة في جدول: mysql> SELECT * FROM table; تمثل علامات النسبة المئوية (٪) صفراً أو أكثر من محارف غير معروفة. mysql> SELECT * FROM table WHERE column LIKE val%; يُستخدم التسطير السفلي (_) لتمثيل محرف واحد غير معروف: mysql> SELECT * FROM table WHERE column LIKE v_lue; حساب المُدخلات في عمود تُستخدم الدّالة COUNT لإيجاد عدد الإدخالات في عمود محدّد. ستُرجع الصياغة التالية إجمالي عدد القيم الموجودة في column: mysql> SELECT COUNT(column) FROM table; يمكنك تضييق نتائج دالة COUNT من خلال إضافة عبارة WHERE، كما يلي: mysql> SELECT COUNT(column) FROM table WHERE column=value; إيجاد قيمة المعدل في عمود تُستخدم الدّالة AVG لإيجاد المعدل بين القيم الموجودة في عمود محدّد. لاحظ أن دالة AVG ستعمل فقط مع الأعمدة التي تحتوي على قيم رقميّة. وقد تُعيد خطأ أو 0 عند استخدامها على عمود يحمل قيم نصيّة: mysql> SELECT AVG(column) FROM table; إيجاد مجموع القيم في عمود تُستخدم الدّالة SUM لإجمالي مجموع القيم الرقميّة الموجودة في عمود: mysql> SELECT SUM(column) FROM table; كما هو الحال مع دالة AVG، إذا نَفّذتَ الدالة SUM على عمود يحوي قيم نصيّة، فقد تُعيد خطأ أو فقط 0، وذلك اعتمادًا على نظام إدارة قواعد البيانات العلائقية خاصتك. إيجاد القيمة الكبرى في عمود استخدم دالة MAX للعثور على أكبر قيمة رقميّة في عمود أو القيمة الأخيرة أبجديًا : mysql> SELECT MAX(column) FROM table; إيجاد القيمة الصغرى في عمود استخدم الدّالة MIN للعثور على أصغر قيمة رقميّة في عمود أو القيمة الأولى أبجديًا: mysql> SELECT MIN(column) FROM table; فرز النتائج باستخدام عبارات ORDER BY تُستخدم عبارة ORDER BY لفرز نتائج الاستعلام. تُعيد الصياغة التالية للاستعلام القيم من column_1 و column_2 وتُرتّب النتائج حسب القيم الموجودة في column_1 بترتيب تصاعدي، أو بترتيب أبجدي بالنسبة لقيم السلاسل النصيّة: mysql> SELECT column_1, column_2 FROM table ORDER BY column_1; أتبع الاستعلام بـ DESC لتنفيذ نفس الإجراء، ولكن مع ترتيب النتائج بترتيب أبجدي تنازلي: mysql> SELECT column_1, column_2 FROM table ORDER BY column_1 DESC; فرز النتائج باستخدام عبارات GROUP BY تشبه عبارة GROUP BY عبارة ORDER BY، ولكنها تُستخدم لفرز نتائج استعلام يتضمن دالة مُجمِّعة مثل COUNT أو MAX أو MIN أو SUM. ستؤدي الدوال التجميعيّة الموضّحة في القسم السابق بمفردها إلى إرجاع قيمة واحدة فقط. ويمكنك مع ذلك عرض نتائج دالة التجميع المنفّذة على كل قيمة مطابقة في العمود من خلال تضمين عبارة GROUP BY. ستَحسب الصياغة التالية عدد القيم المطابقة في column_2 وتُجمّعها بترتيب تصاعدي أو أبجدي: mysql> SELECT COUNT(column_1), column_2 FROM table GROUP BY column_2; أتبِعْ الاستعلام بـ DESC لتنفيذ نفس الإجراء، ولكن بتجميع النتائج بالترتيب الأبجدي التنازلي: mysql> SELECT COUNT(column_1), column_2 FROM table GROUP BY column_2 DESC; الاستعلام عن جداول متعددة مع عبارات JOIN تستخدم عبارات JOIN لإنشاء مجموعات نتائج تجمع بين صفوف من جدولين أو أكثر. لن تعمل عبارات JOIN إلا إذا كان لكل من الجدولين عمود له اسم ونوع بيانات متطابقان، كما في هذا المثال: mysql> SELECT table_1.column_1, table_2.column_2 FROM table_1 JOIN table_2 ON table_1.common_column=table_2.common_column; هذا مثال على عبارة INNER JOIN. ستقوم INNER JOIN بإرجاع جميع السجلات التي تحتوي على قيم متطابقة في كلا الجدولين، ولكنها لن تعرض أي سجلات لا تحتوي على قيم متطابقة. من الممكن إرجاع كافة السجلات من أحد الجدولين، بما في ذلك القيم التي لا تحتوي على مطابق في الجدول الآخر، وذلك باستخدام عبارة JOIN خارجيّة. تُكتب عبارات JOIN الخارجية إما كـ LEFT JOIN أو RIGHT JOIN. تُرجع عبارة LEFT JOIN كافة السجلات من الجدول "الأيسر" والسجلات المطابقة فقط من الجدول "اليمين". في سياق عبارة JOIN الخارجيّة، يكون الجدول الأيسر هو المشار إليه في جملة FROM، والجدول الأيمن هو أي جدول آخر مشار إليه بعد عبارة JOIN. سيَعرض الاستعلام التالي كل سجل من table_1 وفقط القيم المطابقة من table_2. ستظهر القيم غير المطابقة في table2 كـ NULL في مجموعة النتائج: mysql> SELECT table_1.column_1, table_2.column_2 FROM table_1 LEFT JOIN table_2 ON table_1.common_column=table_2.common_column; إن وظيفة عبارة RIGHT JOIN مماثلة لـ LEFT JOIN، ولكنها تُرجع جميع النتائج من الجدول الأيمن، والقيم المطابقة فقط من الجدول الأيسر: mysql> SELECT table_1.column_1, table_2.column_2 FROM table_1 RIGHT JOIN table_2 ON table_1.common_column=table_2.common_column; دمج تعليمات SELECT متعددة باستخدام عبارات UNION يفيد مُعامل UNION في دمج نتائج تعليمتي SELECT (أو أكثر) في مجموعة نتائج واحدة: mysql> SELECT column_1 FROM table UNION SELECT column_2 FROM table; يمكن بالإضافة إلى ذلك أن تجمع عبارة UNION بين تعليمتي SELECT (أو أكثر) والتي تستعلم عن جداول مختلفة في نفس مجموعة النتائج: mysql> SELECT column FROM table_1 UNION SELECT column FROM table_2; الخلاصة يغطي هذا الدليل بعضًا من الأوامر الأكثر شيوعًا في SQL المُستخدمة لإدارة قواعد البيانات، والمستخدمين، والجداول، والاستعلام عن المحتويات الموجودة في هذه الجداول. ومع ذلك، هناك العديد من تجميعات العبارات والمعاملات والتي تنتج جميعها مجموعات فريدة من النتائج. إذا كنت تبحث عن دليل أكثر شموليّة للعمل مع SQL، فإنّنا نُشجعك على مراجعة Oracle's Database SQL Reference بالإضافة إلى ذلك، إذا كانت هناك أوامر SQL شائعة ترغب في رؤيتها في هذا الدليل، فيرجى طرحها أو تقديم اقتراحات في التعليقات أدناه. ترجمة بتصرّف للمقال How To Manage an SQL Database لصاحبه Mark Drake
  14. مقدمة تقدم المواقع والتطبيقات الحديثة في كثير من الأحيان كميّة كبيرة من المحتوى الثابت static content للمستخدمين النهائيين. يتضمن هذا المحتوى الصور، وأوراق الأنماط stylesheets، والجافا سكربت والفيديو. حيث يزداد استخدام عرض الحزمة bandwidth ويزداد زمن تحميل الصفحة مع زيادة حجم وعدد هذه الأصول الثابتة، مما يؤدي إلى تدني عملية التصفح لزبائنك وتقليص السعة المتاحة لخوادمك. يمكنك تنفيذ CDN أو شبكة تسليم المحتوى لتخزين هذه الأصول مؤقتًا عبر مجموعة من الخوادم الموزّعة جغرافيًا لتقليل زمن تحميل الصفحة بشكل كبير، وتحسين الأداء، وتقليل تكاليف عرض الحزمة bandwidth والبنية التحتيّة. سنقدّم في هذه الدورة التعليمية نظرة عامّة عالية المستوى على شبكات CDN وكيفيّة عملها، فضلاً عن الفوائد التي يمكن أن توفّرها لتطبيقات الويب الخاصّة بك. ما هي CDN ؟ شبكات تسليم المحتوى (Content Delivery Networks) هي عبارة عن مجموعة خوادم موزّعة جغرافيًا حُسّنت لتقديم المحتوى الثابت للمستخدمين النهائيين. يمكن أن يكون هذا المحتوى الثابت أي نوع من أنواع البيانات تقريبًا، ولكن تُستخدم شبكات CDN بشكل أكثر شيوعًا لتسليم صفحات الويب والملفات المرتبطة بها، وتدفقات الفيديو والصوت، وحزم البرامج الكبيرة. تتكون CDN من نقاط تواجد متعددة PoPs) points of presence) في مواقع مختلفة، يتألف كل منها من عدّة خوادم طرفيّة ‎.edge servers تخزّن هذه الخوادم الأصول مؤقتًا من ملفاتك الأصليّة، أو من خادم مضيف. وعندما يزور أحد المستخدمين موقعك ويطلب أصولًا ثابتةً كالصور أو ملفات جافا سكربت، ستُوجّه طلباته بواسطة شبكة CDN إلى أقرب خادم طرفي edge server موجود، والذي سيُعرض المحتوى منه. إذا لم يكن لدى الخادم الطرفي الأصول المخزنة وقتيّا أو كانت صلاحيتها منتهية، فسيجلب CDN النسخة الأخيرة من خادم طرفي CDN آخر قريب أو من خوادم الأصل الخاصّة بك وتخزينها مؤقتًا. وستُرجع النسخة المخزّنة إلى المستخدم النهائي إذا كانت طرفيّة CDN تحتوي على إدخالات مخبأة لهذه الأصول (والذي يحدث في معظم الأوقات عندما يستقبل موقعك كمية معتدلة من الزيارات). يسمح ذلك للمستخدمين المتوزعين جغرافيًا بتقليل عدد القفزات اللازمة لاستلام المحتوى الثابت، وجلب المحتوى مباشرة من النسخة المخزّنة للخادم الطرفي المجاور. والنتيجة هي تقليل كبير لزمن الاستجابة ولفقد الحزم، وتسريع أوقات تحميل الصفحات، وتخفيض كبير للتحميل على البنية التحتيّة الأصليّة. غالبًا ما يقدم مزوِّدو خدمات شبكات CDN ميّزات إضافية مثل تخفيف معدل هجمات DDoS، والإحصائيات الخاصّة بالمستخدمين، والتحسينات المتعلّقة بالتدفق أو بحالات الاستخدام المتنقل بتكلفة اضافية. كيف تعمل CDN؟ عندما يزور أحد المستخدمين موقعك على الويب، فإنّه يتلقى أولاً استجابةً من خادم DNS يحتوي على عنوان IP لخادم الويب المضيف. ثم يطلب متصفحهم محتوى صفحة الويب، والذي يتكون غالبًا من مجموعة متنوعة من الملفات الثابتة، مثل صفحات HTML، وأوراق الأنماط المتتالية CSS، وشفرات جافا سكربت، والصور. بمجرد طرح CDN وتفويض هذه الأصول الثابتة إلى خوادم CDN، إمّا عن طريق "دفعها" يدويًا أو جعل CDN "يسحب" الأصول تلقائيًا (كلا الآلتين مشروحتان في القسم التالي)، فأنت عندها توجّه خادم الويب الخاص بك لإعادة كتابة روابط links المحتوى الثابت بحيث تشير هذه الارتباطات إلى الملفات المستضافة بواسطة CDN. بإمكانك إذا كنت تستخدم نظام إدارة محتوى مثل WordPress، تنفيذ إعادة كتابة هذا الارتباط باستخدام إضافات الطرف الثالث third-party plugin مثل CDN Enabler. توفّر العديد من شبكات CDN الدعم للنطاقات المخصّصة custom domains، مما يسمح لك بإنشاء سجل CNAME تحت النطاق الخاص بك للإشارة إلى نقطة نهاية CDN. عندما يتلقى CDN طلب مستخدم عند نقطة النهاية هذه (الموجودة على الطرفيّة ، والأقرب إلى المستخدم من خوادمك الخلفية backend servers، فإنّه يُوجّه الطلب إلى نقطة التواجد (PoP) الأقرب إلى المستخدم. غالبًا ما يتكون PoP هذا من واحد أو أكثر من خوادم طرفيّة CDN مجمّعة في نقطة تبادل الإنترنت (IxP)، وهي في الأساس مركز البيانات الذي يستخدمه مزودي خدمة الإنترنت (ISP) لربط شبكاتهم. يقوم موازن الحمل الداخلي الخاص بـ CDN بتوجيه الطلب إلى خادم طرفي موجود في نقطة التواجد، والذي يقدّم بدوره المحتوى إلى المستخدم. تختلف آليات التخزين المؤقت Caching عبر مزودي خدمات CDN، ولكنها تعمل بشكل عام كما يلي: 1- عندما يتلقى CDN طلبًا لأصل ثابت للمرة الأولى، مثلا صورة PNG، وهو لا يحتوي على نسخة مخبأة من هذا الأصل فيتوجب عليه جلب نسخة من الأصل من خادم طرفي CDN قريب أو من الخادم الأصلي نفسه. يُعرف هذا بفقدان البيانات من ذاكرة التخزين المؤقت " Cache miss"، ويمكن عادةً اكتشافه عن طريق فحص ترويسة header استجابة HTTP، الذي يحتوي على X-Cache: MISS. سيكون هذا الطلب في المرّة الأولى أبطأ من الطلبات المستقبلية له لأن هذا الأصل سيخزّن كنسخة مخبأة على خادم طرفي بعد إكمال هذا الطلب. 2- سيتم الآن تخديم الطلبات المستقبلية لهذا الأصل (المخبأ)، الموجهة إلى موقع الطرفيّة هذا من النسخة المخبأة حتى انتهاء صلاحيتها (عادةً ما تُضبط من خلال HTTP headers ). وستكون هذه الاستجابات أسرع بشكل كبير من الطلب الأول، مما يقلّل وقت الاستجابة بشكل كبير للمستخدمين ويقلّل حركة مرور البيانات traffic إلى شبكة CDN. يمكنك التحقق من أن الاستجابة قد تم عرضها من ذاكرة التخزين المؤقت لـ CDN من خلال فحص ترويسة استجابة الـ HTTP، والذي يجب أن يحتوي الآن على X-Cache: HIT. راجع توثيق مزود CDN الخاص بك لمعرفة المزيد حول كيفية عمل وتنفيذ شبكة CDN محدّدة. سنقدم في القسم التالي نوعين شائعين من شبكات CDN: شبكات "دفع" و "سحب" CDN. مناطق الدفع مقابل مناطق السحب يوفر أغلب مزودي خدمة CDN طريقتين لتخزين بياناتك: مناطق السحب ومناطق الدفع. تنطوي مناطق السحب على إدخال عنوان خادمك الأصلي، والسماح لـ CDN تلقائيًا بجلب وعمل نسخة مخزّنة لجميع الموارد الثابتة المتوفرة على موقعك. تُستخدم مناطق السحب بشكل عام لتسليم "توفير" التحديثات المتكررة، وأصول الويب الصغيرة إلى متوسطة الحجم مثل ملفات HTML وCSS وجافا سكربت. بعد تزويد الـ CDN بعنوان الخادم الأصلي "المصدر"، فإنّ الخطوة التالية هي عادة إعادة كتابة الروابط links إلى الأصول الثابتة بحيث تشير الآن إلى عنوان URL المقدّم من شبكة CDN. ستتعامل شبكة CDN من الآن فصاعدًا مع طلبات الأصول الواردة للمستخدمين وستعرض المحتوى من ذاكرات التخزين المؤقت "النسخ المخبأة" الموزّعة جغرافيًا ومن الأصل عندما يكون ذلك مناسبًا. لاستخدام منطقة الدفع، حمّل بياناتك إلى خانة معيّنة أو موضع تخزين (bucket )، والتي تنقلها شبكات CDN للتخزين المؤقت على أسطول fleet الخوادم الطرفيّة المتوزعة. تُستخدم مناطق الدفع عادةً من أجل الملفات الأكبر حجمًا والقليلة التغيّر، مثل الأرشيفات، وحزم البرمجيات، وملفات الكتب الإلكترونية PDF، وملفات الفيديو والملفات الصوتية. فوائد استخدام CDN يمكن لأي موقع تقريبًا الاستفادة من الفوائد التي يوفرها توزع CDN، ولكن عادةً ما تكون الأسباب الأساسيّة للتنفيذ واحدة وهي لتخفيف استخدام عرض الحزمة بين خوادم الأصل الخاصّة بك وخوادم CDN، ولتقليل زمن الاستجابة للمستخدمين الموزعين جغرافيًا. سنستعرض هذا أدناه إضافة إلى العديد من الفوائد الرئيسيّة الأخرى المتاحة باستخدام CDN. تخفيف الحمل عن الأصل Origin Offload إذا كنت تقترب من استخدام كامل سعة عرض الحزمة على خوادمك، فسيُنقَل تخديم الأصول الثابتة كالصور، ومقاطع الفيديو، وملفات CSS وجافا سكريبت، مما يؤدي إلى تقليل استخدام عرض الحزمة للخوادم بشكل كبير. حيث صُمّمت شبكات تسليم المحتوى وحُسّنت لتخديم المحتوى الثابت، وستوجَّه طلبات العميل لهذا المحتوى إلى خوادم Edge CDN وتخدّم منها. ولهذا فائدة إضافية تتمثل في تقليل الحمل على خوادم الأصل الخاصّة بك، حيث ستُخدّم هذه البيانات بعدها بتكرار أقل بكثير. زمن استجابة أقل لتحسين تجربة المستخدم يمكن لـ CDN تقليل التأخير إذا كان المستخدمين لديك موزعين جغرافيًا، وكان جزء كبير من حركة مرور البيانات traffic الخاصّة بك يأتي من منطقة جغرافيّة بعيدة وذلك عن طريق التخزين المؤقت لأصول ثابتة على خوادم طرفيّة أقرب إلى هؤلاء المستخدمين. يمكنك من خلال تقليل المسافة بين المستخدمين والمحتوى الثابت، تقديم محتوى للمستخدمين بسرعة أكبر وتحسين تجربتهم بزيادة سرعات تحميل الصفحات. تتضاعف هذه الفوائد بالنسبة إلى مواقع الويب التي تُخدّم في المقام الأول محتوى الفيديو المستهلك لعرض الحزمة، حيث يؤدي التأخير المرتفع وأوقات التحميل البطيئة إلى التأثير بشكل مباشر على تجربة المستخدم وترابط المحتوى. إدارة الموجات الكبيرة لحركة مرور البيانات وتجنب التوقف تسمح لك شبكات CDN بالتعامل مع الموجات المروريّة الكبيرة والتدفقات الفائضة bursts من خلال طلبات موازنة الحمل load عبر شبكة كبيرة موزّعة من خوادم طرفيّة. يمكنك استيعاب عدد أكبر من المستخدمين المتزامنين في البنية التحتيّة المتواجدة من خلال إلغاء التحميل offloading عن الأصل والتخزين المؤقت للمحتوى الثابت في شبكة التسليم. يمكن أن تؤدي هذه الموجة الكبيرة في حركة مرور البيانات في مواقع الويب التي تستخدم خادمًا واحدًا إلى إغراق overwhelm النظام، مما يؤدي إلى حدوث انقطاع غير متوقع وتوقف عن العمل. تؤدي عملية نقل الحمل الى شبكات CDN ذات البنية العالية التوافريّة والمتاحّية والمخصّصة للتعامل مع مستويات متعددة من حمل الإنترنت، إلى زيادة توافرية أصولك ومحتوياتك. خفض التكاليف نظرًا لأن المحتوى الثابت يمثل غالبًا معظم استخدام عرض الحزمة، يمكن أن يؤدي تفويض هذه الأصول إلى شبكة تسليم المحتوى إلى تقليل الإنفاق على البنية التحتيّة بشكل كبير. بالإضافة إلى خفض تكاليف عرض الحزمة. يمكن أن تقلل شبكة CDN تكاليف الخادم من خلال تقليل الحمل على خوادم الأصل، مما يمكّن البنية التحتيّة الحالية الخاصّة بك من التوسع. أخيرًا، يقدم بعض مزودي خدمات شبكات CDN فواتير شهرية محدّدة السعر، مما يسمح لك بتحويل استخدامك الشهري المتغيّر لعرض الحزمة إلى إنفاق متكرر ولكن متوقع. زيادة الأمن هناك حالة استخدام شائعة أخرى لـ CDNs وهي التخفيف من هجمات حجب الخدمة DDoS. يُضمّن العديد من موفري خدمات CDN ميزات لمراقبة وتصفية الطلبات على خوادم الحافّة. تقوم هذه الخدمات بتحليل حركة مرور البيانات على شبكة الإنترنت بحثًا عن الأنماط المشبوهة، ومنع حركة المرور الهجوميّة الضارّة بينما تستمر في السماح بمرور الـ trafffic الخاص بالمستخدم النظامي. عادةً ما يقدّم موفرو خدمات CDN مجموعة متنوعة من خدمات التخفيف من هجمات DDoS، بدءًا من الحماية من الهجمات الشائعة على مستوى البنية التحتيّة الأساسيّة (طبقات OSI 3 و 4)، إلى خدمات التخفيف والحد من المعدل الأكثر تقدمًا. تسمح لك معظم شبكات CDN بالإضافة إلى ذلك بتكوين كامل لبروتوكول SSL Secure Sockets Layer configure full SSL، بحيث يمكنك تشفير حركة مرور البيانات بين CDN والمستخدم النهائي، بالإضافة إلى تشفير حركة المرور بين CDN وخوادم الأصل الخاصّة بك، إما باستخدام شهادات CDN أو شهادات SSL المخصّصة. اختيار الحل الأفضل إذا كانت الغاية هي حمل وحدة المعالجة المركزية CPU على الخادم المصدر، وليس عرض الحزمة، فقد لا يكون CDN هو الحل الأنسب. قد يؤدي التخزين المؤقت المحلي local caching في هذه الحالة باستخدام وسائل التخزين الشهيرة مثل NGINX أو Varnish إلى تقليل الحمل بشكل كبير من خلال تخديم الأصول من ذاكرة النظام. قبل طرح CDN، يمكن لخطوات التحسين الإضافية - مثل تقليل وضغط ملفات JavaScript وCSS، وتمكين ضغط طلب HTTP لخادم الويب - أن يكون لها تأثيرُا كبيرًا على أوقات تحميل الصفحة واستخدام عرض الحزمة. تعتبر أداة google لتحليل سرعة الصفحات أداةً مفيدةً لقياس سرعة تحميل صفحتك وتحسينها. ويعتبرPingdom من بين الأدوات المفيدة الأخرى التي توفر تخفيضًا كبيرًا لأوقات الطلب والاستجابة إلى جانب التحسينات المقترحة. الخلاصة يمكن أن تشّكل شبكات تسليم المحتوى حلاً سريعًا وفعالًا لتحسين قابلية التوسّع وإتاحيّة مواقع الويب الخاصّة بك. يمكنك من خلال التخزين المؤقت لأصول ثابتة على شبكة موزّعة جغرافيًا من الخوادم المحسّنة تقليل أوقات تحميل الصفحات ووقت الاستجابة للمستخدمين بشكل كبير. إضافة إلى ذلك، تسمح لك شبكات CDN بتقليل استخدام عرض الحزمة بشكل كبير من خلال استيعاب طلبات المستخدمين والاستجابة لهم من ذاكرة التخزين المؤقت في الخادم الطرفي، وبالتالي تقليل تكاليف عرض الحزمة والبنية التحتيّة. يمكن لشبكات CDN باستخدام الإضافات plugin ودعم الطرف الثالث Support Third-party لمنصّات إدارة المحتوى الرئيسيّة مثل WordPress و Drupal و Django و Ruby on Rails، بالإضافة إلى الميزات الإضافيّة مثل DDoS mitigation و SSL الكامل ومراقبة المستخدمين وضغط الأصول "المحتوى"، يمكنها أن تكون أداةً مؤثرةً في تحسين مواقع الويب ذات المعدّلات العالية لحركة مرور البيانات. ترجمة وبتصرّف للمقال Using a CDN to Speed Up Static Content Delivery لصاحبه Hanif Jetha.
  15. مقدّمة إنّ TaskBoard أو "لوح المهام" هو برمجيّة مجانيّة ومفتوحة المصدر، مستوحاة من ألواح Kanban لتتبُع المهام. وألواح Kanban هي تقنية لإظهار تدفق العمل وتنظيم المشاريع. وخاصّةً في مجال تطوير البرمجيات، فهي توفّر نظامًا مرئيًّا لإدارة العمليّات للمساعدة في تحديد كيفيّة تنظيم الإنتاج. تجعل هذا البرمجيّة التتبع البصري لتطوّر مشاريعك سهلًا كما يظهر في الصورة. ميزات TaskBoard: حرّة، ومفتوحة المصدر (رخصة MIT)، وذاتيّة الاستضافة سهلة التثبيت ألواح (مشاريع) غير محدودة تخصيص الأعمدة داخل الألواح وتوسيع / تصغير مستمر من أجل كل مستخدم تسمح العناصر بالألوان المخصّصة، والتصنيفات، وتنسيق التوصيفات، والمرفقات، والتعليقات تعرض العناصر تاريخًا كاملًا "أرشيف" للأنشطة activities تعرض للمشرفين التاريخ الكامل لجميع أنشطة الألواح سهلة التخصيص تتيح إدارة أوليّة للمستخدمين (المشرف، والمستخدمين العاديين) لا وجود لتبعيّات خارجيّة إنشاء لقاعدة بيانات SQLite عند الاستخدام الأول واجهة برمجيّة RESTful API) RESTful) تبعيّات محدودة جدًا ستشرح هذه الدورة التعليميّة كيفيّة تثبيتها على CentOS 7. تثبيت خادم الويب Apache ثبّت في البداية Apache على جهاز CentOS 7 من خلال تنفيذ الأمر التالي: # yum install httpd شغّل Apache ومكّنه من التشغيل في وقت الإقلاع وذلك بمجرد انتهائك من التثبيت: # systemctl start httpd # systemctl enable httpd تثبيت PHP يجب تثبيت php باعتبار أن TaskBoard مكتوبة بهذه اللغة. ونظرًا لأنّها تتطلب الإصدار PHP الخامس أو أكثر، فسنثبّت PHP7 باستخدام مستودع Webtatic. أولاً، ثَبّت مستودع EPEL المطلوب من قبل Webtatic: # yum install epel-release حدّث: # yum install epel-release بالإمكان الآن تثبيت مستودع Webtatic عن طريق تنفيذ الأوامر التالية: # rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm # yum update ثبّت PHP 7.1 والإضافات التي تتطلبها TaskBoard وذلك بمجرّد أن يصبح المستودع جاهزًا ويصبح بالإمكان لـ yum استخدامه: # yum install php71w php71w-gd php71w-json php71-readline php71w-cli php71w-sqlite3 تثبيت SQLite يستخدم TaskBoard الـ SQLite كقاعدة بيانات، مما يعني أنه بإمكاننا استخدامه دون الحاجة إلى تثبيت MySQL أو أيّة قواعد بيانات "كبيرة" أخرى. يمكن تثبيت SQLite باستخدام أمر yum التالي: # yum install sqlite تثبيت TaskBoard إنّ تثبيت TaskBoard سهلٌ للغاية، كما هو متوقع من قائمة الميزات المطوّلة المعروضة في التمهيد. يتطلب الأمر في الواقع فقط تنزيل واستخراج أرشيف TaskBoard. انتقل إلى المسار الجذر للويب في Apache: # cd /var/www نزّل الأرشيف هنا: # wget https://github.com/kiswa/TaskBoard/archive/master.zip فُك ضغطه: # unzip master.zip سيستَخرج unzip الأرشيف إلى دليل يدعى TaskBoard-master. يمكنك إعادة تسميته (اختياري): # mv TaskBoard-master taskboard ثبّت الملحقات المطلوبة بواسطة Composer: ./taskboard/build/composer.phar install ثم غيّر مالك taskboard إلى مستخدم apache: # chown -R apache:apache /var/www/taskboard إنشاء مضيف افتراضي Virtual Host أنشئ ملف مضيف افتراضي جديد لـ TaskBoard: # $EDITOR /etc/httpd/conf.d/board.example.com.conf ثم الصق المحتوى التالي في هذا الملف: <VirtualHost *:80> ServerAdmin admin@example.com DocumentRoot "/var/www/taskboard" ServerName board.example.com ServerAlias www.board.example.com <Directory "/var/www/taskboard"> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog "/var/log/httpd/board.example.com-error_log" CustomLog "/var/log/httpd/board.example.com-access_log" combined </VirtualHost> أعد تشغيل Apache: # systemctl restart httpd إنهاء التثبيت للقيام بالخطوة الأخيرة لإنهاء التثبيت من خلال متصفح الويب، انتقل إلى عنوان الـ URL: http://board.example.com سجّل الدخول مستخدمًا كلمة admin في كل من اسم المستخدم وكلمة المرور على حد سواء. ثم غيّر كلمة مرور المسؤول administrator بعد تسجيلك للدخول مباشرةً وذلك بالانتقال إلى صفحة الإعدادات Settings. الخلاصة رأينا كيفيّة تثبيت TaskBoard على CentOS 7. سيُساعد بالتأكيد هذا التطبيق المعتمد على Kanban العديد من النّاس في تنظيم سير عمل مشاريعهم. ترجمة وبتصرّف للمقال TaskBoard: Kanban-based Software on CentOS 7 لصاحبه Giuseppe Molica.
  16. مقدمة إذا كنت تعمل(على الشبكة) مُستخدمًا بروتوكول النقل الآمن Secure Shell) SSH)، فإنّك تعلم مُسبقًا أنّ الجلسة session ستُغلق تلقائيًا بعد دقائقٍ قليلةٍ من عدم النشاط "الخمول"، وذلك لأسبابٍ أمنية.من الممكن في الحقيقة أن تكون قد نسيت إغلاقها، وبالتالي فقد يتمكن شخص آخر من السيطرة على نظامك. ولكن إذا كنت لا ترى في ذلك مشكلة، فبإمكانك تغيير هذا السلوك في ضبط GNU/Linux. يجب تنفيذ الأوامر التالية من عميل SSH. كيفيّة منع SSH من قطع الاتصال يجب تنفيذ الخطوات التالية في عميل SSH، وليس في الخادم البعيد. افتح محرّر النص خاصتك في البداية وعدّل ملف الـ config الحالي للمستخدم الخاص بك، والذي تجده في المسار التالي: ~/.ssh/config أضف الأسطر التالية: تأكّد من أن السطر الثاني سيبدأ بمسافة فارغة. يُخبر السطر الأول الـ SSH بتطبيق هذا الضبط على جميع المضيفات البعيدة remote hosts. كما يمكنك بالطبع تحديد واحد منها فقط، وذلك باستبدال رمز الـ "*" بالمضيف المطلوب. ستحتاج بعد الانتهاء من ذلك إلى تطبيق الإعدادات المذكورة أعلاه: sudo source ~/.ssh/config أضف أو عدّل السطر التالي في ملف etc / ssh / ssh_config/ لتطبيق هذه الإعدادات على المستوى العام globally: ServerAliveInterval 60 احفظ الملف واغلقه. وبهذه الطريقة، لن تُغلق جلسة SSH بعد الآن بسبب الخمول. الخلاصة تذكّر أن أمان نظامك، وخصوصًا في حالة الخادم server، ليس أمرًا ثانويًا، وذلك كلّه بيديك. إنّ تغيير سلوك برامج مثل SSH يجب أن يتم فقط في حال كنت تعرف بالضبط ما تريده، وبعد التأكّد من أنّ ذلك لن يضعك في مشكلةٍ ما. ترجمة وبتصرّف للمقال How to prevent SSH from disconnecting sessions لصاحبه Giuseppe Molica
  17. MySQL replication هي العمليّة التي يمكن من خلالها نسخ البيانات أوتوماتيكيًا من أحد مخدّمات قاعدة بيانات MySQL “الرئيسي” (master) إلى واحد أو أكثر من مخدّمات قواعد بيانات MySQL “التابع” (slaves). وعادةً ما تستخدم لتوزيع إمكانيّة وصول القراءة read access على مخدّمات متعددة من أجل قابلية التوسع scalability، كما يمكن أن تستخدم أيضًا لأغراض أخرى مثل تجاوز الفشل failover، أو تحليل البيانات على الـ slave من أجل عدم زيادة التحميل على الـ master. كما أنّ الـ master-slave replication هي عمليّة باتجاه واحد (من الـ master إلى slave)، تستخدم قاعدة بيانات الـ master فقط لعمليات الكتابة. بينما يمكن أن توزّع عمليات القراءة على عدّة قواعد بيانات slave. ما الذي يعنيه إذا استخدم master-slave replication كحل للتوسع، ستحتاج لأن تملك على الأقل مصدرين محدّدين للبيانات، واحد لعمليات الكتابة وآخر لعمليات القراءة. يعمل مطوّرو MySQL عادةً على جهاز واحد فقط و ويسعون لأن يكون لديهم كامل بيئة التطوير على ذلك الجهاز. مع منطق عدم الاعتماد على شبكة أو اتصال بالإنترنت. إذا كان هناك حاجة لـ master-slave replication فلأنه على سبيل المثال، يحتاجون إلى اختبار النسخ المتماثل/التكرار replication في بيئة التطوير قبل نشر التغييرات في مكان آخر، عليهم إنشاؤئه على نفس الجهاز. إن الإعداد لمثال MySQL واحد (single MySQL instance) بسيط نوعًا ما، ونحتاج لبذل بعض الجهد الإضافي لإعداد المثال الثاني، وبعدها عملية التكرار master-slave replication. للمتابعة في هذه الدرس خطوة بخطوة، اخترت Ubuntu Linux كنظام تشغيل مضيف (host). والأوامر الواردة هي من أجل هذا النظام. إذا أردت إعداد الـ MySQL master-slave replication الخاص بك على نظام تشغيل مختلف، ستكون بحاجة إلى القيام بتعديلات على هذه الأوامر. ومع ذلك ، المبادئ العامة لإعداد الـ MySQL master-slave replication على نفس الجهاز هي نفسها بالنسبة لجميع أنظمة التشغيل. تثبيت أول مثالMySQL (MySQL instance) إذا كان لديك مسبقًا مثال قاعدة بيانات MySQL واحد على جهازك، فيمكنك تجاوز هذه الخطوة. هذه أسهل طريقة لتثبيت MySQL على نظام Ubuntu وهي بتشغيل الأوامر التالية في موجّه الطرفية (terminal prompt): sudo apt-get install mysql-server خلال عملية التثبيت، ستُقاطع لوضع كلمة مرور لمستخدم root لـ MySQL. إعداد mysqld_multi من أجل إدارة مثالية لـ MuSQL على نفس الجهاز بكفاءة، نحن بحاجة إلى استخدام mysqld_multi. الخطوة الأولى في إعداد mysqld_multi هي إنشاء مجموعتي [mysqld] منفصلتين في الملف الموجود my.cnf. المكان الافتراضي لملف my.cnf في Ubuntu هو /etc/mysql/. لذلك افتح ملف my.cnf بمحرّر نصوصك المفضّل، وسمِّ مجموعة [mysqld] الموجودة إلى [mysqld1]. هذه المجموعة المسمّاة تستخدم لتكوين أول مثال MySQL وستكوّن أيضا كمثال رئيسي. كما هو الحال في MySQL master-slave replication كل مثال يجب أن يكون له server-id فريد خاص به، أضف السطر التالي في مجموعة [mysqld1]: server-id = 1 نظرًا لأننا بحاجة إلى مجموعة [mysqld]منفصلة لمثال MySQL الثاني ، انسخ المجموعة [mysqld1] مع كافة التهيئات الحالية، والصقها في ملف my.cnf نفسه. الآن، أعد تسمية المجموعة المنسوخة إلى [mysqld2]، وقم بإجراء التغييرات التالية في تكوين الـ slave: server-id = 2 port = 3307 socket = /var/run/mysqld/mysqld_slave.sock pid-file = /var/run/mysqld/mysqld_slave.pid datadir = /var/lib/mysql_slave log_error = /var/log/mysql_slave/error_slave.log relay-log = /var/log/mysql_slave/relay-bin relay-log-index = /var/log/mysql_slave/relay-bin.index master-info-file = /var/log/mysql_slave/master.info relay-log-info-file = /var/log/mysql_slave/relay-log.info read_only = 1 لإعداد مثيل MySQL الثاني كـتابع slave ، اضبط server-id إلى 2، والتي يجب أن تكون مختلفة بالنسبة لـ master’s server-id. كلا المثالين سيُشغّلان على نفس الجهاز، اضبط منفذ المثال الثاني إلى قيمة 3307 بحيث يمتلك رقم مختلف عن المنفذ الخاص بالمثال الأول، والذي يكون افتراضيًا 3306. من أجل تفعيل هذا المثال الثاني ليستخدم نفس MySQL binaries، نحتاج لضبط قيم مختلفة للـ socket، pid-file، datadir و log_error. نحن أيضًا بحاجة لتفعيل relay-log من أجل استخدام المثال الثاني كتابع (slave) (المتغيرات relay-log، relay-log-index و relay-log-info-file)، فضلًا عن تعيين master-info-file. أخيرًا، من أجل جعل المثال التابع للقراءة فقط read-only، ضبط المتغير read_only بقيمة 1. يجب أن تكون حذرًا معه فهو لا يمنع التغيرات بشكل كامل على الـ slave. حتى عندما تضبط read_only إلى 1، سيسمح للتحديثات فقط من المستخدمين الذين يملكون امتياز SUPER. أدخل MySQL المتغير الجديد super_read_only لمنع إجراء تغييرات من قبل مستخدمين الـ SUPER. هذا الخيار متوفر مع الإصدار 5.7.8. بعيدًا عن مجموعات الـ [mysqld1] و [mysqld2]، نحن بحاجة إلى إضافة مجموعة جديدة [mysqld_multi] إلى ملف my.cnf. [mysqld_multi] mysqld = /usr/bin/mysqld_safe mysqladmin = /usr/bin/mysqladmin user = multi_admin password = multipass بمجرد تثبيتنا لمثال MySQL الثاني، والقيام بتشغيلهما، سنمنح الامتيازات المناسبة للمستخدم multi_admin ليكون قادرًا على إيقاف تشغيل أمثلة MySQL. أنشئ مجلدات جديدة من أجل مثال MySQL الثاني في الخطوة السابقة قمنا بإعداد ملف التكوين من أجل مثال MySQL الثاني. في ملف التكوين هذا يتم استخدام مجلدين جديدين. يجب استخدام أوامر لينكس التالية من أجل إنشاء هذه المجلدات مع الامتيازات المناسبة: mkdir -p /var/lib/mysql_slave chmod --reference /var/lib/mysql /var/lib/mysql_slave chown --reference /var/lib/mysql /var/lib/mysql_slave mkdir -p /var/log/mysql_slave chmod --reference /var/log/mysql /var/log/mysql_slave chown --reference /var/log/mysql /var/log/mysql_slave إعدادات أمنية إضافية في AppArmor في بعض بيئات لينكس، هناك حاجة إلى إعدادات أمن AppArmor لتشغيل مثال MySQL الثاني. على الأقل هي مطلوبة في Ubuntu . لإعداد AppArmor بشكل صحيح. حرّر ملف /etc/apparmor.d/usr.sbin.mysqld بمحرّر نصوصك المفضّل، وأضف الأسطر التالية: /var/lib/mysql_slave/ r، /var/lib/mysql_slave/** rwk، /var/log/mysql_slave/ r، /var/log/mysql_slave/* rw، /var/run/mysqld/mysqld_slave.pid rw، /var/run/mysqld/mysqld_slave.sock w، /run/mysqld/mysqld_slave.pid rw، /run/mysqld/mysqld_slave.sock w، بعد أن تحفظ الملف، أعد تشغيل الجهاز حتى تصبح هذه التغييرات نافذة المفعول. تثبيت مثال MySQL الثاني يمكن اتباع عدّة نُهج مختلفة لتركيب مثال MySQL الثاني. يستخدم النهج المعروض في هذه الدورة التعليميّة نفس ثنائيات الـ MySQL كما في الأول، مع ملفات بيانات منفصلة ضرورية للتثبيت الثاني. حيث أننا قمنا بالفعل بإعداد ملف التكوين والمجلدات الضرورية والتغييرات الأمنية في الخطوات السابقة، الخطوة الأخيرة في التثبيت للمثال الثاني لـ MySQL هي تهيئة دليل بيانات MySQL. نفذ الأمر التالي من أجل تهيئة دليل بيانات MySQL جديد: mysql_install_db --user=mysql --datadir=/var/lib/mysql_slave بمجرد تهيئة دليل بيانات MySQL، يمكنك بدء كل من مثالي MySQL باستخدام الخدمة mysqld_multi. mysqld_multi start ضع كلمة سر الـ root لمثال MySQL الثاني باستخدام الـ mysqladmin مع المضيف والمنفذ المناسبين. وضع في اعتبارك ، أنه إذا تَركت المنفذ والمضيف دون تحديد، سيتصل mysqladmin بأول مثال MySQL افتراضيًا. mysqladmin --host=127.0.0.1 --port=3307 -u root password rootpwd في المثال الذي في الأعلى قم بوضع “rootpwd” ككلمة سر، ولكن يستحسن استخدام كلمة سر أكثر أمنًا. تهيئة إضافية لـ mysqld_multi في نهاية قسم " إعداد mysqld_multi، كتبت أننا سنقدم امتيازات مناسبة للمستخدم multi_admin في وقت لاحق، والآن حان الوقت لذلك. نحن بحاجة إلى منح امتيازات هذا المستخدم في كلا المثالين، لذلك دعونا أولًا نقوم بالاتصال بالمثال الأول: mysql --host=127.0.0.1 --port=3306 -uroot -p عند تسجيلك الدخول، نفّذ الأمرين التاليين: mysql> GRANT SHUTDOWN ON *.* TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass'; mysql> FLUSH PRIVILEGES; اخرج من MySQL client، وقم بالاتصال بالمثال الثاني: mysql --host=127.0.0.1 --port=3307 -uroot -p عند تسجيلك الدخول، نفّذ نفس الأمرين كما في الأعلى: mysql> GRANT SHUTDOWN ON *.* TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass'; mysql> FLUSH PRIVILEGES; اخرج من MySQL client. بدء كل من مثالي MySQL أوتوماتيكيًا عند الإقلاع الخطوة الأخيرة في إعداد mysqld_multi هي التثبيت لسكريبت الإقلاع الأتوماتيكي في الـ init.d. لفعل ذلك، أنشئ ملف جديد سمّه mysqld_multi في /etc/init.d، وامنحه الامتيازات المناسبة: cd /etc/init.d touch mysqld_multi chmod +x /etc/init.d/mysqld_multi افتح هذا الملف الجديد بمحرّر نصوصك المفضل، وانسخ السكريبت التالي: #!/bin/sh ### BEGIN INIT INFO # Provides: scriptname # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start daemon at boot time # Description: Enable service provided by daemon. ### END INIT INFO bindir=/usr/bin if test -x $bindir/mysqld_multi then mysqld_multi="$bindir/mysqld_multi"; else echo "Can't execute $bindir/mysqld_multi"; exit; fi case "$1" in 'start' ) "$mysqld_multi" start $2 ;; 'stop' ) "$mysqld_multi" stop $2 ;; 'report' ) "$mysqld_multi" report $2 ;; 'restart' ) "$mysqld_multi" stop $2 "$mysqld_multi" start $2 ;; *) echo "Usage: $0 {start|stop|report|restart}" >&2 ;; esac أضف خدمة mysqld_multi لـ runlevels الافتراضي بالأمر التالي: update-rc.d mysqld_multi defaults أعد تشغيل جهازك، وتحقق من أن كلا مثالي MySQL قيد التشغيل باستخدام الأمر التالي: mysqld_multi report إعداد Setup master-slave replication الآن، عندما يكون لدينا مثالي MySQL قيد التشغيل على نفس الجهاز، نقوم بإعداد المثال الأول كـ master، والثاني كـ slave. تم القيام بجزء واحد من التكوين configuration مسبقا في فصل “إعداد mysqld_multi”. التغيير الوحيد المتبقي في الملف my.cnf هو ضبط binary logging على الـ master. لفعل ذلك، حرّر ملف my.cnf مع التغيرات التالية والإضافات في المجموعة [mysqld1]: log_bin = /var/log/mysql/mysql-bin.log innodb_flush_log_at_trx_commit = 1 sync_binlog = 1 binlog-format = ROW أعد تشغيل مثال MySQL الرئيسي (master MySQL instance) لتأخذ التغيرات مفعولها: mysqld_multi stop 1 mysqld_multi start 1 من أجل اتصال الـ slave بالـ master بامتيازات تكرار replication مناسبة، يجب أن ينشأ المستخدم الجديد في الـ Master. اتصل بمثال maste باستخدام الـ MySQL clien مع المضيف والمنفذ المناسبين: mysql -uroot -p --host=127.0.0.1 --port=3306 أنشئ مستخدم جديد من أجل التكرار replication: mysql> CREATE USER 'replication'@'%' IDENTIFIED BY 'replication'; mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%'; اخرج من MySQL client. نفّذ الأمر التالي من أجل إنشاء ملف نسخ احتياطي (dump) لبيانات الـ master: mysqldump -uroot -p --host=127.0.0.1 --port=3306 --all-databases --master-data=2 > replicationdump.sql هنا استخدمنا الخيار --master-data=2 من أجل الحصول على تعليق يحتوي على عبارة CHANGE MASTER داخل ملف النسخ الاحتياطي، ذاك التعليق يشير الى إحداثيات الـ replication في وقت النسخ الاحتياطي، وسنحتاج هذه الإحداثيات لاحقًا لتحديث معلومات الـ master في مثال الـ slave. وهنا مثال لهذا التعليق: -- -- Position to start replication or point-in-time recovery from -- -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001'، MASTER_LOG_POS=349; استورد dump الذي أنشأته في الخطوة السابقة ضمن مثال الـ slave. mysql -uroot -p --host=127.0.0.1 --port=3307 < replicationdump.sql أخيرًا، من أجل اتصال مثال الـ slave بمثال الـ master، يجب تحديث معلومات الـ master في الـ slave مع متغيرات الاتصال المناسبة. اتصل بمثال الـ slave باستخدام MySQL clien مع المضيف والمنفذ المناسبين: mysql -uroot -p --host=127.0.0.1 --port=3307 نفّذ الأمر التالي لتحديث معلومات الـ master (خُذ احداثيات التكرار replication من ملف (dump) replicationdump.sql، كما شُرح سابقًا): mysql> CHANGE MASTER TO -> MASTER_HOST='127.0.0.1'، -> MASTER_USER='replication'، -> MASTER_PASSWORD='replication'، -> MASTER_LOG_FILE='mysql-bin.000001'، -> MASTER_LOG_POS=349; نفذ الأمر التالي من أجل تشغيل الـ slave: mysql> START SLAVE; نفذ الأمر التالي للتأكد من أن replication قيد التشغيل: mysql> SHOW SLAVE STATUS \G تهانينا. تم إعداد MySQL master-slave replication على نفس الجهاز لديك بنجاح. خاتمة وجود النسخ المتماثل master-slave مهيئًا في بيئة التطوير الخاصة بك مفيد إذا كنت بحاجة لحل للتوسع في بيئة الإنتاج. بهذه الطريقة، سيكون لديك مصادر بيانات منفصلة مُهيئة لعمليات الكتابة والقراءة وبذلك تكون قادرًا على اختبار أن كل شيء يعمل محلياً كما هو متوقع قبل النشر. بالإضافة إلى ذلك، قد تحتاج إلى تكوينات أمثلة slave على نفس الجهاز لاختبار موازن الحمل الذي يوزّع عمليات القراءة إلى عدد من الـ slave. في هذه الحالة، يمكنك استخدام هذه الطريقة لإعداد أمثلة أخرى بتكرار كل الخطوات السابقة نفسها. ترجمة -وبتصرّف- للمقال MySQL Master-Slave Replication on the Same Machine لصاحبه Ivan Bojovic
  18. من الممكن أن تكون المعايرة مهمّة صعبة جدًا، وخاصّة عند العمل مع بيانات ضخمة، حيث أنّ أصغر تغيير من الممكن أن يتسبب بتغيرات غير متوقعه ( إيجابية أو سلبية) على الأداء ككل. تتم معظم عمليات معايرة SQl database في الشركات المتوسطة والصغيرة من قبل مدير قاعدة البيانات (Database Administrator (DBA، لكن صدقني، يوجد العديد من المطوّرين بحاجة للقيام بعمليات متعلقة بالإدارة، وأكثر من ذلك أنا شاهدت أنّهم يقومون فعليًّا بعمليات الإدارة في كثير من الشركات التي تتطلع للعمل مع المطوّرين، حين يتطلب الوضع ببساطة تقنيات مختلفة لحل المشاكل، والتي يمكن أن تؤدي إلى خلاف بين زملاء العمل. عند التعامل مع بيانات ضخمة، فإنّ التغيير الصغير قد يؤدي إلى تغيرات غير متوقعة على الأداء. وبناء على ذلك، فإنّ هيكلية الشبكة أيضًا لها تأثير، افترض أن فريق الإدارة DBA team مع قواعد البيانات التي يديرونها يتوضع في الطابق العاشر، بينما يتوضع المطوّرين في الطابق الخامس عشر، أو حتى في بناء مختلف تحت هيكلية منفصلة تمامًا، وبالتالي من الصعب العمل المشترك بينهم بمرونة تحت هذه الظروف، سأقوم بإتمام شيئين هامين في هذه المقالة: تزويد المطوّرين بتقنيات معايرة لقواعد بيانات خاصة بالمطوّرين. شرح كيف يمكن لمطوّري ومديري قواعد البيانات العمل معًا بكفاءة. تحسين قاعدة البيانات (في Codebase) الفهارس إذا كنت حديثًا في مجال قواعد البيانات أو حتى تسأل نفسك، “ماهي معايرة SQL”، فيجب أن تعلم أنّ الفهرسة هي طريقة فعّالة لمعايرة قاعدة البيانات database SQL الخاصة بك، والتي غالبًا ما يتم إهمالها خلال عملية التطوير، كمصطلح أولي: الفهرس index هو هيكلة للبيانات تسمح بتسريع عملية استخلاص هذه البيانات من جدول قاعدة البيانات، عن طريق تأمين عمليات بحث عشوائية سريعة، وطريقة فعّالة للوصول إلى السجلات المرتبة، هذا يعني أنّه حالما تقوم بإنشاء فهرس يمكنك القيام بعمليات الاستعلام والترتيب بشكل أسرع. تستخدم الفهارس أيضًا لتعريف المفتاح الرئيسي أو فهرس فريد يضمن أنّ أي عمود آخر لن يحتوي نفس القيمة. بالطبع إنّ موضوع الفهرسة متنوع وهام ولا يمكنني إعطاءه حقه في هذا الوصف الموجز. إذا كنت حديثًا على موضوع الفهرسة فأنا أفضل أن تستخدم هذا المخطط لهيكلة استعلاماتك. بشكل أولي، الهدف هو فهرسة أعمدة البحث والترتيب. لاحظ أنه إذا كانت تجري بشكل مستمر عمليات إدخال INSERT أو تعديل UPDATE أو حذف DELETE، فيجب عليك الحذر من القيام بعمليات الفهرسة، حيث يمكن أن يؤدي إلى هبوط في الأداء، إذ أنّه يتطلب تعديل جميع الفهارس بعد هذه العمليات. كذلك مديري قواعد البيانات يقومون بحذف الفهارس قبل القيام مثلًا بإدخال أكثر من مليون سجل دفعة واحدة، وذلك لتسريع عملية الإدخال، ثم يقومون بإعادة إنشاء الفهارس بعد انتهاء الإدخال، تذكر على أية حال أن حذف الفهارس يؤثر على كافة الاستعلامات على الجداول، لذلك هذه الطريقة محبذة فقط عند عملية إدخال واحدة ضخمة للبيانات. معايرة أداء SQL Server: خطط التنفيذ بالمناسبة، أداة خطة التنفيذ في SQL Server مفيدة لإنشاء الفهارس. مهمتها الأساسية تتمثل في الإظهار المرئي لطرق تحصيل البيانات المختارة من قبل منسق استعلام SQL Server. للحصول على خطة التنفيذ (في برنامج الإدارة SQL Server Management Studio)، قم فقط بالنقر على Include Actual Execution Plan" CTRL + M" قبل بدء تشغيل الاستعلام. بعدئذ ،سوف يظهر إطار ثالث اسمه “Execution Plan”، حيث يمكن أن تشاهد اكتشاف فهرس مفقود، ولإنشائه قم بالنقر بالزر اليميني على execution plan وقم باختيار Missing Index Details، بكل بساطة. معايرة استعلام SQL عن طريق تجنب حلقات الشفرة تخيّل سيناريو يقوم فيه 1000 استعلام بإضافة بيانات على قاعدة بياناتك بشكل تسلسلي، كالتالي: for (int i = 0; i < 1000; i++) { SqlCommand cmd = new SqlCommand("INSERT INTO TBL (A,B,C) VALUES..."); cmd.ExecuteNonQuery(); } يجب عليك تجنب مثل هذه الحلقات في شفرتك، وكمثال سنقوم بتحويل باستخدام العبارات الفريدة INSERT UPDATE مع أسطر وقيم عدّة. INSERT INTO TableName (A,B,C) VALUES (1,2,3),(4,5,6),(7,8,9) -- SQL SERVER 2008 INSERT INTO TableName (A,B,C) SELECT 1,2,3 UNION ALL SELECT 4,5,6 -- SQL SERVER 2005 UPDATE TableName SET A = CASE B WHEN 1 THEN 'NEW VALUE' WHEN 2 THEN 'NEW VALUE 2' WHEN 3 THEN 'NEW VALUE 3' END WHERE B in (1,2,3) تأكد من أن عبارة تتجنب تحديث القيم المخزنة إذا كانت تتطابق مع القيمة الموجودة. مثل هذه يمكن أن تحسّن أداء الاستعلام بشكل كبير عن طريق تعديل مئات السجلات بدل الآلاف وكمثال: UPDATE TableName SET A = @VALUE WHERE B = 'YOUR CONDITION' AND A <> @VALUE -- VALIDATION تجنّب الاستعلامات الفرعيّة المرتبطة Correlated Subqueries الاستعلامات المرتبطة هي الاستعلامات التي تستخدم قيم من الاستعلام الأب، هذه النوع من الاستعلامات ينحو إلى العمل سجل بعد سجل row-by-row، مرة لكل سجل معاد من الاستعلام الخارجي الأب، ولذلك فإنه ينقص أداء استعلام SQl. المطوّرين الحديثين غالبًا ما يبنون استعلاماتهم على هذه الشاكلة لأنها عادة الطريقة الأسهل. هنا تجد مثال عن الاستعلامات المرتبطة: SELECT c.Name, c.City, (SELECT CompanyName FROM Company WHERE ID = c.CompanyID) AS CompanyName FROM Customer c بشكل خاص، المشكلة تكون بأن الاستعلام الداخلي(...SELECT CompanyName) ينفذ لكل سجل مسترجع من الاستعلام الخارجي (...SELECT c.Name)، لكن لماذا العودة إلى مرّة ثم أخرى في كل مرة يعالج فيها سجل من الاستعلام الخارجي؟ التقنية الافضل لمعايرة الأداء تكون بمعاملة الاستعلام الفرعي كعملية ربط join SELECT c.Name, c.City, co.CompanyName FROM Customer c LEFT JOIN Company co ON c.CompanyID = co.CompanyID وبهذه الحالة نقوم بالمرور على جدول Company مرة واحدة ، نربطه بجدول Customer، وعندها يمكننا الحصول على القيم التي نريدها (co.CompanyName) بشكل أفضل. الاختيار باعتدال Select Sparingly واحدة من أهم نصائح المعايرة هو تجنب استخدام تعليمة SELECT * . وبدلًا من ذلك يجب تحديد الأعمدة التي تحتاجها فقط مره ثانية. هذا الأمر بسيط، لكن هذا الخطأ منتشر، افترض جدولًا بمئات الأعمدة وملايين السجلات فإذا كان تطبيقك يحتاج إلى عدد محدّد من الأعمدة فقط، فلا حاجة لاستجلاب جميع البيانات، لأن ذلك تضييع للمصادر كمثال: SELECT * FROM Employees مقابل SELECT FirstName, City, Country FROM Employees إذا كنت بالفعل تحتاج إلى كل الأعمدة ، قم بتسميتهم ضمن الاستعلام، هذه ليست قاعدة، لكنها طريقة للمعايرة و لتجنب الأخطاء المستقبلية. كمثال إذا كنت تستخدم التعليمة INSERT... ...SELECT وتم تغيير الجدول عن طريق إضافة عمود جديد، عندها ربما تقع في مشكلة إذا كان هذا العمود غير مطلوبًا في الجدول الهدف وكمثال: INSERT INTO Employees SELECT * FROM OldEmployees Msg 213, Level 16, State 1, Line 1 Insert Error: Column name or number of supplied values does not match table definition ولتجنب هذا الخطأ عليك تسمية كل عمود بشكل مستقل. INSERT INTO Employees (FirstName, City, Country) SELECT Name, CityName, CountryName FROM OldEmployees ملاحظة: على أية حال، هنالك بعض الحالات يكون فيها استخدام SELECT مناسبًا، كمثال من أجل الجداول المؤقتة، وهذا يقودنا الى الفقرة التالية. استخدام الجداول المؤقتة Temporary Tables الجداول المؤقتة عادة ما تزيد تعقيد الاستعلام، فإذا كان بالإمكان كتابة شيفرتك بطريقة بسيطة ومباشرة، فأنا أنصحك بتجنب الجداول المؤقتة. لكن إذا كنت تمتلك إجرائية مخزّنة stored procedure مع عمليات تعديل على البيانات لا يمكن إتمامها باستعلام واحد ، يمكنك استخدام الجداول المؤقتة كوسيط لمساعدتك في تحصيل النتائج النهائية. عندما تودّ أن تقوم بعملية ضم جدول ضخم وهنالك قيود على الجدول المذكور، يمكنك تحسين أداء قاعدة البيانات عن طريق ترحيل البيانات الى جدول مؤقت، والقيام بعملية ضم ذلك الجدول، حيث ان الجدول المؤقت يحتوي على سجلات أقل من الجدول الأساسي الضخم، ولذلك ستتم عملية الضم بشكل أسرع. القرار ليس واضح بشكل دائم، ولكن هذا المثال سوف ينبهك للحالات التي يمكنك فيها استخدام الجداول المؤقتة. تخيّل جدول الزبائن بملايين من السجلات، وعليك أن تقوم بعملية الضم لمنطقة محدّدة، يمكنك القيام بذلك عن طريق استخدام SELECT INTO ،والقيام بعملية الضم مع الجدول المؤقت. SELECT * INTO #Temp FROM Customer WHERE RegionID = 5 SELECT r.RegionName, t.Name FROM Region r JOIN #Temp t ON t.RegionID = r.RegionID لاحظ : مطوري SQl أيضًا يتجنبون استخدام SELECT INTO لإنشاء الجداول المؤقتة، لأن هذا الأمر يؤدي إلى قفل قاعدة بيانات tempdb database مما يمنع باقي المستخدمين من إنشاء جداول مؤقتة ، ولحسن الحظ تم التصحيح في النسخة السابعة وما بعدها. وكحل بديل عن استخدام الجداول المؤقتة يمكن استخدام الاستعلام الفرعي كجدول. SELECT r.RegionName, t.Name FROM Region r JOIN (SELECT * FROM Customer WHERE RegionID = 5) AS t ON t.RegionID = r.RegionID لكن انتظر، هنالك مشكلة في الاستعلام الثاني، كما تم شرحه أعلاه، يجب تضمين الأعمدة التي نحتاجها فقط (عدم استخدام * SELECT )، يجب أخذ هذا الأمر بالحسبان SELECT r.RegionName, t.Name FROM Region r JOIN (SELECT Name, RegionID FROM Customer WHERE RegionID = 5) AS t ON t.RegionID = r.RegionID كل هذه الطرق ستعيد نفس البيانات، لكن باستخدام الجداول المؤقتة، وكمثال يمكننا انشاء فهرس في جدول مؤقت لتحسين الأداء. وأخيرًا، عندما تنهي عملك بالجدول المؤقت، قم بحذفه لتنظيف مصادر tempdb بدل أن تنتظر عملية الحذف الاوتوماتيكي (عندما يتم إنهاء اتصالك مع قاعدة البيانات) DROP TABLE #temp هل يتواجد السجل الخاص بي؟ تقنية المعايرة هذه الخاصة ب SQl متعلقة باستخدام التعليمة ()EXISTS إذا كنت تنوي تفحص فيما إذا كان السجل موجودًا استخدم ()EXISTS بدل من ()COUNT. حيث أن ()COUNT يقوم بفحص كامل الجدول، معتبرًا جميع القيم التي تطابق شروطك، بينما ()EXISTS ستوقف الفحص حالما تجد قيمة مطابقة لما تحتاجه. وهذا يفضي إلى أداء أفضل و شفرة أوضح IF (SELECT COUNT(1) FROM EMPLOYEES WHERE FIRSTNAME LIKE '%JOHN%') > 0 PRINT 'YES' مقابل IF EXISTS(SELECT FIRSTNAME FROM EMPLOYEES WHERE FIRSTNAME LIKE '%JOHN%') PRINT 'YES' معايرة قاعدة البيانات (في المكتب) مديري ومطوري قاعدة البيانات غالبًا ما يتجادلون فيما إذا كانت القضايا التي يواجهونها متعلقة أو غير متعلقة بالبيانات. ومن خبرتي الشخصية أقدم هنا مجموعة من النصائح لكليهما كي يتمكنا من العمل بشكل أكثر فاعلية. للمطوّرين: إذا توقف تطبيقك عن العمل فجأة، فقد لايكون الأمر متعلقًا بقاعدة البيانات، كمثال ربما هنالك مشكلة بالشبكة، قم بالتحقق قليلًا قبل أن ترجع السبب إلى مدير قاعدة البيانات. حتى ولو كنت بارعًا في نمذجة بيانات SQl، قم بطلب المساعدة من مدير قاعدة البيانات في المخطط العلائقي relational diagram فلديه الكثير ليقدمه لك. مديري قاعدة البيانات لا يحبون التغيرات السريعة، هذا طبيعي، عليهم تحليل قاعدة البيانات بشكل كامل واكتشاف مدى تأثير أي تغيير من كافة الزوايا. تغيير بسيط في عمود يمكن أن يستغرق اسبوعًا للإنجاز هذا بسبب أن الخطأ قد يعتبر خسارة ضخمة للشركة. كن صبورًا! لا تقم بالطلب من مدير قاعدة بيانات SQL بإجراء تغييرات على البيانات في بيئة العمل وقت التشغيل. إذا كنت تود الوصول الى قاعدة البيانات النشطة، يجب عليك تحمل المسؤولية عن كافة التغيرات. لمديري قاعدة بيانات SQl: إذا كنت لا تحب أن يسألك النّاس بشأن قاعدة البيانات، قم بتزويدهم بلوحة تبيّن الحالة وقت التشغيل. فالمطوّرين عادة لديهم شك بحالة قاعدة البيانات، وهذه اللوحة تساعد في توفير الوقت والجهد للجميع. ساعد المطوّرين في اختبارات ضمان الجودة للبيئة. قم بتسهيل عملية محاكاة عمل المخدّم مع اختبار بسيط على بيانات حقيقية. مما يوفر الوقت بشكل كبير عليك وعليهم. يقضي المطوّرين كل اليوم متعاملين مع أنظمة بمفاهيم عمل تتغير بشكل مستمر. تفهمك لذلك يجعل الأمر أكثر مرونة، ويمكنك من تجاوز بعض القواعد في اللحظات الحرجة. قواعد البيانات تتطور، سيأتي اليوم الذي تحتاج فيه إلى نقل بياناتك الى إصدار جديد، حيث يعتمد المطوّرين على خصائص جديدة في كل إصدار جديد، لذلك خطط و تحسب لعملية النقل بدلًا من أن تقوم برفض هذه التغيرات. ترجمة -وبتصرّف- للمقال SQL-Database-Performance-Tuning-for-Developers لصاحبه Rodrigo Koch حقوق خلفية الصورة البارزة Gradient clouds background محفوظة لـ Vexels
  19. مقدمة إنّ azk عبارة عن أداة خفيفة مفتوحة المصدر، تستطيع استخدامها لتنسيق بيئات التطبيقات. هل سبق أن كان لديك تطبيق يعمل على محطة العمل المحليّة الخاصة بك، ووجدت أنّ الإعدادات تختلف كليًا عندما تقوم بنشر التطبيق على مخدّم إنّتاج. تُقدّم هذه المقالة أداة تنسيق، تُدعى azk، والتي يتم استخدامها حاليًا من قبل هذه التطبيقات، وهي قابلة للاستخدام لأكثر من ذلك بكثير. عندما تقوم بنشر تطبيق جاهز للعمل مع azk، فإنّه يمكنك بسهولة إنّ تشغلّه محليًا أو في مخدّم إنّتاج. لا يجعل azk تشغيل التطبيق فقط سهلًا و سريعًا بل كل تبعياته أيضًا، بما فيها نظام التشغيل المطلوب، اللغات، أطر العمل، قواعد البيانات و التبعيات الأخرى (المهام الثقيلة، الطويلة، التكرارية، الأكثر عرضة للخطأ)، سواء كنت تعمل في بيئة محلية أو على مخدم. إنّ غرض هذه المقالة، هو إظهار كيف يعمل azk كأداة تنسيق، باستخدام تطبيق Rails بسيط يُدعى Stringer كمثال. يهتم azk بالعديد من التفاصيل خلف الكواليس، لجعل عملية التنسيق أسهل. لهذا، تحوي هذه المقالة على العديد من الخطوات الاختيارية، التي ليست بضرورية لإعداد التطبيق المثال، ولكنها تشرح آلية عمل azk. سوف نقوم بتشغيل التطبيق من شفرة المصدر على جهاز حاسوب محلي، ثم نشره على مخدّم، و من ثم سنقوم ببعض التغييرات المحليّة، وبعدها نقوم بنشر هذه التغييرات، و من ثم سنقوم بعميلة الإرجاع. بعد إتمام هذه المقالة، سوق تحصل على فكرة جيدة حول كيفية عمل azk كأداة تنسيق سير عملية التطوير والنشر الخاصة بك. كيف يعمل؟ بدايةً، يُنسق azk بيئة التطبيق على جهاز الحاسب المحلي الخاص بك. حالما يعمل التطبيق لديك محليًا، سيقوم azk أيضًا بتنسيق نشره إلى المخدّم Droplet الخاص بك. طالما يُشغل azk التطبيقات من شفرة المصدر، فإنّك تستطيع أن تعمل مع التطبيق محليًا (إذا كنت ترغب بذلك)، و من ثم تقوم بنشره أو استرجاعه مرة ثانية بدون أيّة خطوات إضافية خاصة. يعزل azk البيئات التي تستخدم الحاويات، ولهذا فمن الآمن تشغيل التطبيقات على جهاز الحاسب المحلي الخاص بك. يعمل azk مع كل من المشاريع الجديدة، تلك التي تبدأ منذ الصفر، أو مع الشيفرات الموجودة سابقًا. استخدام azk مع تطبيقات مخصّصة باستخدام القائمة الحالية من التطبيقات التي تم تشكيلها مسبقًا للعمل مع azk كأمثلة، و مع قليل من العمل الإضافي ستستطيع إعداد أي مشروع للعمل مع azk. للقيام بهذا أضف الملف Azkfile إلى مشروعك. Azkfile عبارة عن ملف رئيسي manifest، يحتوي العناصر الضرورية لتشغيل التطبيق، و يقوم بتلخيص علاقاتها فيما بينها (نظام التشغيل، اللغات، قواعد البيانات، … ). فوائد إضافة الملف Azkfile إلى مشروعك: استخدام azk لأتمته إعداد البيئة لمشروعك محليًا و عند النشر. يستطيع الأشخاص الأخرين، الذين يرغبون بنشر تطبيقك، القيام بهذا باستخدام azk. المتطلبات الأساسية للمتابعة مع هذه المقالة، فإنّك ستحتاج إلى جهاز حاسوب يقوم بتشغيل أية من أنظمة التشغيل التالية(64 - بت) للبيئة المحليّة الخاصة بك: Mac OS X 10.6 (Snow Leopard) أو أي إصدار لاحق. Ubuntu 12.04، 14.04 or 15.10 Fedora 21 or 22 أيضاً ستحتاج إلى إنّ تكون قادر على تشكيل git commits. يحتاج جهاز حاسوبك إلى تثبيت Git. إنّظر إلى هذه السلسلة لاستخدام Git من أجل التعليمات الخاصة لأنظمة التشغيل Linux، أو قم بزيارة صفحة تحميل Git. تأكّد من قيامك بتشغيل الأوامر المقترحة : git config --global user.email "you@example.com" git config --global user.name "Your Name" وذلك قبل القيام بقراءة المقالة، انظر الروابط السابقة للحصول على التفاصيل حول Git. لاحظ أنّه لا يوجد ضرورة للحصول على مخدّم فعّال Droplet في هذا الدرس. سيقوم azk بتشكيل واحد باستخدام واجهة التطبيق DigitalOcean’s API. يُكلف نشر مخدم Droplet المال، ومن أجل هذا الدرس ستقوم بنشر مخدم Droplet، يحوي افتراضيًا فقط واحد جيجابايت. مستخدمي Linux : تثبيت الـ Docker: إذا كنت تستخدم نظام تشغيل ( Linux Ubuntu أو Fedora)، ستحتاج لتثبيت الـ 1.8.1 Docker أو أي اصدار لاحق، وذلك لاستخدامه كبرمجية حاويّة. إنّ تشغيل سكريبت تثبيت Docker، هي إحدى طرق تثبيته. (بشكل عام، كُن متأكد من فهمك ماذا يفعل السكريبت، وذلك قبل القيام بتشغيله): $ wget -nv https://get.docker.com/ -O- -t 2 -T 10 | bash إذا كنت ترغب بتعلّم المزيد حول تثبيت Docker في نظام التشغيل Linux، تفحّص تعليمات التثبيت المتاحة في ملفات التوثيق الرسمية. مستخدمي Mac OS X : تثبيت الـ VirtualBox: ستحتاج إلى VirtualBox 4.3.6 أو أي اصدار لاحق، وذلك لاستخدامه كبرمجيّة حاويّة. لتثبيت VirtualBox، حمّل رزمة تثبيت Virtualbox المناسبة من صفحة التحميل الرسميّة. الخطوة الأولى: تثبيت azk محليًا سنقوم بتثبيت azk، باستخدام سكريبت تثبيت المشروع. تأكد من فهمك ماذا يفعل أي سكريبت، قبل تنفيذه في نظامك. إذا كان لديك للتو نسخة قديمة مثبتة من azk، فإنّك تستطيع استخدام سكريبت التثبيت لتحديث الـ azk. وإلا قُم بتفحص إرشادات تثبيت الحزم لنظم التشغيل المدعومة. تثبيت azk على Linux: إذا كنت تستخدم نظام التشغيل (Linux Ubuntu أوFedora)، قُم بتشغيل هذا الأمر في الوحدة الطرفية، وذلك لتثبيت azk باستخدام سكريبت المشروع. نحن ننصح بتدقيق أي سكريبت قبل تشغيله على نظامك: $ wget -nv http://azk.io/install.sh -O- -t 2 -T 10 | bash بعد إتمام التثبيت، قُم بتسجيل الخروج، ومن ثم تسجيل الدخول مرة أخرى، وذلك لجعل كل التعديلات فعّالة. يتجلى سبب تسجيل الخروج، في أنّه خلال عملية التثبيت، سيتم إضافة مستخدمك إلى مجموعة الـ docker. تُعد هذه الخطوة مطلوبة، وبذلك نستطيع استخدام الـ Docker بدون أن تكون المستخدم الأساسي (root). أي عليك الخروج من الجلسة الحالية، لتحصل على كل التعديلات المضافة. إذا كنت ترغب بتعلم المزيد حول مجموعة الـ Docker، فإنّك تستطيع تفحص التوثيق الرسمي لـ Docker. تثبيت azk على Mac OS X: قُم بتشغيل الأمر التالي في الوحدة الطرفية، وذلك لتثبيت azk باستخدام سكريبت المشروع. نحن ننصح بتدقيق أي سكريبت قبل تشغيله على نظامك: $ curl -sSL http://www.azk.io/install.sh | bash الخطوة الثانية: التحقق من تثبيت azk حالما يصبح تثبيت azk كامل، قُم بتشغيل الأمر الذي في الأسفل، وذلك للتحقق من نجاح عملية التثبيت: $ azk version يتحقق هذا الأمر من نسخة الـ azk المثبّتة. إذا أعاد هذا الأمر رقم النسخة (على سبيل المثال azk 0.17.0 أو أي إصدار لاحق)، فالوضع جيد و تستطيع الانتقال إلى الخطوة التالية. تهانينا لك على تثبيت azk في البيئة المحليّة الخاصة بك. إذا لم يكن الأمر كذلك، فاقرأ أدناه أحد أقسام تحرّي الأخطاء وإصلاحها للحصول على المساعدة. استكشاف الأخطاء وإصلاحها في عملية تثبيت azk في Linux: دعونا نتفحص نسخة الـ Docker المثبّتة، وذلك عن طريق تشغيل الأمر: $ docker version ستحتاج إلى الإصدار 1.8.1 أو أحدث. على كل حال، إذا حصلت على رسالة خطأ، فهذا يعني لم تحصل حتى الآن على تثبيت Docker، تتبع إرشادات التثبيت الخاصة بنظام التشغيل في ملفات توثيق Docker. بعد قيامك من التأكد من حصولك على النسخة المثبّتة المناسبة من Docker، قُم بتشغيل الأمر التالي كمستخدم sudo و ذلك للتأكد من أنّ مستخدمك في مجموعة docker: $ id -Gn إذا كانت قائمة المجموعات تتضمن docker، هذا يعني أنه تم إعداده بشكل صحيح. و إلا، إذا لم تحصل على الكلمة docker في قائمة المجموعات، قُم بتشغيل هذا الأمر لإضافة مستخدمك إلى المجموعة: $ sudo usermod -aG docker $USER ومن ثم قُم بتسجيل الخروج، و تسجل الدخول مرة أخرى. تحقق من الأمر id –Gn مرة أخرى للتأكد من أنّه يُعيد قائمة المجموعات مع كلمة docker بينهم. إذا كانت هذه الإرشادات غير كافية لجعل الـ Docker يعمل بالشكل المناسب (على سبيل المثال، لا تزال غير قادر على تشغيل أمر docker version بشكل صحيح)، يّرجى الرجوع إلى تعليمات تثبيت Docker. استكشاف الأخطاء وإصلاحها في عملية تثبيت azk في Mac OS X: تأكّد من تثبيت VirtualBox $ which VBoxManage إذا كان هذا يُعيد مسار ملف (مثل، usr/local/bin/VboxManage/)، فنستطيع المضي قُدمًا. و إلا، إذا كان يُعيد رسالة " not found "، هذا يعني ليس لديك تثبيت VirtualBox. في هذه الحالة، قُم بتحميل و تثبيت رزمة تثبيت VirtualBox من الموقع الرسمي لهم. الخطوة الثالثة (اختيارية): التعلّم حول التطبيق التجريبي Stringer لقد قُمنا باختيار Stringer كتطبيق تجريبي لهذه المقالة، وذلك لأنه تطبيق بسيط، وتم إعداده للعمل مع azk. وهو عبارة عن تطبيق Rails مع حالة استخدام محددة جيدًا: قارئ RSS أساسي. المزيد حول Stringer تُقدم بعض مواقع الأخبار أيضًا محتواها في صيغة تغذية RSS. هذه عبارة عن صيغة ملف XML قياسية، تُمكن الناشرين من نشر المعطيات بشكل اتوماتيكي. قارئ RSS هو عبارة عن برنامج مُستخدم للاشتراك، وتقديم محتوى الـ RSS. تُزيل عملية الاشتراك في تغذية RSS لموقع ما، حاجة المستخدمين للتفحص اليدوي للموقع للحصول على المحتوى الجديد. حيث يستطيع المستخدمين تشكيل قائمة بالتغذيات المُشترك فيها، وتخصيص محتواهم على قارئ RSS (عادةً على شكل قائمة مرتبة ترتيبًا زمنيًا) الخطوة الرابعة (اختيارية): إعداد تطبيق مُخصّص لاستخدام azk طالما أنّ التركيز الأساسي لهذه المقالة هو على إظهار كيفية عمل azk للتطبيقات، التي تملك للتو تفاصيل البيئة المنصوص عليها للعمل مع azk، فعلى المدى الطويل هذه الأداة، هي أكثر فائدة عندما يمكنك استخدامها لنشر أي تطبيق. لهذا، خُذ نظرة عن كيفية مقارنة هذه النسخة من Stringer مع النسخة الأساسية من Stringer في المستودع. تملك نسخة azk فقط إضافتين اثنتين إلى نسخة Stringer الأصلية: ملف Azkfile، الذي يزّود بمعلومات البيئة لـ azk زر azk لتشغيل المشروع Run Project يمكن تعلم المزيد حول جعل azk يعمل مع تطبيقات أخرى، وذلك عن طريق ملفات توثيق azk حول ملف Azkfile و زر تشغيل المشروع Run Project. تالياً، سوف نرى كيف يبدو التطبيق الصديق لـ azk في GitHub. الخطوة الخامسة (اختيارية): استخدام زر تشغيل المشروع لـ azk على GitHub إنّ جزء الممارسات الأفضل من azk من أجل مشاريع GitHub، هو التوضيح الجيد لكيفيّة عمل هذا المشروع مع azk. لهذا، بدلاً من إظهار فقط أمر الـ azk في وسط ملف readme للمشروع، فإنّ المشروع الذي يستخدم azk يستطيع استخدام زر تشغيل المشروع، وذلك للعزل البصري لأمر الـ azk. يستخدم Stringer هذا الزر. قُم بزيارة قسم التشغيل المحلي لنسخة azk المتشعبة من Stringer. أضغط زر تشغيل المشروع Run Project. في أول مرة تضغط فيها زر تشغيل المشروع، سوف ترى شرح بسيط عن ماذا يجري. عندما تصبح جاهزا للمضي قُدماً، انقر على الزر OK، DISMISS في أسفل الشرح. بعدها سيتم توجيهك إلى صفحة مع أمر azk لمشروع Stringer. $ azk start -o run-project/stringer يمكنك دائماً أنّ تنقر على إشارة ما هذا؟ على الزاوية العليا اليُمنى، وذلك لترى الشرح مرّة أخرى. في مركز الشاشة، يوجد صندوق أوامر مع ثلاث علامات تبويب: curl، wget، azk. طالما لدينا للتو مُثبت azk فتستطيع استخدام علامة التبويب azk. هذا هو الأمر، الذي سنستخدمه في الخطوة التالية للتشغيل الفعلي لـ Stringer. الخطوة السادسة: تشغيل Stringer محليًا في هذا القسم سنستخدم azk لتشغيل Stringer على محطّة العمل المحليّة. دعونا نتأكد أنّنا في المسار الرئيسي home على جهاز حاسوبنا المحلي (إذا قمت باستخدام مجلد تثبيت مختلف، تذكر فقط تغيير الأوامر إلى مسارك المختار): $ cd ~ أمضي قُدمًا، و قم بتشغيل الأمر التالي على حاسوبك المحلي، وذلك لتشغيل Stringer: $ azk start -o run-project/stringer طالما هذه هي أول مره تقوم بها بتشغيل azk، سيطلب منك قبول بنود الخدمة. و يجب أنّ تظهر رسالة كالتالية: ? ========================================================================= Thank you for using azk! Welcome! Before we start، we need to ask: do you accept our Terms of Use? http://docs.azk.io/en/terms-of-use ========================================================================= (Y/n) اضغط على Y إذا كنت موافق أو N إذا كنت غير موافق. و من ثم اضغط على ENTER لتأكيد جوابك. في حالة عدم موافقتك، فلن تتمكن من استخدام azk. و اخيراً، سيقوم azk أوتوماتيكيًا بتحميل الشفرة المصدر لـ Stringer، إضافة إلى أنّ الملف المسند Azkfile سيقوم بتشغيل هذا الشفرة في بيئة معزولة و آمنة في حاسوبك المحلي. ومن ثم سيتم سؤالك فيما إذا كنت ترغب ببداية تشغيل عميل الـ azk. ? The agent is not running، would you like to start it? (Y/n) العميل هو عبارة عن مُركب azk، الذي يقوم بإعداد Docker (على نظام التشغيل Linux )، أو بإعداد الآلة الافتراضيّة VirtualBox (على نظام التشغيل Mac OS X). اضغط ENTER للجواب “Yes” (الخيار الافتراضي). في أول مرة تُشغل فيها العميل، سيقوم azk بتشغيل إعداداته. يقوم الإعداد بالعديد من الأشياء وراء الكواليس، بما في ذلك توليد الملف /etc/resolver/dev.azk.io، الذي يحوي إعدادات نظام أسماء النطاقات DNS، لتصميم العناوين التي تنتهي باللاحقة dev.azk.io. يستخدم azk هذه اللاحقة عند تشغيل التطبيقات لاستخدام العناوين القابلة للقراءة بدلاً من الاستخدام اليدوي للعناوين من الشكل http://localhost:PORT_NUMBER . أيضاً هذا يقوم بتجنب تعارض أرقام المنافذ بين التطبيقات المختلفة. بشكل أساسي يقوم هذا بنفس الشيء عند تحرير ملفك /etc/hosts لإعادة توجيه اسم نطاق محليًا. إذا حصلت على رسالة من الشكل التالي: ? Enter the vm ip: (192.168.50.4) فإنّك تستطيع إدخال أي عنون IP محلي، ترغب بتشغيل التطبيق عليه. يجب أن تكون الحالة الافتراضية مناسبة لجميع الحالات. للموافقة على هذا، فقط اضغط ENTER. لإتمام إعدادات عميل الـ azk، سيتم سؤالك عن كلمة المرور الخاصة بالمستخدم sudo (لمستخدمي نظام التشغيل Mac OS X، هي عبارة عن كلمة مرور المُشرف admin). الآن سيبدأ azk بالعمل. سوف ترى أنّ azk يُحمّل العناصر المُسردة في الملف Azkfile (على صيغة صور Docker ). من الممكن أن يستغرق تحميل هذه الصور أول مرة عدة دقائق (حوالي 10 دقائق أو أقل). حالما يُكمل azk الإعداد، سيقوم مُتصفحك بشكل أتوماتيكي بتحميل شاشة البدء لـ Stringer على حاسوبك المحلي. كما تستطيع إنّ ترى، أنّه يستخدم اسم نطاق محلي DNS، و هذا التطبيق مرئي على http://stringer.dev.azk.io. و تستطيع الوصول إلى التطبيق بشكل يدوي عبر الذهاب إلى http://stringer.dev.azk.io . إذا كنت ترغب بإعداد كلمة المرور و بداية التشغيل باستخدام التطبيق، فإنّك تستطيع فعل ذلك. نحن نرغب فقط برؤية أنّ azk يستطيع تشغيل Stringer محلياً. والآن طالما لديك Stringer يعمل على الحاسوب المحلي، فتستطيع نشره من جهاز الحاسوب لديك إلى المخدّم Droplet. الخطوة السابعة: الحصول على الرمز DigitalOcean API Token قبل أن نتمكن من نشر Droplet من azk، فإنّنا نحتاج إلى رمز API token. يُعطي هذا الرمز الإذن لـ azk لنشر مخدّم جديد على حسابك. في أول مرّة تقوم بها بتشغيل azk من هذه البيئة باستخدام هذا الرمز، سيتم نشر واحد جيجابايت مخدّم جديد Ubuntu 14.04 Droplet . و ستستخدم عمليات النشر اللاحقة من نفس البيئة المحليّة، نفس المخدّم المفرد Droplet. اتّبع الإرشادات من قسم المراجع المرتبطة بالمقالة حول كيفية تشكيل رمز الوصول الشخصي. و يجب أن يمتلك الرمز المُشكّل تصاريح الكتابة القراءة. قُم بنسخ المحارف الأربعة و الستين بالترميز الست عشري لرمزك، بشكل مشابه للتالي: Example API Token A17d6a72566200ad1a8f4e090209fe1841d77d7c85223f769e8c5de47475a726 سوف ترى هذا الرمز النصيّ فقط مرة واحدة، لذلك قُم بنسخه إلى مكان آمن. (تذكّر، إذا تم اختراق هذا الرمز، فإنّه يمكن استخدامه للدخول إلى حسابك، لذلك حافظ عليه خاصًا). من أجل الإرشادات أسفلا، تذكر استبدال الرمز المثال بالرمز الحقيقي الخاص بك. اذهب إلى مجلد Stringer: $ cd ~/stringer احفظ رمز الوصول الشخصي في ملف ستدعوه env. للقيام بهذا، قُم بتشغيل أمر تشكيل ملف (لا تنسى استبدال الرمز): $ echo "DEPLOY_API_TOKEN=a17d6a72566200ad1a8f4e090209fe1841d77d7c85223f769e8c5de47475a726" >> .env يجب إنّ يبدو محتوى الملف env. بالشكل التالي: DEPLOY_API_TOKEN=a17d6a72566200ad1a8f4e090209fe1841d77d7c85223f769e8c5de47475a726 الخطوة الثامنة (اختيارية): التعلم حول مفاتيح SSH ليس عليك إنّ تقوم بأي شيء لإعداد مفتاح SSH من أجل azk، ولكن من المفيد معرفة الكيفية التي يستخدم فيها azk هذا المفتاح. يستخدم azk مفتاح SSH للوصول إلى المخدّم Droplet. إذا كان لديك للتو مفتاح SSH، فإنّ azk سيستخدمه. لرؤية فيما إذا كان لديك مفتاح SSH على جهاز الحاسوب لديك، شغّل: $ ls ~/.ssh/*.pub إذا قام بإرجاع رسالة “not found”، فهذا يعني إنّه ليس لديك أيّة مفاتيح SSH على جهاز الحاسوب. في هذه الحالة، سيولّد azk بشكل أتوماتيكي مفتاح SSH جديد، ليتم استخدامه حصريًا لنشر أي تطبيق جديد من جهاز الحاسوب لديك. سيقوم azk بتوليد مفتاحه في الذاكرة المحجوزة له، ولن يقوم بأيّة تعديلات على مسارك ~/.ssh. إذا كنت ترغب بتفحص المفتاح العام المولّد، يمكنك تشغيل الأمر التالي بعد نشر التطبيق الأول: $ azk deploy shell -c "cat /azk/deploy/.config/ssh/*.pub" الخطوة التاسعة: النشر مع azk بشكل افتراضي، سيولد azk مخدّم DigitalOcean Droplet واحد جيجابايت، يُشغّل النظام Ubuntu 14.04، وذلك من أجل نشر تطبيقك. إذا كنت ترغب بنشر Droplet بمواصفات مختلفة، فيمكنك تغيير الإعدادات في خصائص envs لنظام deploy في الملف Azkfile.js . من أجل الإرشادات الإضافية أشر إلى ملفات توثيق حول نشر azk . أولاً، اذهب إلى مسار Stringer ( أو إلى مسار تطبيقك): $ cd ~/stringer ومن ثم، ابدأ عملية النشر، فقط قُم بتشغيل: $ azk deploy إنّ الأمر azk deploy، هو الأمر الذي ستقوم بتشغيله معظم الأوقات، عندما تستخدم azk لتنسيق تطبيقك. من الممكن أن تستغرق أول عملية نشر فترة معينة (حوالي عشر دقائق)، حتى يقوم azk بكل العمل. بشكل مخصص، على azk القيام بما يلي: تحميل عناصر الدعم ( صورة Docker للنشر) تشكيل و إعداد الـ Droplet رفع شفرة المصدر للتطبيق إلى المخدّم Droplet تشغيل التطبيق بعدها ستستغرق كل عملية نشر جديده لهذا التطبيق من جهاز الحاسوب لديك مدة زمنية قليلة (حوالي 30 ثانية أو أقل)، هذا لان معظم الخطوات الطويلة جاهزة للتو. إذا كان مفتاحك SSH محمي بكلمة مرور، فسيكون مطلوباً وقت أكبر لعملية النشر. فقط قُم بكتابة كلمة المرور للمفتاح SSH، و أضغط زر ENTER في كل مرة تظهر رسالة كالتالية: Output Enter passphrase for ~/.ssh/id_rsa: سيظهر خرج الوحدة الطرفية بعض الإجراءات المُتخذة على النظام البعيد، تنتهي برسالة النشر الناجحة App successfully deployed at http://your_server_ip. قُم بزيارة الموقع http://your_server_ip لعرض التطبيق المُستضاف على الخادم الخاص بك. من الآن، يُمكنك تغيير شفرة التطبيق على جهاز الحاسوب الخاص بك، و يمكنك اختباره محلياً، و يمكنك نشر التغييرات على المخدّم Droplet بواسطة الأمر azk deploy. الخطوة العاشرة: تعديل Stringer لتوضيح سهولة استخدام azk لنشر تطبيق، للتخصيص، أو للتحكم في النسخة، دعونا نقوم بعدد من التغييرات على صفحة الاشتراك Stringer، و من ثم نقوم بإعادة نشر التطبيق. تأكد من كونك على مسار Stringer: $ cd ~/stringer دعونا نقوم بتعديل الملف app/views/first_run/password.erb، الذي هو عبارة عن الصفحة الحاوية على النص لصفحة الاشتراك الأولى. استخدم nano أو محرر النصوص المفضل لديك: $ nano ~/stringer/app/views/first_run/password.erb هنا نقوم بإضافة السطر الإضافي، الذي يقول "! It’s easy with azk ": app/views/first_run/password.erb <div class="setup" id="password-setup"> <h1><%= t('first_run.password.title') %> <span class="orange"> <%= t('first_run.password.anti_social') %></span>.</h1> <h2><%= t('first_run.password.subtitle') %></h2> <h2>It's easy with azk!</h2> <hr /> . . . </div> قُم بالحفظ و الخروج من محرر النصوص. إذا كنت تستخدم nano، اضغط CTRL+O للحفظ، و CTRL+X للخروج. طالما إنّ Stringer مُعد افتراضياً للعمل في وضع الانتاج، لذلك فإنّ إعادة تحديث صفحة المتصفح ليس بكافٍ لتشغيل التغييرات. بل قُم بإعادة تشغيل التطبيق من azk: $ azk restart stringer -o يجب على علامة التبويب الجديدة للمتصفح أن تفتح النسخة الجديدة من Stringer. أسفل النص الافتراضي مباشرةً “There is only one user: you”، يجب الآن أن يكتب “!It’s easy with azk”. الخطوة الحادية عشر: إعادة نشر Stringer الآن، دعونا نُودع (commit) التغييرات داخل نسخة نظام التحكم، من أجل أن نستطيع نشرها. $ git add app/views/first_run/password.erb $ git commit . سيظهر لك محرر نصوص (على الأرجح nano أو vim). أدخل رسالة إيداع commit، مثل It is easy with azk. سيتم استخدام هذه الرسالة commit لتسمية الإصدارات من تطبيقك داخل azk، لذلك اختر الرسالة التي من شأنها تحفيز ذاكرتك، إذا كنت بحاجة إلى الرجوع إليها في وقت لاحق. احفظ و أغلق رسالة الـ commit. إذا حصلت على الخطأ : fatal: empty ident name (for <sammy@azk.(none)>) not allowed عندها قُم بتشغيل أوامر الإعدادات المقترحة من أجل Git لإعداد عنوان إيميل و اسم (المزيد من التفاصيل في قسم المتطلبات الأساسية). لنشر تغييراتك و رفع تشغيل التطبيق على Droplet، قُم بتشغيل: $ azk deploy بعد الانتهاء من ذلك، قُم بالوصول إلى عنوان IP لـ Droplet من متصفحك (مثلاً http://your_server_ip) .عندها يجب أن ترى أيضاً هنا السطر الجديد !It’s easy with azk سيقوم هذا النشر الجديد بتشكيل نسخة جديدة من التطبيق على Droplet. إنّ كل نسخ التطبيق مخزنة، لذلك يمكنك العودة إلى نسخة سابقة ومن ثم إلى الأمام مرّة أخرى. الخطوة الثانية عشر: الرجوع إلى خطوة سابقة للحصول على كل النسخ المتاحة من تطبيقنا على Droplet، شغّل الأمر التالي محليًا: $ azk deploy versions يجب إنّ تكون النتيجة بقائمة من الشكل: Output ⇲ Retrieving deployed versions... ➜ v2 It is easy with azk v1 Merge branch 'master' of https://github.com/swanson/stringer لإرجاع التطبيق إلى نسخة أقدم، فقط قوم بتشغيل: $ azk deploy rollback v1 إنّ المعامل v1 عبارة عن رقم النسخة، الذي يظهر على خرج الأمر azk deploy versions. إذا قمت بتشغيل الأمر بدون هذا المعامل (مثلاً، . azk deploy rollback )، سيرجع عندها التطبيق إلى نسخة سابقة تماماً قبل النسخة الحالية. لتفحص إتمام عملية الرجوع، فقط قُم بتحديث علامة تبويب المتصفح، التي تظهر نسخة المخدم. الآن عليك إنّ ترى التطبيق بدون النص الذي قمنا بإدخاله، أي يجب أن ترى النسخة الأصليّة من التطبيق. وإذا كنت ترغب بالرجوع للأمام، يمكنك اختيار النسخة الأحدث: $ azk deploy rollback v2 أتت التسمية لهذه النسخ من رسائل الـ git commit في الخطوة السابقة. الخاتمة في هذا الدليل التعليمي، لقد استخدمنا تطبيق Rails بسيط، لتوضيح كيف يقوم azk بأتمتة مهام إعداد بيئة تطبيقنا. يجعل هذا من السهل نشر التطبيق نفسه في عدة بيئات. إذا أعجبت بعملية النشر من azk، خُذ بعين الاعتبار استخدامه لمشروعك الخاص، أو إضافة الملف Azkfile إلى fork مشروع أخر مفتوح المصدر. يدعم azk بالإضافة إلى عملية rollback و versions، غيرها من الأوامر الفرعيّة المساعدة، التي تسمح لنا بإنّجاز بعض الإجرائيات الإضافية (مثلاً، الوصول إلى Droplet’s shell عن طريق المفتاح SSH ). ترجمة -وبتصرّف- للمقال How To Deploy a Rails App with azk لصاحبه Felipe Arenales
  20. في مقال اليوم نقدم دليلًا سريعًا مدعمًا بالأمثلة العملية شرح لغة PHP التي تعد واحدة من لغات البرمجة القوية المستخدمة بشكل أساسي لتطوير الويب، فعلى الرغم من ظهور العديد من لغات البرمجة الأحدث في مجال تطوير الويب إلا أن لغة PHP لا تزال اللغة الأكثر شيوعًا واستخدامًا، وهي تتطور باستمرار لإصلاح أي عيوب أو أخطاء فيها وتعزيز أمان وأداء المواقع المبنية باستخدامها. نبذة مختصرة عن لغة PHP يشير اسم PHP إلى عبارة Hypertext Pre-processor أي المعالج المسبق للنصوص الفائقة وكلمة النصوص الفائقة تعني النصوص التي تملك روابط تنقلك لنصوص أو صفحات صفحات ويب أخرى عند النقر فوقها. وهي لغة برمجة مفتوحة المصدر وشائعة الاستخدام تستخدم في إنشاء وتطوير مواقع الويب الديناميكية، وقد طور باستخدامها أكثر من 75% من المواقع الموجودة على شبكة الإنترنت بحسب w3techs. تتميز لغة PHP بسهولتها ودعمها لمجموعة متنوعة من قواعد البيانات وبروتوكولات الإنترنت وتوفيرها للعديد من مكتبات وأطر العمل المساعدة للمبرمجين، وما زاد من شهرتها وحافظ على مكانتها وأهميتها بين مطوري الويب اعتماد العديد من منصات إدارة المحتوى ومنصات التجارة الإلكترونية المشهورة عليها مثل ووردبريس WordPress ودروبال Drupal وماجنتو Magneto وغيرها الكثير، فإذا كنت مهتمًا بمجال تطوير الويب فإن تعلم لغة PHP خيار مناسب وغني بالفرص. تعمل لغة PHP على الخادم server-side بخلاف لغات برمجة أخرى تعمل على المتصفح أو العميل client-side مثل لغة جافا سكريبت JavaScript أي أنها لا تنفذ الشيفرة البرمجية في متصفح الويب، بل تشغلها مباشرة على خادم الويب وبعدها يرسل خادم الويب نتيجة التنفيذ إلى المتصفح لعرضها، وتفترض هذه المقالة أنك تمتلك معلومات أساسية عن لغة PHP وطريقة عملها في الخلفية عند زيارتك لصفحة ويب من خلال متصفح الويب الخاص بك، وبأنك تعرف مسبقًا كيف تحول جهاز حاسوبك إلى خادم محلي وكيف تعد كل الأدوات اللازمة لكتابة أوامر PHP وتنفيذها، فإذا لم تكن على دراية بهذه المعلومات الأساسية أنصحك قبل ذلك ان تقرأ مقال تعرف على لغة PHP ثم تتابع قراءة هذا المقال. ملاحظة: تعمل الأكواد الواردة في الفقرات التالية مع إصدار PHP 5 والإصدارات اللاحقة فقد قدم الإصدار الخامس من PHP العديد من التغييرات والتحسينات المهمة على الإصدارات السابقة وأبرز هذه التغييرات دعم البرمجة كائنية التوجه oop في PHP ووفر العديد من تحسينات الأداء والأمان، وتابعت الإصدارات اللاحقة التحسين وأضافت ميزات جديدة للغة. كيف تكتب أكواد PHP تكتب أكواد PHP بعد وسم الفتح php?> وقبل وسم الإغلاق ‎<? ثم تحفظ داخل ملفات لها الامتداد ‎.php على خادم الويب، ومن الأفضل عمليًا تجاهل كتابة وسم الإغلاق إذا كان ملف php يحتوي على شفرة php فقط، لتلافي نتيجة خرج غير متوقعة. <?php echo "Hello World!"; ?> كما يمكن أن تدمج أكواد PHP مع أكواد HTML لإنشاء صفحات ويب ديناميكية بالشكل التالي: <!DOCTYPE html> <html> <head> <title> HTML and PHP </title> </head> <body> <h1>PHP code mixed with HTML</h1> <?php echo "Hello World!"; ?> </body> </html> التعليقات Comments التعليقات هي أجزاء من الكود البرمجي لا تنفذ عند تشغيل البرنامج وهي تستخدم لشرح وتوثيق الكود وتوضيح عمله للمطورين الآخرين الذين يقرأون هذا الكود، أو لتوضيحها للمبرمج الذي كتبها نفسه فقد ينسى ما كتبه عند العودة لقراءة الكود بعد فترة من الزمن. يمكن كتابة التعليقات في لغة PHP بعدة طرق كما في المثال التالي: // استخدم علامة القوسين المائلين // لبدأ تعليق بسطر واحد // يمكن استخدام العلامة # لكن علامة // أكثر شيوعيا. /* إحاطة نص بالقوس المائل متبوعا بالنجمة بداية وبالنجمة متبوعة بالقوس المائل نهاية يجعل من هذا النص تعليقا متعدد الأسطر */ طباعة الخرج في PHP يمكنك استخدم تعليمة echo أو print لطباعة الخرج أو عرض البيانات المطلوبة على صفحة الويب. print('Hello '); // بدون سطر فاصل "Hello " طباعة استخدام القوسين ( ) اختياري مع تعليمتي echo و print echo "World\n"; // مع سطر فاصل "World" طباعة يجب أن تنتهي كل العبارات في لغة PHP بالفاصلة المنقوطة ";" وأي شيء مكتوب خارج وسوم php?> ستتم طباعته على الشاشة بشكل تلقائي. دورة تطوير تطبيقات الويب باستخدام لغة PHP احترف تطوير النظم الخلفية وتطبيقات الويب من الألف إلى الياء دون الحاجة لخبرة برمجية مسبقة اشترك الآن الأنماط Types والمتغيرات Variables تستخدم المتغيرات في PHP لتخزين وحفظ قيم البيانات، ويمكن أن تخزن هذه المتغيرات قيمًا مختلفة كالأرقام والنصوص والقيم المنطقية. يمكنك التصريحعن المتغيرات في PHP بكتابة الرمز $ يليه مباشرة اسم المتغير، ويجب ان تبدأ أسماء المتغيرات تبدأ بحرف أو تسطيرة سفلية _ يتبعها بأي عدد من الأحرف أو الأرقام أو التسطيرات السفلية. وتكون أسماء المتغيرات حساسة لحالة الأحرف case-sensitive. من أهم أنماط المتغيرات في لغة PHP نذكر: المتغيرات المنطقية Boolean ويملك المتغير من هذا النمط القيمة true أي صحيح أو القيمة false أي خاطئ. $boolean = true; // TRUE أو True $boolean = false; // FALSE أو False الأعداد الصحيحة Integer حيث يملك المتغير من هذا النمط قيمة صحيحة موجبة أو سالبة $int1 = 12; // => 12 $int2 = -12; // => -12 $int3 = 012; // => 10 (البادئة 0 تدل على عدد ثماني) $int4 = 0x0F; // => 15 (0x تدل على رقم ستة عشري) المحارف الصحيحة الثنائية Binary integer literals متاحة اعتبارًا من PHP 5.4.0 وهي تستخدم لتمثيل الأعداد الصحيحة بالنظام الثاني $int5 = 0b11111111; // 255 (0b يدل على عدد ثنائي) الأرقام العائمة Floats أو (المضاعفة doubles) وهي تستخدم لتمثيل الأعداد العشرية $float = 1.234; $float = 1.2e3; $float = 7E-10; لحذف متغير في PHP وتحرير موارد الذاكرة المحجوزة لأجله نستخدم تعليمة unset unset($int1); يمكن إجراء العمليات الحسابية على المتغيرات العددية كما يلي: $sum = 1 + 1; // 2 $difference = 2 - 1; // 1 $product = 2 * 2; // 4 $quotient = 2 / 1; // 2 كما يمكن إجراء العمليات الحسابية المختزلة بالشكل التالي: $number = 0; $number += 1; // بمقدار 1 $number زيادة echo $number++; // (طباعة 1 (الزيادة بعد التقييم echo ++$number; // (طباعة 3 (الزيادة قبل التقييم $number /= $float; // $number قسمة واسناد ناتج القسمة إلى السلاسل النصية Strings وهي تستخدم لتخزين النصوص ويجب أن تكون النصوص محدودة ضمن إشارة تنصيص واحدة ’ من كل جانب كما يلي: $sgl_quotes = '$String'; // => '$String' تجنب استخدام علامات التنصيص المزدوجة إلا في حالة تضمين متغيرات أخرى $dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.' تحدد المحارف الخاصة حصريًا باقتباسات مزدوجة $escaped = "This contains a \t tab character."; $unescaped = 'This just contains a slash and a t: \t'; قم بإحاطة المتغيرات بالقوسين المائلين عند الحاجة $apples = "I have {$number} apples to eat."; $oranges = "I have ${number} oranges to eat."; $money = "I have $${number} in the bank."; منذ الإصدار الخامس يمكن استخدام nowdocs في حالة عدة أسطر غير مجمعة $nowdoc = <<<'END' Multi line string END; ستقوم heredocs بتجميع النصوص $heredoc = <<<END Multi line $sgl_quotes END; يتم وصل النصوص أو دمجها باستخدام النقطة "." echo 'This string ' . 'is concatenated'; يمكن تمرير النصوص كبارامتر لـ echo echo 'Multiple', 'Parameters', 'Valid';// 'MultipleParametersValid' يعيد الثوابت في PHP يعرّف الثابت باستخدام ()define ولا يمكن تغيير قيمته خلال فترة التشغيل. ويجب أن تبدأ أسماء الثوابت الصحيحة بحرف أو تسطيرة سفلية, متبوعة بأية حروف أو أرقام أو تسطيرات سفلية. define("FOO", "something"); الوصول إلى المتغير الثابت متاح دون الحاجة الى استخدام الرمز $ echo FOO; // 'something' يعيد echo 'This outputs ' . FOO; // 'This outputs something' يعيد المصفوفات Arrays المصفوفات في PHP هي هياكل بيانات تسمح بتخزين مجموعة من القيم ضمن متغير واحد، وكل المصفوفات في PHP هي مصفوفات مترابطة (تسمى hashmaps في بعض اللغات البرمجية) وتعمل في جميع إصدارات php $associative = array('One' => 1, 'Two' => 2, 'Three' => 3); تم إدخال تركيب قواعدي syntax جديد في PHP 5.4 $associative = ['One' => 1, 'Two' => 2, 'Three' => 3]; echo $associative['One']; // 1 تطبع إضافة عنصر للمصفوفة المترابطة $associative['Four'] = 4; القوائم المحرفية يسند لها مفاتيح صحيحة حكمًا $array = ['One', 'Two', 'Three']; echo $array[0]; // => "One" إضافة عنصر إلى نهاية المصفوفة $array[] = 'Four'; أو array_push($array, 'Five'); حذف عنصر من مصفوفة unset($array[3]); المزيد حول تعلميات الطباعة في PHP echo('Hello World!'); تقوم التعليمة السابقة بطباعة !Hello World على شاشة الاظهار القياسية stdout، وstdout هي صفحة الوب إذا كنت تستخدم متصفحًا print('Hello World!'); // echo مشابه لـ // هي أيضًا من تركيبات اللغة لذلك يمكنك إلغاء الأقواس echo و print echo 'Hello World!'; print 'Hello World!'; $paragraph = 'paragraph'; echo 100; // اطبع المتغيرات العددية مباشرة echo $paragraph; // أو المتغيرات إذا تم إعداد الوسوم القصيرة المفتوحة أو كانت نسخة PHP الخاصة بك 5.4.0 أو أحدث يمكنك استخدام قواعد بناء الجمل القصيرة لـ echo <p><?= $paragraph ?></p> $x = 1; $y = 2; $x = $y; المتغير x$ يحتوي نفس قيمة المتغير y$ $z = &$y; المتغير z$ يحتوي إسناد إلى قيمة y$، وأي تغيير في قيمة z$سيغير قيمة y$ وبالعكس المتغير x$ تبقى قيمته بدون تغيير كقيمة y$ الأصلية echo $x; // => 2 echo $z; // => 2 $y = 0; echo $x; // => 2 echo $z; // => 0 تخرج التفريغات Dumps نوع وقيمة المتحول إلى شاشة العرض القياسية stdout var_dump($z); // int(0) يطبع تطبع التعليمة Print المتغيرات إلى شاشة الإظهار القياسية stdout بصيغة مقروءة للإنسان print_r($array); // Array ( [0] => One [1] => Two [2] => Three ) يطبع العمليات المنطقية $a = 0; $b = '0'; $c = '1'; $d = '1'; يقوم assert بإصدار تنبيه إذا كانت معطياته غير صحيحة وهذه المقارنة ستكون دومًا صحيحة حتى إذا كانت الأنواع مختلفة assert($a == $b); // equality المساواة assert($c != $a); // inequality عدم المساواة assert($c <> $a); // alternative inequality عدم المساواة بشكل بديل assert($a < $c); assert($c > $b); assert($a <= $b); assert($c >= $d); التالي سيكون صحيحًا فقط في حال كانت القيم متساوية ومن نفس النوع assert($c === $d); assert($a !== $d); assert(1 === '1'); assert(1 !== '1'); المشغل `Spaceship` <=> (منذ PHP 7) يعيد 0 إذا كانت القيم على طرفيه متساوية، ويعيد 1 إذا كانت القيمة على اليسار أكبر، ويعيد -1 إذا كانت القيمة على اليمين أكبر $a = 100; $b = 1000; echo $a <=> $a; // النتيجة 0 كونهما متساويين echo $a <=> $b; // $a < $b النتيجة -1 كون echo $b <=> $a; // $b > $aالنتيجة 1 كون يمكن تحويل المتغيرات إلى أنواع مختلفة بحسب استخدامها $integer = 1; echo $integer + $integer; // => 2 $string = '1'; echo $string + $string; // => 2 (تم تحويل النصوص الى أعداد صحيحة) $string = 'one'; echo $string + $string; // => 0 النتيجة 0 لأن المشغل + لا يستطيع موائمة النص `one` الى رقم. موائمة الأنواع Type casting يمكن استخدامها للتعامل مع متغير من نوع معين كنوع آخر. $boolean = (boolean) 1; // => true $zero = 0; $boolean = (boolean) $zero; // => false يوجد أيضًا توابع مخصصة لموائمة أغلب الأنواع $integer = 5; $string = strval($integer); null هي قيمة خالية $var = null; بنى التحكم Control Structures تمكنك بنى التحكم في لغة PHP من التحكم في تنفيذ الكود البرمجي بناءً على شروط معينة أو تكرار تنفيذ جزء من الكود عدة مرات ومن أشهر بنى التحكم المستخدمة في لغة PHP العبارات الشرطية if وعبارات الحلقات مثل for و while وعبارات switch. if (true) { print 'I get printed'; } if (false) { print 'I don\'t'; } else { print 'I get printed'; } if (false) { print 'Does not get printed'; } elseif (true) { print 'Does'; } المشغل الثلاثي ternary print (false ? 'Does not get printed' : 'Does'); بدأ استخدام المشغل الثلاثي المختصر من PHP 5.3 وهو مكافئ لـ "$x ? $x : 'Does'"" $x = false; print($x ?: 'Does'); بدأ مشغّل دمج القيم الفارغة null coalesce operator من php 7 $a = null; $b = 'Does print'; echo $a ?? 'a is not set'; // 'a is not set' تطبع echo $b ?? 'b is not set'; // 'Does print' تطبع $x = 0; if ($x === '0') { print 'Does not print'; } elseif ($x == '1') { print 'Does not print'; } else { print 'Does print'; } القواعد البديلة لبناء الجمل مفيدة لبناء النماذج <?php if ($x): ?> This is displayed if the test is truthy. <?php else: ?> This is displayed otherwise. <?php endif; ?> استخدم التعليمة switch لتوفير كتابة جزء من العمليات المنطقية كما يلي switch ($x) { case '0': print 'Switch does type coercion'; break; // 'two' و'three' وإلا سينتقل الى الحالة break يجب تضمين case 'two': case 'three': // 'two' أو 'three' تساوي $variable قم بعمل شيء ما اذا كانت قيمة break; default: // قم بعمل الاجراء الافتراضي } الحلقات while، do…while، for هي حلقات مألوفة غالبًا وتستخدم لتكرار تنفيذ مجموعة من التعليمات البرمجية كما يلي: $i = 0; while ($i < 5) { echo $i++; } // "01234" اطبع $i = 0; do { echo $i++; } while ($i < 5); // "01234" اطبع for ($x = 0; $x < 10; $x++) { echo $x; } // "0123456789" اطبع $wheels = ['bicycle' => 2, 'car' => 4]; يمكن أن تعمل حلقات foreachعلى المصفوفة بالشكل التالي: foreach ($wheels as $wheel_count) { echo $wheel_count; } // "24"اطبع ويمكنك لحلقة foreach المرور إما عبر المفاتيح أو القيم الخاصة بالمصفوفة foreach ($wheels as $vehicle => $wheel_count) { echo "A $vehicle has $wheel_count wheels"; } $i = 0; while ($i < 5) { if ($i === 3) { break; // while اخرج من حلقة } echo $i++; } // "012" اطبع for ($i = 0; $i < 5; $i++) { if ($i === 3) { continue; // تجاوز هذا التكرار من الحلقة } echo $i; } // "0124" اطبع الدوال Functions الدوال في البرمجة هي مجموعات من الأوامر التي لها اسم محدد وتستخدم لأداء مهمة معينة وهي تساعد في تنظيم واختصار التعليمات البرمجية. ونعرّف الدالة PHP باستخدام الكلمة المفتاحية function function my_function () { return 'Hello'; } echo my_function(); // => "Hello" الاسم المقبول للدالة يجب أن يبدأ بحرف أو تسطيرة سفلية متبوعة بأي عدد من الأحرف ،الأرقام، أو التسطيرات السفلية function add ($x, $y = 1) { // اختيارية وقيمتها الإفتراضية تساوي 1 $y $result = $x + $y; return $result; } echo add(4); // => 5 echo add(4, 2); // => 6 لا يمكن الوصول للمتغير result$ من خارج الدالة واستخدام الأمر ;print $result هنا سيعطي خطأ منذ النسخة PHP 5.3 أصبح من الممكن تعريف دوال مجهولة anonymous functions أي دوال لا تملك اسمًا وتخزن قيمها في متغيرات كما يلي: $inc = function ($x) { return $x + 1; }; echo $inc(2); // => 3 function foo ($x, $y, $z) { echo "$x - $y - $z"; } يمكن للدوال أن تعيد دوالًا أخرى function bar ($x, $y) { // استخدم use لإحضار المتغيرات الخارجية return function ($z) use ($x, $y) { foo($x, $y, $z); }; } $bar = bar('A', 'B'); $bar('C'); // "A - B - C" يطبع يمكنك استدعاء الدوال المسماة named functions باستخدام النصوص $function_name = 'add'; echo $function_name(1, 2); // => 3 وهو هام من أجل تحديد أي دالة يتوجب تشغيلها برمجيًا، أو استخدم الدالة التالية call_user_func (callable $callback [, $parameter [, … ]]); يمكنك الحصول على كل البارمترات الممررّة للدالة function parameters() { $numargs = func_num_args(); if ($numargs > 0) { echo func_get_arg(0) . ' | '; } $args_array = func_get_args(); foreach ($args_array as $key => $arg) { echo $key . ' - ' . $arg . ' | '; } } parameters('Hello', 'World'); // Hello | 0 - Hello | 1 - World | يمكنك الحصول على عدد متغير من المعطيات ابتداء من PHP 5.6 function variable($word, ...$list) { echo $word . " || "; foreach ($list as $item) { echo $item . ' | '; } } variable("Separate", "Hello", "World"); // Separate || Hello | World | التضمين في PHP باستخدام include و require يفيد التضمين في PHP لتضمين محتوى ملف في ملف آخر ويمكن القيام بتضمين ملف في آخر باستخدام include كما يلي: include 'my-file.php'; وبهذا تكون الشفرة ضمن الملف my-file.php متاحة ضمن مجال الرؤية، إذا لم يكن بالإمكان تضمين الملف (على سبيل المثال إذا كان الملف غير موجود ) يظهر تنبيه. include_once 'my-file.php'; إذا كانت شفرة الملف my-file.php متضمنة في مكان أخر ، لن يتم تضمينها ثانية. وهذا يمنع الاخطاء التي تحدث بسبب تكرار التصريح عن الصفوف require 'my-file.php'; require_once 'my-file.php'; تقوم الدالة ()require بنفس عمل ()include إلا أنها ستتسبب بخطأ فادح إذا لم يتمكن من تضمين الملف. محتويات ملف my-include.php <?php return 'Anything you like.'; يمكن الدوال Includes، requires أيضًا أن تعيد قيمة $value = include 'my-include.php'; تضمن الملفات بالاعتماد على المسار المعطى، وإذا لم يحدد المسار يتم اعتماد مسار توجيه الاعداد include_path فإذا لم يتم إيجاد الملف يتم البحث في مسار استدعاء السكريبت ومسار العمل الحالي قبل الاعلان عن الاخفاق الأصناف Classes في PHP الأصناف classes في البرمجة هي أنماط بيانات خاصة تستخدم كقوالب لإنشاء الكائنات objects وتعرف الأصناف في PHP باستخدام العبارة class class MyClass { const MY_CONST = 'value'; // ثابت static $staticVar = 'static'; المتغيرات الثابتة Static ومجال رؤيتها public static $publicStaticVar = 'publicStatic'; يمكن الوصول إليها خلال الصنف فقط private static $privateStaticVar = 'privateStatic'; يمكن الوصول اليها من خلال الصنف والأصناف المشتقة protected static $protectedStaticVar = 'protectedStatic'; يجب تحديد مجال الرؤية للخصائص Properties public $property = 'public'; public $instanceProp; protected $prot = 'protected'; يمكن الوصول إليها من الصنف والأصناف الفرعية private $priv = 'private'; // يمكن الوصول إليها من الصنف فقط قم بإنشاء الباني باستخدام __construct public function __construct($instanceProp) { // $this قم بالوصول إلى متغيرات الحالة باستخدام $this->instanceProp = $instanceProp; } تعرًف الطرق methods كدوال داخل الصنف public function myMethod() { print 'MyClass'; } تجعل الكلمة المفتاحية final الدالة غير قابلة للتحميل الزائد unoverridable final function youCannotOverrideMe() { } الطرق السحرية Magic Methods الطرق السحرية في PHP هي طرق أو وظائف خاصة يبدأ اسمها بشرطة سفلية مزدوجة تسمح لك بإضافة وظائف إلى الأصناف دون الحاجة لتعريف هذه الدوال بشكل صريح. على سبيل المثال الدالة toString__ هي دالة سحرية تستدعى تلقائيًا عند استخدام عمليات أو وظائف معينة تتطلب تحويل الكائن إلى سلسلة نصية public function __toString() { return $property; } ومن الدوال السجرية لدينا دالة الهدم ()destruct__ وهي عكس دالة البناء()construct__ وتستدعى عندما لا تعود هنالك حاجة لأن يكون العنصر مشارًا إليه كمرجع public function __destruct() { print "Destroying"; } الكلمة المفتاحية static في PHP تستخدم الكلمة المفتاحية static في PHP لتعريف خصائص الصنف والطرق على أنها ثابتة وهذا يجعلها قابله للوصول بدون الحاجة إلى إنشاء كائن من الصنف. الخاصية المعرّفة بأنها ثابتة لا يمكن الوصول إليها من العنصر المشتق من الصنف (لكن يمكن ذلك في الطرق الثابتة) public static function myStaticMethod() { print 'I am static'; } ثوابت الصنف Class constants يمكن الوصول إليها دائمًا بشكل ثابت echo MyClass::MY_CONST; // 'value' الخرج; echo MyClass::$staticVar; // 'static' الخرج; MyClass::myStaticMethod(); // 'I am static' الخرج; اشتقاق حالات الأصناف instance باستخدام new $my_class = new MyClass('An instance property'); استخدام القوسين اختياري إذا كنت لا تريد تمرير أيّة معطيات يمكننك الوصول إلى أعضاء الصنف class members باستخدام <- echo $my_class->property; // => "public" echo $my_class->instanceProp; // => "An instance property" $my_class->myMethod(); // => "MyClass" قم بتوسيع الصنف باستخدام extends class MyOtherClass extends MyClass { function printProtectedProperty() { echo $this->prot; } // التحميل الزائد للطرق Override function myMethod() { parent::myMethod(); print ' > MyOtherClass'; } } $my_other_class = new MyOtherClass('Instance prop'); $my_other_class->printProtectedProperty(); // => "protected" يطبع $my_other_class->myMethod(); // "MyClass > MyOtherClass" يطبع final class YouCannotExtendMe { } يمكنك استخدام الطرق السحرية magic methods لإنشاء دوال الجلب أو الإرجاع getters وداول الاسناد setters class MyMapClass { private $property; public function __get($key) { return $this->$key; } public function __set($key, $value) { $this->$key = $value; } } $x = new MyMapClass(); echo $x->property; // __get() سوف تستخدم طريقة $x->property = 'Something'; // __set() سوف تستخدم طريقة يمكن أن تكون الأصناف تجريدية (باستخدام الكلمة المفتاحية abstract) أو واجهات تنفيذ (باستخدام الكلمة المفتاحية implements). الواجهات Interfaces في لغة PHP الواجهات في PHP هي طريقة مجردة لتعريف الكائنات، ويصرح عن الواجهة بالكلمة المفتاحية interface. interface InterfaceOne { public function doSomething(); } interface InterfaceTwo { public function doSomethingElse(); } يمكن أن توسّع الواجهات interface InterfaceThree extends InterfaceTwo { public function doAnotherContract(); } abstract class MyAbstractClass implements InterfaceOne { public $x = 'doSomething'; } class MyConcreteClass extends MyAbstractClass implements InterfaceTwo { public function doSomething() { echo $x; } public function doSomethingElse() { echo 'doSomethingElse'; } } يمكن أن يكون للأصناف أكثر من واجهة واحدة class SomeOtherClass implements InterfaceOne, InterfaceTwo { public function doSomething() { echo 'doSomething'; } public function doSomethingElse() { echo 'doSomethingElse'; } } السمات Traits trait هي ميزة تستخدم للسماح بإعادة استخدام مجموعة من الوظائف داخل الأصناف ويمكنك اعتبارها بمثابة طريقة لتضمين سلوك مشترك بين الأصناف وهي ميزة متوفره بدءًا من النسخة PHP 5.4.0 ويصرّح عنها باستخدام trait trait MyTrait { public function myTraitMethod() { print 'I have MyTrait'; } } class MyTraitfulClass { use MyTrait; } $cls = new MyTraitfulClass(); $cls->myTraitMethod(); // Prints "I have MyTrait" فضاءات الأسماء Namespaces في PHP تستخدم فضاءات الأسماء في PHP لتنظيم الشيفرة وتجنب تعارض أسماء الأصناف والوظائف والمتغيرات فهي تجمع العناصر ضمن في مجموعات أو مساحات لها نفس الاسم لتميزها عن غيرها وللقيام بذلك نكتب namespace كأول عبارة في الملف. دعونا نتظاهر بأن هذا ليس هو الحال <?php افتراضيًا, توجد الأصناف في namespace عام, ويمكن أن تستدعى صراحة بـ backslash $cls = new \MyClass(); ضبط namespace لملف namespace My\Namespace; class MyClass { } من ملف آخر $cls = new My\Namespace\MyClass; أو من داخل namespace آخر namespace My\Other\Namespace; use My\Namespace\MyClass; $cls = new MyClass(); أو يمكنك استبدال namespace باسم مستعار namespace My\Other\Namespace; use My\Namespace as SomeOtherNamespace; $cls = new SomeOtherNamespace\MyClass(); الربط الساكن المتأخر Late Static Binding class ParentClass { public static function who() { echo "I'm a " . __CLASS__ . "\n"; } public static function test() { // على الصف الذي عُرّف التابع ضمنه self تؤشر self::who(); // على الصف الذي استدعي التابع منه static تؤشر static::who(); } } ParentClass::test(); /* ParentClass أنا ParentClass أنا */ class ChildClass extends ParentClass { public static function who() { echo "But I'm " . __CLASS__ . "\n"; } } ChildClass::test(); /* ParentClass أنا ChildClass ولكن أنا */ الثوابت السحرية Magic constants الثوابت السحرية هي ثوابت معرفة مسبقًا في PHP يبدأ اسمها وينتهي بشرطتين سفليتين ولها استخداماات مختلفة، على سبيل المثال للحصول على اسم الصنف الحالي نستخدم الثابت السحري __CLASS__ داخل تصريح الصنف كما يلي: echo "Current class name is " . __CLASS__; وللحصول على مسار الدليل الكامل لملف نستخدم __DIR__ echo "Current directory is " . __DIR__; الاستخدام النموذجي require __DIR__ . '/vendor/autoload.php'; الحصول على المسار الكامل للملف echo "Current file path is " . __FILE__; الحصول على اسم الدالة الحالية echo "Current function name is " . __FUNCTION__; الحصول على رقم السطر الحالي echo "Current line number is " . __LINE__; الحصول على اسم الطريقة الحالية. يرجع قيمة فقط عندما يستخدم داخل تصريح سمة أو كائن echo "Current method is " . __METHOD__; الحصول على اسم namespace الحالي echo "Current namespace is " . __NAMESPACE__; الحصول على اسم السمة الحالية. ترجع قيمة فقط عندما تستخدم داخل التصريح عن السمة أو الكائن. echo "Current trait is " . __TRAIT__; معالجة الأخطاء Error Handling في PHP يمكن أن تتم معالجة أخطاء بسيطة باستخدام كتلة try catch try { // افعل شيء ما } catch (Exception $e) { // معالجة استثناء } عند استخدام كتلة try catch في بيئة namespace استخدم التالي try { // افعل شيء ما } catch (\Exception $e) { // معالجة استثناء } استثناءات مخصّصة class MyException extends Exception {} try { $condition = true; if ($condition) { throw new MyException('Something just happened'); } } catch (MyException $e) { // معالجة استثنائية } ترجمة -وبتصرّف- للمقال Learn PHP in Y Minutes
  21. كوتلن (Kotlin) هي لغة برمجة مخصّصة لمنصّة جافا الافتراضية (Java Virtual Machine أو اختصارًا JVM)، الأندرويد، والمتّصفح. تنتمي للغات statically typed (التي تفحص الأنواع وقت الترجمة). وهي متوافقة مع جافا 100%. // (//)التعليقات على سطر واحد تبدأ بـ/* التعليقات المؤلفة من عدة أسطر تبدو كهذه */ تعمل الكلمة المفتاحية package بنفس طريقة جافا package com.learnxinyminutes.kotlin نقطة الإدخال لبرامج Kotlin هي دالة(تابع) تسمى main ،يمرر التّابع مصفوفة تحتوي على وسطاء arguments لسطر الأوامر. fun main(args: Array<String>) { التّصريح عن القيم يتم باستخدام إما var أو val ،تصريح val لا يمكن إعادة تعيينه، في حين يمكن ذلك في var val fooVal =10 لا يمكننا لاحقًا إعادة تعيين قيمة fooVal لقيمة أخرى. var fooVar =10 fooVar =20 من الممكن إعادة تعيين قيمة fooVar. في أغلب الحالات، يمكن لكوتلن أن تحدّد ما هو نوع المتغير، لذلك لا داعي لتحديده صراحة في كل مرّة. يمكننا أن نصرّح بنوع المتغير بوضوح كالتالي: val foo:Int=7 يمكن تمثيل السلاسل بطريقة مماثلة في java. يتم الهروب باستخدام backslash. val fooString ="My String Is Here!" val barString ="Printing on a new line?\nNo Problem!" val bazString ="Do you want to add a tab?\tNo Problem!" println(fooString) println(barString) println(bazString) تُحدد السلسلة الخام string raw باستخدام triple quote ("""). ويمكن أن تحتوي أسطر جديدة و أية محارف أخرى. val fooRawString =""" fun helloWorld(val name :String){ println("Hello, world!")}""" println(fooRawString) السلاسل ممكن أن تحتوي تعابير القالب template expressions. تبدأ تعابير القالب بالرمز $. val fooTemplateString ="$fooString has ${fooString.length} characters" println(fooTemplateString)// => My String Is Here! has 18 characters من أجل المتغيرات التي تحوي قيمة فارغة null يجب تحديد ذلك صراحة nullable. يمكن تحديد المتغير قابلاً للقيمة null بإلحاق? بنوعه. ويمكننا الوصول إلى المتحولات القابلة لـ null باستخدام مُعامل التشغيل? ،ويمكننا استخدام عامل التشغيل :? لتحديد قيمة بديلة للاستخدام إذا كان المتغير فارغ null. var fooNullable:String?="abc" println(fooNullable?.length)// => 3 println(fooNullable?.length ?:-1)// => 3 fooNullable = null println(fooNullable?.length)// => null println(fooNullable?.length ?:-1)// => -1 يمكن التصريح عن الدوال باستخدام الكلمة المفتاحية fun. وتحدد وسطاء الدالة بين قوسين بعد اسم الدالة. ويمكن لوسطاء الدالة اختياريًا الاحتواء على قيمة افتراضية. ويحدّد نوع إرجاع الدالة، إذا لزم الامر بعد المعطيات. fun hello(name:String="world"):String{return"Hello, $name!"} println(hello("foo"))// => Hello, foo! println(hello(name ="bar"))// => Hello, bar! println(hello())// => Hello, world! يمكن لبارامتر الدالة أن يوسم بالكلمة المفتاحية vararg للسماح بتمرير عدد متغير من المعطيات إلى الدالة. fun varargExample(vararg names:Int){ println("Argument has ${names.size} elements")} varargExample()// => لا يحوي الوسيط أية عناصر varargExample(1)// => يحوي الوسيط عنصر واحد varargExample(1,2,3)// => يحوي الوسيط 3 عناصر عندما تتكوّن الدّالة من تعبير واحد فقط، يمكن حذف الأقواس المنحنية { } ويتم تحديد الجسم(العملية) بعد رمز = fun odd(x:Int):Boolean= x %2==1 println(odd(6))// => false println(odd(7))// => true إذا كان نوع الاسترجاع يمكن استنتاجه فلسنا بحاجة لتحديده. fun even(x:Int)= x %2==0 println(even(6))// => true println(even(7))// => false الدوال يمكن أن تأخذ دوال كوسطاء وترجع دالة. fun not(f:(Int)->Boolean):(Int)->Boolean{return{n ->!f.invoke(n)}} يمكن للدوال المسمّاة أن تحدّد كوسائط باستخدام معامل التشغيل val notOdd = not(::odd) val notEven = not(::even) يمكن تحديد تعابير Lambda كوسائط val notZero = not {n -> n ==0} إذا احتوت lambda على بارامتر واحد فقط يمكن حذف التصريح عنه (جنبًا إلى جنب مع<- )وسيكون اسم البارامتر الوحيد it. val notPositive = not {it >0}for(i in 0..4){ println("${notOdd(i)} ${notEven(i)} ${notZero(i)} ${notPositive(i)}")} تستخدم الكلمة المفتاحية class للتّصريح عن الأصناف. class ExampleClass(val x:Int){ fun memberFunction(y:Int):Int{return x + y } infix fun infixMemberFunction(y:Int):Int{return x * y }} لإنشاء حالة instance جديدة نستدعي الباني. ولاحظ أن Kotlin لا تحوي الكلمة المفتاحية new. val fooExampleClass =ExampleClass(7) يمكن استدعاء دوال المستخدم باستخدام التنويت النقطي . println(fooExampleClass.memberFunction(4))// => 11 إذا وُسمت الدالة بالكلمة المفتاحية infix يمكن عندها أن يستدعى باستخدام التنويت الداخلي println(fooExampleClass infixMemberFunction 4)// => 28 أصناف البيانات Data classes هي طريقة مختصرة لإنشاء الأصناف التي تحتوي بيانات فقط وتنشئ دوال hashCode،equals و toString تلقائيًا. data classDataClassExample(val x:Int, val y:Int, val z:Int) val fooData =DataClassExample(1,2,4) println(fooData)// => DataClassExample(x=1, y=2, z=4) أصناف البيانات لديها دالة copy val fooCopy = fooData.copy(y =100) println(fooCopy)// => DataClassExample(x=1, y=100, z=4) يمكن أن تفكَك الكائنات Objects في متغيرات متعددة val (a, b, c)= fooCopy println("$a $b $c")// => 1 100 4 التفكيك باستخدام حلقة for for((a, b, c) in listOf(fooData)){ println("$a $b $c")// => 1 100 4} val mapData = mapOf("a" to 1,"b" to 2) Map.Entry قابل للتفكيك كذلك for((key, value) in mapData){ println("$key -> $value")} الدالة with مشابهة لعبارة with في جافا data classMutableDataClassExample(var x:Int, var y:Int, var z:Int) val fooMutableData =MutableDataClassExample(7,4,9) with (fooMutableData){ x -=2 y +=2 z--} println(fooMutableData)// => MutableDataClassExample(x=5, y=6, z=8) يمكننا إنشاء قائمة (لائحة) باستخدام الدالة listOf. ستكون القائمة غير قابلة للتغيير ولا يمكن إضافة عناصر أو إزالتها. val fooList = listOf("a","b","c") println(fooList.size)// => 3 println(fooList.first())// => a println(fooList.last())// => c// index يمكن الوصول إلى عناصر القائمة من خلال فهرسها println(fooList[1])// => b يمكن إنشاء قائمة قابلة للتعديل باستخدام الدالة mutableListOf val fooMutableList = mutableListOf("a","b","c") fooMutableList.add("d") println(fooMutableList.last())// => d println(fooMutableList.size)// => 4 يمكن إنشاء تعيين set باستخدام الدّالة setOf val fooSet = setOf("a","b","c") println(fooSet.contains("a"))// => true println(fooSet.contains("z"))// => false يمكننا إنشاء خريطة map باستخدام الدّالة mapOf val fooMap = mapOf("a" to 8,"b" to 7,"c" to 9) يمكن الوصول لقيم الـ Map من خلال مفاتيحها println(fooMap["a"])// => 8 تُمثل المتتالية Sequences مجموعات تقييمها مؤجل إلى حين الحاجة lazily-evaluated collections. ويمكننا إنشاء متتالية باستخدام الدّالة generateSequence. val fooSequence = generateSequence(1,{ it +1}) val x = fooSequence.take(10).toList() println(x)// => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] مثال لاستخدام متتالية لتوليد أرقام فيبانوتشي fibonacci fun fibonacciSequence():Sequence<Long>{ var a =0L var b =1L fun next():Long{ val result = a + b a = b b = result return a }return generateSequence(::next)} val y = fibonacciSequence().take(10).toList() println(y)// => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] تزوّد Kotlin دوال عالية الرتبة للعمل مع المجموعات collections val z =(1..9).map{it *3}.filter {it <20}.groupBy {it %2==0}.mapKeys {if(it.key)"even"else"odd"} println(z)// => {odd=[3, 9, 15], even=[6, 12, 18]} يمكن استخدام حلقة for مع أي شيء يؤمن التكرار. for(c in "hello"){ println(c)} تعمل حلقات while بشكل مشابه لعملها في اللغات الأخرى var ctr =0while(ctr <5){ println(ctr) ctr++}do{ println(ctr) ctr++}while(ctr <10) يمكن استخدام if كتعبير يرجع القيم. لهذا السبب ليس هناك حاجة لمعامل التشغيل :? في Kotlin. val num =5 val message =if(num %2==0)"even"else"odd" println("$num is $message")// => 5 is odd يمكن استخدام when كبديل لسلاسل if-else if val i =10 when { i <7-> println("first block") fooString.startsWith("hello")-> println("second block")else-> println("else block")} يمكن استخدام when مع المعطيات. when (i){0,21-> println("0 or 21") in 1..20-> println("in the range 1 to 20")else-> println("none of the above")} يمكن استخدام when كدالة ترجع القيم. var result = when (i){0,21->"0 or 21" in 1..20->"in the range 1 to 20"else->"none of the above"} println(result) يمكننا التحقق فيما إذا كان الكائن object من نوع محدّد باستخدام معامل التشغيل is. إذا مرر الكائن فحص النوع type check عندها يمكن استخدام هذا النوع دون الموائمة بشكل صريح. fun smartCastExample(x:Any):Boolean{if(x is Boolean){ X توائم أوتوماتيكيًا إلى Boolean return x }elseif(x is Int){ X توائم أوتوماتيكيًا إلى Int return x >0}elseif(x is String){ X توائم أوتوماتيكيًا إلى String return x.isNotEmpty()}else{returnfalse}} println(smartCastExample("Hello, world!"))// => true println(smartCastExample(""))// => false println(smartCastExample(5))// => true println(smartCastExample(0))// => false println(smartCastExample(true))// => true تعمل الموائمة الذكيّة smartcast أيضًا مع كتلة when fun smartCastWhenExample(x:Any)= when (x){ is Boolean-> x is Int-> x >0 is String-> x.isNotEmpty()else->false} الملحقات Extensions هي طريقة لإضافة وظائف جديدة للصنف class. وهي مشابهة لدوال ملحقات #C fun String.remove(c:Char):String{returnthis.filter {it != c}} println("Hello, world!".remove('l'))// => Hello, word! println(EnumExample.A)// => A println(ObjectExample.hello())// => hello أصناف Enum مشابهة لأنواع enum في جافا. enumclassEnumExample{ A, B, C } يمكن استخدام الكلمة المفتاحية object لإنشاء كائنات وحيدة. لا يمكننا تمثيلها ولكن يمكن أن نشير لحالتها الفريدة من خلال اسمها. وهذا مشابه لكائنات Scala singleton object ObjectExample{ fun hello():String{return"hello"}} fun useObject(){ObjectExample.hello() val someRef:Any=ObjectExample//كماهي تمامًا objects نستخدم أسماء الكائنات } ترجمة -وبتصرّف- للمقال Learn kotlin in Y Minutes
  22. جافا هي لغة برمجة حاسوبية للأغراض العامة، المتزامنة، المعتمدة على الصفوف، وغرضية التوجه // يبدأ التعليق المكتوب على خط واحد ب .// /* يبدو التعليق المكتوب على عدة سطور بهذا الشكل. */ /** *تبدو التعليقات في ملفات لغة البرمجة جافا بهذا الشكل *و تستخدم لوصف الصف أو الصفات المختلفة لكائن معين. *:الصفات الرئيسية * *@author- اسم مؤلف الكود. *ويحتوي على معلومات الاتصال كالبريد الالكتروني لمؤلف الكود أو للمؤلفين. *@version- النسخة الحالية من البرنامج. *@since -الوقت الذي تم فيه إضافة هذا الجزء من البرنامج. *@param -من أجل وصف البارامترات المختلفة للمنهج (method). *@return -لوصف القيمة التي يرجعها المنهج. *@deprecated -لإظهار انتهاء صلاحية الكود أو عدم وجوب استخدامه. *@see - روابط إلى جزء آخر من المستندات */ استورد الصف ArrayList بدلاً من استيراد الرزمة java.util كلّها import java.util.ArrayList; استورد جميع الصفوف الموجود داخل الرزمة import java.security.*; يحوي أي ملف جافا على صف عام، على المستوى الخارجي، له نفس اسم الملف public class LearnJava { ليعمل برنامج جافا يجب أن يحوي على تابع رئيسي بمثابة نقطة البدء public static void main(String[] args) { الدخل/الخرج دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن الخرج استخدم ()System.out.println لطباعة السطور النصيّة System.out.println("Hello World!"); System.out.println( "Integer: " + 10 + " Double: " + 3.14 + " Boolean: " + true); استخدم ()System.out.print للطباعة بدون سطر جديد System.out.print("Hello "); System.out.print("World"); استخدم ()System.out.printf لتنسيق الطباعة بسهولة System.out.printf("pi = %.5f", Math.PI); // => pi = 3.14159 الدخل استخدم scanner لقراءة الدخل، يجب استيراد الصف ;java.util.Scanner Scanner scanner = new Scanner(System.in); لقراءة السلاسل المحرفية المُدخلة String name = scanner.next(); لقراءة البايتات المُدخلة byte numByte = scanner.nextByte(); لقراءة العدد الصحيح المُدخل int numInt = scanner.nextInt(); لقراءة العدد الحقيقي المٌدخل float numFloat = scanner.nextFloat(); لقراءة العدد الحقيقي مضاعف الدقة المُدخل double numDouble = scanner.nextDouble(); لقراءة القيمة المنطقية المُدخلة boolean bool = scanner.nextBoolean(); المتغيرات التصريح عن المتغيرات يتم التصريح عن متغير باستخدام // <type> <name> int fooInt; يتم التصريح عن مجموعة من المتغيرات من نفس النوع // <type> <name1>, <name2>, <name3> int fooInt1, fooInt2, fooInt3; تهيئة المتغير يتم تهيئة متغير باستخدام // <type> <name> = <val> int barInt = 1; يتم تهيئة مجموعة من المتغيرات من نفس النوع بنفس القيمة باستخدام // <type> <name1>, <name2>, <name3> // <name1> = <name2> = <name3> = <val> int barInt1, barInt2, barInt3; barInt1 = barInt2 = barInt3 = 1; أنواع المتغير البايت (Byte) : وهو 8bit ويستخدم لترميز الأعداد الصحيحة بين -128 و 127 byte fooByte = 100; إذ كنت ترغب بتفسير البايت كعدد صحيح موجب (بدون إشارة). فإن هذه العملية البسيطة من الممكن أن تساعد int unsignedIntLessThan256 = 0xff & fooByte; هذا يناقض عمل cast الذي من الممكن أن يعطي عدد سالب int signedInt = (int) fooByte; القصير (Short): وهو 16bit ويستخدم لترميز الأعداد الصحيحة بين -32,768 و 32,767 short fooShort = 10000; الصحيح (Integer): وهو 32bit ويستخدم لترميز الأعداد الصحيحة بين -2,147,483,648 و 2,147,483,647 int bazInt = 1; الطويل (Long): وهو 64bit ويستخدم لترميز الأعداد الصحيحة بين -9,223,372,036,854,775,808 و 9,223,372,036,854,775,807 long fooLong = 100000L; يستخدم المحرف L للدلالة على أن قيمة المتحول هي من النوع Long. و أي قيمة مُسندة للمتحول بدون استخدام L هي عبارة عن عدد صحيح int بشكل افتراضي. ملاحظة: إن الأنواع byte، short، int، long، هي أنواع ذات إشارة signed. أي من الممكن أن تحوي على قيم موجبة أو قيم سالبة. لا يوجد متغيرات بقيمة موجبة فحسب. ولكن المحارف تعتبر من نوعية unsigned ذات القيمة الموجبة فقط ذات 16bit. العائم (Float): وهو ذو دقة أحادية 32 bit IEEE 754 ويستخدم لترميز الأعداد الحقيقية ذات الفاصلة العائمة بين 149-^2 و 127^2 - (23-^2-2) float fooFloat = 234.5f; يستخدم المحرف f أو F للدلالة على أن قيمة المتحول هي من النوع Float. و إلا سيعتبر المتغير من النوع الحقيقي المضاعف. المضاعف (Double): وهو ذو دقة مضاعفة 64 bit IEEE 754 ويستخدم لترميز الأعداد الحقيقية ذات الفاصلة العائمة بين 1074-^2 و 1023^2 - (52-^2-2) double fooDouble = 123.4; القيم المنطقية (Boolean) ذات القيمة: true و false boolean fooBoolean = true; boolean barBoolean = false; Char هو محرف يونيكود 16بت أحادي char fooChar = 'A'; لا يمكن أعادة تهيئة المعطيات من النوع final final int HOURS_I_WORK_PER_WEEK = 9001; ولكن من الممكن تهيئتها بعد عملية التصريح عنها final double E; E = 2.71828; BigInteger -عبارة عن نوع الأعداد الصحيحة الثابتة بمستويات دقّة مختلفة. يستخدم نوع المعطيات BigInteger للسماح للمبرمج بالتعامل مع الأعداد الصحيحة التي هي أكبر من 64-بت. حيث تُخزّن الأعداد الصحيحة في مصفوفة من البايتات، التي يمكن التلاعب بها باستخدام التوابع المبنيّة في الصف BigInteger . يمكن تهيئة المتغير من النوع BigInteger بمصفوفة من البايتات أو بمصفوفة من السلاسل المحرفية. BigInteger fooBigInteger = new BigInteger(fooByteArray); BigDecimal عبارة عن نوع الأعداد الحقيقية الثابتة بمستويات دقة مختلفة. ويأخذ المتغير من النوع BigDecimal معاملين: عدد صحيح ذو حجم غير مقّيّد، يمثل مستوى الدقّة، وعدد صحيح أخر بحجم 32 بت. يسمح النوع BigDecimal بالتحكم بتقريب الأعداد الحقيقية. عندما يكون مطلوب مستوى دقة محدد للعدد الحقيقي يُنصح باستخدام BigDecimal . من الممكن تهيئة المتغير من النوع BigDecimal بأحد الأنواع التالية: int ،long ،double ،String ،BigInteger BigDecimal fooBigDecimal = new BigDecimal(fooBigInteger, fooInt); كُن حذرًا عند استخدامك للأنواع float ,double لأن عدم الدقّة في تحديد النوع سوف تُنسخ في الـ BigDecimal ويُفضل استخدام سلسلة محرفية ثابتة عندما تحتاج إلى قيمة دقيقة. BigDecimal tenCents = new BigDecimal("0.1"); String -السلاسل المحرفية String fooString = "My String Is Here!"; الحرف الخاص n\ يُعرف بحرف السطر الجديد الذي يحرك مؤشر الكتابة إلى بداية السطر التالي. String barString = "Printing on a new line?\nNo Problem!"; الحرف الخاص t\ يُعرف بالمسافة الأفقية، يقوم بتحريك مؤشر الكتابة مسافة معينة إلى النقطة التالية في السطر. String bazString = "Do you want to add a tab?\tNo Problem!"; System.out.println(fooString); System.out.println(barString); System.out.println(bazString); بناء السلاسل المحرفية: باستخدام عامل الجمع (+) تُعتبر الطريقة الأساسية (الأمثل) للقيام ببناء السلاسل المحرفية. String plusConcatenated = "Strings can " + "be concatenated " + “via + operator.”; System.out.println(plusConcatenated); // Output: Strings can be concatenated via + operator. باستخدام الصف StringBuilder لا تشكل هذه الطريقة أية سلاسل محرفية وسيطة، فقط تقوم بتخزين قطع السلاسل المحرفية و ربطها مع بعضها عندما يتم استدعاء التابع ()toString. تلميح: لا يعتبر الصف StringBuilder إجرائية آمنة. يوجد صف بديل آمن StringBuffer (مع تأثير بسيط على الأداء). StringBuilder builderConcatenated = new StringBuilder(); builderConcatenated.append("You "); builderConcatenated.append("can use "); builderConcatenated.append("the StringBuilder class."); System.out.println(builderConcatenated.toString()); // فقط الآن تمّ بناء السلسة المحرفية // Output: You can use the StringBuilder class. تكون StringBuilder فعاله عندما السلسلة المحرفية الكاملة المبنيّة مطلوبة في نهاية عملية ما. StringBuilder stringBuilder = new StringBuilder(); String inefficientString = ""; for (int i = 0 ; i < 10; i++) { stringBuilder.append(i).append(" "); inefficientString += i + " "; } System.out.println(inefficientString); System.out.println(stringBuilder.toString()); تتطلب inefficientString عمل أكثر، حيث أنها تنتج سلسلة محرفية عند كل دورة للحلقة. يتم ترجمة تجميع السلاسل المحرفية البسيطة بالعامل (+) إلى: toString() و StringBuilder تجنب استخدام تجميع السلاسل المحرفية داخل الحلقات. لاستخدام منسق السلاسل المحرفية طريقة أخرى بديلة لتوليد السلاسل المحرفية سريعة و قابلة للقراءة. String.format("%s may prefer %s.", “Or you”, “String.format()”); // Output: Or you may prefer String.format(). المصفوفات يجب تحديد حجم المصفوفة بشكل فوري بمجرد التصريح عنها. تستخدم الصيغة التالية للتصريح عن مصفوفة. // <datatype>[] <var name> = new <datatype>[<array size>]; // <datatype> <var name>[] = new <datatype>[<array size>]; int[] intArray = new int[10]; String[] stringArray = new String[1]; boolean boolArray[] = new boolean[100]; طريقة أخرى للتصريح عن مصفوفة و تهيئتها int[] y = {9000, 1000, 1337}; String names[] = {"Bob", "John", "Fred", "Juan Pedro"}; boolean bools[] = {true, false, false}; فهرسة المصفوفة - الوصول إلى عنصر فيها System.out.println("intArray @ 0: " + intArray[0]); تبدأ المصفوفات بالفهرس (0)، و هي قابله للتغيير . intArray[1] = 1; System.out.println("intArray @ 1: " + intArray[1]) ArrayLists; // => 1 مجموعة من أنواع المعطيات الأخرى، التي تستحق التدقيق فيها: ArrayLists : مشابهة للمصفوفات، إلا أنها تحوي على وظائف إضافية، وحجمها قابل للتعديل. LinkedLists : عبارة عن تنفيذ لقائمة مترابطة بشكل مضاعف، التي تنفذ جميع العمليات التي من المتوقع لقائمة مترابطة بشكل مضاعف أن تنفذها. Maps : عبارة عن وصل كائنات المفتاح إلى كائنات القيمة. وهي عبارة عن واجهة، و بالتالي لا يمكن أن يتم تشكيل كائنات منها. يجب أن يتم تحديد نوع المفاتيح و القيم بناءً على الكائن المُشكل من الصف. من الممكن ان يُربط كل مفتاح إلى قيمة واحدة فقط، ومن الممكن أن يظهر كل مفتاح مرة واحدة فقط. (لا يوجد نسخ) لتنفيذ الخريطة/الواجهة Map hashtable : يُستخدم هذا الصف الجدول ، HashMaps وينفذ الخريطة Map ، هذا يسمح بتثبيت زمن العمليات الأساسية، مثل الحصول على عنصر أو إدخال عنصر، حتى في المجموعات الكبيرة. TreeMap: عبارة عن Map ، مصنفة حسب مفاتيحها. يُحافظ كل تعديل على ترتيبه، إما باستخدام المقارن المزود عند عملية توليد الكائن، أو باستخدام المقارنات لكل كائن، اذا كان ينفذ واجهة قابلة للمقارنة. سوف يؤدي الفشل المدمج في تنفيذ واجهة قابلة للمقارنة، مع الفشل في تزويد مقارن إلى رمي ClassCastExceptions تأخذ عمليات إدخال و حذف عناصر زمن من الدرجة ((O(log(n ، لذلك تجنب استخدام بنى المعطيات هذه، إلا أذا كنت ترغب من الاستفادة من ميزة الترتيب. العمليات System.out.println("\n->Operators"); int i1 = 1, i2 = 2; // الطريقة المختصرة للتصريح عن عدة متغيرات في نفس الوقت العمليات الحسابية بسيطة System.out.println("1+2 = " + (i1 + i2)); // => 3 System.out.println("2-1 = " + (i2 - i1)); // => 1 System.out.println("2*1 = " + (i2 * i1)); // => 2 System.out.println("1/2 = " + (i1 / i2)); // => 0 (int يعيد int/int) System.out.println("1/2.0 = " + (i1 / (double)i2)); // => 0.5 باقي القسمة System.out.println("11%3 = "+(11 % 3)); // => 2 عمليات المقارنة System.out.println("3 == 2? " + (3 == 2)); // => false System.out.println("3 != 2? " + (3 != 2)); // => true System.out.println("3 > 2? " + (3 > 2)); // => true System.out.println("3 < 2? " + (3 < 2)); // => false System.out.println("2 <= 2? " + (2 <= 2)); // => true System.out.println("2 >= 2? " + (2 >= 2)); // => true العمليات المنطقية System.out.println("3 > 2 && 2 > 3? " + ((3 > 2) && (2 > 3))); // => false System.out.println("3 > 2 || 2 > 3? " + ((3 > 2) || (2 > 3))); // => true System.out.println("!(3 == 2)? " + (!(3 == 2))); // => true العمليات على مستوى البت ~ عامل إيجاد المتمم على مستولى البتات. << عامل الإزاحة الحسابية نحو اليسار (مع الأخذ بعين الاعتبار بت الإشارة). >> عامل الإزاحة الحسابية نحو اليمين (مع الأخذ بعين الاعتبار بت الإشارة). >>> عامل الإزاحة المنطقية نحو اليمين (بدون الأخذ بعين الاعتبار بت الإشارة). & على مستوى البتّات and العملية المنطقية ^ على مستوى البتّات xor العملية المنطقية | على مستوى البتّات or العملية المنطقية عمليات الزيادة int i = 0; System.out.println("\n->Inc/Dec-rementation"); العامل ++ يقوم بالزيادة بمقدار واحد. العامل – يقوم بالإنقاص بمقدار واحد. إذا تم وضع هذين العاملين قبل المتغير، فإنهن يقومان بالزيادة أو الإنقاص، ومن ثم يعيدان قيمة المتحول الجديدة. أما إذا تم وضع هذين العاملين بعد المتغير، فإنهما يقومان بإعادة قيمة المتحول، ومن ثم يقومان بالزيادة أو الإنقاص. System.out.println(i++); // i = 1, يطبع 0 (زياده لاحقة). System.out.println(++i); // i = 2, يطبع 2 (زيادة سابقة). System.out.println(i--); // i = 1, يطبع 2 (إنقاص لاحق) System.out.println(--i); // i = 0, يطبع 0 (إنقاص سابق) بنى التحكم System.out.println("\n->Control Structures"); عبارة if مشابهة لتلك الموجودة في لغة البرمجة C int j = 10; if (j == 10) { System.out.println("I get printed"); } else if (j > 10) { System.out.println("I don't"); } else { System.out.println("I also don't"); } حلقة While int fooWhile = 0; while(fooWhile < 100) { System.out.println(fooWhile); //زيادة العدّاد //(في المجال (0،1،..99 foowhile مكررة 100 مرة ، حيث أن قيم المتغير fooWhile++; } System.out.println("fooWhile Value: " + fooWhile); حلقة Do While int fooDoWhile = 0; do { System.out.println(fooDoWhile); //زيادة العدّاد //في المجال 0-99 foowhile مكررة 99 مرة ، حيث أن قيم المتغير fooDoWhile++; } while(fooDoWhile < 100); System.out.println("fooDoWhile Value: " + fooDoWhile); حلقة For : هيكلية الحلقة على الشكل التالي: for(<start_statement>; <conditional>; <step>) مثال for (int fooFor = 0; fooFor < 10; fooFor++) { System.out.println(fooFor); // fooFor 0->9 مكررة 10 مرات، حيث } System.out.println("fooFor Value: " + fooFor); //outerيتم الخروج من الحلقة الداخلية باستخدام جملة الهروب المعنونّة بـ outer: for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { if (i == 5 && j ==5) { break outer; //يخرج من الحلقة الخارجية أيضا، بدلاً من الخروج فقط من الحلقة الداخلية } } } حلقة For Each : قادرة على العمل مع المصفوفات و الكائنات for إن حلقة التي تنفذ الواجهات القابلة للتكرار. int[] fooList = {1, 2, 3, 4, 5, 6, 7, 8, 9}; هيكلية الحلقة على الشكل التالي: for (<object> : <iterable>) تقرأ هكذا: لكل عنصر في ال iterable ملاحظة: يجب أن يتطابق نوع الكائن مع نوع عناصر ال iterable for (int bar : fooList) { System.out.println(bar); //سوف تتكرر 9 مرات و يطبع 1-9 على سطور جديدة. } Switch تعمل Switch مع أنواع المعطيات: int، char، short ،byte وأيضًا من الممكن أن تعمل مع النوع Enum و String و مجموعة من الصفوف الخاصة التي تجمع الأنواع البدائية: Character, Byte, Short, Integer. بدءًا من جافا 7، من الممكن استخدام النوع String. ملاحظة: تذكر عدم استخدام التعليمة "break" في نهاية حالة جزئية إذا كان هناك يوجد حالة أخرى تستوفي الشرط أيضًا. int month = 3; String monthString; switch (month) { case 1: monthString = "January"; break; case 2: monthString = "February"; break; case 3: monthString = "March"; break; default: monthString = "Some other month"; break; } System.out.println("Switch Case Result: " + monthString); عبارة (Try-with-resources) في Java الإصدار +7 تُستخدم في جافا عبارات Try-catch-finally، و لكن في جافا +7 أيضا ً مُتاح استخدام try-with-resources إن عبارات try-with-resources تُبسط عمل عبارات try-catch-finally عن طريق إغلاق المصادر بشكل أتوماتيكي. لاستخدام try-with-resources ضمّن كائن من صف في تعليمة try. try (BufferedReader br = new BufferedReader(new FileReader("foo.txt"))) { // يمكنك أن تجرّب شيئًا يحتاج إلى استثناء System.out.println(br.readLine()); // في جافا 7 المصادر مغلقة دومًا حتى لو كان هناك استثناء } catch (Exception ex) { //catch سوف يتم إغلاق المصدر قبل أن تنفذ عبارة System.out.println("readLine() failed."); } في هذه الحالة، لا يوجد حاجة إلى عبارة finally حيث أن BufferedReader تم إغلاقه للتو. يتم استخدام هذا لتجنب الحالات الحرجة، عندما عبارة finally لا يمكن استدعاءها. الاختزال الشرطي يمكنك استخدام العامل "?" لسرعة الأسناد . تُقرأ كما يلي: "إذا كانت العبارة صحيحة ، استخدم <أول قيمة> و إلا استخدم <القيمة الثانية> int foo = 5; String bar = (foo < 10) ? "A" : "B"; System.out.println("bar : " + bar); // "bar : A"تطبع // صحيحة (foo < 10) لأن العبارة //أو بشكل مبسط: System.out.println("bar : " + (foo < 10 ? "A" : "B")); التحويل بين أنواع المعطيات تحويل المعطيات تحويل السلاسل المحرفية إلى عدد صحيح Integer.parseInt("123");//يعيد نسخة العدد الصحيح من السلسة المحرفية "123" تحويل العدد الصحيح إلى سلسلة محرفية Integer.toString(123);//يعيد النسخة المحرفية من العدد الصحيح 123 راجع تحويل المعطيات للأنواع التالية من الصفوف: Double Long String الصفوف و التوابع للتصريح عن كائن من الصف Bicycle استخدم الكلمة المفتاحية new Bicycle trek = new Bicycle(); استدعاء توابع الكائن trek.speedUp(3); // setter , getter يجب عليك استخدام توابع الواضع و الآخذ trek.setCadence(100); يُعيد التابع ()toString التمثيل النصي للكائن. System.out.println("trek info: " + trek.toString()); التهيئة مزدوجة الأقواس لا تملك جافا تراكيب لتشكيل مجموعات ساكنة من المعطيات بطريقة سهلة عادةً يتم استخدام الطريقة التالية: private static final Set<String> COUNTRIES = new HashSet<String>(); static { COUNTRIES.add("DENMARK"); COUNTRIES.add("SWEDEN"); COUNTRIES.add("FINLAND"); } ولكن يوجد طريقة أنيقة لإنجاز الشيء نفسه بشكل أسهل، تُدعى هذه الطريقة مزدوجة الأقواس private static final Set<String> COUNTRIES = new HashSet<String>() {{ add("DENMARK"); add("SWEDEN"); add("FINLAND"); }} يولد القوس الاول { } صف داخلي بدون اسم AnonymousInnerClass ويعرّف القوس الثاني{ } كتلة مهيئ الحالة instance. يتم استدعاء هذه الكتلة، عندما يتم توليد الصف الداخلي لا يعمل هذا فقط للمجموعات، إنما يعمل أيضًا لكل الصفوف غير النهائي non-final يمكنك تضمين صفوف أخرى خارجية غير عامة في ملف جافا ، ولكنها ليست بممارسة جيدة. بدلاً من ذلك يفضّل فصل الصفوف في ملفات جافا منفصلة صيغة التصريح عن صف: // <public/private/protected> class <class name> { // } حقول البيانات, أنماط الباني, الوظائف كلها في الداخل تستدعى الوظائف كالدوال في جافا class Bicycle { حقول و متغيرات الصف Bicycle Public: يمكن الوصول إليه من أي مكان public int cadence; Private: يمكن الوصول إليه فقط من داخل الصف private int speed; Protected: يمكن الوصول إليه فقط من داخل الصف و الصفوف الفرعية protected int gear; default: يمكن الوصول إليه فقط من داخل الرزمة. String name; Static متغير صف ساكن static String className; البلوك الساكن Static لا تملك جافا تنفيذ للبواني الساكنة، ولكن جافا تملك كتل برمجية لتعريف متغيرات الصف (المتغيرات لساكنة) سيتم استدعاء هذا البلوك عند تحميل الصف. static { className = "Bicycle"; } الباني هي الطريقة التي يتم فيها توليد الصفوف. هذا هو الباني public Bicycle() { //يمكنك أيضا استدعاء باني آخر: // this(1, 50, 5, "Bontrager"); gear = 1; cadence = 50; speed = 5; name = "Bontrager"; } هذا عبارة عن باني ذو معاملات public Bicycle(int startCadence, int startSpeed, int startGear, String name) { this.gear = startGear; this.cadence = startCadence; this.speed = startSpeed; this.name = name; } صيغة الدالة // <public/private/protected> <return type> <function name>(<args>) أصناف الجافا غالبًا ما تنفّذ getters وsetters في حقولها صيغة التصريح عن الدالة // <access modifier> <return type> <method name>(<args>) public int getCadence() { return cadence; } دوال void لا تحتاج تصريح عودة public void setCadence(int newValue) { cadence = newValue; } public void setGear(int newValue) { gear = newValue; } public void speedUp(int increment) { speed += increment; } public void slowDown(int decrement) { speed -= decrement; } public void setName(String newName) { name = newName; } public String getName() { return name; } دالة لتوليد قيم الصفات لهذا الكائن @Override // موروثة من الصف لهذا الكائن. public String toString() { return "gear: " + gear + " cadence: " + cadence + " speed: " + speed + " name: " + name; } الصف PennyFarthing عبارة عن صنف فرعي من Bicycle class PennyFarthing extends Bicycle { -Penny Farthings //هي عباره عن نوع من الدراجات بعجلات أمامية كبيرة. public PennyFarthing(int startCadence, int startSpeed) { // super استدعي الباني الأب باستخدام الكلمة المفتاحية super(startCadence, startSpeed, 0, "PennyFarthing"); } يجب عليك تعليم المنهج الذي تُعيد كتابته بـ annotation@. @Override public void setGear(int gear) { this.gear = 0; } Object casting بما أن الصف PennyFarthing يرث الصف Bicycle : فمن الممكن القول أن: Bicycle هو PennyFarthing، و يمكن أن نكتب: // Bicycle bicycle = new PennyFarthing(); هذا يُدعى"object casting" حيث يتم تشكيل كائن من كائن آخر. الواجهات صيغة التصريح عن واجهة // <access-level> interface <interface-name> extends <super-interfaces> { // // Constants // // Method declarations // } مثال - الطعام: public interface Edible { public void eat(); //يجب على أي صف ينفذ هذه الواجهة // ان ينفذ هذه الدالة } public interface Digestible { public void digest(); // منذ جافا 8، من الممكن أن تملك الواجهات دالة افتراضية. public default void defaultMethod() { System.out.println("Hi from default method ..."); } } الآن يمكنك تشكيل صف يُنفذ كلا من هاتين الواجهتين. public class Fruit implements Edible, Digestible { @Override public void eat() { // ... } @Override public void digest() { // ... } } في جافا، يمكنك أن تمدد(ترث) صف واحد فقط، ولكن يمكنك أن تنفذ عدّة واجهات . على سبيل المثال: public class ExampleClass extends ExampleClassParent implements InterfaceOne, InterfaceTwo { @Override public void InterfaceOneMethod() { } @Override public void InterfaceTwoMethod() { } } الصفوف التجريدية صيغة التصريح عن صف تجريدي: // <access-level> abstract class <abstract-class-name> extends // <super-abstract-classes> { // // Constants and variables // // Method declarations // } لا يمكن تشكيل كائنات من الصفوف المجردة (تمثيل الصفوف المجردة) يمكن للصفوف المجردة أن تعرف عن دوال مجرّدة. المناهج المجردة لا تحوي على جسم ويجب تعليمها بالكلمة المفتاحية abstract . يجب على الصفوف الأبناء غير المجردة أن تعيد كتابة Override@ جميع الدوال المجردة في صفوفها العليا. من الممكن أن تكون الصفوف المجرّدة مفيدة عند الجمع بين منطق التكرار و السلوك المخصص، ولكن بما أن الصف المجرد يتطلب الوراثة، فإن الصفوف المجردة تنتهك منطق "التركيب عبر الوراثة". لذلك خُذ بعين الاعتبار الطرق الأخرى التي تستخدم هذا التركيب public abstract class Animal { private int age; public abstract void makeSound(); من الممكن أن يحوي المنهج جسم public void eat() { System.out.println("I am an animal and I am Eating."); //(private)ملاحظة: من الممكن هنا الوصول للمتغيرات الخاصة age = 30; } public void printAge() { System.out.println(age); } يمكن أن تحوي الصفوف المجردة على دالة رئيسية public static void main(String[] args) { System.out.println("I am abstract"); } } class Dog extends Animal { لاحظ بأنه لا يزال هناك حاجة لإعادة كتابة الدوال التجريدية في الصف التجريدي // @Override public void makeSound() { System.out.println("Bark"); // age = 30; ==> ERROR! // Animal خاص بالنسبة للصف age خطأ- و ذلك لأن المتغير } ملاحظة: من الممكن أن تحصل على خطأ إذا قمت هنا باستخدام Override@ لأن جافا لا تسمح لك بإعادة كتابة الدوال الساكنة. ما يحدث هنا يُدعى إخفاء الدالة METHOD HIDING public static void main(String[] args) { Dog pluto = new Dog(); pluto.makeSound(); pluto.eat(); pluto.printAge(); } الصفوف النهائية final class صيغة التصريح عن الصفوف النهائية // <access-level> final <final-class-name> { // // Constants and variables // // Method declarations // } الصفوف النهائية هي عبارة عن الصفوف التي لا يمكن وراثتها، (أي هي الولد النهائي). بطريقة ما، تُعد الصفوف النهائية معاكس الصفوف المجردة. لأنه يجب توسيع (وراثة) الصفوف المجردة، أما الصفوف النهائية لا يمكن توسيعها. public final class SaberToothedCat extends Animal { لاحظ بأنه ما يزال يوجد حاجة لإعادة كتابة الدوال المجردة في الصف المجرد.// @Override public void makeSound() { System.out.println("Roar"); } } الدوال النهائية public abstract class Mammal() { // صيغة الدالة النهائية: // <access modifier> final <return type> <function name>(<args>) // لا يمكن إعادة كتابة الدوال النهائية بواسطة صف ابن، // وبالتالي الدالة النهائية هو أخر تنفيذ للدالة . public final boolean isWarmBlooded() { return true; } } النوع Enum еnum هي طريقة تنظيمية للثوابت (Constants) في الكود بحيث تجمع الثوابت التي لها علاقة ببعضها تحت فئة واحدة بطريقة تنظم الوصول إليها .بما أن هذه القيم هي عبارة عن ثوابت، لذلك فإن أسماء الحقول من النوع enum يجب أن تكتب بحروف كبيرة. في لغة جافا يتم تعريف هذا النوع باستخدام الكلمة المفتاحية enum. لتعريف متحول عن يوم من أيام الأسبوع، باستخدام النوع enum : public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY } من الممكن استخدام متغيرنا Day من النوع enum كما يلي: public class EnumTest { //Enumالمتغير من النوع Day day; public EnumTest(Day day) { this.day = day; } public void tellItLikeItIs() { switch (day) { case MONDAY: System.out.println("Mondays are bad."); break; case FRIDAY: System.out.println("Fridays are better."); break; case SATURDAY: case SUNDAY: System.out.println("Weekends are best."); break; default: System.out.println("Midweek days are so-so."); break; } } public static void main(String[] args) { EnumTest firstDay = new EnumTest(Day.MONDAY); firstDay.tellItLikeItIs(); // => Mondays are bad. EnumTest thirdDay = new EnumTest(Day.WEDNESDAY); thirdDay.tellItLikeItIs(); // => Midweek days are so-so. } } الأنواع enum هي فعالة بشكل أكبر مما تم توضيحه فوق. من الممكن أن يحتوي جسم المتغير enum على دوال و حقول أخرى. ترجمة -وبتصرّف- للمقال Learn Java in Y Minutes
  23. تُظهر هذ الإرشادات كيفية إنشاء تطبيقات JS/HTML Cordova ونشرها على منصّات موبايل أصليّة متنوعة باستخدام واجهة سطر أوامر كوردوفا (cordova (CLI, راجع CLI reference لتفاصيل مرجعية عن واجهة سطر أوامر Cordova. تثبيت Cordova CLI واجهة سطر أوامر Cordova موزّعة كحزمة npm (نظام إدارة حزم). اتبع الخطوات التالية لتثبيت أداة cordova CLI : 1- حمّل وثبّت Node.js. خلال التثبيت يجب أن تكون قادراً على استدعاء node و npm على سطر الأوامر الخاص بك. 2- (اختياري) حمّل وثبّت git client, إذا لم يكن لديك نسخة مسبقًا. قم بتثبيتها, وبعدها يجب أن تكون قادرًا على استدعاء git على سطر الأوامر الخاص بك. حيث يستخدمها CLI لتحميل الموارد عندما يتم الاشارة إليها باستخدام git repo 3- ثبّت cordova باستخدام أداة npm لـ Node.js. حيث سيُحمّل cordova أوتوماتيكيًا باستخدام أداة npm . في OS ولينكس $ sudo npm install -g cordova في أنظمة OSX و LINUX قد يكون الحاق الأمر npm بـ sudo ضروريًا لتثبيت أداة التطوير هذه في الأدلة المقيّدة مثل /usr/local/share إذا كنت تستخدم الأداة الاختيارية nvm/nave أو تمتلك صلاحية الوصول الى دليل التثبيت. يمكنك الاستغناء عن البادئة sudo . في نظام التشغيل ويندوز Windows C:\>npm install -g cordova تخبر العلامة g- الأمر npm بتثبيت cordova بشكل عام. وإذا لم يتم التحديد سيتم التثبيت في الدليل الفرعي node_modules من مسار التثبيت الحالي. بعد إتمام التثبيت يجب أن تتمكن من تشغيل cordova من موجه الأوامر بدون معامِلات، ويجب أن تقوم Cordova بطباعة نص للمساعدة على شاشة موجه الأوامر.. إنشاء التطبيق اذهب الى الدليل الذي تدير فيه شفرتك المصدرية. وأنشئ مشروع Cordova $ cordova create hello com.example.hello HelloWorld هذا ينشئ بنية الدليل المطلوب لتطبيق cordova الخاص بك. افتراضيًا, سكريب cordova create يولد هيكلية تطبيق معتمد على الوب والذي صفحته الرئيسية هي ملف المشروع www/index.html. إضافة منصّات يجب تشغيل جميع الأوامر اللاحقة ضمن الدليل الرئيسي المشروع، أو أي دليل فرعي: $ cd hello أضف المنصّات التي ترد لتطبيقك أن يستهدفها. سنضيف منصّة أندرويد و IOS والتأكد من حفظها الى config.xml و package.json: $ cordova platform add ios $ cordova platform add android للتأكد من مجموعتك الحاليّة للمنصّات: $ cordova platform ls تشغيل أوامر لإضافة أو إزالة المنصّات يؤثّر على محتويات دليل منصّات المشروع، حيث تظهر كل منصّة محدّدة كدليل فرعي. ثبيت المتطلبات المسبقة للبناء لإنشاء التطبيقات وتشغيلها، يلزمك تثبيت حزم SDK لكل منصّة تريد استهدافها. بدلاً من ذلك، إذا كنت تستخدم متصفح للتطوير فيمكنك استخدام منصّة browser التي لا تتطلب أية SDKs للمنصّة. للتحقق مما إذا كنت مستوفيًا لمتطلبات إنشاء المنصّة: $ cordova requirements Requirements check results for android: Java JDK: installed . Android SDK: installed Android target: installed android-19,android-21,android-22,android-23,Google Inc.:Google APIs:19,Google Inc.:Google APIs (x86 System Image):19,Google Inc.:Google APIs:23 Gradle: installed Requirements check results for ios: Apple OS X: not installed Cordova tooling for iOS requires Apple OS X Error: Some of requirements check failed بناء التطبيق افتراضيًا، Cordova تنشئ سكريبت يولد هيكلية تطبيق معتمد على الوب والذي صفحة البداية له هي ملف المشروع www/index.html. يجب تحديد أيّة تهيئة كجزء من معالج حدث deviceready المعرّف في www/js/index.js. قم بتشغيل الأمر التالي لبناء المشروع لجميع المنصّات: $ cordova build يمكنك اختياريًا تحديد المجال في كل بناء لمنصّات محدّدة- في هذه الحالة"ios" $ cordova build ios اختبار التطبيق غالباً ما تأتي حزم SDK لمنصّات الموبايل مع محاكي تشغّل صورة الجهاز, وبذلك يمكنك تشغيل التطبيق من الشاشة الرئيسية ومشاهدة كيفية تفاعله مع العديد من ميزات المنصّة. شغّل أمر مثل التالي لإعادة بناء التطبيق وعرضه ضمن محاكي منصّة معيّنة: $ cordova emulate android تبعاً لأوامر محاكي Cordova تحدّث (refreshes) صورة المحاكي لعرض أحدث تطبيق, والذي قد أصبح متاحاً للوصول من الشاشة الرئيسية: في نفس الوقت يمكنك توصيل الهاتف إلى حاسوبك واختبار التطبيق مباشرةً: $ cordova run android قبل تشغيل هذا الأمر، تحتاج إلى إعداد الجهاز للاختبار، باتباع الإجراءات التي تختلف حسب كل منصّة. إضافة الإضافات Plugins يمكنك تعديل التطبيق المولَّد افتراضياً للاستفادة من ميزات تقنيات الوب المعيارية, ولكن ستكون بحاجة لإضافة Plugins لكي يتمكّن التطبيق من الوصول لميزات على مستوى الجهاز. تعرض الإضافة واجهة برمجة تطبيقات جافا سكربت Javascript API لوظيفة SDK الأصلية. يتم استضافة الإضافات عادةً على npm ويمكنك البحث عنهم في صفحة plugin search. تُزوَّد بعض مفاتيح API من قبل مشروع المصدر المفتوح Apache Cordova ويشار إليها باسم Core Plugin APIs $ cordova plugin search camera لإضافة وحفظ إضافة الكاميرا إلى config.xml و package.json، سنحدّد اسم حزمة لإضافة الكاميرا: $ cordova plugin add cordova-plugin-camera Fetching plugin "cordova-plugin-camera@~2.1.0" via npm Installing "cordova-plugin-camera" for android Installing "cordova-plugin-camera" for ios يمكن أن تضاف الإضافات أيضاً باستخدام الدليل أو باستخدام git repo استخدم plugin ls أو plugin list أو plugin لوحدها لعرض الإضافات المثبّتة حالياً. كلٌ يُعرض من خلال معرّفه الخاص: $ cordova plugin ls cordova-plugin-camera 2.1.0 "Camera" cordova-plugin-whitelist 1.2.1 "Whitelist" استخدام mergesلتخصيص كل منصّة في حين أن Cordova تسمح لك بنشر التطبيق بسهولة على منصّات مختلفة, إلا أنه في بعض الأحيان ستحتاج لإضافة تخصيصات. في هذه الحالة, لن تقوم بتعديل الملفات المصدرية في أدّلة www المتعددة ضمن دليل المستوى العالي platforms , لأنه يتم استبداله بشكل منتظم مع مصدر المنصّات المتعددة لدليل المستوى العالي www بدلاً من ذلك، دليل المستوى الأعلى merges يوفر مكاناً لتحديد الموارد للنشر على منصّات محدّدة. يعكس كل دليل فرعي خاص بالمنصّة ضمن عمليات merges بنية الدليل لشجرة المصدر www، مما يسمح لك بتجاوز أو إضافة ملفات حسب الحاجة. على سبيل المثال، إليك كيفية استخدام عمليات merges لزيادة حجم الخط الافتراضي لأجهزة أندرويد: حرّر ملف www/index.html , مضيفاُ رابط ملف CSS إضافي, overrides.css في هذه الحالة: <link rel="stylesheet" type="text/css" href="css/overrides.css" /> يمكن اختياريا إنشاء ملف www/css/overrides.css فارغ. والذي سيطبق من أجل كل بناء غير مخصص للأندرويد, لمنع خطأ الملف مفقود (missing-file) أنشئ ملف css على دليل فرعي ضمن merges/android, ثم أضف ملف overrides.css المقابل. حدّد CSS الذي يتجاوز حجم الخط الافتراضي 12-نقطة داخل www/css/index.css, على سبيل المثال: body { font-size:14px; } عندما تعيد بناء المشروع, تضمّن نسخة الأندرويد حجم الخط المخصص, بينما تظل البقية دون تغيير. كما يمكن استخدام merges لإضافة ملفات غير موجودة في الدليل الأصلي www. على سبيل المثال, تطبيق يمكنه تضمين back button رسومي داخل واجهة الـ iOS, مخزّن في merges/ios/img/back_button.png , ، في حين أنه يمكن لنسخة الأندرويد بدلاً من ذلك التقاط الأحداث backbutton من زر الأجهزة المقابلة. تحديث كوردوفا وتطبيقك بعد تثبيت أداة Cordova, يمكنك دوماً تحديثها إلى آخر إصدار من خلال تشغيل الأمر $ sudo npm update -g cordova استخدم هذه الصّياغة لتثبيت إصدار محدّد: $ sudo npm install -g cordova@3.1.0-0.2.0 نفّذ cordova -v لمعرفة النسخة الحالية قيد التشغيل. شغّل الأمر التالي لإيجاد آخر نسخة تم إصدارها Cordova: $ npm info cordova version لتحديث المنصّة التي تستهدفها: $ cordova platform update android --save $ cordova platform update ios --save ...etc. ترجمة -وبتصرّف- للمقال Create your first Cordova app للمساهمين في كتابة المقال على GitHub هذا المقال منشور تحت الرخصة Apache License, Version 2.0
  24. نظرة عامة أباتشي كوردوفا (Apache Cordova) هي منصّة مفتوحة المصدر لتطوير تطبيقات الموبايل. تمكّنك من استخدام تقنيات الويب المعياريّة مثل HTML5, CSS3, وJavaScript للتطوير متعدد المنصّات “cross-platform development” حيث تنفذ التطبيقات من خلال محزّم مخصص لكل منصّة، ويعتمد على الواجهات البرمجيّة القياسيّة للوصول إلى موارد الأجهزة كالحسّاسات، البيانات، وحالة الشبكة. قم باستخدام Apache Cordova إذا كنت: مطوّر تطبيقات موبايل وتريد أن توسّع قدرة تطبيقك ليعمل على أكثر من منصّة، بدون الحاجة إلى إعادة تنفيذه بلغة ومجموعة الأدوات الخاصّة بكل منصّة. مطوّر تطبيقات ويب، وتريد أن تنشر تطبيق محزّم للتوزيع على متاجر تطبيقات متنوعة. مطوّر تطبيقات موبايل مهتم بدمج مكونات التطبيق الأصليّة بطريقة عرض الويب WebView (نافذة تصفح خاصّة) يمكنها الوصول إلى الواجهات البرمجية للتطبيقات على مستوى الأجهزة (device-level APIs)، أو إذا كنت تودّ تطوير واجهة إضافة (plugin interface) بين المكونات الأصليّة ومكونات الويب. البنية يتواجد العديد من المكونات لتطبيقات Cordova, يبيّن المخطط التالي نظرة عالية المستوى على بنية تطبيق Cordova. عرض الويب WebView WebViewالمدعم بـ Cordova يمكن أن يزود التطبيق بكل واجهات المستخدم الخاصّة به، كما يمكن أن يكون في بعض المنصّات كمكوّن ضمن تطبيق مختلط أكبر يدمج WebView مع مكوّنات التطبيق الأصليّة تطبيق الويب Web App هو الجزء الذي تتوضع فيه شفرة تطبيقك، التطبيق بحد ذاته ينفذ كصفحة ويب، وبشكل افتراضي هو الملف المسمّى index.html والذي يرتبط بـ JavaScript ، CSS، صور، ملفات وسائط متعددة، أو مصادر أخرى ضرورية لتشغيله. ينفذ التطبيق في WEBVIEW ضمن محزّم البرنامج الأصلي, الذي قمت بتوزيعه على متاجر التطبيقات. ويحتوي أيضًا على ملف مهم للغاية وهو config.xml والذي يؤمّن معلومات عن التطبيق ويحدّد البارامترات التي تؤثر على كيفية عمله، كتحديد فيما إذا كان يستجيب لتغيرات الاتجاه. الإضافات Plugins تشكل الإضافات جزء أساسي من النظام الوظيفي لـ Cordova. فهي تؤمن الواجهة لـ Cordova والمكونات الأساسيّة للاتصال فيما بينها، وعملية التغليف إلى واجهات تطبيقات الجهاز القياسيّة APIS ، وهذا يمكنك من استدعاء الشفرة الأصليّة للبرنامج من خلال Javascript. مشروع Apache Cordova يدير مجموعة من الإضافات تسمّى الإضافات الجوهرية Core Plugins. هذه الإضافات تمكّن تطبيقك من الوصول إلى موارد جهازك (كالبطارية، الكاميرا، جهات الاتصال، ..الخ). وبالإضافة إلى المكونات الجوهريّة يوجد العديد من الإضافات التابعة لجهات أخرى third-party plugins والتي تؤمّن تغليفات إضافية لخصائص قد لا تكون متوافرة بالضرورة في جميع الأجهزة. يمكنك البحث عن إضافات Cordova باستخدام (plugin search(npm، كما يمكنك أيضًا تطوير إضافاتك الخاصة. يمكن أن تكون الإضافات ضروريّة . كمثال، من أجل الاتصال بين Cordova والمكونات الاصليّة العاديّة. لا تؤمن Cordova أي أدوات واجهات UI widgets أو بنى تعتمد عرض النماذج MV* frameworks. تؤمن لها فقط زمن التشغيل الذي يمكنها التنفيذ خلاله. إذا كنت تريد استخدام أدوات الواجهات أو بيئة عرض النماذج، يتوجب عليك اختيارهم وتضمينهم في تطبيقك. مسارات التطوير Development Paths تزودك Cordova بمخططي عمل workflow أساسيين من أجل إنشاء تطبيق موبايل، بينما يمكنك غالبًا استخدام أيّ منهما لإنجاز نفس المهمة، فإنّ كل منهم يقدم خصائص إيجابية: مخطط عمل موجه الأوامر متعدد المنصات (Cross-platform (CLI) workflow) استخدم هذا المخطط إذا كنت تودّ أن يعمل تطبيقك على أنظمة تشغيل مختلفة قدر الامكان. مع حاجة قليلة للتطوير المتعلق بالمنصة (platform-specific development) يركّز مخطط العمل هذا على موجه الأوامر في كوردوفا (Cordova CLI)، والذي هو عبارة عن أداة عالية المستوى تمكنك من بناء مشاريع لمنصّات متعددة في نفس الوقت. تستخرج العديد من خصائص سكربتات شيل(الصدفة) الأقل المستوى lower-level shell .scripts يقوم CLI بنسخ مجموعة من تجهيزات الويب الشائعة إلى مجلدات فرعية لكل منصّة موبايل، القيام بتغيير الإعدادات الضرورية لعمل كل منها، وتشغيل سكريبتات البناء لتوليد الملفات التنفيذية للتطبيقات. يؤمن CLI أيضًا واجهة عامة لتنصيب الإضافات على تطبيقك. إذا لم تكن بحاجة إلى مخطط مخصّص لمنصّة محددة يفضل اعتماد المخطط لمنصّات متعددة. مخطط العمل المتعلق بمنصّة Platform-centered workflow قم باستخدام هذا المخطط إذا كنت تودّ إنشاء تطبيق مخصّص لمنصّة واحدة, ولديك حاجة لأن تكون قادرًا على تعديله بالمستويات الأدنى. وكمثال إذا كنت تريد من تطبيقك أن يدمج المكونات الأصلية العادية مع مكونات Cordova المعتمدة على الويب (web-based Cordova components)، كما نوقش في تضمين WebViews. وكقاعدة متعارف عليها، استخدم هذا المخطط إذا كنت تريد تعديل المشروع من خلال حزمة تطوير النظام الخاصّة به SDK. هذا CLI مجموعة على مجموعة من سكريبتات المستوى الأدنى التي تم تعديلها لتلائم كل من المنصّات المدعومة. بالإضافة إلى أداة منفصلة (Plugman) تمكّنك من تنصيب الإضافات. بالرغم من أنّه يمكنك استخدام هذا المخطط لإنشاء تطبيقات لمنصّات متعددة، لكن ذلك يتم عادة بصعوبة أكبر، وذلك بسبب أن نقص أدوات المستوى الأعلى يعني دورات بناء منفصلة وتعديلات على الإضافة لكل منصّة. في بداية العمل، من الأسهل البدء باستخدام مخطط العمل متعدد المنصّات لإنشاء التطبيق، يمكننا بعدها الانتقال إلى مخطط العمل المخصص لمنصّة إذا كنت تريد تحكم أوسع يتم تأمينه من قبل حزمة تطوير النظام الخاصة بالتطبيق SDK. تدير CLI مجموعة شائعة من الشفرات المصدرية متعددة المنصّات، تستخدمها في كل عمليّة بناء للكتابة فوق الشفرة المخصصة لمنصّة واحدة. للحفاظ على أيّة تعديلات قمت بإجرائها على المكونات المخصصة لمنصّة، يتوجب عليك الانتقال إلى استخدام أدوات شيل المخصصة لتلك المنصّة التي تتجاهل الشفرات المصدريّة متعددة المنصّات وتقوم بدلاً عن ذلك بالاعتماد على شفرات مصدريّة مخصصة لمنصّة واحدة. تنصيب Cordova يختلف تنصيب Cordova بحسب مخطط العمل الذي تختاره. مخطط العمل متعدد المنصّات: (سنتعرّف عليه في الدرس القادم) مخطط العمل المخصص لمنصّة. بعد تنصيب Cordova, يفضل الاطلاع على قسم (Develop for Platforms) لمنصّات الموبايل التي تطوّر التطبيق من أجلها. ترجمة -وبتصرّف- للمقال Architectural overview of Cordova platform للمساهمين في كتابة المقال على GitHub هذا المقال منشور تحت الرخصة Apache License, Version 2.0
×
×
  • أضف...