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

Mohamad Ibrahim3

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

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

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

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

    166

كل منشورات العضو Mohamad Ibrahim3

  1. إنّ أي مطوّرٍ يَستخدم تقنيات Sass أو LESS، يعلم تمامًا ما هي المُتغيّرات (variables) وكيفيّة استخدامها في صفحات التنسيق CSS، ويَعلم أيضًا فائدتها وما يُمكن أنّ تُقدّم له، في المُقابل، ولمن لا يَستخدِم المُعالج المُسبق (preprocessor)، رُبّما يَسأل: لماذا كل هذه الجلبة حولها، ولماذا يتحدّث الجميع عنها، وفائدتها؟، وعليه سيتناول هذا المقال فائدة المُتغيّرات، والمُتغيّر currentColor بشكل خاصّ. ما فائدة المُتغيّرات في CSS؟ تأتي أهميّة المُتغيّرات في CSS في سماحها للمطوّر بكتابة شيفرة (كود) نظيفة، ومُرتّبة وغير مُكرّرة، وذلك عبر تكريس مبدأ “لا تُكرّر نفسك” (Don’t Repeat Yourself)، والمعروف بالاختصار DRY، وتتجلّى أهميتها في إدارة وصيانة المشاريع الكبيرة، والّتي تحتوي على قيم مُكرّرة هنا وهناك. يُشاع استخدام المُتغيّرات مع سمات الألوان (color themes) والّتي تجعل من إنشاء وإدارة توزّع الألوان في كامل مُستند CSS أسهل وأكثر مرونةً من أي وقتٍ مضى، فعلى سبيل المثال، يتطلّب توزيع الألوان عادةً إلى إعادة استخدام بعض قيم الألوان لخواصٍّ عدّة ومُختلفة في أرجاء ملفّ CSS، وعند الرغبة في تغيير اللّون الرئيسيّ للموقع، فسيُغيّر المُطوّر أو المُصمّم مضطرًا جميع القيم في صفحة التنسيق، ولكن مع استخدام مُتغيّرات CSS، يتمّ تعريف مُتغيّر ولمرّة واحدة، وليكن المُتغيّر يحمل الاسم “primary-color” مثلًا، وإسناد قيمة لونيّة له، ومن ثُمّ استخدام قيمة المُتغيّر في أي مكان في صفحة التنسيق، وعندما يُتطلّب تغيير هذا اللّون في وقتٍ لاحقٍ، فكل ما على المُطوّر فعله هو إسناد القيمة اللونيّة الجديدة إلى المُتغيّر، وعليه ستُحدّث قيمة المُتغيّر في جميع أرجاء صفحة التنسيق أوتوماتيكيًّا. لم تطرح CSS 2.1 مفهوم المُتغيّرات، (على الرغم من أنّ ذلك ليس دقيقًا تمامًا)، ولكن في عام 2014، قُدّم مفهوم المُتغيّرات في بيانات CSS، وبشكل مُشابه للمُتغيّرات المُقدّمة من المُعالجات المُسبقة (preprocessor)، وعلى ما يبدو أنّها تملك إمكانيات أكبر مما تقدّمه مُتغيّرات المُعالجات المُسبقة المعروفة، حيثُ يُقبَل مُتغيّر CSS كقيمة من قبل جميع خاصيّات CSS. كما قدّمت CSS بالإضافة إلى المُتغيّرات قيمة مفتاحيّة، والّتي تُعتبر عمليًا أيضًا مُتغيّر وهي:currentColor. المُتغيّر/الكلمة المفتاحيّة currentColor تُشبه الكلمة المفتاحيّة currentColor مُتغيّر CSS، ماعدا أنّها تَملك تقييدًا مُهمًّا، فهي تُستخدم فقط كبديل للمُعطى/المُعامل <color>، فإن كانت الخاصيّة لا تقبل قيمة هذا المُعامل، فهي لن تَقبلcurrentColor قيمة لها. أمثلة على خواصّ تقبل استخدم currentColor كقيمة: box-shadow: inset 2px 2px 3px currentColor; background-color: currentColor; background-image: linear-gradient(currentColor, transparent); إن الاختلاف الآخر بين المُتغيّر currentColor وبين المُتغيّرات المعروفة، يَكمن في عدم المقدرة على إسناد قيمةٍ له بنفس طريقة إسناد القيم للمُتغيّرات كما جرت العادة، فإن قيمة currentColor يتمّ تحديدها بالقيمة المحسوبة لخاصيّة اللّون الّتي حاليًا تُستخدم/تُطبّق على العنصر، وهذا يعني أنّ قيمة currentColor تساوي قيمة خاصيّة اللّون الحاليّ، ومن هنا جاء الاسم currentColor (اللّون الحاليّ). يُظهر المثال السابق كيف تُعيّن/تَضبط الكلمة المفتاحيّة currentColor لون ظل الصندوق (box shadow) إلى أيّما كانت قيمة اللّون المعيّنة للعنصر div، وفي حال عدم ضبط أي لون له (الوسم div)، فسيتمّ استخدام اللّون المَوروث من أسلاف الـ div، وعند عدم امتلاك أيًا من هذه الأسلاف قيمة لونيّة، فإن مُعظم المُتصفّات ستُعين اللّون الأسود كقيمة بديلة. بعبارةٍ أُخرى، إن الكلمة المفتاحيّة تُستخدم لجعل خواصّ عنصر، أو العناصر الأبناء لعنصر، تَرث اللّون المُعيّن من قِبل المُعطى <color>، ولذلك فإنّها تتصرّف كما تفعل القيمة inherit في السّماح بوراثة قيمة اللّون والّتي ما كان له أنّ يُورّث إلى العنصر الابن بدونها. يعني هذا أيضًا أن الخاصيّات الّتي تَرث بالأصل قيمة color، لن تكون الكلمة المفتاحيّة currentColor بتلك الفائدة بالنسبة لها. الخاصّيّات والعناصر الّتي ترِث قيمة color بشكل افتراضي عندما يَملك عنصر قيمة لونيّة، سواءً كانت مُعيّنةً بشكل صريح أو وراثةً، فإن بعض العناصر الأماميّة (foreground) –وهي عكس خلفيّة (background) ويُقصد بها لون النصّ الظاهر للعيان- لهذا العنصر والّتي تقبل القيمة <color> ستَرث قيمة اللون بشكل افتراضيّ. فعلى سبيل المثال، إن حدود (borders) عنصر هي جزء من أماميّة (foreground) هذا العنصر، ولذلك حتّى مع عدم تحديد لون للحدود، فإنها ستأخذ نفس القيمة اللونيّة للخاصيّة color، وإن لم يَملك العنصر إي لونٍ فإن مُعظم المُتصفّحات عادةً ما ستستخدم اللون الأسود. ستكون لون الحدود زرقاء في المثال التّالي: .parent { color: blue; } .child { border: 5px solid; /* لم يتمّ تعيين قيمة لونيّة للحدود */ } العناصر الّتي تَرث قيمة color هي: نصيّة العنصر، والّتي تُعنى بها خاصيّة color. إطار النصّ (text outline). حدود العنصر (element border) ظل الصندوق (box shadow) نصّ الصورة البديل (alt)، وهو النصّ الّذي يُعرض عند عدم عرض الصورة لسببٍ ما. علامات التنقيط/الكرات الصغيرة الخاصّة بالقائمة (list item bullet) وحدودها (borders). حدود المسطرة الأفقيّة (hr) في بعض المُتصفّحات، مثل المُتصفّح كروم، ومع الانتباه أنّه لن يتأثّر لون المسطرة عند عدم وجود حدود. عدم إسناد قيمة لونيّة لهذه العناصر (السابقة) بشكل صريح، سيجعلها يرثون قيمة color المحسوبة. يظهر المثال التّالي عمليًّا كيف تتأثر العناصر السابقة باللّون المُسند لجذع الصفحة (body)، وعليه فإن تغيير لون جذع الصفحة سيُغيّر من لون هذه العناصر جميعًا: body { color: rgb(255, 20, 20); background-color: white; height: 100vh; padding: 2em; } hr { border: 3px solid; } div { padding: 1em; width: 200px; height: 150px; border: 5px solid; box-shadow: 5px 5px 5px; } p { background-color: currentColor; padding: .5em; width: 80%; margin: 1em auto; } li { border: 1px solid } strong { outline: 2px solid; } السؤال الّذي قد يُسأل الآن، إنّ كانت أغلب العناصر أو الخاصّيّات ترث قيمة color، إذًا ما فائدة currentColor؟ توسيع وراثة اللّون باستخدام currentColor يوجد بعض الحالات الّتي يكون فيها جلب قيمة color واستخدامها أمرًا مُفيدًا للغاية، يتبيّن ذلك في استخدام currentColor مع الحالات الّتي لا تُطبق الوراثة، وهي التدرجات اللّونيّة (gradients)، فصور التدرجات في CSS، إن كانت التدرّجات الخطيّة أو التدرّجات النصف قطريّة، لا ترث قيم الألوان، ولكن باستخدام currentColor يُصبح بالإمكان استخدام التدرّج الخطّي كصورة خلفيّة: background-image: linear-gradient(to bottom, currentColor, #fff); تمّ أخذ هذا المبدأ إلى أبعد من ذلك، حيثُ تمّ عمل شيء يُشبه التحريك (animation) لخاصيّة color، فعندما تتغيّر قيمة الخاصيّة color، فإن جميع العناصر ستتأثّر وتُغيّر من لونها: مثال حيّ: http://codepen.io/scottkellum/pen/Fhxql يُظهر المثال السابق بحق قوة هذه الميّزة الّتي تُقدّمها CSS، وخاصّةً في جزئيّة التحريك. ظهر مؤخرًا المزيد من الأمثلة التطبيقيّة لهذه الميّزة، وهو ما سيتمّ التركيز عليه في بقيّة المقال. استخدامات currentColor العمليّة تَكمن الفكرة الرّئيسيّة خلف currentColor في توسيع تسلسل أو تعاقب اللّون، وهو أمرٌ يستفاد منه في العديد من الحالات. استخدام currentColor في قَوْلَبة عناصر واجهة المُستخدِم (UI) يُمكن استخدام currentColor في حالات تطبيقيّة عديدة، فعلى سبيل المثال يُمكن استخدامcurrentColor مع عناصر واجهة المُستخدِم لتنسيق صفحة ويب كاملة (أو تطبيق ويب كامل) مُباشرةً باستخدام المُتصفّح. يُظهر المثال التّالي عمليًا، وباستخدام أدوات المطوّرين (devtools) الخاصّة بالمُتصفّح ومنها من منتقي الألوان، كيف أنّ تغيير قيمة خاصيّة color، سيُغيّر من ألوان جميع عناصر واجهة المُستخدِم وذلك باستخدام المُتغيّر currentColor. استخدام currentColor في قَوْلَبة وتنسيق SVG إنّ الرسوم المُتجهة القابلة للتوسّع (Scalable Vector Graphics) رائعة بلا شك، ولكنّها مع ذلك تأتي مع بعض القصور، عند استخدامها بطرقٍ مُعيّنة، مثلًا عند إعادة استخدام أجزاء من SVG باستخدام العنصر <use>. يُستفاد من العنصر <use> في إعادة استخدام أجزاء من SVG في أي مكان يُرغب في أنّ تظهر به هذه الأجزاء على الصفحة، ما يتمّ عمليًا عند استخدام عنصر SVG هو إنشاء نسخة حيّة من ذلك العنصر، فالأمر مُشابه لفكرة نسخ ولصق العناصر في أي مُحرّر رسومي، ما عدا أنّ هذه النسخة هي نسخة حيّة، أي أنّ خصائصها ستتغيّر عند تَغيّر النسخة الأصل. يُستخدَم العنصر <use> بشكل كبير عند إنشاء SVG sprites، فيُمكن استخدام SVG يحتوي على جميع الرموز الصوريّة (الأيقونات) والّتي ستستخدم كـ sprite، ومن ثُمّ إدراج الأيقونات على حدى من ذلك الـ sprite وفي أي مكان على الصفحة، باستخدام <use>، ويُمكن الاستزادة حول هذا الموضوع عبر قراءة: طريقة إنشاء الـ sprites. عند استخدام العنصر، فإن نسخة من محتواه ستُنسخ إلى shadow DOM، وهذا يعني أنّ هذا المُحتوى لا يُمكن اختياره وتنسيقه باستخدام CSS كما يتمّ عادةً عبر اختيار و تنسيق عناصر SVG، أو حتّى عناصر HTML متمثلةً بالـ DOM الاعتيادي، هذا أحد الأسباب الّتي تجعل من تنسيق أيقونات SVG المُنشئة بهذه الطريقة ذو إمكانيات وقدرات محدودة. إن استخدام currentColor يَسمح بتخطّي هذه المحدوديّة، عن طريق السماح للّون المُعيّن في CSS بالتسرّب إلى محتويات SVG المُستعمل، وذلك بضبط currentColor كقيمة للخواصّ المُراد من قيمة اللّون أنّ تتسرّب إليها: <svg class="home-icon"> <use xlink:href="#home"></use> </svg> وعلى فرض أنّ الأيقونة #home مُعرّفة كما في التّالي: <symbol id="home"> <rect id="bottom" fill="currentColor" ... /> <polygon id="roof" ... /> </symbol> أصبح من المُمكن الآن تطبيق التنسيقات على الأيقونة وجعل اللون fill يتعاقب نزولًا إلى #roof(والذي لا يَملك الخصلة fill) وتوريث قيمة color إلى #bottom: .home-icon { fill: red; color: white; } سيتعاقب اللّون المملوء نزولًا من <svg> إلى <use>، وبعد ذلك إلى #roof، وستُستخدم قيمةcolor كقيمة لـ #bottom، وذلك فقط بسبب استخدام currentColor. يُستفاد من هذا الأسلوب عند الحاجة إلى إنشاء أيقونات عديدة، كلٍ منها ذو لونٍ مُختلف، فكل ما يجب عمله في هذه الحالة هو تغيير قيمة color و fill في ملفّ CSS، وهو ما يَستعرضه المثال الحيّ التّالي: مثال حيّ: http://codepen.io/FWeinb/pen/rGBsC يُمكن استخدام currentColor على عناصر عدّة داخل SVG، ولكن هذا يَسمح فقط بتغيير لونين داخل SVG. وإن كانت الرغبة هي الحصول على تحكم أكبر على الألوان وتعيين المزيد من قيم الألوان لتتسرّب إلىSVG، فعندها يجب توفّر المزيد من المتغيّرات، وهنا بالضَّبط تأتي قيمة متغيّرات CSS المقدّمة في البيان (specification) الخاصّ بها، يُمكن القراءة أكثر عن هذا الأمر من خلال موضوع بعنوان: تخصيص أيقونات SVG باستخدام متغيّرات CSS الخاتمة تمّ التوضيح في المثال السابق كيفيّة استخدام currentColor في أماكن عدّة، ومن ثمّ تغيير الألوان المُراد تغييرها في مكان واحد فقط، ليُطبّق هذا التعديل على هذه الأماكن المُختلفة، بدلًا من إنشاء عدّة حالات من نفس اللّون ومن ثُمّ تغييرها جميعها عند الحاجة، وهذا من شأنه أنّ يُساعد المطوّر على كتابة ملفّ تنسيق CSS قصير ونظيف، وتقديم نوعًا من الآليّة في الإعداد، خاصّةً في حالات مثل عناصر ومكوّنات واجهة المُستخدِم UI. يَمتلك المطوّر أو المُصمم مع مُتغيّرات CSS القدرة على تعريف مجموعة من المُتغيّرات واستخدامها في حالات عديدة ومُختلفة، طالما أنّ المُتغيّرات الجديدة ستكون قيم صالحة مع أي خاصيّة من خواصّ CSS، وليس فقط تلك الّتي تقبل قيم المُعطى/المُعامل <color>، فالتعامل مع أيقونات SVG بالتأكيد سيُصبح أسهل، وكذلك الأمر مع صون المشاريع الكبيرة في إعدادها الأولي، وعند تنقيحها. ترجمة –وبتصرّف- للمقال Extending the Color Cascade with the CSS currentColor Variable لصاحبته سارة سويدان
  2. تطبيق صور الخلفيّة (background images) على العناصر هو أحد أكثر الميزات المُستخدمة في CSS، ولذلك يوجد العديد من الخصائص الّتي تَسمح بالتّحكم بخلفيّة العنصر وعلى أكثر من ناحية. يُمكن أنّ يَملك العنصر أكثر من صورة خلفيّة واحدة، فيُمكن إسناد قيم الصّور كقائمة يُفصل فيما بينها الفاصلة، وذلك للخاصيّة background-image، أما الخاصّيّة background-position فتُستخدم لتحديد مَوضع صورة الخلفيّة، وتَستحق هذه الأخيرة بعض التفحّص، وذلك بسبب أنّ قيمها المُحتملة تُنتج نتائج مُختلفة غير متوقّعة للمطوّر الّذي لم يتعمّق في تفاصيل CSS. سيتمّ استخدام صورة خلفيّة وحيدة طوال هذا المقال، بغرض تبسيط الشرح والشيفرة البرمجيّة، ولكن ما يَنطبق على صورة واحدة، يَنطبق على صور مُتعدّدة. تتمَوضع صورة خلفيّة داخل ما يُسمّى مجال تَمَوْضُع الخلفيّة (background positioning area) لعنصر، وهي كما يَدل اسمها، تُحدّد المنطقة الداخليّة الّتي ستتموضع بها الخلفيّة، وهي تملك نظام إحداثي يُستخدم لمُعالجة التَمَوْضُع. سيتمّ أوّلًا التطرّق إلى مفهوم نموذج الصندوق (CSS box model)، ورؤية تأثيره على تَمَوْضُع صور الخلفيّة داخل العنصر، وذلك قبل الدخول في مفهوم التَمَوْضُع. مجالات نموذج الصندوق (CSS Box Model Areas) تَملك العناصر في CSS ثلاثة مجالات، يُطلق عليها صناديق، مُعرّفة على العنصر: صندوق الحدود (border box) صندوق الحشو/الحشوة (padding box) صندوق المُحتوى (content box) صندوق الحدود هو المنطقة من العنصر الّتي تتضمّن كامل الأجزاء الداخليّة للعنصر بالإضافة إلى المنطقة أسفل تلك الحدود. أما صندوق الحشوة فهو المنطقة من العنصر، والّتي لا تتضمّن الحدود (borders)، وتتضمّن محتويات العنصر والحشوة المُحيطة، وتحدّد قيمة هذه الحشوة باستخدام الخاصيّة padding. صندوق المُحتوى هي المنطقة التي أنشأها محتوى العنصر، ولا تتضمّن الحشوة ولا الحدود. يوجد أيضًا مجال رابع يُدعى صندوق الهامش (margin box)، والّذي يتضمّن العنصر والهامش الخارجي، وتحدّد قيمة هذا الهامش بالخاصيّة margin. إضافة خلفيّة إلى عنصر، سواء كانت صورة أو لون مُصمت (solid color)، سيجعل من هذا الخلفيّة تُرسم ضمن مجال حشوة العنصر افتراضيًا، ويُمكن تعديل هذا السلوك عبر استخدام خاصيّة background-origin. ولكي يتمّ تحديد أين يجب بالضَّبط على صورة الخلفيّة أنّ تتموضع داخل مجال التَمَوْضُع (positioning area)، فإن المجال يحتاج نظامًا إحداثيًّا ليُستخدم في تفسير وترجمة قيم التَمَوْضُع. نظام إحداثيَّات العنصر (Element’s Coordinate System) يَملك كل عنصر بشكلٍ افتراضيٍّ نظامًا إحداثيًا مُنشئ نسبةً إلى ارتفاعه (height) وعرضه (width)، ويعود هذا الأمر إلى طبيعة نموذج صندوق العناصر في CSS، ويُستخدم هذا النّظام في توضيع العنصر نسبةً إلى باقي العناصر، وتوضيع أبناء العنصر نسبةً إلى العنصر نفسه. تَملك عناصر HTML نظام إحداثيَّات في CSS، ولكن لا تَملك عناصر SVG نظامًا مُماثلًا، بسبب أنها لا تُحكم بمفهوم نموذج الصندوق. يُعرّف مبدأ نظام الإحداثيَّات في CSS في أعلى يسار زاوية العنصر. يُحكم مجال تَمَوْضُع الخلفيّة (background positioning area) أيضًا من قبل نظام إحداثيَّات مُنشئ في هذا المجال، ويُستخدم في توضيع صورة الخلفية في هذا المجال، ويكون مبدأ هذا النّظام أعلى يسار زاوية مجال التَمَوْضُع. إن مجال التَمَوْضُع الافتراضيّ هو صندوق الحشوة، إذًا وبشكلٍ افتراضي، فإن مبدأ نظام الإحداثيَّات لمنطقة تَمَوْضُع الخلفية هو أعلى يسار زاوية صندوق الحشوة. يعني هذا أنّه عند تطبيق صورة الخلفيّة على عنصر، سيُوضع المُتصفّح الصّورة الأولى وما هو مُكرّر منها ابتداءً من أعلى يسار زاوية منطقة أو مجال الحشوة. على سبيل المثال، وعلى فرض وجود صورة خلفيّة مطبّقة على عنصر وغير مكرّرة (ستُعرض الصّورة مرّة واحدة) فسيكون تَمَوْضُع صورة الخلفيّة داخل نظام الإحداثيَّات عند مبدأ نظام إحداثيَّات صندوق الحشوة، أي أنّ أعلى يسار زاوية الصّورة ستتموضع عند أعلى يسار زاوية صندوق الحشوة: .element { box-sizing: border-box; width: 100vw; min-height: 100vh; padding: 2em; border: 20px solid rgba(0,0,0,0.5); background-color: beige; background-image: url(http://cdns2.freepik.com/free-photo/foggy-pine-forest_426-19323742.jpg); background-repeat: no-repeat; } p { text-align: center; padding: .5em; } .element p { text-align: left; background-color: rgba(255, 255, 255, .4); line-height: 1.5; margin: 0; } يُمكن استخدام خاصيّة background-position، وذلك بهدف تغيير مَوضع الصّورة داخل نظام الإحداثيَّات. يُمكن أيضًا تغيير مجال تَمَوْضُع الخلفيّة لتغيير مبدأ الإحداثيات المُستخدم في توضيع الصّورة داخل مجال خلفيّة العنصر. تغيير مجال تَمَوْضُع الخلفيّة ونظام الإحداثيّات باستخدام background-origin تُستخدم الخاصّيّة background-origin لتغيير مبدأ نظام الإحداثيَّات المُستخدم لتوضيع صورة الخلفيّة في مجال تَمَوْضُع الخلفيّة. تَقبل الخاصّيّة background-origin واحدة من هذه القيم: padding-box وهي القيمة الافتراضيّة. content-box border-box سيتغيّر مبدأ نظام الخلفيّة –وهو مبدأ نظام الإحداثيّات المُنشئ في هذا المجال-الموافق بناءً على مجال تَمَوْضُع الخلفيّة المُختار، وكذلك الأمر مع التَمَوْضُع الأوّلي والافتراضي لصورة الخلفيّة. تُظهر الأمثلة الحيّة التّالية الاختلاف عمليًا. .element { box-sizing: border-box; width: 100vw; height: 100vh; padding: 2em; border: 20px solid rgba(0,0,0,0.3); background-color: beige; background-image: url(http://cdns2.freepik.com/free-photo/foggy-pine-forest_426-19323742.jpg); background-repeat: no-repeat; } .element-2 { background-origin: content-box; } .element-3 { background-origin: border-box; } p { text-align: center; padding: .5em; } .element p { text-align: left; background-color: rgba(255, 255, 255, .4); line-height: 1.5; margin: 0; } سيتغيّر نظام الإحداثيَّات ليُغطّي كل مجال تَمَوْضُع خلفيّة مُعيّن باستخدام الخاصّيّة background-origin. يُمكن بعد ذلك تحديد مَوضع صورة الخلفيّة في هذا النّظام الإحداثي باستخدام الخاصّيّة background-position. لن يتمّ تغيير مجال تَمَوْضُع خلفيّة العنصر بعد الآن، وذلك بغرض تبسيط الأمثلة والشرح، ولذلك جميع الأمثلة هي على العنصر الّذي مجال الحشوة الخاصّة به هو المجال الّتي ستتموضع على أساسها الخلفيّة. توضيع صور الخلفيّة باستخدام خاصيّة background-position توضّح سابقًا كيف أنّ صورة الخلفيّة تتموضّع افتراضيًّا (بدون إعداد مُسبق) عند أعلى يسار زاوية مجال التَمَوْضُع، يَكمن السبب في ذلك إلى حقيقة أنّ قيمة التَمَوْضُع الافتراضيّة للخاصيّة background-position هي 0% 0%. يُقاس التَمَوْضُع وبشكل افتراضي بالقيمة المئويّة، حيثُ من المُمكن الإسناد إلى background-position إما قيمة مئويّة (percentage value) أو قيمة مُطلقة (absolute value)، والّتي تُحدّد إزاحة (offset) الصّورة من أحد الحوافّ (edges) الأربعة (top, right, bottom, left). يوجد خمس كلمات مفتاحيّة للإزاحة، بالإضافة إلى القيم المئويّة والمُطلقة، وهي: top right bottom left center يُوصف (يُعيّن) التَمَوْضُع عبر: تحديد قيمة إزاحة واحدة، سواءً كانت كلمة مفتاحيّة أو نسبة قيمة مئويّة أو طوليّة. تحديد قيمتي إزاحة، وذلك عبر الجمع بين قيمتين من القيم الثّلاث المُحتملة. تحديد أربع قيم إزاحة، كلمة مفتاحيّة وقيمة عدديّة نسبيّة. background-position: top left; background-position: 50px 30%; background-position: top 25%; background-position: right 10px bottom 20px; background-position: center center background-position: 10px 20px; background-position: 5em 2em; background-position: 75% 50%; إن تحديد قيمة وحيدة فقط، سيجعل من القيمة الثّانية هي center، وعند تحديد قيمتين، سيجعل الأولى تحدّد الإزاحة من الحافّة اليُسرى (التَمَوْضُع الأفقي)، والثّانية هي الإزاحة إلى الأسفل من الحافّة العلويّة (التَمَوْضُع العمودي). background-position: 10% 50%; /* 10% of the width to the right, and 50% down from the top */ background-position: top; /* equivalent to `top center` */ background-position: 50px; /* equivalent to `50px center` */ يُمكن الخلط والمزج، أي الجمع بين قيم الأطوال مع القيم المئويّة ومع أو الكلمات المفتاحيّة، الجدير بالذكر هنا، أنّه يُمكن إسناد زوج من الكلمات المفتاحيّة بدون النظر إلى الترتيب، ولكن لا يُمكن الجمع بين كلمة مفتاحيّة وقيمة طوليّة أو قيمة مئويّة، وعليه فإن القيمة center left هي قيمة سليمة وصحيحة، بينما القيمة 50% left ليست قيمة سليمة، بل من المُفترض أنّ تكون left 50%، فعندما يتمّ الجمع واستخدام كلمة مفتاحيّة وطول أو قيمة مئويّة، فإن القيمة الأولى دائمًا تعبّر عن الإزاحة الأفقيّة والقيمة الثانية تعبّر عن الإزاحة العموديّة. إن الجدير بالذكر هنا، أن الكلمات المفتاحيّة هي اختزال أو اختصارات للقيم المئويّة: top مساوية للقيمة المئويّة 0% من الحافّة العلويّة. bottom مساوية للقيمة المئويّة 100% إزاحة من الحافّة العلويّة. left مساوية للقيمة المئويّة 0% إزاحة من الحافّة اليساريّة. right مساوية للقيمة المئويّة 100% إزاحة من الحافّة اليسارية. center مساوية للقيمة المئويّة 50% إزاحة من في أي اتجاه تُطبّق عليه. إن آلية عمل كل قيمة والتفريق بينها لأمرٌ هامٌ، خاصّة مع وجود اختلاف جوهري في تعامل المُتصفّحات مع القيم المئويّة والقيم المُطلقة، وذلك في توضيع صور الخلفيّة. آليّة عمل قيم التَمَوْضُع ذات القيم المُطلقة إن تعيين قيمة تَمَوْضُع باستخدام قيم مُطلقة، سيزيح أعلى يسار زاوية صورة الخلفيّة بالقيمة المُحدّدة، بمعنى آخر، ستُنقل الصّورة بحيثُ تتموضع زاويتها اليساريّة العلويّة عند الإزاحة المُحدّدة في قيمة background-position. يُقال إن الصّورة بألف كلمة، حيثُ يتوضّح في الصّورة التّالية مثالان للخاصيّة background-position وبالقيمة المُطلقة، وكيف يُفسر المُتصفّح هاتين القيمتين ليوضع صورة الخلفيّة، علمًا أنّ أبعاد العنصر في المثالين هي: 100px X 80px. يُمكن أنّ يكون التَمَوْضُع المُطلق مُمثّلًا بقيمة سالبة، وفي هذه الحالة ستنزاح الصّورة في الاتجاه المُعاكس من الحافّة. مثالٌ حيّ: http://codepen.io/SaraSoueidan/pen/bfc8b59ddbc9beb63eee9f26e2754ade آلية عمل قيم التَمَوْضُع ذات القيم المئويّة تَنقل قيم الإزاحة الطوليّة المُطلقة زاوية العنصر اليساريّة العليا بالمسافة المُحدّدة، ولكن مع استخدام القيم المئويّة فالأمر مُختلف، فالقيمة X% ستُرصِف (align) النقطة X% من الصّورة مع النقطة X% من حاوية الصّورة (the container) فعلى سبيل المثال، ستُرصِف القيمة المئويّة 0% 0% النقطة ذات الإحداثيّات 0% 0% من الصّورة مع النقطة 0% 0% من نظام الإحداثيّات مجال تَمَوْضُع الخلفيّة، وستُرصِف قيمة التَمَوْضُع 50% 75% النقطة ذات الإحداثيّات 50% 75% من الصّورة (50% إلى اليمين و 75% إلى الأسفل) مع النقطة ذات الإحداثيّات 50% 75% في مجال تَمَوْضُع الخلفيّة. يُطلب بعض التركيز لفهم الكلام النظريّ السابق، ولكن دائمًا ما لا يَتوضّح بالكلمات حتمًا سيتوضّح بالمرئيّات، كل ما يَهم من الأمر هو التركيز على أنّ الانزياح 50% هو نسبة إلى النقطة 50% من الصّورة وليس الزاوية العلويّة اليساريّة، وهنا مَرْبِطُ الفَرس والذي يُوضّح الاختلاف بين القيم المئويّة وقيم الأطوال المُطلقة. يُمكن تحديد قيم إزاحة مئويّة سالبة، كما هو الأمر مع القيم المُطلقة، الأمر الّذي من شأنه أنّ يَنقل صورة الخلفيّة بالقيمة المُحدّدة ولكن بالاتجاه المُعاكس لمحاور الإحداثيّات: تمّت عمليّة التَمَوْضُع في الأمثلة السابقة نسبةً إلى الحافتين العلويّة واليساريّة، ولكن في الحقيقة من المُمكن توضيع الصّور نسبةً إلى أيًا من الحوافّ الأربعة. الإزاحة نسبةً إلى الحوافّ الأربع تمّ تحديد قيم إزاحة في الأمثلة السابقة، واستخدامها في إزاحة الصّورة نسبةً إلى الحافّة العلويّة والحافّة اليساريّة، وهو السلوك الافتراضيّ لقيمة أو قيمتي تَمَوْضُع. إن الجمع بين الكلمات المفتاحيّة مع القيمة العدديّة باستخدام الصياغة (syntax) ذات الأربع قيم، يُمكّن المُطوّر من إزاحة صورة الخلفيّة من الحافّة اليمينيّة والحافّة السُفلى لمجال التَمَوْضُع. يتمّ استخدام صياغة هذا الأسلوب عبر تحديد اسم الحافّة متبوعًا بالقيمة المطلوبة، ويمكن أنّ تكون القيم على الشكلين: قيم مُطلقة أو قيم مئويّة، وذلك كما في الأمثلة التّالية: background-position: top 1em right 3em; background-position: right 1em bottom 1em; background-position: left 20px bottom 50px; يجب الانتباه إلى أنّ إغفال القيمة الرابعة يجعلها تُفرض على أنّها صفر. background-position: bottom 10px right 20px يوضّح المثال السابق كيف أنّ الإعداد أصبح أسهل بكثير عند الرغبة في إزاحة صورة نسبةً إلى الحافّة اليمينيّة والسُفلى بدلًا من حساب قيم الإزاحة نسبةً إلى الحافتين العلويّة واليُسرى. المزيد مع خواصّ الخلفيّة في CSS يُمكن استعمال أكثر من صورة على عنصر، ولكل صورة خلفيّة يُمكن تعيين قيمة تَمَوْضُع، على أنّ يتمّ الفصل فيما بينها باستخدام الفاصلة: .element { background-image: url(path/to/first/image.jpg), url(path/to/second/image.png); background-position: top left, 75% 80%; } يوجد عامًّا تسع خاصِّيَّات تتحكم بتوزّع العناصر (layout)، والتَمَوْضُع، وقياس ورسم صور الخلفيّة، بما في ذلك خاصيّة background، وتقوم كل خاصيّة بعمل شيء واحد مُحدّد مع إمكانيّة الجمع والمزج فيما بينها لإعطاء المُطوّر تحكم كامل في كيفيّة تطبيق صور الخلفيّة على عناصر HTML. ظَهر مؤخرًا خاصيّة إضافيّة لخواصّ الخلفيّة الرئيسيّة، والّتي تسمح في تطبيق تأثيرات المزج (blending) على صور الخلفيّة وبشكل مُشابه لتأثيرات المزج المتوفّرة في مُحرّرات الصّور مثل فوتوشوب، من هذه الخواصّ الخاصّيّة background-blend-mode، ويُمكن الاستزادة حول الموضع بقراءة المزج في CSS. الخاتمة يُنصح بالقراءة والاستزادة حول هذا الموضوع لأهميته، حيثُ أنّ الفهم الصحيح لهذه الخواصّ من شأنه أنّ يُقدّم للمُطوّر مرونةً في الاستخدام وخياراتٍ أوسع في التصميم. ترجمة –وبتصرّف- للمقال A Primer To Background Positioning In CSS لصاحبته سارة سويدان.
  3. يزداد نمو المواقع يومًا بعد يوم، ومنه إلى ازديار في نسبة مرور البيانات (traffic)، الأمر الّذي من شأنه أن يزيد من الضغط على قواعد البيانات، وباعتبار أنّ قواعد البيانات هي عنق الزجاجة لأداء أي موقع، فعليه يجب أنّ يتمّ إعدادها بشكل مُناسب لِتتولّى الضغط العالي بشكل يُلائم مُتطلّبات العمل.يُمكن اعتبار تقنيّة memcached أحد الطّرق العمليّة في رفع معدّل تخبئة الكائنات في ذاكرة النظام، فهي نظام يعمل على تخزين البيانات وبشكلٍ مؤقّت في الذّاكرة على أن يتمّ استدعائها من الذّاكرة بدلًا من قاعدة البيانات، بحيث تكون هذه البيانات جاهزةً إلى الطلب التّالي ومن الذّاكرة، الأمر الّذي يزيد من سرعة الاستجابة وبشكلٍ ملحوظ. سيتناول هذا الشرح كيفيّة تنصيب وإعداد الذّاكرة المُخبّئة على الخادوم Ubuntu 14.04، ومناقشة ما يلزم من تفاصيل. مُتطلّبات العملقبل بدء العمل، يجب توفّر مُستخدِم ذو صلاحيات وصول عالية، لتطبيق مُحتويات هذه الدليل. تنصيب Memcached وباقي المُقَوِّمات المطلوبةيُمكن تنصيب كافة المُقَوِّمات (components) اللازمة لبدأ العمل من مستودعات أبونتو حيثُ أنّه يوفّرها جميعها. سيتمّ أولًا تحديث الحزم المحلّيّة، ومن ثمّ تنصيب باقي البرامج سيتمّ تنصيب memcached، بالإضافة إلى قواعد البيانات MySQL، ولغة PHP لتتولّى عمليّة الوساطة مع قواعد البيانات، وكما سيتمّ الحاجة إلى تنصيب تَوْسِعَة/إضافة (extension) للغة PHP لِتتولّى عمليّة الربط مع الذّاكرة المُخبّئة (memcached): sudo apt-get update sudo apt-get install mysql-server php5-mysql php5 php5-memcached memcachedيجب الانتباه هنا إلى توفّر توسعتان من الذّاكرة المخبّئة الخاصّة بلغة PHP، تحمل الأولى الاسم php5-memcache، وتحميل الثّانية الاسم php5-memcached، -حرف “d” الإضافي في الثّانية-سيتمّ الاعتماد على الإضافة الثّانية في هذا الشرح بسبب استقرارها، وتقديمها إلى مساحة أكبر من الخيارات والمزايا. إنّ لم تكن قواعد البيانات منصّبة من قبل، فإن المُنصب سيَطلب اختيار وتأكيد كلمة مرور حساب المُدير. ويكون بهذا قد تمّ تنصيب ما سيتمّ الحاجة له خلال الشرح. اختبار تنصيب الذّاكرة المُخبّئةقد يبدو الأمر صعب التصديق، ولكن بهذا الإعداد البسيط فإن الذّاكرة المُخبئة أصبحت جاهزة للعمل، ويُمكن اختبارها بطرقٍ عدّة. تُعتبر الطريقة الأولى سهلة إلى حدٍّ ما، حيث من المُمكن فقط سؤال PHP إن كانت تعلم حول تَوْسِعَة memcached، وفيما إذا كانت مُفعّلة أو لا، وذلك عبر إنشاء صفحة PHP info المعروفة. سيتمّ إنشاء ملف بالاسم info.php في المسار الجذر لخادوم الوب، والّذي سيكون /var/www/html على اعتبار أنّ خادوم الوب هو Apache: sudo nano /var/www/html/info.phpسيتمّ كتابة السطور التّالية في هذا الملفّ، والّتي من شأنها استدعاء دالّة (PHP function)، والّتي من شأنها أنّ تجمع وتطبع معلومات حول الخادوم بصفحة ويب مُنسقة بشكل مقروء ومُبسّط. <?php phpinfo(); ?>يُمكن الآن زيارة خادوم الوب متبوعًا بـ /info.php، وبعد التدرّج في الصفحة إلى القسم الخاص بـ “memcached”، سيكون هناك معلومات مُشابهة إلى التّالي: http://server_domain_name_or_IP/info.php تشير المعلومات السابقة إلى أنّ تَوْسِعَة memcached مُفعّلة، وقد تمّ ربطها مع خادوم الوب. يُمكن أيضًا اختبار فيما إذا كانت خدمة memcached تعمل عن طريقة ترشيح العمليات الحاليّة باستخدام الأداة grep: ps aux | grep memcachedيعرض الأمر السابق معلومات على الشكل التّالي: memcache 6584 0.0 0.0 327448 3004 ? Sl 14:07 0:00 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1 demouser 6636 0.0 0.0 11744 904 pts/0 S+ 14:29 0:00 grep --color=auto memcachedوكما هو الأمر دائمًا مع خدمات أنظمة لينكس فيمكن إيقاف، تشغيل، أو إعادة تشغيل أي خدمة، فالإعادة تشغيل خدمة memcached يُمكن تنفيذ الأمر التّالي: sudo service memcached restartاختبار الذّاكرة المُخبّئةبعد أن تمّ التأكّد من عمل الذّاكرة المُخبّئة، وأن تَوْسِعَة PHP مُتصلة بها ومُفعّلة، فمن المُمكن تجربة استخدامها في تخبئة/تخزين بعض البيانات. سيتمّ كتابة شيفرة/سكريبت PHP آخر لذلك، وسيكون أكثر تعقيدًا من سابقه: sudo nano /var/www/html/cache_test.phpسيتمّ تغليف الشيفرة بوسم PHP: <?php ?>سيتمّ إنشاء حالة/نموذج (instance) من كائن Memcached، وتخزينه في مُتغيّر، ومن ثُمّ سيتمّ تعريف المَوضع الّذي يُمكّن هذا الكائن من الاتصال بخدمة memcache، والّتي تعمل على المنقذ 11211 بالإعداد الافتراضيّ. <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); ?>سيتمّ في الخطوة التّالية إخبار حالة Memcached، المُنشئة في الخطوة السابقة، بالاستعلام (query) عن مفتاح (key) من *التخبئة (cache)، يُمكن أنّ يكون اسم المُفتاح اعتباطيًا باعتبار أنّه لم ينشئ بعد، وليكن “test”، وستُخزّن نتيجة هذا الطلب في المتغيّر $result: <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); $result = $mem->get("test"); ?>سيتمّ في الخطوة التّالية اختبار فيما إذا تمّ الحصول على أي عائد: فلو وجدت memcached مفتاحًا بالاسم “test”، سيتمّ طباعته مع قيمته.أما لو لم تجد مفتاحًا مُطابقًا، سيتمّ طباعة رسالة تُشير إلى ذلك.يجب بعد ذلك تعيين قيمة للمفتاح، ليكون حاضرًا عند السؤال عن البيانات/القيمة في المرّة القادمة، ستجد memcached البيانات/القيمة المُعيّنة له. <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); $result = $mem->get("blah"); if ($result) { echo $result; } else { echo "No matching key found. I will add that now"; $mem->set("blah", "I am data! I am held in memcached") or die("Couldn't save anything to memcached..."); } ?>أصبحت الشيفرة/السكريبت جاهزةً في هذه المرحلة، وبزيارة الصّفحة باستخدام المُتصفّح، سيتمّ رؤية التّالي: http://server_domain_name_or_IP/cache_test.phpستظهر النتيجة على الشكل التّالي في الزيارة الأولى، والّتي تُشير إلى عدم وجود مُفتاح مُطابق، على أنّ تتم إضافته إلى حين الطلب اللّاحق: وستكون النتيجة على الشكل التّالي في الزيارة التّالية: يُوضّح المثال السابق، كيف استطاعت خدمة memcached على تخبئة المعلومات المُعيّنة كما هو مُبرمجٌ لها أن تفعل. اختبار تخبئة قيم قواعد البيانات بشكل مؤقّت (Caching Database Values)أصبح الآن من المُمكن تخزين البيانات في الذّاكرة المُخبئة، ومن المُمكن توضيح المزيد من الأمثلة الواقعيّة، وذلك بالتّطرّق إلى تخبئة النتائج المُستعلمة من قواعد البيانات بشكل مؤقّت في الذّاكرة. إنشاء عيّنة بيانات في MySQLسيتمّ إعداد قواعد البيانات بشكلٍ مُلائم أولًا، وذلك قبل أنّ يتمّ إنشاء هذه العيّنة سيتمّ الاتصال بقواعد البيانات كمُستخدِم مُدير مع إدخال كلمة المرور المُعيّنة خلال تنصيب MySQL، ليتمّ استحضار موجّه الأوامر الخاصّ بـ MySQL: mysql -u root -pسيتمّ إنشاء قاعدة بيانات ليتمّ الاختبار عليها، وبعد ذلك البدء في استخدامها: CREATE DATABASE mem_test; USE mem_test;سيتمّ إنشاء مُستخدِم بالاسم “test”، وبكلمة مرور “testing”، وبصلاحيات وصول إلى القاعدة الّتي تمّ إنشاؤها: GRANT ALL ON mem_test.* TO test@localhost IDENTIFIED BY 'testing123';سيتمّ بعد ذلك إنشاء جدول يحتوي على سجل وحيد، سيحمل الجدول الاسم “sample_data”، مُحتويًا على عمودان، نصيّ وعددي. CREATE TABLE sample_data (id int, name varchar(30)); INSERT INTO sample_data VALUES (1, "some_data");تمّ بذلك إنشاء بنية قاعدة البيانات اللازمة، وأصبح بالإمكان الخروج من موجّه الأوامر الخاصّ بـ MySQL: exitكتابة شيفرة PHP لتخبئة بيانات MySQLأصبح من المُمكن كتابة شيفرة تُحاكي بيئة عمل تطبيق حقيقي في البيئة الحيّة، وذلك بعد أنّ أصبحت قواعد البيانات مجهّزة بشكل مُناسب. ستقوم الشيفرة بالبحث عن البيانات في الذّاكرة المُخبّئة والعودة بالبيانات المُتوفّرة، ولكن عند عدم إيجاد أي بيانات، سيتمّ الاستعلام من قواعد البيانات نفسها، ومن ثمّ تخزين النتائج في الذّاكرة المخبّئة من أجل الاستعلامات المُستقبليّة. سيتمّ كتابة الشيفرة في المسار الجذر الخاصّ بخادوم الوب، وسيحمل الملفّ الّذي يحتوي هذه الشيفرة الاسم database_test.php: sudo nano /var/www/html/database_test.phpستبدأ سُطور الشيفرة بشكل مُشابه إلى الشيفرة السابقة، وذلك بإنشاء حالة وإخبارها بمكان خدمة memcached على الخادوم، كما تمّ الأمر في المثال السابق: <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); ?>ستكون الخطوة التّالية هي تحديد كيف لـ PHP الاتصال بقواعد بيانات MySQL، وذلك بتمرير بيانات الاعتماد/الدخول الخاصّة بالمُستخدِم المُنشئ سابقًا، ومن ثُمّ تحديد أيًا من قواعد البيانات يجب استخدامها: <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); ?>سيتوجّب في الخطوة التّالية بناء الاستعلام، الّذي وظيفته جلب البيانات الموجودة في جدول قاعدة البيانات، وتخزينه في المُتغيّر $query. سيتمّ بعد ذلك إنشاء مُتغيّر $querykey ليخزّن المفتاح الذي ستستخدمه memcached لاسترجاع المعلومات سيتمّ بناء هذا المُفتاح بالجمع بين الكلمة “KEY”، وبعثرة (hashing) من نوع md5، ويضمن ذلك أن كلَّ مُفتاح هو مُفتاح فريد عن الآخر، فعندما يتمّ استخدام هذا الأسلوب مع مجموعة كبيرة من البيانات، وليس كما هو حال هذا المثال المُبسّط، سيضمن ذلك أن أي استعلام مُماثل سيُنتج نفس المُفتاح للطلبات المُستقبليّة. <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); $query = "SELECT ID FROM sample_data WHERE name = 'some_data'"; $querykey = "KEY" . md5($query); ?>سيتمّ في الخطوة التّالية إنشاء المُتغيّر querykey، ليتمّ تعيينه إلى المُتغيّر $result في حال توفّره. <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); $query = "SELECT name FROM sample_data WHERE id = 1"; $querykey = "KEY" . md5($query); $result = $mem->get($querykey); ?>سيتمّ عمل اختبار منطقي (جملة شرطيّة)، والّذي من شأنه أن يُحدّد ماذا سيحدث عند وجود نتائج (جواب الشرط true) في الذّاكرة المُخبّئة، وفي حال ذلك سيتمّ طباعة البيانات المسحوبة، وإخبار المُستخدم أنه قد تمّ استدعاء البيانات من الذّاكرة المُخبّئة بشكل مُباشر: <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); $query = "SELECT name FROM sample_data WHERE id = 1"; $querykey = "KEY" . md5($query); $result = $mem->get($querykey); if ($result) { print "<p>Data was: " . $result[0] . "</p>"; print "<p>Caching success</p><p>Retrieved data from memcached!</p>"; } ?>سيتمّ في الخطوة التّالية كتابة الحالة البديلة، وستكون عند عدم وجود نتائج (جواب الشرط false)، ولذلك يجب استخدام الاستعلام الذي تمّت صياغته سابقًا لسؤال MySQL عن البيانات، ومن ثمّ تخزينها داخل المُتغيّر $result، والذي سيكون على شكل مصفوفة (array). أصبح من المُمكن بعد ذلك إضافة النتائج إلى الذّاكرة المُخبّئة، بعد توفّر نتيجة الاستعلام، لتكون هذه البيانات مُخبّئة للطلب التّالي، ولذلك سيتمّ تمرير ثلاثة مُعاملات لتعيين الذّاكرة المُخبّئة: المفتاح الّذي سيتمّ استخدامه كإشارة مرجعيّة للبيانات، وهو نفس المُفتاح المُنشئ بالمُتغيّر $querykey.البيانات نفسها، وهي مخزّنة في المُتغيّر $result بعد إجراء استعلام MySQL.مُدّة التخبئة بالثانية.سيتمّ تخزين التخبئة لمُدّة ثوانٍ قليلة، في البيئة الحقيقية، سيكون من المُفيد تخبئة المُحتوى لمدّة أطول، ربما دقائق عدّة، خاصّة إذا كان المُحتوى لا يتغيّر بشكل كبير، ولكن لأغراض التجربة، سيتمّ الالتزام بهذه الثواني بدلًا من إعادة تشغيل خدمة memcached لتكملة الاختبار. بعد ذلك، سيتمّ طباعة رسالة بنتائج الاستعلام، مع إخبار المُستخدِم بطريقة الحصول على البيانات: <?php $mem = new Memcached(); $mem->addServer("127.0.0.1", 11211); mysql_connect("localhost", "test", "testing123") or die(mysql_error()); mysql_select_db("mem_test") or die(mysql_error()); $query = "SELECT name FROM sample_data WHERE id = 1"; $querykey = "KEY" . md5($query); $result = $mem->get($querykey); if ($result) { print "<p>Data was: " . $result[0] . "</p>"; print "<p>Caching success</p><p>Retrieved data from memcached!</p>"; } else { $result = mysql_fetch_array(mysql_query($query)) or die(mysql_error()); $mem->set($querykey, $result, 10); print "<p>Data was: " . $result[0] . "</p>"; print "<p>Data not found in memcached.</p><p>Data retrieved from MySQL and stored in memcached for next time.</p>"; } ?>اكتملت الشيفرة بهذا الشكل، وبالمُختصر ما سيحدث هو مُحاولة الحصول على البيانات من الذّاكرة المُخبّئة، واستعراضها عند توفرها، وفي حال الفشل في الحصول على البيانات من الذّاكرة المُخبّئة، سيتمّ التوجّه مُباشرةً لاستعلام قواعد البيانات، ومن ثُمّ تخزين النتائج للطلب التّالي ولفترة ثواني معدودة. اختبار الشيفرةتمّ الانتهاء من كتابة الشيفرة، وأصبح بالإمكان اختبارها، وذلك عبر التوجّه إلى المُتصفّح واستعراض ملفّ الشيفرة: http://server_domain_name_or_IP/database_test.phpيجب أنّ تكون المُخرجات في الزيارة الأولى على الشكل التّالي: ما أن يتمّ تحديث الصفحة، وقبل انقضاء الثواني العشر، حتّى تَعرض الصفحة رسالة مُختلفة كما في التّالي: ما إنّ تنقضي الثواني العشر، ستنتهي صلاحيّة المُحتوى المُخبّئ، وسيُحذف من الذّاكرة المُخبّئة (memcached)، وستُعرض الرسالة الأولى الّتي تُشير إلى أنّ البيانات قد تمّ استدعاؤها من قاعدة البيانات بدلًا من الذّاكرة المُخبّئة. كلمات أخيرةيُفترض الآن وبعد الانتهاء من هذا الشرح الحصول على فهم كامل لكيفيّة إعداد الذّاكرة المُخبّئة، وكيف من المُمكن الحفاظ على أداء خادوم الوب، بتجنيبه من إجراء استعلامات مٌتكرّرة على قواعد البيانات للحصول على نفس المُحتوى. يجب الانتباه إلى أنّ الشيفرة المُستخدمة في هذا الدليل هي فقط لأغراض الشرح، ولتُعطي فكرة واضحة عن آلية العمل وكيفيّة بناء منظومة كاملة وصحيحة تعتمد على الذّاكرة المُخبئة، واستعلام قواعد البيانات في حال فشلها. ترجمة – وبتصرّف – للمقال How To Install and Use Memcache on Ubuntu 14.04 لصاحبه Justin Ellingwood.
  4. تمّ تطوير Redis في عام 2009، وهو مُخزّن بيانات بنمط المفتاح والقيمة (key value)، وهو مفتوح المصدر، ويُقدّم مرونة في الاستخدام، وكما في جميع نمط قواعد البيانات من نوع NoSQL الّتي اتبعها Redis، أمثال Cassandra, CouchDB, MongoDB، فإن Redis يَسمح للمُستخدِم بتخزين كميات ضخمة من البيانات بدون التقيد المفروض بقواعد البيانات العلائقيّة/الارتباطيّة (relational database)، بالإضافة إلى أنّه قد تمّ مُشابهته ومقارنته مع memcache، فيُمكن استخدامه بعناصره الأساسية كنظام تخبئة. إعداد بيئة ومتطلبات Redis قبل الشروع في تنصيب redis، يجب توفّر بعض المُتطلّبات والّتي من شأنها أنّ تجعل من عمليّة التنصيب أكثر سهولة. سيتمّ في البداية تحديث جميع حزم apt-get: sudo apt-get update سيتمّ بعد ذلك تحميل مُترجم (compiler) باستخدام الحزمة build-essential، والّتي من شأنها المساعدة في تنصيب Redis من المصدر: sudo apt-get install build-essential سيتمّ في الخطوة الأخيرة تحميل الأداة tcl الّتي يَعتمد عليها Redis: sudo apt-get install tcl8.5 تنصيب Redis بعد أنّ تمّ تنصيب المُتطلّبات الأساسيّة، فمن المُمكن الآن الشروع وتنصيب redis، ويُمكن تحديد الإصدار المطلوب أو تحميل الإصدار الأخير والذي سيحمل دائمًا الاسم redis-stable: wget http://download.redis.io/redis-stable.tar.gz يجب بعد ذلك فك ضغط الملفّ والانتقال إليه: tar xvzf redis-stable.tar.gz cd redis-stable يجب الآن المُتابعة مع الأمر make: make ولتنصيب Redis على كامل النّظام، فيُمكن إما نسخ ملفاته من المصدر: sudo cp src/redis-server /usr/local/bin/ sudo cp src/redis-cli /usr/local/bin/ أو تنفيذ الأمر التّالي: sudo make install بعد انتهاء عمليّة التنصيب، من المُستحسن تشغيل Redis كحارس (daemon) في خلفيّة النّظام، ولعمل ذلك يأتي Redis بملفّ برمجي (سكريبت) لهذه المُهمّة. يجب الانتقال إلى المسار utils للوصول إلى هذا الملفّ: cd utils ومن ثم تشغيل الملفّ الخاص بتوزيعات Ubuntu/Debian: sudo ./install_server.sh سيَعرض السكريبت بعض الأسئلة لإتمام عمليّة التهيئة، ولكن يُمكن الاعتماد على الإعداد الافتراضي والاكتفاء بالضغط على Enter، وبعد انتهاء عملية التهيئة سيكون خادم Redis يعمل في الخلفيّة (background). يُمكن تنفيذ الأمر التّالي للوصول إلى قاعدة البيانات Redis: redis-cli يُمكن اختبار Redis كالتّالي: $ redis-cli redis 127.0.0.1:6379> ping PONG redis 127.0.0.1:6379> set mykey somevalue OK redis 127.0.0.1:6379> get mykey "somevalue" أوامر Redis يتمّ إضافة بعض المُعطيات إلى سلسلة رموز (string)، والّتي تُعتبر من أبسط أنواع البيانات (datatype)، باستخدام الأمر التّالي: > SET users:SomeOne "job: SomeJob, email:example@example.com, age: some number " OK تمّ في الأمر السابق استخدام الأمر SET متبوعًا بالمُفتاح users:SomeOne، ومن ثمّ القيمة (value)، وهي سلسلة الرموز (string) نفسها. لا تُؤثر النقطتان (:) الموجودة في المُفتاح على الأمر السابق، ولكن من المُمكن الاستفادة منهما في وصف أوضح للمُفتاح المُراد تعيينه. يُمكن استعراض تفاصيل سلسلة الرموز السابقة باستخدام الأمر GET: GET users:SomeOne "job: SomeJob, email:example@example.com, age: some number " المجالات (Ranges) يتمّ تحديد مجال باستخدام مُعاملين والذين سيُمثلان العنصر الأوّل والعنصر الأخير، فالعنصر الأوّل سيُعتبر 0، وإن كان المُعامل الأخير -1، فإن جميع العناصر حتّى نهاية القائمة سيتمّ شملها، فعلى سبيل المثال، إن كانت قائمة تحتوي على ألوان قوس قزح مُرتبة بالترتيب ROYGBV، فيُمكن استعراضها كما في التّالي: > LRANGE ROYGBV 0 3 1) "red" 2) "orange" 3) "yellow" 4) "green" > LRANGE ROYGBV 0 -1 1) "red" 2) "orange" 3) "yellow" 4) "green" 5) "blue" 6) "violet" > LRANGE ROYGBV 3 -1 1) "green" 2) "blue" 3) "violet" انتهاء الصلاحية (Expiration) لا يُعتبر Redis ذو فائدة في تخزين المعلومات فقط، بل يُمكن استخدامه أيضًا في إنهاء صلاحيتها. يُعيّن الوقت اللازم على المُفتاح أنّ يتواجد خلاله إما بالثواني أو باستخدام طابع الوقت الخاصّ يونكس (Unix Time stamp)، ويتحكم الأمر EXPIRE بالمُدّة الّتي يتوجب على المُفتاح التواجد فيها، ويَعرض الأمر TTL الوقت المُتبقي حتّى انتهاء الصلاحيّة. > SET classified:information "Secret Stuff" OK > EXPIRE classified:information 45 (integer) 1 > TTL classified:information (integer) 31 وفي مُحاولة لاستعادة المعلومات بعد انقضاء مدّة الصلاحيّة، ستكون النتيجة هي nil: > GET classified:information (nil) التزايد أو العلاوة (Incrementing) يَملك Redis القدرة على زيادة سلاسل الرموز (strings) في قاعدة بياناته، مع الانتباه أنّه في حال وجود عمليّة جارية في زيادة قيمةٍ ما، فلا يستطيع أمر آخر التدخل والتعديل، هذا الأمر من شأنه أن يجعل من قاعدة البيانات ثابتة وغير شائبة. > SET population 6 OK > INCRBY population 10 (integer) 16 > INCR population (integer) 17 المداولات (Transactions) يملك Redis القدرة على إنجاز المُداولات (transactions)، والّتي يجب أنّ تخضع إلى: تنفيذ الأوامر بالترتيب، ولن يتمّ مقاطعتها خلال العمليّة من قبل طلبات أُخرى. على المُداولات أنّ تُعالج كلها دفعةً واحدة. تبدأ المُداولات بالأمر MULTI وبعد ذلك لتنفيذها يتمّ استخدام الأمر EXEC. سيتمّ الخروج من المُداولة، عند أي مُقاطعة للعمليّة، وسيواجه Redis خطًا سيوقفه من إعادة التشغيل حتّى تنفيذ الأمر edis-check-aof ليتمّ التراجع عن المُداولة الجزئية الّتي تمّت بالفعل قبل حدوث الخطأ وحذفها. سيَتمكّن الخادم بعد ذلك من إعادة التشغيل. > MULTI OK > SET population 6 QUEUED > INCRBY population 10 QUEUED > INCR population QUEUED > EXEC 1) OK 2) (integer) 16 3) (integer) 17 أنواع البيانات في Redis يَملك Redis خمسة أنواع من البيانات: Strings Sets Sorted Sets Lists Hashes سلاسل الرموز (Strings) تُعتبر سلاسل الرموز جوهر وأساس الأنواع في Redis الأوامر التّالية هي الأوامر الشائعة مع سلاسل الرموز: SET: يُعيّن قيمة إلى مُفتاح. GET: يجلب قيمة من مُفتاح. DEL: حذف مُفتاح وقيمته. INCR: زيادة قيمة مُفتاح. INCRBY: زيادة قيمة مُفتاح بقيم مُحدّدة. EXPIRE: الوقت اللازم على المُفتاح التواجد به، ويُعيّن بالثواني. تُستخدم سلاسل الرموز في تخزين الكائنات (objects): > SET newkey "the redis string begins" OK > GET newkey "the redis string begins" المجموعات (Sets) يُمكن الجمع بين سلاسل الرموز (strings)، ولذلك يُمكن استخدام مجموعات Redis، والّتي يُمكن القول عنها أنها مجموعة من سلاسل الرموز غير المُرتبة. بعض الأوامر الشائعة مع المجموعات: SADD: إضافة عنصر أو عناصر إلى مجموعة. SMEMBERS: جلب جميع العناصر المُعيّنة. SINTER: إيجاد تقاطع أكثر من مجموعة. SISMEMBER: التأكّد من وجود قيمة في مجموعة. SRANDMEMBER: جلب عنصر عشوائي. يُستفاد من المجموعات في Redis في العديد من الحالات، ولأن كل عنصر من مجموعة هو فريد، فإن إضافة عنصر إلى المجموعة لا يتطلّب عمليّة “افحص قبل الإضافة”، بدلًا من ذلك، فإن المجموعة ستتأكّد فيما إذا كان العنصر مكرّرًا أم لا، وذلك عند أي تنفيذ للأمر SADD: > SADD colors red (integer) 1 redis 127.0.0.1:6379> SADD colors orange (integer) 1 redis 127.0.0.1:6379> SADD colors yellow (integer) 1 redis 127.0.0.1:6379> SADD colors orange (integer) 0 redis 127.0.0.1:6379> SMEMBERS colors 1) "red" 2) "yellow" 3) "orange" يُستفاد من المجموعات بشكل خاصّ في فحص وضبط عناوين IPs في حال أنها فريدة لزوار صفحة ما، أو مثلًا في استخلاص عناصر بشكل عشوائي بالأمر SRANDMEMBER. المجموعات المرتبة (Sorted Sets) إن المجموعات المُرتبة هي اسمٌ على مُسمّى، فهي مجموعة من سلاسل الرموز (strings) مُرتبطة مع رقم مع ترتيب، وهو بشكلٍ افتراضيّ من الأصغر إلى الأكبر. يَعمل هذا النوع من البيانات بشكل مُلائم جدًا مع المجالات (ranges)، وبسبب التّرتيب الخاصّ به، فإن إضافة وحذف وتحديث القيم تتمّ بسرعة ملحوظة. بعض الأوامر الشائعة مع المجموعات المُرتّبة: ZADD: إضافة عناصر إلى مجموعة مُرتّبة. ZRANGE: عرض عناصر مجموعة مُرتّبة. ZREVRANGE: عرض عناصر مجموعة مُرتّبة بشكل عكسي. ZREM: إزالة عناصر من مجموعة مُرتّبة. يُمكن إنشاء مجموعة مُرتّبة كما في المثال التّالي، وهو لمساحة بعض البلدان، فعلى الرغم من تعيينها بشكل عشوائي، فإن استعراضها يَكون على التّرتيب: > ZADD countries 9 Tuvalu (integer) 1 > ZADD countries 62 Liechtenstein (integer) 1 > ZADD countries .7 Monaco (integer) 1 > ZADD countries .2 VaticanCity (integer) 1 > ZADD countries 107 Seychelles (integer) 1 redis 127.0.0.1:6379> ZRANGE countries 0 -1 1) "VaticanCity" 2) "Monaco" 3) "Tuvalu" 4) "Liechtenstein" 5) "Seychelles" القوائم (Lists) تُعتبر القوائم في Redis مجموعة من القيم المُرتّبة، وبالتّالي فهي عكس المجموعات (Sets)، والّتي هي غير مُرتّبة، فيُمكن إضافة عناصر إلى بداية ونهاية قائمة، حتّى بوجود ملايين العناصر داخل القائمة، وبسرعة كبيرة جدًا. الأوامر الأكثر شيوعًا مع القوائم: LPUSH: إضافة قيمة في بداية قائمة. RPUSH: إضافة قيمة في نهاية قائمة. LPOP: جلب وإزالة العنصر الأوّل في قائمة. LREM: إزالة العناصر من قائمة. LRANGE: جلب مجال من العناصر من قائمة. LTRIM: تعديل قائمة بترك عناصر مُحدّدة من مجال. أمثلة: > RPUSH lunch.provider alice (integer) 1 > RPUSH lunch.provider bob (integer) 2 > RPUSH lunch.provider carol (integer) 3 > RPUSH lunch.provider don (integer) 4 > RPUSH lunch.provider emily (integer) 5 عند الرغبة بالدفع (push) إلى واجهة صف الانتظار (queue)، فمن المُمكن استخدام الأمر LPUSH: LPUSH lunch.provider zoe (integer) 6 يُمكن استخدام الأمر LRANGE لاستعراض عناصر القائمة جميعًا: LRANGE lunch.provider 0 -1 1) "zoe" 2) "alice" 3) "bob" 4) "carol" 5) "don" 6) "emily" تُستخدم القوائم في مُعظم الأحيان لإنشاء خط زمني للأحداث، أو في الحفاظ على مجموعة مُحدودة من العناصر المبعثرات (Hashes) تُعتبر المبَعثرات في Redis من الأدوات المُفيدة في تمثيل الكائنات (objects) ذو العديد من الحقول (fields)، فهي مُعدّة لتخزين عدد هائل من الحقول في حجم صغير، وتستطيع البَعثرة تخزين أكثر من أربعة مليارات من أزواج قيم الحقول (field-value). بعض أوامر البعثرة الأكثر شيوعًا في Redis: HMSET: تعيين قيم بعثرة مُتعدّدة. HSET: تعيين حقل البعثرة بقيمة سلسلة رموز (string). HGET: جلب قيمة حقل البعثرة. HMGET: جلب جميع القيم من حقول البعثرة المعطاة. HGETALL: جلب جميع القيم لبعثرة ما. تُستخدم البَعثرة في وصف حساب المُستخدِم: > HMSET user:1 username someuser password 4bAc0s email someuser@example.com OK > HGETALL user:1 1) "username" 2) "jsmith" 3) "password" 4) "4bAc0s" 5) "email" 6) "jsmith@gmail.com" يتمّ استخدام الأمر HMGET للبحث عن معلومة مُحدّدة، وعرض القيم للحقول المطلوبة فقط. > HMGET user:1 username email 1) "someuser" someuser@example.com الختام انتشر Redis بسرعة كبيرة، واكتسب شهرةً واسعة بين المواقع أمثال: Github, Flickr, Disqus، وغيرها من المواقع، وذلك لتوافقه مع مُعظم لغات البرمجة، فهو بالفعل تقنية مُفيدة يُنصح بالاعتماد عليها وتجربتها. ترجمة -وبتصرّف- للمقال How To Install and Use Redis لصاحبته Etel Sverdlov.
  5. يُعتبر خادوما الويب Apache و Nginx الأكثر شهرةً من بين الخواديم المفتوحة المصدر في عالم الشبكة العنكبوتيّة، على اعتبار أنّهما مسؤولان عن خدمة وتأمين نصف تدفّق البيانات على الإنترنت، وعلى مَقدرة على تولّي مُختلف حجوم الأحمال، والعمل مع برمجيات أخرى في سبيل توفير حزمة من خدمات الويب الشاملة والكاملة لتلبية مُختلف الاحتياجات. بينما يَتشارك الخادومان Apache و Ngnix العديد من الميّزات والخاصيّات، فلا يُمكن اعتبارهما مُتشابهان، أو التفكير بأن أحدهما هو بديل عن الآخر، فكل منهما يتفّوق عن الآخر بشيءٍ ما، وعلى مُدير النظام فهم وإدراك لماذا يجب اختيار أحدهما دون الآخر، فهذا الدليل يَهدف إلى مُناقشة كيف أنّ كُل خادوم يَتميّز ويَبرز في شيء ويُخفق في آخر. مقدّمة عامّةسيتمّ أخذ نظرة سريعة عن تاريخ وبداية المشروعين وخواصّهم العامّة قبل التعمّق في الاختلاف بينهما. تاريخ خادوم الويب Apacheأَنْشَأَ “روبت ماك كول” (Robert McCool) “خادم الـ HTTP أباتشي” (Apache HTTP Server) في عام 1995، وتمّ مُتابعة تطويره تحت مظلّة “مُنشأةُ برمجيات أباتشي” (Apache Software Foundation) مُنذ العام 1999، وكان هذا الخادم هو المشروع الأساسي للمُنشأة والأكثر شهرةً عن باقي البرمجيات، فأصبح ببساطة يُشار إليه بالاسم “Apache”. يُعتبر خادم الويب أباتشي الخادم الأكثر استخدامًا على الإنترنت منذ العام 1996، وبسبب هذه الشهرة، استفاد أباتشي من توثيق ودعم باقي مشاريع البرمجيات الأُخرى. يَختار مُدراء الأنظمة الخادم أباتشي غالبًا بسبب مرونته، وقُدرته على التحمّل، وتوفّر دعمه العالي والمُنتشر، كما يُحسب له قابليته على التوسّع عبر نظام الوحدات (modules) الديناميكيّة، واستطاعته على مُعالجة عدد كبير من اللغات المُفسّرة (interpreted languages) من دون الحاجة إلى برمجيّة مٌستقلّة وسيطة. تاريخ خادوم الويب Nginxبَدأ “ايجور سيسيوﭫ” في عام 2002 العمل Nginx للإجابة وحلّ المُشكلة المعروفة بالاسم C10K، والّتي كانت تُشكّل تحدّيًا كبيرًا لخوادم الويب لتُصبح قادرة على تولّي عشرة آلاف اتصال مُتزامن (concurrent) وذلك في تلبية حاجة الويب الحديث، وأُنتجت الإصدارة الأوليّة والمُتاحة للعُموم في عام 2004 مُقدمةً حلًا لهذه المُشكلة، وذلك بالاعتماد على معماريّة مدفوعة بالحالة (event-driven) ولا مُتزامنة. انتشر Nginx كالنار في الهشيم مُنذ إصداره، بمُقتضى خفته واستخدامه الخفيف للمَوارد، وقدرته على التوسّع وتحمّل الضغط العالي وبأقل عتاد مُمكن، وتفوّق Nginx بتأمين المُحتوى الثّابت (static content) بسرعة، وبتصميمه لتمرير الطلبات الديناميكيّة (المُتغيّرة) إلى برمجيات أُخرى قادرة على مُعالجة هذا النوع من المُحتوى. يختار مُدراء الأنظمة الخادم Nginx غالبًا بسبب استهلاكه الأمثل للمَوارد، واستجابته العالية مع الضغط المتزايد. معماريّة مُعالجة الاتصال (Connection Handling Architecture)يَكمن الاختلاف الواضح بين أباتشي و Nginx في طريقة كلٍ منهما في مُعالجة الاتصالات وتدفّق البيانات (traffic)، وربّما هذا السبب وراء الاختلاف في طريقة كل من الخادمين في الاستجابة إلى حالة تدفّق البيانات المُختلفة. وحدات أباتشي (Apache Modules)يقدّم أباتشي تشكيلةً من وحدات المُعالجة المُتعدّدة (multi-processing)، والّتي يُطلق عليها بـ MPMs، والغرض منها تحديد آليّة مُعالجة طلبات العميل، ويَسمح ذلك مُدراء الأنظمة عامّةً بالتبديل بين معماريّة مُعالجة الاتصال بسهولة، والوحدات هي: mpm_prefork: تَستنسخ وتُوالد هذه الوحدة الخاصّة بالمُعالجة عمليّات (processes) باستخدام سلسلة وحيدة (single thread)، على أنّ تكون كل عمليّة لمُعالجة طلب، ويستطيع كل ابن مُعالجة اتصال واحد في نفس الوقت، وطالما أنّ عدد الطلبات أقل من عدد العمليّات، فستكون هذه الوحدة سريعةً جدًا، ولكن يَنخفض الأداء بسرعة بعد تخطّي الطلبات عدد العمليّات، ولذلك لا يُعتبر هذا النمط بالخيار الجيّد للعديد من السيناريوهات، فكل عمليّة لها تأثير بليغ على استهلاك الذاكرة (RAM)، ولهذا السبب تُصعّب هذه الوحدة من عمليّة التوسّع بطريقة مُلائمة، ومع هذا تبقى هذه الوحدة خيارًا جيّدًا إن تمّ استخدامها مقترنةً مع مُقوّمات (components) أُخرى لم تُبنى بالأساس آخذةً بعين الاعتبار السلاسل (threads)، فلغة PHP ليست سلسلة آمنة (thread-safe)، ولذلك يُنصح بهذه الوحدة باعتبارها الطريقة الوحيدة الآمنة للعمل مع mod_php والّتي هي وحدة من وحدات أباتشي لمُعالجة هذا النوع من الملفّات. mpm_worker: تستنسخ وتُوالد هذه الوحدة عمليّات (processes) كل منها ذات قُدرة على إدارة سلاسل مُتعدّدة (multiple threads)، تستطيع كل واحدة من هذه السلاسل مُعالجة اتصال وحيد، تُعتبر هذه السلاسل أكثر كفاءة من العمليّات، بسبب أنّ هذه الوحدة تتوسّع (scales)، وتتحمّل المزيد من الضغط أفضل من الوحدة prefork MPM، وباعتبار أنّه يوجد سلاسل أكثر من العمليّات، فهذا يعني أيضًا أنّ الاتصالات الجديدة تستطيع مُباشرةً استهلاك واستخدام سلسلةبدلًا من اضطرارها إلى الانتظار لتوفّر عمليّة مُتاحة. mpm_event: تَعمل هذه الوحدة بشكل مُشابه إلى الوحدة worker، ولكنها مُحسّنة لتتولّى اتصالات keep-alive، فعند استخدام الوحدة worker فإن الاتصال سيَحتفظ بالسلسلة (thread) بصرف النظر فيما إذا كان الطلب نشطًا فيما صُنع من أجله ما دام الاتصال محفوظًا نشطًا، فالوحدة mpm_event تتولّى الاتصالات keep-alive بالاحتفاظ جانبًا بسلاسل مكرّسة لمُعالجتها، وبتمرير الطلبات النشطة إلى سلاسل أُخرى، وهذا من شأنه أنّ يُبعد الوحدة من الغوص بطلبات keep-alive، الأمر الّذي يُجيز بتنفيذ الطلبات (execution) بشكل أسرع، وهذا الأسلوب أصبح يعمل بشكل مُستقر مع الإصدار Apache 2.4. أصبح الأمر أكثر وضوحًا، حيث تقدّم خوادم أباتشي بنية معماريّة مرنة للاختيار بين مُختلف الاتصالات وخوارزمية مُعيّنة في مُعالجة الطلبات، وبُنيت هذه الخيارات في الدرجة الأولى من تطوّر الخادم والحاجة المُتزايدة للاتصالات المُتزامنة لتواكب طبيعة الإنترنت بعد تغيرها وتطوّرها. آليّة مُعالجة الاتصال في خادوم Nginxقَدِم Nginx إلى عالم خوادم الويب بعد قدوم أباتشي، مَبنيًّا ومُعدًّا لمشاكل الاتصالات المُتزامنة (concurrency) الّتي تواجه المواقع عند التوسّع، مُحمّلًا بهذه المعرفة، صُمّمَ Nginx من جذوره ليستخدم خوارزميّة في مُعالجة اتصالات مدفوعة بالحالة (event-driven)، غير مُستوقفة (non-blocking)، ولا مُتزامِنة. يستنسخ ويُوالد Nginx من العمليّات العاملة (worker processes)، ويستطيع كلٍ مِنها مُعالجة آلاف الاتصالات، وتُنجذ العمليّات العاملة ذلك عن طريق تطبيق/تنفيذ آلية حلقيّة سريعة، والّتي تفحص بشكل مُستمر حالات العمليّات (processes events)، وإن فصل المُهمّة الفعليّة عن الاتصالات يسمح لكلعامل بالاهتمام بنفسه باتصال فقط عند بدء حالة جديدة. يتموضع كل اتصال مُعالج من قبل العامل ضمن حلقة الحالة (event loop) في مكان تواجد بقية الاتصالات، وتُعالج الأحداث بشكل لا مُتزامن ضمن الحلقة، ليتمّ إنجاز المُهمّة بطريقة غير مُستوقفة (non-blocking)، وعندما يُغلق الاتصال سيتمّ نزعه من الحلقة. يَسمح هذا الأسلوب من مُعالجة الاتصال Nginx بتحمّل الضغط العالي بشكل لا يُصدّق وبأقل المَوارد المُتاحة، وباعتبار أنّ الخادم ذو سلسلة وحيدة (single-threaded) ولا تتوالد العمليّات لتُعالج كل اتصال جديد، فإن استهلاك المُعالج (CPU)، والذّاكرة يبقى ثابتًا نسبيّا، حتّى في أوقات الذروة. كيف يُعالج أباتشي و Nginx المُحتوى الثّابت والمحتوى الديناميكي (المُتغيّر)إن أبرز ما يتمّ النظر إليه عند المُقارنة بين الخادمين هي طريقة كلٍ منهما في التعامل مع طلبات المُحتوى الثّابت (static)، والمُحتوى المُتغيّر (dynamic). كيف يتعامل أباتشي مع المُحتوى الثّابت والمُتغيّرتستطيع خوادم أباتشي التعامل مع المُحتوى الثّابت باستخدام الطريقة التقليديّة المُعتمدة على الملفّات، ويعود أداء هذه الإجراءات (operations) في الدرجة الأولى على دور ووظيفة أساليب الوحدات (MPM) المشروحة سابقًا. يستطيع أباتشي أيضًا مُعالجة المُحتوى الديناميكي (المُتغيّر) بدمج مُعالج اللغة المُراد مُعالجتها داخل كل من نماذجه العاملة (worker instances)، وهذا يَسمح له بتنفيذ المُحتوى الديناميكي داخل خادم الويب نفسه بدون الحاجة إلى الاعتماد على مُقوّمات خارجيّة، ومن المُمكن تفعيل هذه المُعالجات الديناميكيّة (المُتغيّرة) من خلال استخدام وحدات قابلة للتحميل بشكل ديناميكي. إن قدرة أباتشي على مُعالجة المُحتوى الديناميكي بشكل داخلي تعني أنّ الإعداد يُصبح أسهل لمُعالجة هذا النوع من المُحتوى، فليس من الضروري تنسيق عمليّة الربط مع برمجيات إضافيّة، وتستطيع الوحدات وبسهولة أنّ تقوم بالتبديل عندما تتغيّر مُتطلّبات المُحتوى. كيف يتعامل Nginx مع المُحتوى الثّابت والمُتغيّرلا يَملك Nginx بطبيعته أي قدرة على مُعالجة المُحتوى الديناميكي، ولمُعالجة شيفرة PHP وطلبات المُحتوى الديناميكي، فإن على Nginx تمرير الطلبات إلى مُعالج خارجي من أجل التنفيذ (execution) والانتظار ريثما يتم الانتهاء من مُعالجة هذا المُحتوى ليتمّ إعادة إعادته، ومن ثم عرض النتائج على العميل. يَنبغي على مُدراء الأنظمة الانتباه إلى أنّ الأسلوب الّذي ينتهجه Nginx يستوجب إعدادًا بينه وبين المُعالج وباستخدام واحدًا من البرتوكولات الّتي يفهمها Nginx أمثال: HTTP, FastCGI, SCGI,uWSGI, memcache، وهذا من شأنه أنّ يُعقّد الأمور بعض الشيء، خصوصًا عند مُحاولة توقّع عدد الاتصالات اللازم السماح بها، حيثُ أنّه سيتمّ استخدام اتصالًا إضافيًا لكل مُعالج يتمّ استدعاؤه. من ناحية أخرى، إن هذا الأسلوب يقدّم بعضًا من الأفضليّة، عندما نعلم أنّ مُفسّر المُحتوى الديناميكي غير مُدمج في عمليّة العامل، وتكلفة هذه الطريقة ستُدفع للمُحتوى الديناميكي فقط، وعلى أنّ يُقدّم المُحتوى الثّابت بطريقة مُباشرة، ولا يتمّ الاتصال بالمُفسر إلا عند الحاجة، والجدير بالذكر أنّ أباتشي يستطيع العمل بهذا الأسلوب، ولكن بعمله ذلك سيتخلّى عندها عن بعض ميزاته. الاختلاف بين الإعداد الموزّع (Distributed) والإعداد المركزي (Centralized)يَعتبر مُدراء الأنظمة الاختلاف الأكبر والبارز بين هذين الخادمين هو فيما إذا كان الإعداد والتخصيص على مُستوى المسار مسموحًا أو لا ضمن مسارات (directories)المُحتوى. فلسفة Apache في الإعداديُضمّن أباتشي خيارًا للسماح بالإعداد لكل مسار عن طريق تَفحُّص (inspecting) وتفسير (interpreting) التعليمات أو التوجيهات الموجودة في الملفات المخفيّة داخل مسارات المُحتوى نفسها، وهذه الملفّات معروفة بملفات .htaccess. باعتبار أنّ هذه الملفّات تَقطن داخل مسارات المُحتوى نفسها، فعند مُعالجة طلبٍ ما، فإن أباتشي يَفحص كل جزء من مسار الملفّ المطلوب باحثًا عن ملفّ .htaccess ليُطبّق التوجيهات الّتي بداخله، وهذا من شأنه أنّ يسمح للإعداد اللامركزي لخادم الويب، والذي غالبًا ما يُستخدم لإنجاز: إعادة كتابة عنوان الموقع (URL rewrites)تقييد الوصول (access restrictions)التفويض والمُصادقة (authorization and authentication)سياسات التخبئة (caching policies)بالطبع يُمكن للأمثلة السابقة إعدادها عن طريق ملفّ إعدادات أباتشي الرئيسي، ولكن استخدام ملفات.htaccess يَملك بعض الميزات: أوّلًا، باعتبار أنّها تُفسّر في كل مرّة توجد بها مع المسار المطلوب، فهي تُنفّذ مُباشرةً بدون إعادة تحميل الخادم.ثانيًا، تجعل من المُمكن السماح للمُستخدِمين غير المصرّح لهم بالتحكم بجانب معيّن من المُحتوى الخاصّة بهم بدون إعطائهم تحكم كامل لملفّ الإعدادات.يُقدّم هذا النمط من الإعداد طريقة سهلة ونموذجيّة، وخاصّة لبعض برمجيات الويب، مثل أنظمة إدارة المُحتوى (CMS)، لغرض إعداد بيئتها بدون مَنح إذن وصول إلى ملفّ إعدادات مركزيّ، وكما هو معروف يُستخدم هذا الأسلوب مع مزودات الاستضافة المُشتركة (shared hosting providers) لصون والحفاظ على الإعدادات الرئيسية مع إمكانيّة منح العُملاء أفضليّة التحكّم بمسارات مُعيّنة. فلسفة Nginx في الإعدادلا يُفسّر Nginx ملفّات .htaccess، ولا يُقدّم أي آليّة للتعامل مع كل مسار من دون استخدام ملفّ إعدادات رئيسي، قد يبدو هذا الأسلوب أقل مرونةً من أسلوب أباتشي، ولكن من ناحية أُخرى فلهذا الأسلوب أفضليته. إن عدم الاعتماد على نظام ملفّات .htaccess الخاصّ بالإعداد على مستوى المسارات يُقدّم سرعةً في الأداءً، فخادم أباتشي عليه القيام بتفحّص المسار الجذر لكل طلب يصله، وعند وجود ملفّ أو أكثر خلال عمليّة البحث، يتم قراءة محتوياته وتفسيرها، ولكن Nginx لا يفعل ذلك، فهو يخدم الطلبات بسرعة أكبر بالاعتماد على مكان وحيد للبحث عنه. أفضليّة أُخرى مُتعلّقة بالحماية، فإن توزيع ملفّات الإعدادات على مستوى المسارات يوزّع مسؤوليّة الحماية على كل المُستخدِمين، الّذين قد يكونوا في معظم الأحوال غير موثوقون لتولّي هذه المُهمّة بالشكل الأمثل، فعندما يقوم مُدير النظام بتولّي مُهمة التحكم بالخادم ككل، يمنع ذلك من حدوث أخطاء، والتي قد تحدث في حال منح صلاحيات وصول لأطراف أُخرى. يجدر الذكر أنّه من المُمكن تعطيل تفسير ملفّات .htaccess’ فيأباتشي`، في حال أنها تُشكل نوعًا من القلق لمُدير النّظام. الاختلاف بين تفسير الملفّات وتفسير URIلا يقتصر الاختلاف بين الخادومين على ما سبق فقط، فيظهر الاختلاف الآخر في كيفيّة تفسير كلٍ منهما للطلبات (requests) وربطها مع المَوارد المُتواجدة على النّظام. كيف يُفسر Apache الطلباتيقدّم أباتشي القدرة على تفسير الطلب إما كمَورد فيزيائي (حقيقي) على نظام الملفّات (filesystem) أو عنوان URI الّذي قد يحتاج أسلوب أكثر تجرّد، ويستخدم أباتشي بشكلٍ عام للأسلوب الأول كتل (blocks) وهي إما <Directory> أو <Files>، بينما يستخدم كتل <Location>للمَوارد الأكثر تجرّدًا. صُمّم أباتشي من الأساس كخادم ويب، لذلك في مُعظم الأحيان فإن السلوك الافتراضيّ هو تفسير الطلبات كمَوارد نظام ملفّات (filesystem)، حيثُ يبدأ بتتبّع جذر المُستند وإلحاقه بجزئية الطلب متبوعًا باسم المُضيف (host) ورقم المنفذ في مُحاولة لإيجاد الملفّ المطلوب، بمعنى آخر وببساطة، تتمثّل هرميّة نظام الملفّات على الويب كشجرة مُستند. يُقدّم أباتشي عددًا من البدائل عندما لا يتوافق الطلب مع نظام الملفّات المقصود، فمثلًا من المُمكن استخدام الموجّه Alias لربط عنوان البديل، مع العلم أنّ استخدام الكتل <Location> هو طريقة للتعامل مع URI نفسها بدلًا من نظام الملفّات، كما يُمكن استخدام التعابير النمطيّة (regular expression)، والّتي من المُمكن استخدامها لتطبيق الإعداد بسهولة أكبر في كامل نظام الملفّات. يُعوّل أباتشي على نظام الملفّات بشكل كبير، يظهر ذلك جليًا في اعتماده على ملفّات .htaccessلإعداد كل مسار، حتّى أنّ التوثيق الرسميّ الخاصّ به يحذر من استخدام كتل مُعتمدة على URI في تقييد الوصول عندما يكون الطلب يَعتمد بشكل أو بآخر على نظام الملفّات. كيف يُفسّر Nginx الطلباتأُنشِأ Nginx ليكون خادمًا للويب وخادمًا وكيلًا/وسيطًا (proxy server)، ونظرًا إلى المعماريّة المطلوبة للعمل بهذه الأدوار، فإنه يعمل بشكل رئيسي مع URIs، والتحويل إلى نظام الملفّات عند الضرورة. يُمكن رؤية ذلك في بعض جوانب بناء وتفسير ملفّات إعدادات Nginx، فلا يوفّر Nginx آليّة لتحديد إعدادًا لمسار نظام الملفّات، بل يَستعيض عنها بتحليل URI نفسه. يُمكن توضيح ذلك بالمثال، كتل الإعداد الأوليّ لـ Nginx هي: server و location، الكتلة serverتُفسّر المُضيف الجاري طلبه، بينما الكتل مسؤولة عن مُطابقة أجزاء من URI التي تأتي بعد المُضيف والمنفذ، في هذه المرحلة يتمّ تفسير الطلب كـ URI، وليس كعنوان على نظام الملفّات. يتوجّب في نهاية المطاف على جميع الطلبات أنّ تُربط مع عنوان على نظام الملفّات وذلك للملفّات الثّابتة، فأولًا، سيَختار Nginx كتل server و location الّتي سوف تتولّى الطلب، ومن ثم ضم جزر المُستند مع الـ URI. إن تحليل ومُعالجة الطلب قبل كل شيء على شكل URIs بدلًا من عناوين نظام الملفّات يَسمح لـ Nginxالعمل بسهولة وعلى حدٍّ سواء كخادم وسيط (بروكسي)، وكخادم بريد، وخادم ويب، فقد تمّ إعداده ليُلائم كيف له أنّ يستجيب لأنماط الطلبات المُختلفة، ولا يفحص Nginx نظام الملفّات حتّى يكون جاهزًا ليَخدم الطلب، وهذا يُفسّر لماذا هو لا يُطبّق نمط ملفّات .htaccess. الوحداتيتوسع كلا الخادومان عن طريق نظام الوحدات، ولكن طريقة عملهما تختلف عن الآخر بشكل كبير. كيف يستخدم أباتشي نظام الوحدات (Modules)؟يَسمح نظام وحدات أباتشي بطريقة آليّة وديناميكيّة بتركيب ونزع الوحدات ليتناسب مع مُتطلّبات مُدير النظام خلال عمليّة تشغيل الخادم، وتتواجد نواة أباتشي دائمًا بكل جاهزية، بينما يُمكن تشغيل أو تعطيل الوحدات، أو حتّى حذفها أو إضافة ما يلزم إلى الخادم. يستخدم أباتشي الوحدات في العديد من المهام، ونظرًا للباع الطويل لمنصة أباتشي، فيتوفّر عدد هائل من مكتبات الوحدات، والّتي من المُمكن استخدامها في تعديل بعض الوظائف الداخليّة في بنية خادم أباتشي، فمثلًا الوحدة mod_php تقوم بدمج مُفسّر PHP داخل كل عامل (worker). لا تنحصر الوحدات لمُعالجة المُحتوى الديناميكي (المُتغيّر) فقط، فيُمكن استخدامها في العديد من الوظائف، فيُمكن استخدامها في: rewriting URLs: إعادة كتابة العناوينauthenticating: المُصادقةlogging: التّتبّعcaching: التخبئةcompression: الضغطproxying: الوساطةencrypting: التشفيركيف يتعامل Nginx مع نظام الوحدات (Modules)يُطبّق ويتعامل Nginx مع نظام الوحدات، ولكن يختلف الأمر عما هو في نظام أباتشي، فلا تُحمّل الوحدات بشكل ديناميكي في نظام Nginx، لذلك يجب على هذه الوحدات أنّ تُختار وتُترجم (compiled) إلى النواة. قد يبدو الأمر صعبًا للعديد من المُستخدمين وخاصّة لهؤلاء الذين لا يُحبذون صيانة برمجياتهم المُترجمة (compiled) بدون الاستعانة بنظام حزم تقليدي، وعلى الرغم من أنّ حزم الموزّع تتضمّن الوحدات الأكثر استخدامًا، ولكن عند الحاجة إلى وحدة غير شائعة، سيتوجب على مُدير النظام بناء الخادم من المصدر بنفسه. تَبقى وحدات Nginx مع ذلك ذات فائدة، وتسمح لمُدير النّظام بتحديد ماذا يجب على الخادم أنّ يحتوي من وظائف، أيضًا بعض المُدراء ينظر إلى الأمر من منظور الحماية، حيثُ أنّ المُكوّنات الاعتباطيّة لا يُمكن أن تُدرج داخل الخادم. تُقدّم وحدات Nginx مقدرات مُماثلة للوحدات الّتي المُقدّمة من أباتشي، على سبيل المثال، توفّر وحدات Nginx: proxying support: الوساطةcompression: الضغطlogging: التّتبّعrewriting: إعادة كتابة العنوانauthentication: المُصادقةencryption: التشفيرالدعم والتوافُقيّة والتوثيقيجب دائمًا التأكد من آليّة بناء الخادم ومُتطلباتها، وما الّذي على مُدير النّظام عمله لبناء خادم يعمل بأبسط الإمكانيات، وما هو حجم الدعم والمُساعدة المتوفّر لهذه البرمجية. الدعم في أباتشييُعرف الخادم أباتشي بباعه الطويل في هذا المجال، ولذلك فإن الدعم الخاصّ به متواجد وبقوّة، حيثُ يتوفّر توثيق مُمتاز لمكتباته الخاصّة به ومكتبات الطرف الثالث (الخارجيّة)، وعلى كافّة المُستويات، سواء كان لنواة الخادم أو للجزئيات المُرتبطة ببرمجيات أُخرى. يتوفّر بجانب التوثيق، العديد من الأدوات ومشاريع الويب لتسريع بدء العمل مع بيئة الخادم، وهي موجودة ضمن المشاريع نفسها أو مُتوفّرة ضمن برمجيات الحزم المعروفة. يَملك أباتشي بشكلٍ عام دعمًا قويًا من قِبل مشاريع الطرف الثالث، وذلك بسبب حصته السوقيّة، وقِدَمه، كما يَملك مُعظم مُدراء الأنظمة بشكل أو بآخر معرفة جيّدة بخادم أباتشي، ليس فقط بسبب انتشاره، ولكن أيضًا بسبب أنّ معظمهم بشكل أو بآخر يستخدم الاستضافة المُشتركة (shared-hosting)، والّتي تعتمد على خادم أباتشي بشكل حصري، لمقدرته الإدارية الموزّعة باستخدام ملفّ .htaccess. الدعم في Nginxيكسب Nginx المزيد من الدعم مع ازدياد المُستخدِمين بسبب أدائه العالي، ولكن يبقى عليه التطوير من نفسه في بعض الجزئيات. قد كان من الصعب إيجاد توثيق مفهوم وواضح بالغة الإنكليزية للخادم Nginx في البداية، نظرًا إلى أنّ تطويره وتوثيقه تمّ بالغة الروسية، ومع ازدياد الاهتمام بالمشروع، أصبح هناك وفرة من المصادر على الموقع الرسميّ وغيره من الدعم الخارجي. أصبح الدعم متوفّرًا أكثر من ذي قبل فيما يخص تطبيقات الطرف الثالث، وبدأت بعض الحزم بتقدم خيارات الإعداد التلقائي سواءً لـ أباتشي أو Nginx، وعند عدم توفّر الدعم، فإن إعداد Nginx مع البرمجيات البديلة عادةً ما يكون واضحًا ومُيسرًا طالما أنّ برمجية الطرف الثالث تملك توثيقًا جيّدًا لمُتطلّباتها. استخدام Apache و Nginx معًاتمّ عرض فوائد وقصور كلا الخادومين، ويجب على مُدير النّظام في هذه المرحلة أنّ يُحدّد أيًا منهما يُناسب احتياجاته، ولكن يجد العديد من المُستخدِمين أنّه من المُمكن تقوية خادوم الويب عند استخدام كلٍ من أباتشي و Nginx جنبًا إلى جنب. إن إتمام هذه الشراكة يتمّ عن طريق تَمَوْضُع Nginx أمام أباتشي كوكيل/وسيط عكسي (reverse proxy)، وهذه يسمح لـ Nginx بمُعالجة جميع الطلبات من العُملاء، الأمر الّذي يَسمح بالاستفادة من سرعة Nginx وقدرته على تولّي عدد كبير من الاتصال في وقتٍ واحد. إن خدمة الملفّات الثّابتة بسرعة كبيرة ومباشرةً إلى العُملاء، هو الأمر الّذي يتفوّق به Nginx، ولكن وللمُحتوى الديناميكي، ملفات PHP مثلًا، سيُوكل Nginx الطلبات إلى أباتشي لمُعالجتها والعودة بصفحة بالنتيجة النهائيّة، ليستطيع Nginx عندها تمرير المُحتوى إلى العميل. يعمل هذا الإعداد بشكل جيّد للعديد من مُدراء الأنظمة، وذلك بسبب أنّه يسمح لـ Nginx ليعمل كآلة فرز وتصنيف، بمعنى أنّه سيتولّى مُعالجة جميع الطلبات طالما أنّه يستطيع ذلك، وتمرير ما لا يستطيع التعامل معه، وبتخفيض الطلبات المطلوب من خادم أباتشي تولّيها، سيُخفف بعضًا من الاستيقاف (blocking) الّذي قد يحدث عندما يستهلك أباتشي المزيد من المُعالج. يَسمح هذا الإعداد أيضًا لمُدراء الأنظمة بالتوسّع عن طريق إضافة خادم خلفي (backend) على حسب الحاجة والضرورة، ومن المُمكن إعداد Nginx لتمرير الطلبات إلى تجمّع (pool) من الخوادم بسهولة، الأمر الّذي يزيد من الأداء والفعاليّة. الختاميُقدّم كلًا من أباتشي و Nginx مُرونة في الاستخدام، وقوّةً في الأداء، والتفضيل بينهما هو لأمرٌ يَعتمد على تقدير مُتطلبات ووظائف الخادم، وعلى مُدير النّظام أنّ لا يسأل: هو أفضل خادم ويب؟، بل السؤال الّذي يجب سؤاله هو، ما هو أفضل خادم ويب لمشروعي الّذي يتطلّب كذا وكذا؟ يوجد بالفعل اختلافات بين المشروعين، هذه الاختلافات من شأنها أن تأثر على الأداء، والقدرات، والوقت المُستغرق في إتمام أي منهما للعمل بالجاهزيّة الكاملة، ولكي يتمّ اختيار الأفضل يُنصح بعمل تسوية أو مقايضة بين المحاسن والمساوئ، ففي نهاية المطاف لا يوجد خادم يُلبي كافة الاحتياجات، ويَكمن الحلّ في ترتيب الأولويات. ترجمة –وبتصرّف– للمقال Apache vs Nginx: Practical Considerations لصاحبه Justin Ellingwood.
  6. يتناول هذا المقال محاسن ومساوئ استخدام ذاكرة وهميّة (virtual memory)، أو كما يُطلق عليها بملفّ التبديل (swap file)، أو كما تُطلِق أنظمة ويندوز على هذه التقنيّة بالترقيم (paging)، أيضا سيتمّ التَّطَرُّق إلى كيفيّة تحديد فيما إذا كان النّظام المؤجّر (الخادوم) يستخدم هذه الذّاكرة الوهميّة أم لا، كما سيتمّ التَّطَرُّق إلى الاختلاف بين ملفّ التبديل (swap file)، وقسم التبديل (swap partition)، وكما سيتمّ تناول آلية إنشاء ملفّ تبديل، وكيفيّة إعداد ملفّات “swappiness”، والّتي تسمح لمُدير النظام بتحديد مدى الاعتماد على الذّاكرة الوهميّة، والحجم المُناسب للاستخدام. يمكن الاستزادة والقراءة عن التبديل (Swap)، والذّاكرة الوهميّة على موسوعة ويكبيديا، والّتي ستجيب على الكثير من الأسئلة الّتي لن يتطرّق لها هذا الشرح. سيتمّ اقتباس أحد الأجزاء المهمّة: الذّاكرة الوهميّة ومُتطلّباتُهاماهي الذّاكرة الوهميّة ولماذا يجب استخدامها؟ليس المهم إن كان النظام يَملك ذاكرة وصول عشوائي من الحجم 512mb، أو حتّى 8mb، وليس مُهمًا إن كان نظام التشغيل هو Arch أو Fedora أو CentOS أو Debian، أو حتّى Ubuntu، فإن التطبيقات أوالخواديم ستحتاج إلى المزيد من الذّاكرة العشوائيّة الفيزيائيّة، أو الذّاكرة المُحدّدة (memory allocated) الوهميّة عندما يكون الخادوم خادومًا وهميًّا، كما هو حال الخادوم المُستخدم في هذا الدليل. إنّ معرفة فيما إذا كانت الذّاكرة الوهميّة غير مفعّلة على النّظام لأمرٌ ضروريٌ يجب على مُدير النظام أن يُدركه، حيثُ أنّ النّظام في حال وصوله إلى نقطةٍ ما لا يتوفّر به أي ذاكرة حرّة، وطلبت خدمةٌ ما، أو برنامجٌ ما، أو ربما خادم الوب نفسه إلى المزيد من الذّاكرة، سيؤدي ذلك إلى فشل هذه الخدمة أو البرنامج عن العمل، وبناءً على نظام التشغيل وإعداداته، فمن المُمكن جدًا أنّ يسبب ذلك إلى مشاكلٍ لا تُحمد عُقباها، أو على الأقل ستصبح البرامج في حالة من عدم الاستقرار، وأيضًا قد تُجبر بعض التطبيقات على التوقف عن العمل لتحرير مساحة الذّاكرة المطلوبة، الأمر الّذي يزيد من تعقيد الأمور، خاصّة عندما يكون هذا الخادوم خادومًا يعمل في البيئة الحقيقية (production server)، وليست البيئة التّطويريّة (development server). يَنصح الخبراء، وبسبب الاحتماليّة السابقة، مُدراء الأنظمة، وحتّى الأشخاص غير المتخصّصين، وعلى أي نظام تشغيل، سواء Windows، أو OSX، أو حتّى الأجهزة اللّوحيّة الخاصّة الّتي تعمل بنظام التشغيل Android، بوجوب تفعيل الذّاكرة الوهميّة، حتّى ولو بحجمٍ صغيرٍ. آلية عمل الذّاكرة الوهميّةتُقدّم الذّاكرة الوهميّة للنظام، وبطبيعة الحال للتطبيقات الخاصّة به، ذاكرة RAM وهميّة إضافية، بالإضافة إلى ما يقدمه النّظام من ذاكرة فيزيائيّة – في حالة الخادوم الوهميّ ستكون الذّاكرة هي الذّاكرة المُحدّدة (allocated memory)، وليست الذّاكرة الفيزيائيّة – تعمل الذّاكرة الوهميّة عملها بالاستعانة بأقراص التخزين (disks) في سبيل تقديم هذه المساحة الإضافيّة، وذلك عن طريق تبادل المعطيات ذهابًا وإيابًا بين ذاكرة النّظام، والذّاكرة الوهميّة، وعلى حسب الحاجة. يجب أنّ يعي مُدراء الأنظمة أنّ عمليّة الكتابة والقراءة على الأقراص (disks) – حتّى السريع منها SSD – هي أبطأ بكثير من الكتابة على ذاكرة النّظام الحقيقيّة، فعلى الرغم من أنّ الذّاكرة الوهميّة ستقدّم مساحة تخزين لتنقذ بها موارد النّظام، من تطبيقات وخدمات لتعمل بشكلٍ ملائم، وتجنيبها الخروج عن العمليّة التشغيليّة المخصّصة لها (وذلك عن طريق عدم الوقوع في شرك “امتلاء الذّاكرة“) فإن الذّاكرة الوهميّة ليست بالبديل عن الذّاكرة الفيزيائيّة، وليست بالحلّ العمليّ الذي يُمكن الاعتماد عليه، ولا يُمكن بأي حالٍ من الأحوال الاستغناء عن ترقية الذّاكرة الفعليّة الخاصّة بالنظام إنّ كان النظام يستعين بالذّاكرة الوهميّة بشكلٍ كبير. قد لا تبدو فكرة هذا الدليل بتلك الأهميّة لبعض خُبراء الأنظمة، ولكنها في حقيقة الأمر معلومات لا يُمكن تجاهلها، وخاصّةً لأي شخص يستخدم خدمات الاستضافة (hosting services)، وبالتحديد لهؤلاء الجُدد منهم على أنظمة VPS بشكلٍ عام، أو أي خادومٍ مهما كان. مُتطلّبات بيئة العملتتطلّب بيئة العمل إعدادًا بسيطًا للغاية، ومن المُفترض أنّ تعمل هذه التقنيّة على جميع التوزيعات باختلاف أشكالها ونكهاتها، أو مع الأنظمة الوهميّة أو الفيزيائيّة، حتّى أنها تعمل على أنظمة Android، سواءً أجهزة الهاتف المحمول، أو الأجهزة اللوحيّة ولكن بشرط توفّر صلاحيات وصول عالية (root). مُتطلّبات تطبيق هذا الدليلخادوم وهميّ يعمل بأحد أنظمة التشغيل المُعتمدة على Linuxصلاحيات وصول كاملة سواءً كان الخادوم محلي local أو يعتمد على تقنيّة الوصول عن بُعد vnc أو باستخدام تقنية ssh.الأوامر الّتي سيتمّ استخدامها هي: free, swapon, dd, mkswap، والّتي من المُفترض توفّرها على أي منصّة.تَقوم مُعظم المنصّات وبشكل آليّ بإنشاء إما قسم تبادل، أو ملفّ خاص داخل قسم النظام، وذلك خلال عمليّة إعداد النّظام، وبحجمٍ عادةً ما يكون مُعتمدًا على الذّاكرة الحقيقيّة للنظام RAM، فإما أنّ يكون نفس الحجم الذّاكرة أو ضعفها. المحاسن والمساوئتجدُر الإشارة قبل الدخول في التفاصيل، أنّ أقراص SSD: أسرع بكثير من الأقراص الصلبة العاديّة.لا تعاني من انخفاض أداء عند البحث (low seek times)، والذي يُسببه رأس القرص الصلب عند تنقله الفيزيائيّ لقراءة البيانات.معدّل طلبات إدخال وإخراج (IO) مُنخفض خلال الثانية الواحدة.تستطيع القراءة من أجزاء متعدّدة وفي نفس الوقت، بينما لا تستطيع الأقراص الصلبة العاديّة القراءة سوى من جزء مُحدّد في الوقت نفسه.تُقدم أقراص التخزين SSD قيمةً إضافيّة للذاكرة الوهميّة، وتُقلّل من المعاناة الّتي قد يُواجها مُدير النّظام مع الأقراص الصلبة، ومع ذلك فليس من المُستحسن الاعتماد عليها واستخدامها بدلًا من الذّاكرة RAM، خاصّةً مع الخواديم ذات الحِمل العالي: خواديم البريد الإلكتروني (web mail)، أو خواديم الوب (web server)، أو خواديم قواعد البيانات (database server). محاسن استخدام الذّاكرة الوهميّةحماية ضد أخطاء “امتلاء الذّاكرة” (out of memory)، أو ما يُشار إليها بالاختصارOOM، بالإضافة إلى الحماية من انهيار النّظام، والحماية من دخول الخادوم في حالة عدم استقرار.زيادة الذّاكرة المُتوفّرة للنظام، الأمر الّذي يسمح بتشغيل المزيد من البرامج والتطبيقات بنفس الوقت، مع توفّر أمان عالي أثناء عملها.تقوم أقراص التخزين من نوع SSD بالتقليل من الفتور (lag)، بالإضافة إلى التقليل من عدد النقرات (thrashing)، وذلك عن طريق زيادة وقت استجابة الترقيم (paging).مساوئ استخدام الذّاكرة الوهميّةتزداد معدّل النقرات (thrashing)، عندما يكون النّظام مشغولًا جدًا، ويطلب ذاكرة أكثر من المُعدّل الطّبيعيّ، وعندما لا تستطع الذّاكرة الفيزيائية تلبية حاجة النّظام، سيُجبر النّظام على الدخول في دوامة يقوم بها بنقل بيانات البرامج من وإلى القرص، ومن وإلى الذّاكرة العشوائيّة، وعلى مُقتضى الحاجة، ولرُبما تبدو هذه الحالة بالمألوفة لمُستخدمي أنظمة التشغيل ويندوز، عندما يتمّ تحميل النظام فوق طاقته، سيدخل القرص الصلب في قيلولة، قد لا يستيقظ منها قبل أنّ ينتهي فنجان القهوة، ولكن هذه الحالة من المُمكن تجنبها بالإعداد المُناسب، واستخدام أقراص من SSD استهلاك مساحة القرص الصلب، حيث تعتمد هذه المساحة على ذاكرة النّظام الرئيسية، فعند توفّر ذاكرة بسعة 512mb، فمن المُستحسن استخدام 512mb إلى 1.5g للتبديل، ولكن على صِغر هذه المساحة، ستبقى مساحةً ناقصةً من قرص الخادوم في جميع الأحوال. يُنصح بشكلٍ عام باستخدام قرص مُقسّم ومُخصّص لعمليّة التبديل، ولكن هذا الأمر قد لا يتوفّر في بعض الأنظمة المؤجّرة، ولذلك سيكون لا محالة من استخدام نظام ملفّ التبديل (swap file) أو صورة قرص (disk image) كيف يتمّ التأكد من تفعيل خدمة الذّاكرة الوهميّة على الخادوم الخاصّ الوهميّقد يكون الخادوم المؤجّر بالفعل يستخدم الذّاكرة الوهميّة، وللتأكّد من ذلك يُمكن الاستعانة بالأمر free، والّذي يَكشف لمُدير النّظام إن كانت خدمة التبديل مفعّلة أم لا، ويُظهر العديد من الخيارات الإضافيّة، والّتي تكون مُساعدة لمُدير النّظام، مع الانتباه أنّه يجب استخدام المُستخدِم root لتنفيذ الأمر، ولتحديد المُستخدِم الحاليّ يُمكن الاستعانة بالأمر whoami. bash-root@academy.hsoub:/# freeيُظهر الأمر free معلومات عن ذاكرة النّظام الوهميّة والذّاكرة الفيزيائيّة، وفيما إذا كانت الذّاكرة الوهميّة مُفعّلة أم لا، فالمُخرجات التّالية هي لخادوم قد تمّ تفعيل خدمة التبديل عليه: bash-root@academy.hsoub:/# free total used free shared buffers cached Mem: 361996 360392 1604 0 1988 54376 -/+ buffers/cache: 304028 57968 Swap: 249896 0 249896وفي حال كانت خدمة الذّاكرة الوهميّة مُعطّلة ستكون المُخرجات على الشكل التّالي: bash-root@academy.hsoub:/# free total used free shared buffers cached Mem: 361996 360392 1604 0 2320 54444 -/+ buffers/cache: 303628 58368 Swap: 0 0 0يُمكن استخدام الأمر free | grep Swap لعرض المُخرج المطلوب فقطّ، وهو السطر الخاصّ بالخاصيّة Swap. bash-root@academy.hsoub:/# free | grep Swap Swap: 249896 0 249896الفرق بين أقسام التبديل وملفّات التبديلملاحظة حول أقسام التبديل (Swap Partitions)يُفضل بشكلٍ عام استخدام قسم/تجزئة تبديل مُخصّص (dedicated swap partition) على القرص الصلب، وذلك للأنظمة الّتي تعتمد على لينكس في بُنيتها، مع العلم أنّ مُعظم الأنظمة تقوم بهذه العمليّة خلال عمليّة الإعداد (التنصيب)، وفي هذه الحالة ستكون الذّاكرة الوهميّة من نوع “قسم التبديل” (swap partition) في مُعظم الأحيان. ولكن يُمكن استخدام الطريقة الّتي سيتمّ شرحها في هذا الشرح لزيادة الذّاكرة الوهميّة المتاحة باستخدام ملفّ التبديل swap file، ليتمّ به زيادة مساحة قسم التبديل، مع العلم أنّه إنّ كان النّظام يدير عمليّة التبديل، فقد يكون إضافة ذاكرة وهميّة غير ضروريّ، وقد يكون من الأفضل الاعتماد على الإعداد الافتراضيّ. ما هو ملفّ التبديل (Swap File)تخزّن بعض الأنظمة (خاصّةً نظام التشغيل ويندوز) الذّاكرة الوهميّة في ملفّ مُحدّد، بدلًا من استخدام قرص كامل لذلك، وهذا الأسلوب هو المُستخدم دائمًا عندما لا يكون من المُمكن استخدام قسم كامل للذاكرة الوهميّة، وإن هذا النوع من الملفّات يقابله بما يُسمى صورة قرص disk image على أنظمة التشغيل لينكس. ما هو صورة القرص (Disk Image)يتضمّن هذا النوع عادةً ملفّات التبديل وبياناتها، بالإضافة إلى ملفّات النّظام المرتبطة معها، ويُستخدَم هذا النوع في بعض الأنظمة المؤجّرة لأخذ نسخة احتياطيّة كاملة عن النّظام، أو في تهجير النّظام (migration) من مكان إلى آخر، ومن الأمثلة الشائعة أيضًا عن هذا النوع من الملفات هو توزيعات لينكس كيف أنّها تأتي باللاحقة .iso، والّتي تستخدم في تنصيب النّظام كما هو معروف. إنشاء ملفّ تبديل (Creating the Swap File)لا تَسمح بعض الأنظمة المؤجّرة بتقسيم وتهيئة مساحة التخزين، لذلك يَتوجّب على مُدير النّظام استخدام صورة قرص (disk image)، ومع العلم أنّ أنظمة التشغيل المبنيّة على NIX* تستخدم نظامًا خاصًا ومكرّسًا لعمليّة التبديل (swap)، ولهذا السبب يُفضّل البعض قسم التبديل على ملفّ التبديل، ولإنشاء هذا النوع من الملفّات يجب إنشاء صورة قرص فارغة (empty disk image) بحجم مُتوافق مع الذّاكرة الوهميّة المطلوبة، وتهيئتها لبدء العمل. يجب أولًا تحديد مكان الملفّ، ويجب توفّر مساحة كافية على القرص، فعند الرغبة بإضافة ذاكرة وهميّة بحجم 512mb، سيكون عندها ملفّ التبديل تقريبًا بذلك الحجم. يُمكن استخدام الأمر df-h، لاستعراض التقسيمات المُدرجة (mounted partitions)، كما يُظهر هذا الأمر معلومات عن نظام الملفّات المُستخدَم وحجم كل تقسيم، والمساحة الحرّة الخاصّة بكل قسم. سيتمّ إضافة ملفّ التبديل في المسار /var، وبالاسم ”swap.img”، وبالصلاحيات 600، وذلك فقطّ لكي لا يستطيع أيًا كان من المُستخدمين قراءة مُحتويات ذاكرة النّظام (الوهميّة). bash-root@academy.hsoub:/# cd /var bash-root@academy.hsoub:/var# touch swap.img bash-root@academy.hsoub:/var# chmod 600 swap.imgاختيار حجم ملفّ التبديل (Sizing Swap File)سيتمّ في هذه الخطوة اختيار حجم الملفّ، وهو أمرٌ هامٌ جدًا، ويَختلف الحجم الأنسب على حسب نظام التشغيل وحسب الحالة، ولكن بشكلٍ عام، يُنصح دائمًا بأن تكون الذّاكرة الوهميّة أما بنفس حجم ذاكرة الوصول العشوائي (RAM)، وأو ضعف حجمها، ولكن عندما يتوفّر بالنظام ذاكرة فيزيائيّة كبيرة الحجم، فلا يُنصح بتكبير حجم ملفّ التبديل. سيتمّ استخدام الأمر dd لحشو ملفّ التبديل بمعطيات وهميّة، ليتوسع إلى الحجم المطلوب، في المثال التّالي سيكون 1024mb. bash-root@academy.hsoub:/var# dd if=/dev/zero of=/var/swap.img bs=1024k count=1000 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB) copied, 4.0868896 s, 253 MB/sتحضير صورة القرص (Disk Image)سيتمّ تطبيق الأمر mkswap، وذلك لتحضير نظام الملفّات للملفّ swap.img، بعد ذلك سيكون الملفّ جاهزًا للاستخدام. bash-root@academy.hsoub:/var# mkswap /var/swap.img Setting up swapspace version 1, size = 1020 GiB no label, UUID=72761533-8xbe-436l-b07e-c0sabe9cedf3كيفيّة تفعيل وتعطيل ملفّ التبديل (Enabling and Disabling Swap)تفعيل ملفّ التبديلسيتمّ استخدام الأمر swapon لتفعيل ملفّ التبديل، مع الانتباه أنه في حال نجاح عمليّة التفعيل، فالأمر السابق لا يَعرض مُخرجات بنجاح العمليّة والحالة النهائيّة، ولذلك يُمكن استخدام الأمر free. bash-root@academy.hsoub:/var# swapon /var/swap.img bash-root@academy.hsoub:/var# free total used free shared buffers cached Mem: 503596 478928 24668 0 38832 102384 -/+ buffers/cache: 337712 165884 Swap: 1048572 1780 1046792ولتعطيل ملفّ التبديل يُمكن استخدام الأمر swapoff /var/swap.img. تفعيل ملفّ التبديل خلال عمليّة الإقلاعيقوم الأمر swapon بتفعيل ملفّ التبديل فقط للإقلاع الحاليّ للنظام، بمعنى أنّه عند إعادة إقلاع الخادوم، سيكون ملفّ التبديل معطلًا، إلا إذا تمّت برمجة الأمر ليتم تنفيذه عند الإقلاع، أو تمّ التعديل على الملفّ /etc/fstab، وهي الطريقة الأسهل والأكثر استخدامًا. ما يجب عمله هو إضافة سطر إلى الملفّ /etc/fstab، ليتمّ تفسيره عند الإقلاع، ولكن يجب الحذر في استخدام هذا الأمر، فالتعديل الخاطئ من شأنه أنّ يعطب النّظام. bash-root@academy.hsoub:/var# echo "/var/swap.img none swap sw 0 0" >> /etc/fstabيُستخدم الرمز >> للإضافة، ولو تمّ استخدام الرمز >، لتمّ الكتابة من جديد ومسح الإعدادات (مُحتويات الملفّ) السابقة. إعدادات إضافيّة ومعلومات تفصيليّةما أنّ يتمّ تفعيل ملفّ التبديل، لتصبح الذّاكرة الوهميّة على أتمّ الاستعداد لتعمل عملها، ولكن هناك بعض التفاصيل الّتي سيتمّ التّطرّق لها لفهم أفضل لعمل هذه التقنيّة. الأولَوِيّاتيجب تحديد أولَويّات عند استخدام أكثر من ملفّ تبديل، أو عند استخدام أقسام موزّعة عبر أجهزة عدّة، بمعنى أنه يجب تحديد ترتيب أولويّة لكل جزء من أجزاء التبديل، فالحاجة إلى توزيع الأولويات هو للتفضيل بين الجزء السريع على البطيء، أو للتفضيل بين قسم التخزين الخامل (idle) على القسم النشط، ولذلك يتمّ تمرير الأولويّة كمُعامل للأمر swapon، أو استخدام الملفّ /etc/fstab في ذلك. سيستخدم النّظام قسم التبديل ذو الأولويّة الأعلى على أقسام التبديل ذو الأولويّة المُنخفضة: ​bash-root@academy.hsoub:/var# swapon -p 100 /var/swap.img bash-root@academy.hsoub:/var# swapon -p 10 /mnt/SecondDrive/swap.imgولاستخدام الملفّ /etc/fstab لتحديد الأولويّة يُمكن كتابة السطور التّالية: /var/swap.img none swap defaults,pri=100 0 0 /mnt/SecondDrive/swap.img none swap defaults,pri=10 0 0خيارات الأمر sysctlسيتمّ استخدام الأمر sysctl، وذلك لتغيير الإعدادات المخصّصة بمُدير الذّاكرة الوهميّة (virtual memory manager) لنظام التشغيل لينكس. يُعتبر الإعداد الخاصّ بـ vm.swappiness هامًا جدًا، ومُهمته إخبار مُتولّي (handler) نواة النّظام كيف من المُفترض أنّ تُستخدَم الذّاكرة الوهميّة، وقيمة هذا الخيار تُحدّد بالنسبة المئويّة أي بين 0-100، والنسبة 60 هي الافتراضيّة في مُعظم التوزيعات، وعند الإعداد يجب الانتباه إلى التّالي: القيمة 0: بالكاد ستستخدم النواة أيًا من مساحة التبديل المتوفّرة، بل ستصب كافة الأحمال على ذاكرة النّظام المتوفّرة أولًا.القيمة 100: ستستخدم النّواة مُعظم مساحة التبديل المتوفّرة، وستُحاول إبقاء المساحة العُظمى من ذاكرة النّظام حرّة للاستخدام.لا يوجد قيمة مثاليّة هنا، أو قاعدة يجب الالتزام بها، بل تختلف الحالة، ولكن القيمة 30% مُناسبة بشكل عام، والّتي من شأنها الموازنة بين التبادل (swapping)، وذاكرة النّظام (system memory). bash-root@academy.hsoub:/var# sysctl -w vm.swappiness=30 vm.swappiness = 30كلمات أخيرةيجب أن يُدرك مُدير النّظام بعد هذا الشرح أهمّيّة ملفّات التبديل ومدى تأثيرها على استقرار النّظام في بيئة العمل الحقيقيّة (production environments)، وهذا من شأنه أيضًا أنّ يسمح لمُدير النّظام باستخدام هذا النوع من التقنيّة في بيئة التّطوير لتجربة بعض التّقنيّات الّتي يعمل عليها. ترجمة – وبتصرّف – للمقال How To Configure Virtual Memory (Swap File) on a VPS لصاحبه Jai Boudreau.
  7. في خضم العمل مع العُملاء السيناريو التّالي قد يحدث كثيرًا: - المُصمّم: قد انتهيت من العمل على الجزء الأخير للمشروع الخاصّ بك، وهذا هو تصميم الجزء الخاصّ بنموذج “اتصل بنا”. ما رأيك؟ - العميل: لا يعجبني. يهاب مُعظم المُصمّمين "لم يُعجبني"، ويُعتبر من أكثر ردود الفعل المُحبطة الّتي قد تصدر من العميل أو مدير المشروع أو حتّى زميل العمل. الفكرة هنا والمُراد تسليط الضوء عليها غير مُرتبطة في نفسية المُصمّم أو ما قد يؤثر عليها فقط مع هذا النوع من الردود، إنما الأمر يتعلّق بالنقد البناء الذي يقدم قيمة حقيقية للتصميم والمشروع ككل. يتمّ الحصول على نتائج أفضل عندما تكون الاستجابة وردود الفعل (feedback) قائمة على فهم حاجات ومُتطلبات المُستخدِم، ولذلك يجب التأكد أنّ هذا النوع من الردود غير نابعٍ عن رأي العميل وذوقه الخاصّ، والذي قد يكون رأيًا صائبًا، ولكن ليس بالضرورة أن يكون الرأي الأنسب للمُنتج النهائيّ. إن مسألة الجماليّة هي مسألة مُرتبطة بالذوق، والتّصميم ليس فقط مجموعة من الجماليات، فبالطبع هناك قرارات تُتّخذ في مسألة الجماليّة ولكنها ليست الأمر الفصل، وهي تُتّخذ على مُستوى التصميم ككل. إنّ هذا التصميم بشكله النهائي سيكون موجّهًا إلى الجمهور المُستهدف له، ولذلك ومن ناحية موضوعيّة فإن مسألة الجماليّة هي مسألة يجب أخذها بعين الاعتبار من دون شك. قد يُبدي معظم العُملاء آراءهم بناءً على ذوقهم الخاصّ، محاولين بذلك تبصّر ذوق الجمهور المُستهدف، أو قد يحاولون حل المُشكلة المعنيّة للمُستخدِم. لا يُفترض في هذه الحالة أخذ الرد “لا تعجبني” بمعناه السطحي، والتسليم به على أنّه أمرٌ لا مهرب منه. كيف يتمّ الحصول على استجابة/رد أفضل؟يتمّ الحصول على استجابة إيجابية أفضل ونقدًا بناءً من العميل عبر حثّه على تفسير الأسباب خلف الرد أو الاستجابة السلبية، والّتي عادةً ما تكون هذه الردود تستخدم صيغة من نوع “لا يعجبني بسبب…” هذه الصيغة من الردود تُقدّم استجابة ذو قيمة للمُصمّم وللمشروع ككل. - المُصمّم: لماذا لم يعجبك تصميم نموذج “اتصل بنا” الجديد؟ - العميل: لم يعجبني بسبب أنّ الخط المُستخدَم كبيرٌ جدًا. قد يكون تحقيق أهداف الجمهور مع المُنتج هو العامل الرئيسيّ في نجاحه، ولذلك يجب على العُملاء أنّ يعوا بأنّهم قد لا يستطيعون تمثيل الجمهور المُستهدف. لن يكون ذلك بالأمر الهَيّن لكي يتمّ إدراكه خصوصًا للشخص القريب من المُنتج (العميل). على الطرف الآخر قد يكون المُصمّم نفسه واحدًا من المُستخدمين لهذا المُنتج الّذي يقوم بتصميمه، ولكن يجب الأخذ بعين الاعتبار أنّ المُنتج هنا لا يتمّ تصميمه فقط من أجل مُستخدمين من نوع واحد دون الآخر، حيثُ أنّ المُنتج له جمهور مُعيّن، مع هدف مُحدّد. عندما يعي المُصمّمون أهميّة المُستخدِم النهائي، سيتمكنون عندها من إعادة بناء ردود فعلٍ/استجابة (feedback) أفضل عبر التّساؤل بشكل متجرد على النّحو التّالي: “كيف سيتقبّل المُستخدم النهائيّ هذا التصميم؟” - المُصمّم: هل تظن أنّ المُستخدم النهائيّ سيجد أن الخط المُستخدَم كبير الحجم؟ - العميل: نعم. وأظن أنّه يفضل رؤية كامل مُحتوى الصفحة من دون الحاجة إلى تحريكها (scrolling) صعودًا ونزولًا لرؤية كامل المُحتوى. - المُصمّم: سيكون الخط صغيرًا جدًا في حال قمنا بتصغيره ليتناسب مع الصفحة، الأمر الّذي قد يجعل من النموذج صعب القراءة. - العميل: لا بأس. فجميع مُستخدمينا من فئة الشباب، ويملكون بصرًا جيّدًا. يجب على المُصممين مراجعة الآراء والافتراضات الخاصّة بهم حول المُستخدِم النهائي. كما يجب عليهم التأكد أنّ أي ردٍ أو استجابة يحصلون عليها ليست مقرونةً أو قائمةً على أساسٍ أو افتراضٍ لا صحة له. بمعنى إن قال العميل: أنّ المُستخدِم النهائيّ لن يعجبه التصميم، يجب السؤال هنا عن السبب، أي يجب الكشف عن خلفيّة هذا الافتراض، وما الذي دعا إلى افتراضه في الأساس. - المُصمّم: هل يُمكننا التأكد من أنّ جميع العُملاء هم من فئة الشباب؟ وهل يُمكن القول أنّ جميع الشباب تملك حدّة بصر جيّدة؟ فربما نحن بهذا نخاطر بخسارة عُملاء محتملين عندما لا يكون الموقع سهل القراءة للجميع. يبرز سؤالٌ مهمٌ هنا وهو كيف يُمكن للمُصمّم أنّ يفصل بين الافتراض (الّذي قد يكون غير موضوعيًّا) وبين المعرفة الحقيقية (والّتي تكون صحيحة بطبيعة الحال). إن أي نظرة عامّة حول سلوك المُستخدم خاصّة تلك الّتي تفترض أنّ جميع المُستخدِمين يتشاركون في صفات وميزات شائعة سيكون من المُفترض التحقق منها والتشكيك فيها. يُمكن الحصول على هذا النوع من الافتراضات المُسبقة عبر الاطّلاع على بعض البحوث واستطلاعات الرأي حول المُستخدم، وبذلك سيملك المُصمّم دليلًا واضحًا يُمكن الرجوع إليه عند الضرورة. السر في المناقشةلا يجب أن يعتمد المُصمّم على وصف الآخرين لمشكلتهم وألا يتوقع منهم معرفة استخدام الكلمات الصحيحة والمعبرة عند وصفهم للسّبب الذي يدفعهم إلى الاعتقاد بوجود خلل ما في التصميم. لذلك على المُصمّم أن يَعرف كيف يَطرح السؤال الّذي من شأنه أن يحثّ العميل أن يُقدّم نقدًا بناءً واستجابة ذات قيمة تعود على المشروع والمُنتج بالفائدة المرجوّة. كان قد تمّ الكتابة عن كيف يُمكن اجتناب المشاكل قبل حدوثها (المُستقلّ الحذق هو من يصنع العميل الجيّد) عن طريق شرح وتفسير التصميم عند مشاركته مع الآخرين، ولكن من الصعب شرح كل تفصيل من تفصيلات العمل والعلاقة بينهما. إنّ كان العميل لا يستطيع أن يعبّر عما يجول في خاطره ولماذا هو لا يحب التصميم النهائي ككل، فربما تقديم التصميم بعناصره وجزئياته الصغيرة قد يزيد من فرصة ضبط وتحديد الجزء الذي يُسبب المُشكل لدى العميل. - المُصمّم: أي جزء من الخط يبدو بأنه كبير الحجم بالنسبة لك؟ - العميل: عناوين حقول النموذج (form labels). عندما يقوم المُصمّم بتحديد المكوّن أو الجزء الّذي يُسبب مُشكلة للعميل، عندها عليه أنّ يستخلص بعض الأسباب المُحتملة والّتي قد لا تكون ذو صلة مع المُشكلة. - المُصمّم: هل تعتقد أنّ حجم عنوان الحقل لا يترك مساحة كافية لبقية العناصر، والذي يجبر المُستخدم على التدرّج بين أعلى وأسفل الصفحة؟ - العميل: نعم. من المُفترض جعل عنوان الحقل يبدو بحجم أصغر مما هو عليه الآن. عندما يكون المُصمّم هو المُتحكمتُعتبر الجماليّة مسألة ذوق تختلف من شخصٍ لآخر، إن أي شخص يعرف ما يحب وما يكره من الألوان، والّتي تحدد ما يختاره من لباس إلى أمورٍ أُخرى، وفي نفس الوقت على هذا الشخص أنّ لا يتوقع من الجميع مُشاركته تفضيله لنفس الألوان الّتي يحبها. كان قد كتب “Nishant” سطورًا من ذهب بعنوان “الذوق الجيّد لا يقدِّم ولا يؤخِّر” لخصها بشكل مُتقن عندما قال: عندما يُصبح الذوق أمرًا عظيمًا- المُصمّم: ولكن إن تمّ تصغير الخط المُستخدَم، سيجعل ذلك من القراءة أمرًا عسيرًا، كما أنّ معظم الصفحات تتطلّب تصفّحها صعودًا ونزولًا، وبالتّالي فإن ذلك لن يُسبّب أيّة مشاكل للمُستخدِم. هل تعتقد أنّ النموذج طويل بعض الشيء، وهو ما قد يُنفّر المُستخدم من ملئه كاملًا؟؟ - العميل: نعم، أرغب أنّ يكون نموذج “اتصل بنا” أبسط من ذلك. - المُصمّم: ما رأيك أنّ نتخلّى عن جميع الحقول الحاليّة ماعدا الحقل الخاصّ بـ “البريد الإلكتروني” وحقل “الرسالة”، حيثُ أنّ ذلك كل ما هو مطلوب في حقيقية الأمر؟ - العميل: نعم، هذا يجعل من النموذج أبسط وأكثر وضوحًا. عندما يقوم المُصمّم بتقديم وعرض بعض الاقتراحات، عليه أنّ لا يدع العميل يقول: “نعم” للاقتراح الأول، حيثُ أنّ هذه الاقتراحات لا يقصد بها بأن تكون مخرجًا سريعًا من النقاش، أو أنها طرحت فقط لتغيير شيءٍ ما ليناسب ذوقه. بل هي فرصة للدخول في عصف ذهني (brainstorm) هدفه تحريض الأفكار وخلق بدائل وحلول مُحتملة بشكل مُباشر وسريع، وهو أمرٌ هام يستدعي العمل بشكل تعاونيّ بين المُصمّم والعميل، ولذلك على المُصمّم عدم التغريد خارج السرب واختيار البدائل الأولى بنفسه. إن استطاع المُصمّم استنباط طريقة مُناسبة للعمل بها بينه وبين العميل، حينها سيكون الحلّ المُقترح حلًا ذو قيمة يعود بالنفع على الطرفين، حيثُ أنّ العميل سيكون أكثر التزامًا مع هذا التصميم بما أنّه كان طرفًا في اتخاذ القرار، خاصّة عندما يقطف ثمار هذا التعاون المُشترك، ويُدرك أن هذه النتيجة هي الأمثل الّتي تكللت بتعاون كلا الطرفين. ترجمة وبتصرّف للمقال I Don’t Like It لصاحبته Laura Kalbag.
  8. هذا المقال هو الجزء الثّالث من سلسلة استخدام puppet لإدارة الخواديم التي تتكوّن من كل من: تنصيب Puppet لإدارة البنية التَّحتِيَّة للخواديمملفّات البيان (Manifests) والوحدات (Modules) في Puppetكيف تستخدم Foreman لإدارة نقاط Puppet على الخادوم Ubuntu 14.04مُقدمةForeman هي أحد الأدوات مَفتوحة المَصدر، والّتي تُستخدم في إدارة الخواديم، وذلك بتوفير طريقة سهلة ومرنة في العمل جنبًا إلى جنبٍ مع الأداة Puppet (أو Chef) وذلك بهدف أتمتة المهام ونشر التطبيقات، وهي مناسبة لكافة أحجام البُنى التَّحْتِيَّة، وتعمل على معظم توزيعات لينكس. تُقدّم هذه التسهيلات عبر توفير واجهة ويب، وAPI، وبالإضافة إلى أوامر الطرفية CLI، مما يجعل الإعداد المُسبق provisioning ومُراقبة الخواديم أسهل من أي وقتٍ مضى. سيتناول هذا الشرح كيفيّة تنصيب الأداة Foreman مع الأداة Puppet، واستخدامها في إدارة الخواديم. سيتمّ استغلال Foreman في قدرتها على إصدار التقارير وميزة External Node Classifier والّتي يُشار إليها بالاختصار (ENC)، بهدف تسهيل إدارة الأداة Puppet. مُتَطَلَّبات بيئة العملسيتمّ تنصيب الأداة Foreman على خادوم جديد، يحمل الاسم “foreman”، وسيُمثل خادومًا مَركزيًّا آخر للأداة Puppet. يُمكن تنصيب الأداة Foreman على الخادوم المَركزيّ الحالي، ولكن يجب التنبه هنا إلى أنّه سيتمّ استبدال ملف البيان الافتراضيّ site.pp بمَلفّ جديد، وذلك من شأنه أنّ يُلغي العلاقة بين العُملاء الحاليين والخادوم المَركزيّ، ويُمكن تجاوز ذلك بالإعداد مرّة أخرى ليُدير الخادوم Foreman نقاط العُملاء هذه Puppet agent nodes تَعتمد الأداة Foreman على الأداة Puppet بشكل كبير لإدارة إعدادات العُملاء، ولذلك فمن الضروريّ توفّر الأمور التّالية قبل البدء بتطبيق محتويات هذا الشرح: صلاحيّة وصول كامل: بالاستعانة بالأمر sudo يُمكن عمل كافّة التغيرات المطلوبة.خدمة DNS على الشبكة الخاصّة: إعداد خدمة DNS لترجمة أسماء الخواديم إلى IPs أي (Forward DNS lookup)، وترجمة الـIPs إلى أسماء الخواديم أي (reverse DNS lookup)، ويَجب على كل خادوم أنّ يَمتلك اسمًا فريدًا خاصًا به على مستوى الشبكة الداخلية. يُمكن الرجوع إلى الشرح الخاصّ كيفية إعداد خادوم DNS في الشبكة الخاصّة. في حال عدم توفّر خادوم DNS، فيُمكن استخدام الملف hosts لترجمة العناوين.إعداد الجدار الناري firewall: من الضروريّ الوصول إلى الخادوم المَركزيّ الخاصّ بالأداة Puppet عبر المنفذ 8140، ولذلك يجب التأكد من عدم منع الجدار الناري لهذا المنفذ. يُمكن الاستعانة بالشرح التّالي لمعرفة كيفية السماح بالطلبات الواردة باستخدام UFW.بعد إتمام المُتَطَلَّبات السابقة من المُمكن الآن الانتقال إلى إنشاء الخادوم Foreman والذي سيكون بنفس الوقت هو خادوم مَركزيّ Puppet master. إنشاء خادوم Foremanسيتمّ إنشاء خادوم جديد يعمل بالتوزيعة Ubuntu 14.04 x64، ويحمل اسم المجال المؤهل بالكامل “foreman.nyc2.example.com”، وإعداد خادوم DNS بناءً على هذا الاسم. يُمكن الرُجوع إلى القسم الخاصّ بـ صيانة سجلات DNS في حال عدم توفّر المَعرفة لفعل ذلك. في حقيقة الأمر كل ما يجب عمله هو إضافة سجلّين الأول من نوع “A” والثاني من نوع “PRT”، والسماح للعميل الجديد بعمل استعلامات دوريّة recursive queries، وأيضًا يجب التأكد من إعداد DNS لترجمة أسماء الخواديم من دون استخدام “اسم النطاق المُؤهل بالكامل” Fully Qualified Domain Name التأكّد من أنّ اسم الخادوم هو اسم المجال المؤهل بالكامل:لمعرفة اسم الخادوم الكامل FQDN يُمكن استخدام الأمر التّالي hostname –fالأمر السابق يجب أنّ يَعرض اسم المجال المؤهل بالكامل الخاصّ بالخادوم أي “foreman.nyc2.example.com”، وفي حال عرض اسم فقط أي “foreman” فيجب إجراء التعديلات التالية: تحرير الملف hosts ليُشير السجل 127.0.0.1 إلى اسم المجال الكامل.سيتمّ استخدام المُحرر Vi: sudo vi /etc/hostsالسجل سيكون بالشكل التّالي: 127.0.1.1 foremanليُعدّل ويصبح بالشكل التّالي: 127.0.1.1 foreman.nyc2.example.com foremanتحرير الملف hostnameسيتمّ تحرير المَلفّ الخاصّ باسم الخادوم: sudo vi /etc/hostnameيجب التأكد من أنّ الاسم هو اسم المجال الكامل: “foreman.nyc2.example.com”ولتطبيق التعديلات بشكل مُباشر وآني يُمكن تنفيذ الأمر التّالي: sudo hostname --file /etc/hostnameتنصيب الأداة Foremanسيتمّ استخدم المُنصب الخاصّ بالأداة Foreman، فهو أسهل طريقة لتنصيب هذه الأداة مع المُكونات الخاصّة بها، مع إعدادات افتراضيّة تسمح لنا بالعمل بشكل أسرع مع الأداة، وذلك بتوفير العناصر التّالية: تنصيب الأداة Foremanتنصيب الأداة Puppetخادوم الويب Apache مع SSL والوحدة Passengerسيتمّ في البداية إضافة مستودع Foreman: sudo sh -c 'echo "deb http://deb.theforeman.org/ trusty 1.5" > /etc/apt/sources.list.d/foreman.list' sudo sh -c 'echo "deb http://deb.theforeman.org/ plugins 1.5" >> /etc/apt/sources.list.d/foreman.list' wget -q http://deb.theforeman.org/pubkey.gpg -O- | sudo apt-key add –تحميل المُنصب: sudo apt-get update && sudo apt-get install foreman-installerقبل تشغيل المُنصب يجب التأكد من أنّ الأمر ping $(hostname –f) يُظهر العنوان الحقيقي للخادوم وليس العنوان 127.0.0.1 تشغيل المُنصب: sudo foreman-installerالأمر السابق يعرض مُخرجات output كما في التّالي: Your puppet version does not support progress bar Preparing installation Done Success! * Foreman is running at https://foreman.nyc2.example.com Default credentials are 'admin: hzdQZPZ97KJ32BKn ' * Foreman Proxy is running at https://foreman.nyc2.example.com:8443 * Puppetmaster is running at port 8140 The full log is at /var/log/foreman-installer/foreman-installer.logتدلّ السطور السابقة على استكمال تنصيب الأداة بشكل صحيح. كما تعرض بيانات الدخول المُستخدمة مع واجهة الويب. تفعيل Diffsيَسمح تفعيل الخيار “diffs” لمُدير النظام باستعراض تغييرات مَلفّ الإعدادات على شكل تقرير ضِمن الأداة Foreman Reports. ولتفعيل هذه الميزة سيتمّ تحرير المَلفّ puppet.conf: sudo vi /etc/puppet/puppet.confوتغيير قيمة الخيار show_diff إلى true: show_diff = trueإضافة الخادوم Foreman إلى قاعدة البياناتيَقوم الأمر puppet agent بإضافة الخادوم “foreman” إلى قاعدة البيانات الخاصّة بالأداة Foreman، وبذلك يكون الخادوم “foreman” أول عميلٍ خاصّ بالأداة Foreman، وتتمّ إدارته من قبلها. sudo puppet agent –testتسجيل الدخول باستخدام واجهة الويبيجب في بداية الأمر الدخول وتغير كلمة المرور الخاصّة بحساب المُدير admin، حيثُ يُمكن الوصول لواجهة الويب عن طريق الشبكة العامّة public network الخاصّة بالخادوم الافتراضيّ الخاصّ VPS، إما عن طريق اسم المجال المؤهل بالكامل أو عنوان الـIP public network. يَستخدم Foreman بشكل افتراضيّ شهادات الأداة Puppet، والّتي على الأغلب لن تكون مَوثوقة بالنسبة للمُتصفح. يُمكن تجاهل التحذير الخاص بالمُتصفح في الوقت الحالي، أو يُمكن استبدال الشهادة الحالية بأُخرى تُطابق اسم المجال ومُوقعة من قبل مُفوّض شهادات مَوثوق (trusted CA authority). بغض النظر عن الطريقة المُتبعة في الاستمرار ستكون صفحة تسجيل الدخول على الشكل التّالي: عند تنصيب الأداة Foreman بالأمر foreman-installer كانت بيانات الدخول الافتراضيّة على الشكل التّالي، والّتي سيتمّ استخدامها لتسجيل الدخول: اسم المُستخدم: adminكلمة المُرور: hzdQZPZ97KJ32BKnلوحة المعلومات المُختصرة الخاصّة بالأداة Foremanيُظهر تسجيل الدخول مُباشرةً لوحة التحكم، ويُعرض من خلالها نظرة شاملة على بيئة عمل Puppet، حيثُ يوجد مُلَخَّص يُسمى “حالة إعدادات المُضيف” (Host Configuration Status)، والذي يَعرض عدد نقاط العُملاء (Puppetagent nodes) وحالة كلٍ منها. يُظهر المُلَخَّص الحالي خادوم وحيد وذلك في القسم “good host”. يوجد في الجانب الأسفل من المُلَخَّص السابق مُلَخَّص آخر للأحداث الأخيرة، ورسمٌ بيانيٌ مع عدد العُملاء الّتي قامت بعمل اتصال في الثلاثين دقيقة الأخيرة. تُقدّم هذه المعلومات لمحة عامّة وشاملة عن عمل منظومة Puppet. كما ستكون لوحة المعلومات على الشكل التّالي عند وجود أي خطأ: تغيير كلمة مرور حساب المُدير Admin Passwordتمّت الإشارة سابقًا إلى ضرورة تغيير كلمة مُرور حساب المُدير admin ولعمل ذلك يجب التوجّه إلى “Admin User” في الزاوية العلوية من جهة اليمين والنقر على “My account”: ومنها إلى النماذج واختيار الكلمة المناسبة. إضافة خدمة مُزامنة الوقت NTP إلى Foremanتتطلّب Puppet الحفاظ على دقةٍ وانسجامٍ في الوقت بين الخواديم، ولهذا سوف يُستخدم Foreman لإدارة خدمة NTP على المُضيف “foreman” والذي هو بنفس الوقت Puppet master. يُمكن التوجّه إلى https://forge.puppetlabs.com والبحث عن الوحدة NTP لمعرفة المزيد عنها وماتُقدمه، والّتي ستكون بالاسم puppetlabs/ntp. سيتمّ تنصيب الأداة NTP البيئة “production” الخاصّة بالأداة Puppet master وذلك عبر الأمر التّالي: sudo puppet module install -i /etc/puppet/environments/production/modules puppetlabs/ntpمن المُفترض عرض مخرجات كما في التّالي والتي تدل على تنصيب الوحدة module بشكل صحيح: Notice: Preparing to install into /etc/puppet/environments/production/modules ... Notice: Downloading from https://forge.puppetlabs.com ... Notice: Installing -- do not interrupt ... /etc/puppet/environments/production/modules └─┬ puppetlabs-ntp (v3.1.2) └── puppetlabs-stdlib (v4.3.2)قد تمّ تنصيب الوحدة على Puppet master، ولكن يجب إضافتها إلى الأداة Foreman قبل أنّ يُصبح بالإمكان استخدامها. في واجهة الويب الخاصّة بالأداة Foreman، ومن القائمة “configure” والاختيار “puppet classes”: سيتمّ النقر على الزر “Import from foreman.nyc2.example.com”: ومن ثمّ اختيار بيئة العمل “production”، ثُمّ الضغط على الزر “update”، وبذلك تكون الوحدة ntp مُستوردة imported داخل الأداة Foreman، وجاهزة للاستخدام. الاستغناء عن الإعدادات الافتراضيّة للأداة NTPمن الجيّد اختيار إعدادات مُخصّصة بدلًا من الافتراضيّة للأداة NTP لتوافق الموقع الجغرافي للخواديم الخاصّة بنا، ويُمكن الرجوع إلى صفحة المشروع لاختيار الخيار الأنسب. في الصفحة السابقة وهي “Puppet Classes”، وبعد الضغط على الصنف “ntp”، سيتمّ الانتقال إلى وضع التحرير، ومنه إلى التبويب “Smart Class Parameter” وبعد التدرّج بالصفحة إلى الأسفل يوجد اختيار بالاسم “servers” في الشريط الجانبيّ بعد اختيار “servers”، سيتمّ اختيار “Override”، وذلك لكتابة الإعدادات المُخصّصة. بعد ذلك سيتمّ اختيار نوع المُعامل ليكون على شكل مصفوفة array، وبعد ذلك سيتمّ تغيير القيمة الافتراضيّة إلى القيم المُخصّصة، وذلك على شكل مصفوفة. ["0.us.pool.ntp.org","1.us.pool.ntp.org","2.us.pool.ntp.org","3.us.pool.ntp.org"]أصبح من المُمكن تطبيق الإعدادات وذلك بالضغط على “Submit”. بعد تطبيق الإعدادات المُخصّصة فإن أي عميل يستخدم هذه الوحدة ستكون هذه الإعدادات المُخصّصة هي الافتراضيّة الخاصّة به. إعداد Foreman ليستخدم الوحدة NTPأصبح الآن من المُمكن استخدام الوحدة NTP في إدارة الأداة NTP على المُضيف Foreman. من القائمة “Hosts”، ومن ثمّ الاختيار “ALL Hosts”، ومن ثمّ زر التحرير “Edit” على الجانب الأيمن. من التبويب “puppet classes”، ومن القسم الخاصّ بالأصناف المُتاحة، سيتمّ الضغط على الصنف “ntp” لتوسيعه، بعد ذلك سيتمّ الضغط على إشارة الزائد (+) الّتي بجانب الخيار “ntp”. سينتقل الصنف “ntp” بعد الضغط على إشارة الزائد إلى القسم الخاصّ بالأصناف المُدرجة. بذلك ستُطبّق هذه الوحدة على العُملاء عند اتصالها مع الخادوم المَركزيّ، ولتطبيق الإعدادات سيتمّ الضغط على “submit”. استعراض إعدادات Puppetبعد الانتهاء من إعداد المُضيف السابق والضغط على زر “الإرسال”، سيتمّ الانتقال التلقائي إلى صفحة مُلخّص المُضيف. ولرؤية المعلومات الّتي تمّ تطبيقها على العميل عند الاتصال بالخادوم المَركزيّ، يُمكن الضغط على زر “YAML”. لتُعرض المعلومات على الشكل التّالي: --- classes: ntp: server_list: - 0.us.pool.ntp.org - 1.us.pool.ntp.org - 2.us.pool.ntp.org - 3.us.pool.ntp.org parameters: puppetmaster: foreman.nyc2.example.com root_pw: foreman_env: production owner_name: Admin User owner_email: root@nyc2.example.com environment: productionتشغيل عميل Puppetسيتمّ تطبيق التغييرات السابقة الآن، ودون الحاجة للانتظار للاتصال التّالي، ولذلك سيتمّ تشغيل نسخة العميل من الأداة Puppet على الخادوم Foreman. sudo puppet agent –testبهذا يكون قد تمّ استخدام الأداة Foreman لإعداد الخادوم “foreman”، وإنّ إعداد بقية خواديم العُملاء هو مُشابه تمامًا لما تمّ عمله مع الخادوم “foreman”. إضافة عُملاء جُدد إلى Foremanالآن بعد أنّ انتهى إعداد الخادوم Foreman، أصبح بالإمكان إضافة المزيد من hosts لتصبح مُدارة من قبل الأداة Foreman، وطريقة الإضافة هي نفس طريقة إضافة نقاط عُملاء Puppet إلى الخادوم المَركزيّ. يتوفّر المزيد من التفاصيل في [الجزء الأول](رابط الجزء الأول) من هذه السلسلة. مع الانتباه إلى ربط العُملاء مع الخادوم المَركزيّ للأداة Puppet (وهو الخادوم Foreman في نفس الوقت). يجب توقيع الشهادة الخاصّة بكل عميل على الخادوم Foreman، ويتمّ ذلك عبر سطر الأوامر، كما تمّ الأمر مع إعداد Puppet، أو من المُمكن استخدام واجهة الويب الخاصّة بالأداة Foreman. يُمكن استخدام واجهة الويب لتوقيع الشهادات من الصفحة “smart proxy” والاختيار “Certificates”. أو بالإمكان حذف شهادة عميل حاليّة: الخاتمةالآن وبعد أنّ تمّ بناء خادوم Foreman، أصبح من المُمكن استخدام الوحدات الخاصّة بالأداة Puppet على مستوى مُتقدم من الفعاليّة لإدارة الخواديم على مستويات متعددة وفي كامل البِنيَة التَّحتيَّة، ومن المُستحسن الآن استعراض المزيد من الوحدات المُتوفّرة على مُجتمع Puppet، أو حتّى كتابة وحدة جديدة مخصّصة لُتلبي احتياجات مُعيّنة. ترجمة -وبتصرّف- للمقال How To Use Foreman To Manage Puppet Nodes on Ubuntu 14.04 لصاحبه Mitchell Anicas
  9. أحبّذ كثيرًا العمل كمُستقلّ فالعمل كُمُستقل يجلب لي سرورًا خاصًا في النفس، ولكن غالبًا هذا ليس حال جميع المُستقلين، فهم يعتقدون عكس ذلك، ويظنون أنّي صاحب عقليّة خاصّة. يسري في مجتمع الويب مُعتقدٌ مُعيّن، أنّ العمل كمُستقلّ وتحمل تبعاته وعقباته هو أمرٌ يفعله البعض فقط عند حاجتهم لتمويل المشاريع الّتي يهتمون بها، يعتبرني البعض بأن شخص مُنعزل وأغني على ليلاي، وذلك فقط لأني لا استهوي العمل مع الشركات الناشئة أو حتَّى العمل على مشروعي الخاصّ، فقد ارتبط العمل الحرّ بمظاهر التوتّر وعدم المرونة، خاصّة تلك المشاريع الّتي يكون أصحابها من النوع صعب التعامل وأصحاب طلبات متكرّرة، ولكنّي أنظر إلى الأمور من منظور آخر، فالعمل مع العُملاء والعمل الحرّ هو أمرٌ لطالما بعث في نفسي الحماس، فهو يجعل مني أقدّر المشروع الّذي أعمل عليه أكثر كما لو كان مشروعي، وليس بالضّرورة أنّ يكون الأمر بذلك التعقيد الذي يتحدّث عنه البعض، بل على العكس، قد يكون الأمر فرصة للدخول في تجربةٍ فريدةٍ تستحق العناء. هل هي عقليّة العميل؟ أرى يوميًا على صفحات التواصل الاجتماعيّ سواءً فيسبوك أو تويتر كيف يُبدي المُستقلّون شكواهم حول العُملاء، أو أنّهم على الأقل يشيرون إلى بعض الحالات الشائبة والتجارب الفاشلة، حيث ُيَميل مُعظم المُستقلّون إلى الترويح عن نفسهم والتحدث عن عوز العُملاء إلى إدراك حقيقة الأمور، بجانب ترددهم في مشاريعهم، وعدم رضاهم في معظم الأحيان. كنت أتحدث قبل مُدّة مع أحد المُستقلين عن العمل الحر وعن تجربتي الشخصيّة في هذا المجال، وأذكر أنّي قلت: لسبب ما أنا لم يحدث وسبق لي أنّ تعاملت مع عميل ذو تعامل سيّئ من النوع الّذي يتحدث عنه مُعظم المُستقلّون كنت أعتقد ولفترة طويلة أنّه الحظّ وفقطّ الحظّ هو السّبب في أنّ جميع عُملائي من أصحاب التفكير العمليّ والعقول الليّنة والمرنة، ولكن ما كان منّي أن أدركت أنها ليست الصُدفة والحظّ وراء السبب في تعاملي مع هذا النوع من العُملاء، بل ربما يكون السبب هو أسلوبي وعقليتي كمُستقلّ ذو منهجية هي السر في أن جميع عملائي من العُملاء الذي يتمناهم أي مُستقلّ. لا أنكر أنّ للحظّ دورًا ما في حصولي على هذا النّوع الطيّوب من العُملاء بطبيعة الحال، ولكن أريد أن أوضح نقطة هامّة، وهي أنّي عندما أقوم بالبحث عن مشاريع مُحتملة لي، فأنا أبحث عن المشاريع الّتي يَبدو على أصحابها الشغف حول مشاريعهم، وليس ذلك فقطّ بل من يَهتم بالجودة النهائيّة بشكل حقيقيّ وبشكل نابعٍ من القلب، وهذا النّوع من العُملاء وفقطّ هذا النّوع هو من سيجعل من المشروع مُيسّرًا من دون الدخول في متاهاتٍ لا يُحمَد عُقباها. غيّر العمل الحرّ من نظرتي المُسبقة حول العُملاء، حيثُ أنّي كنت أنظر نظرة استخفاف إلى بعضهم، بالضبّط أولئك الذين لا يُدركون حقيقة الأمور، وأصبحت أجد فيهم فرصةً لتثقيفهم ووضعهم على الخطوات الأولى نحو فهم الأمور بشكلها الصحيح، على عكس ما كنت أفعل سابقًا وهو الشكوى والتّذمّر، حيثُ أنّ هذا التغيير من شأنه أن يَنقل المُستقلّ من حالة عدم الثقة بالعميل إلى حالةٍ مُغايرةٍ تمامًا، وهي التعامل مع العميل بشفافيّة تامّة تُسهل من إنجاح المشروع. السر في التواصل بحكم طبيعة عمل المُصمّمين، فإن جلّ عملهم هو في التواصل مع العُملاء، ولذلك فإن المُصمّم الّذي يجد صعوبة في التواصل مع عملائه سيُعاني الأمرين مع العمل الحرّ، وإن كان يَعتقد المُصمّم أن عمله كمُستقلّ أو عمله عن بُعد (remotely) سيكون خاليًا من أي نوعٍ من أنواع الاتصال، فإن هذا المُستقلّ ليس فقطّ مُخطئ، بل هو يَطير ويُحلّق خارج السرب ويغرد بعيدًا عنه. يَجب على المُصمّم أنّ يكون قادرًا على وصف حقيقة الأمور وماهيتها، فإن القدرة على توصيل الأفكار بشكل شفهيّ أو كتابيّ، أو حتَّى بصري هو أمرٌ سيَمنع المُستقلّ من إنشاء نماذج (mockups) مُتلاحقة لكلٍ تفصيل صغير في المشروع. يجب على المُصمّم أنّ يكون قادرًا على تفسير وشرح تفصيلات تصميمه وتقديم الأسباب وراء اختيار جزئيّة مٌعيّنة دون غيرها، وذلك في سبيل تجنب طلبات التعديل المتكرّرة وغير النهائيّة، وبشكلٍ يجعل من المُستقلّ مجرّد أداة تخضع لذوق العُميل وآرائه الاعتباطيّة، ولأن المُصمّم هو الخبير، وصاحب التجارب السابقة، فمن واجبه تفسير وتوضيح الأمور للعميل. يجب على المُصمّم أنّ يكون قادرًا على التحكم بزمام الأمور، فهو صاحب النّظرة التصميميّة الأقوى، وألا ينتظر من العميل أن يَطرح قائمة من المهام لكي يتمّ تنفيذها، حيثُ أن هذا الأسلوب قد يدفع العُملاء إلى الإحباط، الأمر الذي قد لا يترك فرصة ثانية للمُستقلّ ليُثبت بها نفسه، مع العلم أن بعض العُملاء تتوقع من المُستقلّ استلام قيادة المشروع والتحكم به من الألف إلى الياء، وذلك في سبيل الوصول إلى بر الأمان، ولذلك على المُصمم أن يَعي أهميّة تحديد واختيار المُستوى المطلوب من المُتابعة والتفاعل مع العميل لقيادة المشروع إلى بر الأمان. يجب أن يَملك المُصمّم ثقةً بعمله وبتصميمه، حتَّى لو كان التصميم في مرحلته الأوليّة وغير مُدقّقٍ بشكل نهائيّ، حيث أن مشاركة التصميم الأوليّ مع العميل وقبل الموعد النهائيّ وبشكل متكرّر هو السبيل في الحصول على ردود فعلٍ إيجابية (feedback) ذات قيمة، وسيمنع ذلك من طلب العميل تعديلًا جذريًّا في نهاية المشروع، وتسمح للعميل بالتركيز على النقد البنّاء الّذي من شأنه أن يَسمح بدوران عجلة الإنتاجيّة نحو الأمام. لوم العميل يبدأ مُعظم المُستقلّين في عالم العمل الحرّ جاعلين نصب أعينهم عدم طرح شيءٍ من عملهم قد يَظهر عليه شيءٌ من النّقص أمام عُملائهم، بمعنى آخر يَجد المُستقلون أنفسهم مدفوعين إلى بذل أقصى ما لديهم لتقديم أعمالهم بشكلٍ يميل إلى المثاليّة، وفي حال حصولهم على استجابة تقلّ عن توقعاتهم، سيصابون بشيءٍ من الإحباط الأمر الّذي من شأنه أن يُؤثر على المُنتج النهائيّ، مما يدفعهم نحو الدفاع عن آرائهم ولوم العميل لعدم تزويدهم بالمعلومات الكافية والوافية للصورة النهائيّة للمشروع. مُساعدة العُملاء في جعلهم عُملاءً أفضل من النادر أن يُوظّف صاحب المشروع مُستقلًا وهو يَعلم باطن الأمور وخفاياها بنفسه، فالعُملاء ليس بالضّرورة أن تأتي حاملة معها المعرفة المطلوبة لتكون من النوع المرن في المُعاملة، فمن المُحتمل جدًا أن يكون العميل لم يسبق له أن عمل مع مُستقلٍ من قبل، ولذلك على المُستقلّ أن يكون صاحب المُبادرة في توجيه العميل نحو الطريق الصحيح. كيف يُطوّر المُستقلّ نفسه وصلّت إلى نقطةٍ من مسيرتي المهنيّة كمُصمّم ومُستقلّ مُحترف أدرك فيها أنّ التعامل مع العُملاء هو لأمرٌ لا ينتهي عند نقطة مُحددة، بل هو عمليّة مُستمرّة وخبرة مُكتسبة، ومعرفة تراكميّة تزداد مع الوقت، وعندما أقوم بمقارنة بداياتي مع وضعي الحاليّ، أجد أنّي بالفعل قد تطوّرت كثيرًا، ولكنّي إلى الآن لم أصل إلى مرحلة الكمال والمثاليّة. ليس من المُفترض أن يكون العمل كمُستقلّ بذلك الصعوبة، ولكن بنفس الوقت هو ليس سهلًا ويتطلّب العمل بهذا النظام جهدًا لا يُستهان به، وهذا الجهد سيحصد ثماره لا محاله، فعندما يَستثمر المُستقلّ الوقت في التواصل مع العُملاء، فهو يُقوّي من العلاقة بينه وبين العميل ويزيد من الثقة بينهما، هذا التواصل المُثمر هو الّذي سيصب في النتائج النهائيّة للمشروع. ترجمة وبتصرّف للمقال Good Designers, Good Clients لصاحبته Laura Kalbag
  10. هذا المقال هو الجزء الثّاني من سلسلة استخدام puppet لإدارة الخواديم التي تتكوّن من كل من: تنصيب Puppet لإدارة البنية التَّحتِيَّة للخواديمملفّات البيان (Manifests) والوحدات (Modules) في Puppetكيف تستخدم Foreman لإدارة نقاط Puppet على الخادوم Ubuntu 14.04مُقدمةبعد إتمام إعداد منظومة Puppet الّتي تعتمد على مفهوم الخادم المَركزيّ والعُملاء، أصبح من المُلائم الآن التطرّق إلى آليّة كتابة الوحدات modules ومَلفّات البيان manifests، ولكي تُستخدام الأدة Puppet بالشكل الأمثل، يجب فهم بنية أوتركيبة هذا النوع من الملفات. سوف يتناول هذا الشرح أساسيات الشيفرة الخاصّة بالأداة Puppet، وكيفيّة بناء مَلفّات البيان والوحدات التي تساعد على فهم المبادئ الأساسية في استخدام Puppet لإدارة الخوادم، وذلك عن طريق شرح ثلاث طرق لاستخدام هذه الأداة في إعداد حِزم LAMP على خادم Ubuntu 14.04 يعمل على "خادم افتراضيّ خاصّ" VPS. مُتَطَلَّبات بيئة العملقبل الشروع في تطبيق مُحتويات هذا الشرح من الضروريّ توفّر بيئة عمل تستخدم نظام العُملاء والخادم المَركزيّ باستخدام الأداة Puppet، ويمكن الرجوع إلى الجزء الأول من هذا الشرح لمزيد من التفاصيل عن كيفية تنصيب Puppet لإدارة البنية التحتية للخوادم ، كما أنّه يجب توفّر خادم جديد ليكون نقطة عميل (Puppet agent node) للخادم المَركزيّ Puppet master. إنشاء نقطة عميل جديدةسيتمّ إنشاء خادم جديد يعمل بتوزيعة أوبونتو 14.04 ويحمل الاسم “lamp-1”، وتنصيب الأداة Puppet عليه، وضمّه إلى بقيّة العُملاء المُدارة من قبل الخادم المَركزيّ، وذلك بنفس الطريقة الّتي تمّت بها إضافة العُملاء في الجزء الأول. أساسيات كتابة شيفرة Puppetستتمّ مراجعة بعض المفاهيم والمُصطلحات المُرتبطة بالأداة Puppet، وذلك قبل الخوض في التفاصيل في كتابة الشيفرة الخاصّة بها. المَواردتتكوّن شيفرة الأداة Puppet بشكلٍ أساسيّ من تصريحات المَورِد resource declarations، والّتي تَصف حالةً مُعينة من النظام، مثل اسم مُستخدم مُعين أو وجوب وجود مَلفٍّ مُعين، أو حتّى وجوب توفّر أحد الحزم على الخادم. في الشيفرة التّالية مثالٌ على تصريح مَورِد لاسم مُستخدم مُعيّن: user { 'samir': ensure => present, uid => '1000', gid => '1000', shell => '/bin/bash', home => '/home/samir' } تَكون بنية تصريح المَورِد على الشكل التّالي: resource_type { 'resource_name' attribute => value ... } نوع المَورِد { 'اسم المَورِد' الخاصيّة => القيمة ... } يصف تصريح المَورِد السابق مَورِدًا مُعينًا وهو اسم المُستخدم "samir" والخواصّ الخاصّة به. يتمّ استعراض أنواع المَوارِد الافتراضيّة المُتاحة للأداة Puppet، بتنفيذ الأمر التّالي: puppet resource --typesمَلفّات البيان Manifestsتُدعى التعليمات الخاصّة بالأداة Puppet بمَلفّات البيان manifests، والّتي تحتوي على شيفرة Puppet، وهذه الملفات تستخدم اللاحقة .pp. يوجد مَلفّ البيان الافتراضيّ في المسار /etc/puppet/manifests/site.pp. في الجزء الأول من هذا الشرح تمّ كتابة مَلفّ بيانٍ كانت مُهمته إنشاء مَلفّ وتنصيب خادم الويب Apache، سوف يتمّ كتابة المزيد من هذا النوع من المَلفّات في هذا الجزء. الأصناف Classesالأصناف في Puppet هي عبارة عن قطعة من الشيفرة البرمجية والتي من المُمكن استدعائها في أي مكان من شيفرةً ما. تُوتيح استخدام الأصناف إعادة استخدام الشيفرة، مما يُقلّل من وقت التعديل وصيانة الشيفرة في وقتٍ لاحقٍ. كما تجعل هذه الأصناف من مَلفّ البيان أوضح وأسهل في الفهم والقراءة. كيفيّة تعريف الصنفيجعل تعريف الصنف من الصنف مُستخدمًا في أجزاءٍ مُختلفة من مَلفّات البيان manifests، ولكن في نفس الوقت هذه الأصناف لا تُفسر. يوضح المثال التّالي كيفيّة كتابة وتعريف الصنف في Puppet. class example_class { ... code ... } تُعرّفُ السطورُ السابقة صنفًا بالاسم “example_class”، وتتوضع الشيفرة الخاصّة بالأدة Puppet بين الحاصِرتين “{}” التصريح عن الأصنافلا يتمّ التصريح عن الصنف إلا عندما يتمّ استدعاؤه في مَلفّ البيان manifest، حيثُ أنّ هذا التصريح يخبر الأداة Puppet أنّ تقوم بتفسير evaluate الشيفرة المُتوضعة داخل هذا الصنف، ويُمكن التصريح عن الأصناف بطريقتين مختلفتين: طريقةٌ عادية normal، وطريقةٌ تشبه طريقة التصريح عن المَورِد resource-like. تَكون طريقة التصريح العادية باستخدام الكلمة المفتاحيّة include ضمّن شيفرة الأداة Puppet، كما في المثال التّالي: include example_classستقوم الأداة Puppet بتفسير الشيفرة الموجودة داخل الصنف “example_class” بعد التصريح السابق. يحدث النوع الثّاني من التصريح عندما يتمّ التصريح عن الصنف كما هو الحال عند التصريح عن مَورِد، و كما في المثال التّالي: class { 'example_class': }يسمح استخدام النوع الثّاني من التصريح resource-like بتحديد مُعاملات parameters، والتي تقوم بتجاهل وتجاوز القيم الافتراضيّة لخواصّ الصنف class attributes. في حال الرجوع إلى الجزء الأول من هذا الشرح فسيتضح أنّه بالفعل قد تمّ استخدام هذا النوع من التصاريح عندما تمّ استخدام الوحدة المُقدمة من معامل Puppet لتنصيب خادم الويب Apache على الخادم “host2”. node 'host2' { class { 'apache': } # use apache module apache::vhost { 'example.com': # define vhost resource port => '80', docroot => '/var/www/html' } } والآن بعد أنّ تمّ شرح المَوارِد ومَلفّات البيان والأصناف، سيتمّ تناول الوحدات modules بمزيد من التفصيل. الوحدات Modulesتتألّف الوحدات من مجموعة من مَلفّات البيان manifests ومجموعة من المُعطيات (مثل الحقائق facts ومَلفّات files، ونماذج templates)، ولهذه المجموعة تنظيم مساري مُحدد. تُساعد الوحدات على تنظيم شيفرة الأداة Puppet، حيثُ أنّها تُقدم المُرونة في تقسيم الشيفرة البرمجية المتمثّلة بمَلفّات البيان إلى أجزاءٍ مُستقلة، ويُعتبر ذلك طريقةً فعّالةً وعمليّة في استخدام الوحدات لتنظيم معظم مَلفّات البيان manifests الخاصّة بالأداة Puppet. تُوضع الوحدات modules الخاصّة بالأداة Puppet في المسار /etc/puppet/modules. سيتمّ التطرّق إلى التفاصيل اللازمة لكتابة وحدة مُبسّطة basic module، ولمزيد من التفاصيل يُمكن الرجوع إلى التوثيق الرّسميّ والجزء الخاص بأساسيات الوحدة في Puppet. تطوير مَلفّ البيانلشرح كيفيّة كتابة ملفّات البيان الخاصّة، والأصناف والوحدات، سوف يتمّ استخدام Puppet لإعداد وتنصيب حِزم LAMP على نظام التشغيل أوبونتو (بشكل مُشابه إلى هذا الشرح)، ومن الجيّد قراءة هذا الشرح لمعرفة كيفيّة تنصيب وإعداد هذه الحِزم بشكلٍ يدويّ قبل استخدام Puppet في ذلك. الهدف النهائي الذي يصبو إليه هذا الشرح هو خادم أوبونتو مع العناصر التّالية: تنصيب حزمة خادم الويب Apacheتشغيل خدمة خادم الويب Apacheتنصيب حزمة خادم قواعد البيانات MySQLتشغيل خدمة خادم قواعد البيانات MySQLتنصيب حزمة PHP5مَلفّ script لاختبار PHP وهو الملف info.phpتحديث "أداة الحزم المتقدمة" apt قبل تنصيب الحِزم السابقة.فيما يلي ثلاثة أقسام تشرح طُرقًا مُختلفة لاستخدام الأداة Puppet لتحقيق نفس الغاية، وهي خادم يحتوي على الحِزم LAMP ويعمل بشكل مُلائم. سيُوضّح المثال الأول كيفيّة كتابة مَلفّ بيان وحيد وبشكل مُبسّط، أما المثال الثّاني سيوضّح كيفيّة بناء واستخدام الأصناف والوحدات بناءً على مَلفّ البيان المطوّر في المثال الأول، وأخيرًا سيوضّح المثال الثّالث كيفيّة استخدام وحداتٍ مُطوّرة بشكل مُسبق لإعداد حِزم LAMP بشكلٍ سريعٍ وسهل. المثال الأول: تنصيب حِزم LAMP باستخدام مَلفّ بيان وحيد:هذا المثال هو مُلائم جدًا لمُدراء الأنظمة الذين لم يكتبوا مَلفّ بيان من قبل، سيُطوَّر مَلفُّ البيان على نقطة عميل Puppet agent node، ويُنفذ باستخدام الأمر puppet apply، ولذلك ليس من الضروريّ توفّر منظومة العُملاء والخادم المَركزيّ لإتمام هذا المثال. سيتمّ التركيز على كيفيّة كتابة مَلفّ بيان يَستخدم الأنواع التّالية من تصاريح المَورِد resource declarations: exec: لتنفيذ الأوامر مثل الأمر apt-getpackage: لتنصيب حزمة باستخدام الأداة aptservice: لتأكد من عمل خدمة ماfile: للتأكد من وجود ملفٍ ما أوعدمهإنشاء مَلفّ البيانسيتمّ إنشاء مَلفّ بيان جديد على خادم جديد يحمل الاسم "lamp-1" باستخدام الأمر التّالي: sudo vi /etc/puppet/manifests/lamp.ppوبإضافة السطور التالية إلى المَلفّ السابق يكون قد تمّ التصريح عن المَوارِد المطلوبة. # تحديث أداة الحزم المتقدمة exec { 'apt-update': # exec resource named 'apt-update' command => '/usr/bin/apt-get update' # command this resource will run } # تنصيب خادم أباتشي package { 'apache2': require => Exec['apt-update'], # require 'apt-update' before installing ensure => installed, } # التأكد من عمل خدمة أباتشي service { 'apache2': ensure => running, } # تنصيب خادم قاعدة البيانات package { 'mysql-server': require => Exec['apt-update'], # require 'apt-update' before installing ensure => installed, } # التأكد من عمل خادم قاعدة البيانات service { 'mysql': ensure => running, } # تنصيب لغة بي إتش بي package { 'php5': require => Exec['apt-update'], # require 'apt-update' before installing ensure => installed, } # التأكد من وجود مَلفّ file { '/var/www/html/info.php': ensure => file, content => '<?php phpinfo(); ?>', # phpinfo code require => Package['apache2'], # require 'apache2' package before creating } أصبح من المُمكن الآن استخدام الأمر puppet apply، الذي يُعتبر من نوع standalone، فهو يختلف عن الأمر puppet agent الذي يستدعي مَلفّ البيان من الخادم المَركزيّ. لتنفيذ مَلفّ البيان وهو ما سوف يتمّ عمله على الخادم "lamp-1" سيتمّ تنفيذ الأمر التّالي: sudo puppet apply --testسوف يتمّ عرض سطور عدّة كمخرجات output، يَظهر من خلالها حالة الخادم والتغييرات الّتي تمّت عليه، وذلك بشكل مُتوافق مع ما تمّ التصريح به من مَوارِد في مَلفّ البيان manifest. في حال عدم وجود أخطاء،أو مشاكل في عملية الإعداد، فيُفترض عند استعراض الصفحة info.php عرض معلومات تُشير إلى عمل خادم الويب Apache ولغة PHP كما هو مطلوب. لم يكن الإعداد السابق إلّا إعدادًا بسيطًا لما يُمكن عمله بالأداة Puppet، وذلك أنّه لم يتمّ استخدام منظومة الخادم المَركزيّ والعُملاء (agent/master setup)، أيضًا لا يتوفّر مَلفّ البيان السابق لبقية العُملاء لاستخدامه مرّةً أُخرى، كما لاتقوم الأداة Puppet بالتَفحّصِ بشكل دوريٍّ (كلّ 30 دقيقة) من حالة خوادمها في حال أنّها مُتوافقة مع ما هو مُعدّ لها في مَلفّ البيان. في المثال الثّاني، سوف يتمّ تحويل مَلفّ البيان السابق إلى وحدة module، وبذلك يُصبح من المُمكن استخدامه مع بقيّة العُملاء. المثال الثّاني: تنصيب حِزم LAMP باستخدام الوحدات modulesسيتمّ إنشاء وحدة مُبسّطة اعتمادًا على مَلفّ بيان حِزم LAMP المُطوّر في المثال السابق، وذلك بالاستعانة بالخادم المَركزيّ Puppet master. يتمّ إنشاء وحدة جديدة عبر إنشاء مسار جديد في المسار modules الخاصّ بالأداة Puppet، وهذا المسار يجب أنّ يُطابق اسم الوحدة الجديدة، مُحتويًا بداخله مسارًا بالاسم manifests، وبداخله مَلفّ init.pp. هذا المَلفّ يجب أنّ يحتوي فقط على صنف يُطابق اسم الوحدة. إنشاء الوحدة Moduleلإنشاء وحدة جديدة سيتمّ إنشاء مسار جديد بالاسم lamp، والذي هو اسم الوحدة أيضًا: cd /etc/puppet/modules sudo mkdir -p lamp/manifests ومن ثُمّ إنشاء وتحرير مَلفّ الوحدة init.pp sudo vi lamp/manifests/init.ppداخل هذا المَلفّ سيتمّ إنشاء صنف بالاسم “lamp” class lamp { } بعد ذلك سيتمّ نسخ مُحتويات مَلفّ البيان الّذي تمّ إنشاؤه في المثال الأول داخل هذا الصنف، وبذلك يكون قد تمّ تعريف صنف جديد بالاسم “lamp”، ولكن الشيفرة التي يحتويها هذا الصنف لن يتمّ تفسيرها (evaluate) هنا، ولكنها أصبحت جاهزة لكي تُستدعى (أي يُصرح عنها)، وأصبح بالإمكان الوصول إلى هذا الصنف كوحدة module من قبل مَلفّات البيان الأُخرى، وذلك فقط لأنّه يُحقّق قواعد تعريف الوحدة طبقًا للأداة Puppet. استخدام الوحدات Modules في مَلفّ البيان الرئيسيّبعد أنّ تمّ إنشاء مَلفّ وحدة مُبسّط، سيتمّ إعداد مَلفّ البيان الرئيسيّ (main manifest) لاستخدامه في تنصيب حِزم LAMP على الخادم “lamp-1”. على الخادم الرئيسيّ للأداة Puppet والذي يحمل الاسم “puppet” سيتمّ تحرير مَلفّ البيان الرئيسيّ: sudo vi /etc/puppet/manifests/site.ppومن ثمّ إضافة السطور التّالية، مع الانتباه أنّه في حال وجود إعدادات مُسبقة في هذا المَلفّ من الجزء الأول فلا بأس من خذفها. node default { } node 'lamp-1' { } تَسمح قطعة نقطة node block بتحديد شيفرة Puppet التي سوف تُطبّق على نقطة عميل مُعين، وتُطبّق النقطة “default” على جميع نقاط العُملاء التي لا تملك قطعة نقطة مُحددة لها، وهي في المثال السابق فارغة ولن يتمّ التعديل عليها. ما يهم من المثال السابق هو قطعة النقطة الّتي تحمل الاسم “lamp-1” والّتي سوف تُطبّق على العميل “lamp-1” فقط. سيتمّ تضمين الوحدة “lamp” داخل قطعة النقطة “lamp-1”. include lampستكون النتيجة النهائيّة للمّلفّ السابق على الشكل التّالي: de default { } node 'lamp-1' { include lamp } بعد الإعداد السابق، ستقوم نسخة العميل من الأداة Puppet الموجودة على الخادم “lamp-1” عند سحب الإعدادات الخاصّة بها من الخادم المَركزيّ، بتفسير مَلفّ البيان الرئيسي وتنفيذ الوحدة “lamp” لإعداد حِزم LAMP، وفي حال الرغبة في التجربة المُباشرة دون انتظار الاتصال التلقائيّ، بالإمكان تنفيذ الأمر التّالي على الخادم “lamp” sudo puppet agent --testبعد استكمال كافة الإعدادات من الجيّد التأكد من أنّ الأمور تيسير على مايُرام، وذلك باستعراض الصفحة info.php على خادم “lamp”. http://lamp_1 _IP/info.phpأو استخدام الأداة cURL من الطرفيّة terminal. من المُلاحظ أنّه بالإمكان الآن إعادة استخدام الوحدة الخاصّة بالخادم “lamp” الّتي تمّ إنشاؤها بالتصريح عنها في node blocks أُخرى. إنّ استخدام الوحدات هو أفضل طريقة لتهيئة شيفرة Puppet لإعادة استخدامها مرّة أُخرى، كما أنّ استخدام الوحدات يُساعد على تنظيم الشيفرة بأسلوب منطقيّ، الأمر الذي ينعكس على قراءة وفهم الشيفرة الخاصّة بالأدة Puppet. المثال الثّالث: تنصيب حِزم LAMP باستخدام وحدات مُعدّة مُسبقًايوجد مُستودعٌ خاصٌّ بالوحدات مُتوفّر على Puppet Forge، والذي يُسهل من الإعداد عند تطوير البِنْيَة التَّحْتِيَّة. يُمكن تنصيب الوحدات المُعدّة مُسبقًا بشكلٍ سريعٍ عبر الأمر puppet module، ومن ضمن هذه الوحدات المُعدّة مُسبقًا يوجد وحدات خاصّة بتنصيب خادم الويب Apache وخادم قواعد البيانات MySQL. لذلك سوف يتمّ استخدامُ هذه الوحدات الجاهزة في إعداد حِزم LAMP. تنصيب وحدات Apache وMySQLسيتمّ تنصيب الوحدة ذات الاسم puppetlabs-apache على الخادم “master” باستخدام الأمر التّالي: sudo puppet module install puppetlabs-apacheيَعرض الأمر السابق مُخرجات تُشير إلى تنصيب الوحدات بشكل صحيح: Notice: Preparing to install into /etc/puppetlabs/puppet/modules ... Notice: Downloading from https://forgeapi.puppetlabs.com ... Notice: Installing -- do not interrupt ... /etc/puppet/modules └─┬ puppetlabs-apache (v1.0.1) ├── puppetlabs-concat (v1.0.0) [/etc/puppet/modules] └── puppetlabs-stdlib (v3.2.0) [/etc/puppet/modules] أيضًا الوحدة الخاصّة بخادم قاعدة البيانات puppetlabs-mysql: sudo puppet module install puppetlabs-mysqlوبهذا تكون الوحدات “apache” و”mysql” جاهزة للاستخدام. تحرير مَلفّ البيان الرئيسيأما الآن وبعد أنّ تمّ تحميل هذه الوحدات، سيتمّ تحرير مَلفّ البيان الرئيسي ليستخدم الوحدات الجديدة لتنصيب حِزم LAMP، وذلك بتحرير هذا الملف على الخادم “master”. sudo vi /etc/puppet/manifests/site.pp يُمكن حذف أيّة إعدادات مُسبقة في حال وجودها، ومن ثمّ إضافة السطور التّالية: node default { } node 'lamp-1' { }سيتمّ التصريح عن صنف باستخدام نمط المَورِد ليستخدم الوحدة الّتي تحمل الاسم “apache”، وذلك داخل النقطة “lamp-1”: class { 'apache': # use the "apache" module default_vhost => false, # don't use the default vhost default_mods => false, # don't load default mods mpm_module => 'prefork', # use the "prefork" mpm_module } include apache::mod::php # include mod php apache::vhost { 'example.com': # create a vhost called "example.com" port => '80', # use port 80 docroot => '/var/www/html', # set the docroot to the /var/www/html }تقبل الوحدة “apache” مُعاملات parameters، والّتي من شأنها إلغاء الإعدادات الافتراضيّة الخاصّة بها، في السطور السابقة تمّ تمرير بعض الإعدادات البسيطة، حيثُ تمّ تعطيل المُضيف الافتراضيّ، والاستعاضة عنه بمُضيف يستطيع استخدام PHP، لمزيد من التفاصيل، يُمكن مُراجعة الموقع الرسميّ. استخدام الوحدة الخاصّة بخادم قواعد البيانات MySQL مُشابه لاستخدام الوحدة الخاصّة Apache. لن يتمّ تعقيد الإعداد هنا باعتبار أنّه لن يتمّ استخدام قواعد البيانات في مثالنا بشكلٍ فعليّ. سيتمّ إضافة السطور إلى داخل node block. class { 'mysql::server': root_password => 'password', }كما في وحدة خادم الويب Apache، من المُمكن تخصيص إعداد وحدة MySQL بتمرير مُعاملات parameters، ولمزيد من التفاصيل يُمكن الرجوع إلى الموقع الرسميّ. أما الآن فسيتمّ إضافة مَلفّ مَورِد مُهمته التأكد من نسخ المف info.php إلى المكان المُلائم. هذه المرّة سيتمّ استخدام المُعامل “source”، كما هو مُوضح في السطور التّالية. file { 'info.php': # file resource name path => '/var/www/html/info.php', # destination path ensure => file, require => Class['apache'], # require apache class be used source => 'puppet:///modules/apache/info.php', # specify location of file to be copied }يختلف التصريح السابق نسبيًا عمّا تمّ سابقًا، الاختلاف هو أنّه تمّ استخدام المُعامل “source” بدلًا من المُعامل “content”، حيثُ يخبر المُعامل “Source” الأداة Puppet بأنّ تقوم بنسخ المَلف بدلًا من كتابة محتواه. تُفسّر الأداة Puppet المصدر المُحدد (القيمة) puppet:///modules/apache/info.php إلى /etc/puppet/modules/apache/files/info.php، ولذلك يجب إنشاء مَلفّ المصدر لكي يعمل تصريح المَورِد السابق بشكل صحيح. يتمّ إنشاء الملف info.php بتنفيذ الأمر التّالي: sudo sh -c 'echo "<?php phpinfo(); ?>" > /etc/puppet/modules/apache/files/info.php' بعد أنّ يقوم العميل “lamp-1” بسحب إعداداته من الخادم المَركزيّ، سيقوم بتفسير evaluate مَلفّ البيان الرئيسيّ وتطبيق الوحدة الّتي تُشكل إعداد حِزم LAMP. لتطبيق الإعدادات الجديدة بشكل مُباشر يُمكن استخدام الأمر التّالي على الخادم “lamp-1”: sudo puppet agent --testبعد الانتهاء، ستكون حِزم LAMP مُنصبة، كما في المثال الأول، وللتأكد من عمل خادم الويب Apache وPHP، يُمكن استعراض الصفحة التّالية: http://lamp_1 _IP/info.phpتَعرض الصفحة السابقة معلومات عن استكمال تنصيب مُفسّر PHP بشكلٍ مُلائم، أيضًا بذلك يكون خادم الويب Apache مُنصبًا بشكل صحيح. الخاتمةفي هذه المرحلة وبعد مُتابعة الأمثلة السابقة وتطبيقها، والّتي قَدمت معرفة أساسية في استخدام الشيفرة الخاصّة بالأداة Puppet، وطريقة كتابة مَلفّ بيانٍ مُبسّط، وتطوير الوحدات modules، أصبح من المُمكن استخدام Puppet لإعداد أمورٍ أُخرى في منظومة الخوادم، وإدارتها بشكل يُلبي الحاجة أكثر مما هو عليه الأمر من دونها. يُعتبر استخدام الأداة Puppet في إدارة النظام والمُستخدمين والتطبيقات وغيره من المَوارد بدايةً جيّدة لاستغلال هذه الأداة بالشكل الأمثل. مع الانتباه إلى أنّ تغيير هذه المَوارد يجب أنّ يتمّ على الخادم المَركزيّ، وإلا سوف يتم إلغاء هذه التغييرات في المرّة القادمة الّتي تقوم بها العُملاء بالاتصال الدوريّ لسحب إعداداتها من الفهرس الخاصّ بها. في الجزء الثّالث والأخير من هذه السلسلة سيتمّ التعرّف على الأداة Foreman لإدارة العُملاء.  ترجمة -وبتصرّف- للمقال Getting Started With Puppet Code: Manifests and Modules
  11. سنتناول في هذه المقالة بقليلٍ من التفصيل شرح خاصّيّة هامّة من خواصّ أوراق الأنماط المُتتالية CSS وهي "ظلال النصّ" text-shadows، وتجدرُ الإشارة إلى أنه يوجد خاصّيّة مُشابهة لهذه الخاصّيّة وهي "ظلّ الصندوق" box-shadow، والخاصّيّتان مُعرفتان في وحدتين مختلفتين في المعايير القياسية لـ W3C على الرُغم من أنها مُتطابقتان إلى حدٍ كبير. سيكون من السهل تعلّم خاصّيّة "ظلّ النصّ" عند توفر معرفة مُسبقة بخاصّيّة "ظلّ الصندوق"، ولكن قبل كل شيء لكي يُفهم الفرق بينهُما، يجب القراءة قليلًا عن الجانب النظري من الموضوع، ودعم المُتصفحات لهذه الخاصّيّة، ومن ثُمّ التطبيق مع الأمثلة العملية. دعمُ المتصفحاتتدعمُ مُعظم المُتصفحات الحديثة الخاصّيّتان "ظلّ النصّ" و"ظلّ الصندوق" كما هو موضّح في الشكل التالي: يدعم المُتصفح Opera mini خاصّيّة "ظلّ النصّ" بشكل جزئيّ حيث لايَظهر تأثير الغشاوة blur على النصّ، وتُحاكي الإصدارات السابقة للإصدار العاشر من IE لخاصّيّة "ظلّ النصّ" باستخدام مُرشّحات filters غير معياريّة non-standard مثل مُرشّح dropshadow. الفرقُ بين "ظلّ النصّ" text-shadow و"ظلّ الصندوق" box-shadow طريقة كتابة الشيفرة الخاصّة بـ "ظلّ الصندوق" هي كالتالي: box-shadow: none|h-shadow v-shadow blur spread color |inset|initial|inherit;أمّا طريقة كتابة الشيفرة البرمجية لـ "ظلّ النصّ" فهي كالتالي: text-shadow: h-shadow v-shadow blur color|none|initial|inherit;تعملُ الخاصّيّتان بأسلوب مُماثل مع بعض الاستثناءات، حيثُ لا يُمكن إنشاء ظلّ داخليّ للنصِّ كما في خاصِّيَّة "ظلّ الصندوق"، كما لا يُمكن التحكم بمقدار التوسّع spread في "ظلّ النصّ"، ولكن يُمكن إنشاء أكثر من ظلّ لتُعرض فوق بعضها البعض بطريقة مُماثلة لـ "ظل الصندوق" كما سوف نوضّح بالأمثلة. يُوضّح الشكل التالي الاختلاف بين المفاهيم الأربعة التي سوف نعمل عليها. الجانب العمليّ لخاصّيّة "ظلّ النصّ"الألوان والإزاحةتُحرّكُ قيمُ الإزاحة الموجبة الظلّ بالاتجاه الأيمن والأسفل، وتُحرّكُ القيمُ السالبة الظلّ بالاتجاه المُعاكس أيّ نحو اليسار والأعلى. تحديدُ لون الظلّ هو أمرٌ إختياريّ، وسيأخذ الظلّ لون العنصر الأب في حال عَدم تحديد لون مُحددٍ له، ويُنصح دائمًا بتحديد اللون وذلك لأن المُتصفّحات سوف تُظهر لون الظلّ بشكل مُختلف فيما بينها. في الأمثلة التالية سوف نُحدّد الإزاحة الأُفقيّة والعموديّة مع ألوان مُخصّصة text-shadow:10px 10px; text-shadow:-5px -5px; color:blue; text-shadow:-1px -1px white; color:blue; background:#888; text-shadow:1px 1px rgba(255,255,255, 0.5); color:blue; background:#eee; الغشاوة blurالمُعامل الخاصّ بالغشاوة هو مُعاملٌ اختياريّ، وقيمته تُحدد مدى انتشار الغشاوة لحواف الظلّ، ويجب أن تكون قيمتُه موجبة، حيث القيمة صفر تعني بدون غشاوة، أي أنّ حواف الظلّ ستكون حادّة. /*blur*/ .example1 { text-shadow:5px 5px 3px darkred; color:red; } .example2 { text-shadow:4px -4px 10px red; color:azure; background:#333; } .example3 { text-shadow:0px 0px 4px ; } .parent-of-example3 { color:red; } .example4 { text-shadow:0px 0px 4px ; } .parent-of-example4 { color:lightgray; background:#333; } استخدمنا في المثال الأول والثاني غشاوة مُختلفة، حيثُ الأول 3px والثاني 10px، ولم نُحدد لون العنصر بشكل مُباشر في المثال الثالث والرابع بل على العنصر الأب. التوسّع والانكماش Expansion and contractionسوف يتم إضافة إمكانية تحديد التوسّع spread لخاصّيّة "ظلّ النصّ" في الإصدار الرابع من `أوراق الأنماط المُتتالية` CSS4، ولكن IE10 يدعم هذه الخاصّيّة مُنذ الآن، ولذلك في الأمثلة سوف يظهر تأثير هذا المُعامل parameter -وهو الرابع للخاصّيّة text-shadow- على المُتصفح IE10 وIE11. تزيد القيّم الموجبة من توسّع الظلّ وتُقلّص القيّمُ السالبة من توسّع الظل، وتُستخدم القيمة صفر لإضافة حدود خارجية للنصّ. text-shadow:5px 5px 0px 3px lightgreen; color:green; text-shadow:8px 8px 2px -3px darkgreen; color:green; font-weight:900; text-shadow:0 0 0 3px rgba(128, 255, 0, 0.75); color:green; background:#333; الظلّ المُتعدد Multiple shadowتُمكنك خاصّيّة "ظل الصندوق" من إنشاء أكثر من ظلّ لنفس النصّ، وذلك عبر كتابة قيمة كل ظلّ والفصل بينها بالفاصلة (,) /*Multiple shadow*/ .example1 { text-shadow: 0 0 0 3px white, 0 0 0 4px gray; color:magenta; } .example2 { text-shadow: 3px 3px 4px 2px rgba(255,255,255,0.35), 6px -6px 4px 2px rgba(255,255,255,0.25), -3px -3px 4px 6px rgba(255,0,255,0.15); } .example3 { text-shadow: 0 0 0 3px white, 0 0 2px 6px magenta, 0 0 1px 9px white, 0 0 6px 12px magenta; color: magenta; } .example4 { text-shadow: 0 0 2px #fff, 0 0 4px 2px rgba(255,255,255,0.5), 0 0 6px 6px #f0f, 0 0 4px 7px #fff, 0 0 3px 15px #222, -4px 0 2px 9px #f0f, 4px 0 2px 9px #f0f, 0 -4px 2px 9px #f0f, 0 4px 2px 9px #f0f; color: white; } .example5 { text-shadow: 0 -3px 3px 15px white, 0 1px 2px 9px; color: magenta; } مُحاكات التوسّع Emulating expansionأشرت سابقًا إلى أنّ إمكانية عمل التوسّع spread للنصّ مُتوفرة فقط في الإصدار الرابع من CSS، ولكن يُمكن عمل مُحاكات لها في الإصدار الثالث. text-shadow: 0px 0px 0px 4px magenta; /* الشيفرة السابقة مُشابهة للشيفرة التالية */ text-shadow: 0px 2px magenta, 2px 0px magenta, -2px 0px magenta, 0px -2px magenta, -1.4px -1.4px magenta, 1.4px 1.4px magenta, 1.4px -1.4px magenta, -1.4px 1.4px magenta; كما هو مُبيّن في المثالين السابقين أنّ المُحاكات ليست مثاليّة من ناحية المظهر ودقّة الحواف الخاصة بالظلّ، وكما تختلفُ سرعة المُتصفح في عرض المثالين السابقين. أمثلة إضافيةظلّ مزدوج /*Twin shadow*/ .twin { text-shadow: 0 0 2px 2px white, 2px 0 2px 5px #222, 3px 0 3px 6px #933, 5px 0 2px 14px #222, 6px 0 5px 16px #533; background-color: #222; color: white; } تأثير Letter-press /*Letter-press*/ .le-pr { text-shadow: 0px 2px 3px #555; background-color:#333; }قوس قزح /*Rainbow*/ /*IE*/ .rainbow { text-shadow: 0 0 2px 3px yellow, 0 0 2px 6px orange, 0 0 2px 9px red, 0 0 2px 12px lime, 0 0 2px 15px blue, 0 0 2px 18px violet; }ثلاثي الأبعاد /*3D*/ .threed { text-shadow: 0 0 1px #999, 1px 1px 1px #888, 2px 2px 1px #777, 3px 3px 1px #666, 4px 4px 1px #555, 5px 5px 1px #444; background-color:#333; color:white; }تأثير Retro /*Retro / Vintage effect*/ .retro { text-shadow: 2px 2px #fff, 3px 3px #666; }الحرف الأول باستخدام "شبه الصنف" pseudo-class المُسمى "الحرف الأول" first-letter /*First-letter-only shadow */ .text { text-shadow: 0 0 5px; } .text::first-letter { color:azure; text-shadow: 0 0 5px, 0 0px 6px 3px blue, 0 -2px 6px 6px cyan, 0 -4px 9px 9px lightblue ; }التوهج .flame { text-shadow: 0 0 2px #eee, 0 0 4px 2px #fff, 0 -2px 4px 2px #ff3, 2px -4px 6px 4px #fd3, -2px -6px 11px 6px #f80, 2px -8px 18px 8px #f20; background-color:#222; color:white; } ترجمة -وبتصرّف- للدّرس Practice with Text Shadows
  12. إنّ أي مُطوّر أو مُصمّم يُحب كتابة الشيفرة البرمجية، ستكون تقسيمات الصفحة layouts المُعتمدة على أوراق الأنماط المُتتالية هي صميم وجوهر عمله. فيما قد تكون هذه المقالة مُراجعة للبعض، أو حتّى تصحيح بعض المفاهيم للبعض الآخر، سيتمّ تناول خاصّيّة التَمَوْضُع position، وكيفيّة استخدامها في تصميم تقسيمات صفحة layouts مُسايرة ومُتوافقة مع المعايير القياسيّة، ولا تعتمد على الجداول. يُساء فهمُ خاصّيّة التَمَوْضُع، ممّا يؤدي في بعض الأحيان عند تصحيح علّة مُعينة في شيفرةٍ ما من المُمْكن أنّ يتمّ استخدام قيم مُختلفة بأسلوب التجربة والخطأ للخاصّيّة position لمُحددٍ ما حتّى يتمّ الحصول على القيمة المطلوبة. إنّ هذه الطريقة المُملّة قد تفي بالغرض، ولكن من المُفترض على المُطوّر معرفة بالتحديد لماذا القيمة position: relative قد استطاعت إصلاح مُشكلة ما في تقسيم الصفحة دون قيمة أُخرى. هدف هذا الشرح هو تعلّم دلالات قيمة الخاصّيّة position وتأثيرها على الصفحة، وبالأخصّ، كيف سوف تؤثّر هذه القيم على بقية أجزاء الصفحة (markup). يُقدم بَيان specification أوراق الأنماط المُتتالية خمس خواصٍّ وهي: ساكن: staticنسبيّ: relativeكامل أو مُطلق: absoluteثابت: fixedمَوروث: inheritكما تمّ إضافة قيم جديدة ولكنها مازالت في مرحلة "مسودة عمل". يُستفاد من كل خاصّيّة لغرضٍ مُعينٍ، لذلك فَهمُ الغرض من كلٍ منها هو الطريق الأمثل لاحتراف تقسيمات الصفحة المُعتمدة على CSS. الخطوات الأولى مع أليّة عمل خواصّ التَمَوْضُعسيتمّ العودة إلى الأساسيّات لفهم الأمور بشكلٍ صحيحٍ. في CSS وبطبيعة الحال، يتمّ العمل ضمن حدود وقواعد ما يهم هُنا هو ما يُدعى بـ "التدفّق الطبيعيّ" normal flow. في العودة إلى بيان مُنظمة رابطة الشبكة العالميّة W3C سيكون تعريف التدفّق الطبيعيّ بالشكل التّالي: يُمكن اعتبار الصندوق المَذكور في البيان السابق كالصندوق الخشبي، والتدفّق الطّبيعيّ كما لو أنّه قانون كما هو قانون الجاذبيّة، التدفّق الطّبيعيّ للمُستند يُعبر عن اصطفاف العناصر فوق بعضها البعض تدريجيًّا من الأعلى إلى الأسفل، لكي تَظهر بالشّكل المُفترض لها أنّ تظهر عليه. يُمكن تشبيه التدفّق الطّبيعيّ بصناديق (مُكعبات) الأحرف الأبجديّة الّتي يُبنى منها ذلك البرج الضخم -الّذي يبنيه الأطفال بشكل مُتسلسل للأحرف- حيثُ أنّ هذه الصناديق الخشبيّة مُقيّدة بفعل الجاذبيّة الأرضيّة، ولا يُمكن إعطائها خصائص تُعارض قانون الجاذبيّة. في الجهة المُقابلة تتبع العناصر بعضها البعض في ترتيب عناصر الصفحة الخاصّة بمُستند HTML. ولكن من المُمكن إعطاء هذه العناصر خصائص لتُعرض بشكلٍ مخالفٍ لترتيبها الطبيعيّ. الخاصيّتان static و relativeتشبه خاصِّيَّات التَمَوْضُع "ساكن" static و "نسبيّ" relative سلوك صناديق الأبجديّة، حيثُ أنّها تصطفّ فوق بعضها البعض كما هو مُتوقعٌ لها. مع الانتباه إلى أنّ الخاصّيّة static هي القيمة الافتراضيّة للخاصّيّة position لأي عنصر. وعندما يكون هناك ثلاثة عناصر تحمل الخاصّيّة static فإنّها سوف تصطفّ فوق بعضها البعض. في المثال التّالي يوجد ثلاثة عناصر جميعها تحمل القيمة static. #box_1 { position: static; width: 200px; height: 200px; background: #ee3e64; } #box_2 { position: static; width: 200px; height: 200px; background: #44accf; } #box_3 { position: static; width: 200px; height: 200px; background: #b7d84b; } يُلاحظ من المثال السابق كيف أنّ هذه الصناديق تصطفّ فوق بعضها البعض. هذه الفكرة على بساطتها تعتبر أساسيات بناء الكتل block building ومن المُهم جدًا إدراكُها. يُمكن استخدام القيمة static لإنشاء تقسيمات صفحة مُبسّطة بعمود واحد single-column، حيثُ كل عنصر يتموضع فوق العنصر الّذي يليه. وعند الرغبة في نقل هذه العناصر فيما بينها باستخدام خواصّ الإزاحة offset مثل: الأعلى top، اليمين right، الأسفل bottom، اليسار left ستكون النتائج غير مُرضيةٍ أبدًا، حيثُ لا تؤثر هذه الخواصّ على عنصر ساكن static (أي يقوم بتجاهلها). كما لا يستطيع العنصر الساكن إنشاء نسق إحداثيَّات جديد للعنصر الابن. ولكن ما هو نسق الإحداثيَّات، هذا ما سيتمّ توضيحه باستخدام القيمة نسبيّ relative. تتصرّف العناصر المُتموضعة بشكل نسبيّ relative كما هي العناصر المُتموضعة بشكل ساكن static، حيثُ تتوافق فيما بينها بشكل مُتناسق، من دون أنّ تسبب أي مشاكل. قد يبدو الأمر غريبًا، ولكن عند تطبيق القيمة relative على المثال السابق ستكون النتائج مُشابهة للمثال السابق: #box_1 { position: relative; width: 200px; height: 200px; background: #ee3e64; } #box_2 { position: relative; width: 200px; height: 200px; background: #44accf; } #box_3 { position: relative; width: 200px; height: 200px; background: #b7d84b; } يُبرهن المثال السابق كيف أنّ العناصر المُتموضعة بشكل نسبيّ relatively تسلك سلوك العناصر المُتموضعة بشكل ساكن statically. لكن ما هو غير واضح أنّ هذه العناصر الّتي تحمل القيمة relative تختلف بمَيْزة هامة جدًا عن العناصر الّتي تحمل القيمة static. يكمُن الاختلاف الأوَّليّ في أنّ العناصر المُتموضعة بشكل نسبيّ من المُمكن تعديل مَوضعها باستخدام خاصِّيَّات الإزاحة: top و right و bottom و left. سيتمّ استخدام المثال السابق، ولكن بإضافة تَمَوْضُع الإزاحة على الصندوق الثاني “box_2”: #box_2 { position: relative; left: 200px; width: 200px; height: 200px; background: #44accf; } يُظهر المثال السابق التَمَوْضُع النسبيّ بشكلٍ عمليٍّ. حيثُ أنّ الصناديق الثّلاثة مُتموضعة فوق بعضها ماعدا الصندوق الثّاني فقد تمّ دفعه 200px من اليسار. في هذا المثال قد تمّ كسر قانون الجاذبية بناءً على رغبتنا. ومازال الصندوق الأزرق ينتمي إلى التدفّق العام الخاصّ بمُستند HTML، حيثُ أنّ الصندوق الأخضر يأتي أسفل الصندوق الأزرق على الرغم من أنّ الصندوق الأزرق ليس فوقه بشكل مُباشر. عند استخدام خاصِّيَّات الإزاحة لنقل عنصر مُتموضع بشكلٍ نسبيٍّ، فإن ذلك لا يؤثّر على العنصر أو العناصر التّالية، حيثُ أن الصندوق الأخضر مازال مُتموضعًا كما لو كان الصندوق الأزرق غير مُزَاح. وهو أمرٌ لا ينطبق على التشبيه الخاصّ بصناديق الأبجديّة. يُعتبر إنشاء نسق إحداثيَّات للعنصر الابن مَيْزةً أُخرى من ميزات خاصيّة التَمَوْضُع النسبيّ. حيثُ يُمثل هذا النسق نقطةً مرجعيّةً لخاصِّيَّات الإزاحة. سيتمّ العودة إلى المثال السابق لتوضيح هذه الفكرة، حيثُ أنّ الصندوق الأزرق لا يتموضع داخل أيًا من العناصر، لذلك نسق الإحداثيَّات المُستخدم لإزاحة نفسه 200px من جهة اليسار يعود إلى المُستند نفسه. ولو تمّ وضع الصندوق الثّاني داخل الصندوق الأول، سيتمّ الحصول على نتائج مُختلفة، حيثُ أنّ الصندوق الثّاني سيتموضع نِسْبَة إلى نسق الإحداثيّات من الصندوق الأول (الأحمر). في المثال التّالي سيتمّ التعديل على مُستند HTML دون التعديل على التنسيق CSS، وذلك بنقل الصندوق الثّاني داخل الصندوق الأول: <div id="box_1"> <div id="box_2"></div> </div> يُظهر المثال السابق ترميز مُستند HTML الجديد. وبسبب نسق الإحداثيّات الجديد، يقيس الصندوق الأزرق إزاحته 200px من جهة اليسار نسبةً إلى المكان الّذي كان سيكون عليه الصندوق الأزرق لو لم يكن مُتموضعا بشكلٍ نسبيٍّ. القيمة Absoluteتُمثّل القيمة absolute درجة عالية من الأهمية وأكثر من سابقتها relative، حيثُ التخصيص هو ما يُميز هذه القيمة. يُسحب العنصر المُتموضع بشكلٍ نسبيٍّ من التدفّق الطّبيعيّ، وذلك عكس ما يتمّ في العناصر الّتي تحمل القيمة relative و static. ويمكن التحكم بالعنصر بطريقةٍ مرنة عندما يتمّ سحبه من التدفّق الطّبيعيّ، حيثُ يُمكن وضعه في أي مكان من دون أنّ يؤثّر أو يتأثّر بباقي العناصر المُنتمية إلى هذا التدفّق. يُمكن التفكير بهذه العناصر كما لو أنّ لها على الجهة الخلفية قطعة كبيرة من مشبك velcro، حيثُ يُمكن إلصاق هذه العناصر في أي مكان حسب الرغبة والحاجة. تَستجيب العناصر المُتموضعة بشكل مُطلق (كامل) absolutely إلى خاصِّيَّات الإزاحة. حيثُ يُمكن تحديد القيم top: 100px و left: 200px للعنصر ليتوضع العنصر بالضَّبط 100px من الجهة العلوية و200px من الجهة اليُسرى للمُستند. سيتمّ التوضيح بالمثال التّالي وباستخدام أربعة صناديق: #box_1 { position: absolute; top: 0; left: 0; width: 200px; height: 200px; background: #ee3e64; } #box_2 { position: absolute; top: 0; right: 0; width: 200px; height: 200px; background: #44accf; } #box_3 { position: absolute; bottom: 0; left: 0; width: 200px; height: 200px; background: #b7d84b; } #box_4 { position: absolute; bottom: 0; right: 0; width: 200px; height: 200px; background: #ebde52; } يُظهر المثال السابق أربعة صناديق تتموضع في زَوايا المُتصفّح الأربع، وذلك بسبب أنّ كل صندوق يحمل القيمة absolute للخاصيّة position، بكلماتٍ أُخرى تمّ إلصاق هذه الصناديق في كل زاوية من زوايا نافذة المُتصفّح. ستبقى هذه الصناديق بالزاوية الخاصّة بها عند تغيير حجم المُتصفّح. وإنّ تصغير حجم المُتصفّح بحيثُ تتداخل أو تتشابك هذه الصناديق مع بعضها لن يُحدث أي تفاعل فيما بينها على الإِطْلاق، أي لن يزيح أحدها الآخر، وكأنّ كل صندوق في طبقةٍ مُختلفة، وذلك لأنّ هذه الصناديق قد أصبحت خارج التدفّق الطبيعيّ للمُستند. تُنشئ العناصر المُنسّقة بالقيمة absolute نسق إحداثيَّات جديد للعناصر الأبناء الخاصّة بها. المثال التّالي يوضّح كيف أنّ الصناديق البرتقاليّة الصغيرة تتموضع داخل الصناديق الآباء الخاصّة بها، وإحداثيّات الإزاحة مُرتبطة بالعناصر الآباء لا بنافذة المُتصفّح. <div id="box_1" class="box"> <div class="orange"></div> </div> <div id="box_2" class="box"> <div class="orange"></div> </div> <div id="box_3" class="box"> <div class="orange"></div> </div> <div id="box_4" class="box"> <div class="orange"></div> </div>} .box { position: absolute; width: 200px; height: 200px; } #box_1 { background: #ee3e64; top: 0; left: 0; } #box_2 { background: #44accf; top: 0; right: 0; } #box_3 { background: #b7d84b; bottom: 0; left: 0; } #box_4 { background: #ebde52; bottom: 0; right: 0; } .orange { background: #f95b34; position: absolute; top: 39%; left: 41%; width: 40px; height: 40px; } تُقدم القيمة absolute خصائص مُميّزة عند استخدام قيم الإزاحة معها، حيثُ سيُصبح من المُمْكن تَمْديد العنصر من دون تحديد أيًا من أبعاد العَرض width أو الارتفاع height، والّتي ستكون مُختلفة بناءً على حجم نافذة المُتصفح أو قياس الشاشة. وعليه فإنّ العنصر الابن سيكون مُقيّدًا بالعنصر الأب الخاصّ به، أو المُستند نفسه. المثال التّالي سيُوضح الفكرة: a { position: absolute; top: 10px; right: 10px; bottom: 10px; left: 10px; background: #44accf; } #box_b { position: absolute; top: 20px; right: 20px; bottom: 20px; left: 20px; background: #ff9c34; } يُوضّح المثال السابق كيف أنّ العناصر قد أصبحت أكثر مُرونة fluid، حيثُ يَتغيّر حجمها مع تَغيّر حجم الصفحة. ويوضّح المثال التّالي كيفيّة إنشاء صفحة بعمودين وبارتفاع الصفحة بالكامل. #box_1 { position: absolute; top: 0; right: 20%; bottom: 0; left: 0; background: #ee3e64; } #box_2 { position: absolute; top: 0; right: 0; bottom: 0; left: 80%; background: #b7d84b; } يُظهر المثال السابق تقسيم صفحة بعمودين، والّذي يُوضّح ما يُمكن عمله باستخدام القيمة absolute. أخذًا بعين الاعتبار أنّ هذا الأسوب ليس أفضل طريقة في إنشاء تقسيم صفحة بعمودين. يُمكن استخدام بعض الحِيَل في إيجاد تطبيقات عمليّة لهذه الخاصّيّة. على سبيل المثال: #box_1 { width: 200px; height: 200px; background: #ee3e64; } #box_2 { position: absolute; left: 100px; width: 200px; height: 200px; background: #44accf; } عند التركيز في المثال السابق والصندوق الثّاني بالتحديد، سيتمّ مُلاحظة كيفيّة استخدام قيمة إزاحة واحدة left: 100px;، وهذا ما يَسمح للصندوق الثّاني في الحفاظ على حافته العلوية في مكانها مع مقدرته على الانتقال 100px من جهة اليسار، ولكن عند تطبيق قيمة إزاحة ثانية إلى الجهة العلوية، سيتمّ سحب الصندوق الأزرق إلى أعلى المُستند: #box_2 { position: absolute; top: 0; left: 100px; width: 200px; height: 200px; background: #44accf; } القيمة ثابت Fixedيُشارك العنصر الّذي يحمل التنسيق position: fixed جميع الأحكام والقواعد الّتي يحملها العنصر المُتموضع بشكل مُطلق absolutely، حيثُ أنّ العنصر يُسحب من التدفّق الطّبيعيّ للمُستند. ويكمُن الاختلاف في أنّ العنصر الثّابت fixed يتمَوضع نسبة إلى المُستند، وليس إلى عنصر أب مُعيّن. كما لا يتأثر العنصر الثابت بالتدرّج، فيبقى في مجال الرؤية مهما تمّ النزول أو الصعود في الصفحة. #box_2 { position: fixed; top: 0; left: 0; right: 0; } يُظهر المثال السابق شريطًا عُلويًّا يحتوي على نصّ، وذلك كعنصر fixed، من المُلاحظ عدم تحرك هذا الشريط عند التدرّج في الصفحة. أيضًا من المُلاحظ أنّ خاصِّيَّات الإزاحة left وright تحمل القيمة صفر. باعتبار أنّ القيمة fixed تنتهج سلوكًا مشابهًا لسلوك القيمة absolute، فمن المُمكن أنّ يتمّ تمديد عرض العنصر ليتناسب مع مجال الرؤية عند تثبيت العنصر أعلى الصفحة باستخدام top: 0;. القيمة Inheritتمّ في بداية المقالة الإشارة إلى وجود خَمس قيم مُتوفّرة للخاصيّة position. القيمة الخامسة هي مَوروث inherit والأقل أهميّة. تعمل هذه القيمة كما يدلّ الاسم الخاصّ بها، حيثُ أنّ العنصر يرث القيمة الخاصّة بالعنصر الأب. علمًا أنّه في الأساس، عناصر الخاصّيّة position لا ترث قيمتها من العنصر الأب الخاصّ بها، وتكون القيمة static هي القيمة الافتراضيّة. الفرق بين relative وabsoluteيُظهر هذا التشبيه الفرق بين التنسيقين "نسبيّ" و "مُطلق". يُزاح دائمًا العنصر الّذي يحمل التنسيق "نسبيّ" نسبةً إلى موضعه الأصليّ في التدفّق الطّبيعيّ، بمعنى أنّ هذا العنصر يتحرك نسبة إلى المكان الّذي كان سيكون عليه في الظروف العاديّة. وهذا الانتقال لا يؤثّر على تقسيم الصفحة أو العناصر المُحيطة، أي كأنّ هذا العنصر قد أصبح شبحًا قد ترك جسمه خلفه. هذا الجسم له عرض وارتفاع ويؤثّر على محيطه ولكنه غير ظاهر. ويستطيع الصندوق الشبح التحرك ولكنه مازال مُرتبطًا بجسمه القديم، بمعنى أنّ موقعه الحاليّ يُقاس بناءً على موقعه القديم. أمّا العنصر الّذي يحمل التنسيق "مُطلق" فهو لا يؤثّر على محيطه أبدًا، وذلك لأنّه قد تمّ سحبه من التدفّق الطّبيعيّ. وبذلك فهو أيضًا شبح ولكنه لم يترك جسمه خلفه كما فعل الشبح النسبيّ. وبالنسبة للعناصر المُحيطة فإنّ هذا العنصر غير موجود. يحصل الشبح المُطلق على موضعه بعد النظر عبر جميع الآباء الخاصّة به حتّى يجد واحدًا منها يتموضع إما بشكلٍ "نسبيّ" أو "مُطلق" ليكون نسق إحداثيَّات لهذا العنصر. وعندما لا يجد هذا الشبح أيًا من الآباء يتموضع بشكلٍ "نسبيّ" أو "مُطلق"، ستكون نقطته المرجعيّة هي المُستند العام. تطبيقٌ عمليّسيتمّ تَوظيف الشرح السابق في مثالٍ عمليّ يجعل من الأمور أكثر وضوحًا لهذه الخاصِّيَّات. المثال هو للتوضيح فقط، ولا يُعتبر تطبيقًا مثاليًا لاستخدامه في الواقع العمليّ. <div id="container"> <div id="nav"> <a href="#">Link</a> <a href="#">Link</a> <a href="#">Link</a> <a href="#">Link</a> <a href="#">Link</a> </div> <div id="content"> <div id="callout"> <p>...</p> </div> <p>...</p> <p>...</p> <p>...</p> <p>...</p> <p>...</p> <p>...</p> <p>...</p> <p>...</p> <p>...</p> </div> <div id="footer"> <p>Copyright © 2015 - webtuts Web Sites</p> </div> </div> تُظهر الصورة السابقة تقسيم صفحة شائع الاستخدام في الكثير من المواقع، شريط تنقل علوي navigation، المحتوى content، ذيل الصفحة footer. سيتمّ مُناقشة كل عنصر، وخاصيّة التَمَوْضُع الخاصّة به، ولماذا تمّ اختيار كلٍ منها. سيتمّ استخدام #container لجعل بقية العناصر مُتمركزة في المُنتصف. العنصر #nav سيكون العنصر الأول داخل العنصر #container. لم يتمّ تخصيص العنصر #nav بالخاصيّة position، لذلك ستكون القيمة static هي المُعَيَّنة. وستفي القيمة الافتراضيّة بالغرض على اعتبار أنّه لن يتمّ إزاحة هذا العنصر، أو استخدامه في إنشاء نسق إحداثيَّات جديد. على الجهة الأُخرى سيتمّ تخصيص العنصر التّالي وهو #content بخاصيّة التَمَوْضُع position بالقيمة relative. لا تؤثر قيمة التَمَوْضُع position على العنصر #content عند عدم استخدام أيًا من قيم الإزاحة، ولكن قد تمّ تخصيصها بالتنسيق position: relative; لتُكوّن نقطة الإحداثيَّات للعنصر #callout. كما تمّ تنسيق العنصر #callout بالتنسيق position: absolute. أخذًا بعين الاعتبار أنّ العنصر الأب وهو #content الخاصّ بهذا العنصر قد تمّ تنسيقه بشكل نسبيّ relative، فإنّ خاصِّيَّات الإزاحة المُطبقة على العنصر #callout ستكون مُعتمدة على الإحداثيَّات المُنشأة من قبل العنصر الأب #content. كما تمّ تخصيص العنصر #callout بإزاحته -80px إلى جهة اليمين بهدف سحبه خارج العنصر الأب. علاوةً على ذلك، تمّ تخصيص العنصر #callout بإزاحته من الجهتين العلويّة والسفليّة بالقيمة 100px، وبذلك سيحافظ هذا العنصر على ارتفاع شبه كامل منقوصًا 200px مهما كان حجم الصفحة. لا يؤثّر العنصر #callout على باقي العناصر بما أنّ له القيمة absolute، ولذلك يجب إضافة بعض الحشو padding للعنصر #content وذلك كي لا تختفي الفَقْرات paragraphs أسفل العنصر #callout. كما سيتمّ تخصيص ذيل الصفحة بخاصيّة التَمَوْضُع مع القيمة fixed مما يجعله ثابت ضمن مجال الرؤية viewport عند التدرّج في الصفحة نزولًا أو صعودًا. كما سيتمّ إضافة حشو إلى العنصر #content ومن الناحية السفلية وبقيمة 60px وذلك لعدم اختفاء الفقرة الأخيرة تحت ذيل الصفحة. الخاتمةتُعتبر خواصّ التَمَوْضُع من المواضيع الّتي لا بُد على أي مُطوّر الإلمام بها بشكل مُعمّق، وذلك كي لا يتمّ الاعتماد على أسلوب التجربة والخطأ trial and error في التعامل مع هذه الخاصّيّة. يعطي فهم هذه الخاصّيّة احترافيّة عالية للمُطوّر ويزيد من إنتاجيّته عن باقي المُطوّرين الّذين يعتمدون على أسلوب التجربة والخطأ. ترجمة -وبتصرّف- للمقال CSS Positioning 101 لصاحبه Noah Stokes
  13. يكفي استخدام أي محرر نصوص متوفّر لديك على نظام التشغيل، أو يُمكن استخدام Notepad++ لمزيد من الميزات.
  14. تُحدّد الجودة بناءً على المُستقل نفسه وليس على المنصة أو الأسعار، حيثُ أنك ستجد نفس المُستقل يعمل على الموقعين، وبالتّالي عليك التعامل مع صاحب الخبرة وذلك بالتحقق من أعماله السابقة وتقييماته بغض النظر عن الأمور الأُخرى.
  15. اجعل اسمك معروفًا في المجال الذي تبرع فيه وتحبه، شارك في المجتمعات مثل مجتمع "حسوب IO"، اكتب كتيّبًا عن أمرٍ تبرع فيه، دوّن في مُدوّنة، اكتب في تويتر. يعني بالمُختصر سوّق نفسك. بعد ذلك سجّل في مواقع العمل الحر مثل "مستقل".
  16. بشكل عام يختلف الأمر على حسب طبيعة الشركة والمُهمة المطلوبة، ولكن الأمر المؤكد أنّه لا يُعتبر الاعتماد على مُستقلين من المواقع الّتي ذكرتها أمرًا غير احترافي بل على العكس هو الاحترافيّة بحد ذاتها، حيث سيتسنّى لك التّالي: زيادة الفرصة في التعرّف على أشخاص محترفين، إدخال أفكار جديدة إلى الشركة، التوفير في التكلفة مقارنة مع موظف يعمل بدوام كامل أو جزئي. تصميم شعار أو هوية للموقع هو أمرٌ تحتاجه مرّة واحدة، وبالتّالي التعامل مع مُستقل هو أمرٌ بديهيٌ، ولكن إدارة الحسابات الاجتماعيّة هو مُهمة مستمرة طالما الشركة مُستمرة، وبالتّالي التعامل مع موظف دائم هو الصواب بعينه. ستكون طريقة الدفع على حسب المُهمة والخدمة المطلوبة وبطبيعة الحال طُرق الدفع ستكون واضحة في كل موقع، وأنصحك دائمًا بالاعتماد على المنصات العربية في التعامل مع المُستقلين لضمان حقوقك بالشكل المطلوب.
  17. ستتناول هذه السلسلة حول استخدام puppet لإدارة الخواديم، والّتي هي عبارة عن ثلاثة أجزاء، الأداة Puppet وما تُقدمه لمُدراء الخوادم من تسهيلات في إدارة وإعداد الخوادم، وكيفيّة كتابة الشيفرة الخاصّة بهذه الأداة، كما سيتمّ التعامل مع الأداة Foreman والتعرّف على ماتُقدمه في هذا الخصوص. تُركز السلسلة على التطبيق العمليّ، لذلك يُنصح بالتطبيق المُباشر للأفكار المَطروحة فذلك أفضل سبيلٍ لتثبيث المَعلومة واحتراف التعامل مع هذه الأداة. مقالات سلسلة "استخدام puppet لإدارة الخواديم : تنصيب Puppet لإدارة البنية التَّحتِيَّة للخواديمملفّات البيان (Manifests) والوحدات (Modules) في Puppetكيف تستخدم Foreman لإدارة نقاط Puppet على الخادوم Ubuntu 14.04 مُقدّمةتُقدم مَعامل Puppet أداةً لإدارة الإعدادات وتُطلق عليها Puppet، ومُهمتها مُساعدةُ مُدراء الأنظمة في أتمتت الإعداد المُسبق provisioning وإعداد وإدارة البِنْيَة التَّحْتِيَّة الخاصّة بالخوادم. يُقلل التخطيط المُسبق واستخدام أدوات إدارة الإعدادات مثل الأداة Puppet من الوقت المُستغرق في تكرار المَهام الأساسية، ويُساعد على التأكّد من أنّ الإعدادات مَضْبُوطَةً بشكل دقيق، وتقومُ على أساسٍ واحد فيما بينها في جميع الخوادم. سيتوفّر المَزيد مِن الوقت الذي من المُمكن استغلاله في تحسين جوانب أُخرى في إعداد مَنظومة العمل، بعد احتراف إدارة الخوادم باستخدام الأداة Puppet أو حتّى أي أداة أتمتة أُخرى. يتوفّر إصداران من الأداة Puppet، إصدار المشاريع الكبيرة والمؤسسات Puppet Enterprise، والمَفتوح المَصدر. تعمل الأداة Puppet على مُعظم توزيعات نظام التشغيل لينكس ومُختلف مِنصّات UNIX وأنظمة التشغيل Windows. سيتناول هذا الشرح كيفيّة تنصيب الإصدار مفتوح المَصدر من الأداة Puppet على نظام رئيسيّ Master ومُمثل/عميل Agent، حيثُ يتألّف هذا النظام أو التقسيم من خادمٍ مركزيّ Puppet Master يحتوي جميع الإعدادات والبيانات المطلوبة لاستكمال المنظومة الإدارية للخوادم، وباقي الخوادم هي عُمَلاء للجهاز المَركزيّ Puppet Agent، والتي تُدار من قِبَله. مُتَطَلَّبات بيئة العمليَتطلّب تطبيق وإتمام هذا الشرح صلاحيّة وصولٍ كامل root access على جميع الخوادم الّتي ستكون جزء من منظومة Puppet، كما يُطلب إنشاء خادم جديد بتوزيعة Ubuntu الإصدار 14.04 والذي سوف يُمثل النظام المَركزيّ للأداة Puppet. قبل الشروع بتنصيب الأداة Puppet يجب التأكّد من الأمور التّالية: نظام أسماء النطاقات DNS للشبكة الخاصّة: يجب إعداد خادم DNS لتحويل العناوين بالاتّجاهين، من الأسماء إلى IPs ومن IPs إلى الأسماء، ويَجب على كل خادم أنّ يَمتلك اسمًا فريدًا خاصًا به. يُمكن الرجوع إلى الشرح التّالي بعنوان: إعداد خادم الـ DNS في الشبكة الداخليّة لإعداد الخادم الداخليّ، ويَجب استخدام المَلفّ hosts لترجمة الأسماء إلى عنوانين IPs بشكلٍ يدويٍّ في حال عدم توفّر مُخدم DNS.مَنافِذُ مَفتوحة على الجدارِ الناريّ firewall: تعمل الأداة Puppet على المنفذ 8140، لذلك في حال وجود جدارٍ ناريٍّ يُقيد الوصول عبر هذا المنفذ فيُمكن الرجوع إلى الشرح الخاصّ بالأداة UFW لاستعراض الخطواط المَطلوبة للسماح بمرور الطلبات عَبْر هذا المَنفذ.سيتمّ العمل على الخوادم التّالية الآن، ولاحقًا سيُضاف إليها خادمٌ في الجزء الثّاني، وآخر في الثّالث. ستتمّ تنصيب الأداة Puppet على جميع الخوادم السابقة. بيئة العمل السابقة هي نفسها الّتي تمّ العمل بها في هذا الدّرس. إنشاء الخادوم المَركزيّ Puppet Master Serverسيتمُّ استخدام توزيعة أوبونتو الإصدار 14.04 لتَكوْن الخادم المَركزيّ، ويحمل الخادم الاسم “puppet”. يُمكن الرُجوع إلى القسم الخاصّ بـ صيانة سجلات DNS في حال عدم توفّر المَعرفة لفعل ذلك. في حقيقة الأمر كل ما يجب عمله هو إضافة سجلّين الأول من نوع "A" والثاني من نوع "PRT"، والسماح للعميل الجديد بعمل استعلامات دوريّة recursive queries، وأيضًا يجب التأكد من إعداد DNS لترجمة أسماء الخوادم من دون استخدام "اسم النطاق المُؤهل بالكامل" Fully Qualified Domain Name. استخدام الاسم "puppet" للجهاز المَركزيّ سوف يُبسّط إعداد خوادم العُملاء بشكلٍ نسبيٍّ، وذلك لأنّه الاسم الافتراضيّ الذي سوف تَستخدمه هذه العُملاء عند مُحاولتها الاتصال مع الخادم الرئيسيّ Puppet Master. تنصيب NTPيجب على الخادم الرئيسيّ/المَركزيّ puppet master الحفاظ على توقيتٍ دقيقٍ في ساعة النظام لتفادي أو تجنب المشاكل المُحتملة عند إصدار شهادات العُملاء، وذلك بصفته مُفوّض الشّهادة للعُملاء agent. حيثُ كما يبدو أنّ صلاحيّة هذه الشهادات قد تنتهي عند وجود تعارضٍ في الوقت، ومن أجل ذلك سوف نستخدم "بروتوكول توقيت الشبكة" Network Time Protocol والذي يُشار إليه بالاختصار NTP. من المُمكن عمل مُزامنة يدويّة ولمرّة واحدة باستخدام الأمر ntpdate sudo ntpdate pool.ntp.orgيقوم الأمر السابق بتحديث الوقت، ولكن من الضروريّ الاعتماد على الأداة ntpd من أجل المُزامنة التلقائيّة وذلك من شأنه أنّ يقلّل من زمن ظاهرة "انجراف الوقت" Clock drift. sudo apt-get update && sudo apt-get -y install ntpمن الشائع تحديث إعدادات بروتوكول NTP ليستخدم "pools zones" قريبةً جغرافيًا من خادم NTP، حيثُ من المُمكن الرجوع إلى مشروع NTP والبحث عن أقرب pool zone إلى مركز البيانات datacenter المُستخدم، وللتعديل سوف يتمّ تحرير الملف المُسمى ntp.conf بواسطة المُحرر Vi، والذي سوف يتمّ استخدامه طوال هذه السلسلة في التحرير. sudo vi /etc/ntp.confسوف يتمّ إضافة الخوادم التّالية في بداية مَلفّ الإعدادات: server 0.us.pool.ntp.org server 1.us.pool.ntp.org server 2.us.pool.ntp.org server 3.us.pool.ntp.orgيتمّ حِفظ الإعدادات السابقة إما بتنفيذ الأمر :wq، أي الحفظ والخروج، أو عبر الاختصار ZZ. والآن يجب إعادة تشغيل الخدمة ليتمّ إضافة الخوادم الجديدة. sudo service ntp restartتنصيب الخادوم المَركزيّ Install Puppet Masterيوجد طرقٌ عدّة لتنصيب Puppet Master الإصدار مفتوح المصدر، سوف يتمّ استخدام حزمةٍ خاصّة مُقدمة من Puppet Labs وتُسمى “puppetmaster-passenger”، والّتي تتضمّن Puppet master بالإضافة إلى خادم ويب مُجهزٍ بشكل مُسبق للعمل مُباشرةً (Passenger مع Apache)، وذلك من شأنه أنّ يُسهل عمليّة الإعداد مُقارنةً مع الحزمة الأساسيّة فقط puppetmaster. يقوم الأمر التّالي بتحميل الحزمة السابقة الذكر من موقع PuppetLabs في المَسار الرئيسيّ $HOME cd ~; wget https://apt.puppetlabs.com/puppetlabs-release-trusty.debولتنصيب الحزمة يتمّ تنفيذ الأمر التّالي: sudo dpkg -i puppetlabs-release-trusty.debومن ثمّ التحديث للحصول آخر الحزم المُتوفّرة. sudo apt-get updateومن ثمّ تنصيب حزمة puppetmaster-passenger. sudo apt-get install puppetmaster-passengerوبهذا يكون قد تمّ تنصيب: الخادم المَركزيّ Puppet masterخادم الويب Apacheالحِزم المَطلوبة لعملية الإعدادبسبب استخدام الحزمة الخاصّة (Apache مع Passenger) يتحكم خادم الويب Apache بالأداة Puppet master، بمعنى أنّ هذه الخدمة سوف تعمل عندما يعمل خادم الويب Apache، وتتوقف بتوقفه. قبل المُتابعة سوف يتمُ إيقاف Puppet master وذلك بإيقاف خدمة apache2: sudo service apache2 stopقفل الإصدار الحالييُسبب في بعض الأحيان الانتقال من إصدارٍ لإصدارٍ آخر إلى توقّف منظومة الأدة Puppet عن العمل بشكلٍ مُلائمٍ، لذلك من الجيّد الحفاظ على إصدار الأداة Puppet في كامل المَنظومة على إصدار مُوحّد. وفي حال التحديث، من الضروريّ تحديث النسخة المَركزيّة master قبل نسخة العُملاء agent، حيثُ أنّ النسخة المَركزيّة لاتستطيع إدارة نُسخ العُملاء مع إصدارٍ أحدث من إصدارها. لمعرفة الإصدار الحالي للأداة Puppet يُمكن تنفيذ الأمر التّالي: puppet help | tail -n 1الإصدار الحالي والذي تعتمد عليه هذه السلسلة هو Puppet v3.7.4. من المُمكن استخدام الأداة APT وميزة pin لقفل إصدار الأداة Puppet للتحديثات الجذرية major والبسيطة minor والسماح بالترقيعات patches -يُمكن الرُجوع إلى الإدارة الدلاليّة لنُسخ البرمجيات لمزيد من التفاصيل حول إدارة الإصدار- ولذلك سوف يتمّ إنشاء مَلفّ جديد في المسار الخاصّ بتفضيلات الأداة apt. sudo vi /etc/apt/preferences.d/00-puppet.prefكما سوف يتمّ قفل التحديثات لثلاث حزم وهي: puppet، puppet common، puppetmaster-passenger وذلك بإضافة السطور التالية إلى المَلف السابق. # /etc/apt/preferences.d/00-puppet.pref Package: puppet puppet-common puppetmaster-passenger Pin: version 3.7* Pin-Priority: 501 إعداد الأسماء والشهاداتتستخدم الأداة Puppet شهادات SSL لتوثيق الاتصال بين الخادم المَركزيّ والعُملاء، حيثُ يُمثل الجهاز المَركزيّ دور "مُفوّض الشهادة" certificate authority، ويجب على CA أنّ يُولد الشهادة الخاصّة به والّتي تُستخدم في توقيع طلبات شهادات العُملاء. التخلّص من الشهادات الحاليّةيجب حذف أيّة شهادات SSL حاليّة قد تمّ إنشاؤها أثناء تنصيب حزمة puppet لإعداد مُفوّض الشهادة بشكل مُلائم. المسار الافتراضيّ لشهادات SSL الخاصّة بالحزمة توجد في المسار التّالي: /var/lib/puppet/ssl sudo rm -rf /var/lib/puppet/sslإعداد الشهادةعند إنشاء شهادة الجهاز المَركزيّ، يجب إضافة أي اسم DNS من المُمكن أنّ تستخدمه العُملاء للاتصال مع الجهاز المَركزيّ puppet master، في المثال الحالي سوف يتمّ إضافة اسم الخادم “puppet”، و"اسم نطاق مؤهل بالكامل" “puppet.nyc2.example.com”، وذلك بتحرير مَلفّ الإعدادات التّالي: sudo vi /etc/puppet/puppet.confوالذي يحتوي على البيانات التّالية: [main] logdir=/var/log/puppet vardir=/var/lib/puppet ssldir=/var/lib/puppet/ssl rundir=/var/run/puppet factpath=$vardir/lib/facter templatedir=$confdir/templates [master] # These are needed when the puppetmaster is run by passenger # and can safely be removed if webrick is used. ssl_client_header = SSL_CLIENT_S_DN ssl_client_verify_header = SSL_CLIENT_VERIFYسيتمّ حذف السطر الخاصّ بالخيار templatedir بعد أنّ أصبح غير مُستخدمًا بعد الآن، ومن ثمّ إضافة السطرين التاليين إلى نهاية القسم [main]. certname = puppet dns_alt_names = puppet,puppet.nyc2.example.com من الضروريّ تخصيص اسم الشهادة certname بالاسم “puppet”، لأنّ إعدادات Apache/Passenger مُعدّة لأنّ يكون اسم الشهادة بهذا الاسم. في جميع الأحوال يُمكن تخصيص الاسم حسب الرغبة بالتعديل على مَلفّ الإعداد الخاصّ بـApache: /etc/apache2/sites-available/puppetmaster.confوبهذا يكون قد تمّ الانتهاء من الإعداد بشكل مُلائم بعد الحفظ والخروج. توليد شهادةٍ جديدةيتمّ إنشاء شهادة جديدة بتنفيذ الأمر التّالي: sudo puppet master --verbose --no-daemonizeالأمر السابق سوف يعرض معلومات تُشير إلى إنشاء الشهادات ومفاتيح SSL، كما يُشير السطر الأخير بدء عمل الأداة Notice: Starting Puppet master version 3.7.4 Info: Creating a new SSL key for ca Info: Creating a new SSL certificate request for ca Info: Certificate Request fingerprint (SHA256): EC:7D:ED:15:DE:E3:F1:49:1A:1B:9C:D8:04:F5:46:EF:B4:33:91:91:B6:5D:19:AC:21:D6:40:46:4A:50:5A:29 Notice: Signed certificate request for ca ... Notice: Signed certificate request for puppet Notice: Removing file Puppet::SSL::CertificateRequest puppet at '/var/lib/puppet/ssl/ca/requests/puppet.pem' Notice: Removing file Puppet::SSL::CertificateRequest puppet at '/var/lib/puppet/ssl/certificate_requests/puppet.pem' Notice: Starting Puppet master version 3.7.4 لمعرفة معلومات عن الشهادة التي تمّ إصدارها بالإمكان تنفيذ الأمر التّالي: sudo puppet cert list -allيعرض الأمر السابق قائمة بجميع الشهادات المُوقعة وطلبات الشهادة غير المُوقعة. حتّى الآن سوف يعرض الأمر السابق الشهادة الخاصّة بالخادم الرئيسيّ فقط، وذلك لأنّه لم يتمّ إضافة أي شهادات أخرى ليتمّ عرضها. + "puppet" (SHA256) A5:72:AA:19:AF:E8:D2:9A:E8:99:B9:F0:19:B6:0A:7D:05:0D:0D:F6:BA:CE:F5:09:6F:73:0F:0C:DE:24:11:84 (alt names: "DNS:puppet", "DNS:puppet.nyc2.example.com") إلى هنا تكون الخدمة الخاصّة بالجهاز المَركزيّ Puppet master service هي تقريبًا جاهزة للعمل. إعداد الجهاز المَركزيّ Puppet Masterيحتوي مَلفّ الإعداد الرئيسيّ الخاصّ بالأداة puppet المُسمى puppet.conf على ثلاثة أقسام: [main] و [master] و [agent]. كما هو واضح، يحتوي القسم الرئيسي “main” على الإعدادات العامّة أو الشاملة، أما القسم المُسمى “master” فيحتوي على الإعدادات الخاصّة بالخادم الرئيسي puppet master، ويحتوي القسم “agent” على الإعدادات الخاصّة بخوادم العُملاء. بغض النظر عن التعديلات السابقة الّتي تمّت على هذا المَلفّ، تعمل الإعدادات الافتراضيّة بشكل مُناسب في بيئة العمل البسيطة وغير المُعقدة. يُمكن الرجوع إلى التوثيق الرسمي لمزيد من التفاصيل حول مَلفّ puppet.conf. ولتحرير هذا المَلف يُمكن تنفيذ الأمر التّالي: sudo vi /etc/puppet/puppet.confمَلفّ البيان الرئيسيّ (Main Manifest File)تستخدم الأداة Puppet لغة مُحددة المجال DSL وهي اختصار domain-specific language، ومُهمّة هذه اللغة هي كتابة أوصاف أو تصوّرات مَلفّ الإعدادات الخاصّ بالنظام، وتُحفظ هذه الأوصاف في ملفات تُسمى “mainfests”، والّتي تحمل اللاحقة .pp. يتوضّع مَلفّ الـ manifest الرئيسيّ وهو الافتراضيّ في المسار /etc/puppet/manifests/site.pp. سوف يتمّ تناول أساسيات التعامل مع هذا النوع من الملفات فيما بعد، ولكن الآن سيتمّ استخدام مَلفّ خُلَّبي placeholder للمُتابعة: sudo touch /etc/puppet/manifests/site.ppتشغيل الخادوم المَركزيّ Puppet Masterأصبح من المُمكن الآن تشغيل Puppet master عبر تشغيل خدمة apache2: sudo service apache2 startيعمل الخادم الرئيسيّ Puppet master كما يجب، ولكن حتى الآن هو لا يُدير أيًا من العُملاء بعد. تنصيب خوادم العُملاء Puppet Agentيجب تنصيب أداة العميل الخاصة بالأداة Puppet على جميع الخوادم التي من المُفترض إدارتها من قبل الجهاز المَركزيّ Puppet master، في أغلب الحالات هذا يتضمّن كل الخوادم في البِنْيَة التَّحْتِيَّة، حيثُ كما تمّت الإشارة في المُقدمة أنّ الأداة Puppet مُتوافقة مع أغلب توزيعات لينوكس الشائعة، وبعض منصات يونكس وأنظمة التشغيل "ويندوز". بسبب الاختلاف في الإعداد بين الأنظمة سوف يتمّ التركيز على خوادم Ubuntu و Debian، أما التعليمات الخاصّة بالتنصيب على بقيّة المنصات فيُمكن الحصول عليها من التوثيق الرسميّ: Puppet Labs Docs ملاحظة: من المُهم جدًا إعداد جميع العُملاء لاستخدام DNS مُلائم قبل تنصيب نسخة العُملاء على الخوادم. التعامل مع خوادم Ubuntu / Debianتستخدم جميع خوادم العُملاء في أمثلة هذا الشرح توزيعة أوبونتو 14.04، وذلك باستخدام خادم افتراضيّ خاصّ VPS، والإعدادات التّالية سوف يتمّ تطبيقها على جميع هذه الخوادم وهي: host1، host2، ns1، ns2. سوف يتمّ في البداية تحميل الحزمة من موقع مَعامل Puppet كما حصل مع نسخة Puppet master. cd ~; wget https://apt.puppetlabs.com/puppetlabs-release-trusty.debتنصيب الحزمة: sudo dpkg -i puppetlabs-release-trusty.debتحديث قوائم الحزم المُتوفّرة: sudo apt-get updateتنصيب حزمة العُملاء puppet: sudo apt-get install puppetالأداة بشكل افتراضيّ تَكون غير مُفعلة، ولتغيير ذلك يجب تحديث مَلفّها الافتراضيّ: sudo vi /etc/default/puppetتغيير قيمة START إلى “yes”: START=yesقفل الإصدار الحاليسوف يتمّ استخدام ميزة pin الخاصة بالأداة apt لقفل الإصدار الحالي الخاصّ بـ Puppet agent: sudo vi /etc/apt/preferences.d/00-puppet.prefلقفل الإصدار الحالي سوف يتمّ إضافة السطور التّالية إلى المَلفّ السابق: # /etc/apt/preferences.d/00-puppet.pref Package: puppet puppet-common Pin: version 3.7* Pin-Priority: 501 إعداد نسخة العميل Puppet Agentقبل تشغيل نسخة العميل من الضروريّ تغيير بعض الإعدادات، وذلك بتحرير مَلفّ إعداد نسخة العميل puppet.conf، وهو نسخة مُطابقة لنسخة لملف الإعداد الأوليّ لنسخة Puppet master: sudo vi /etc/puppet/puppet.confسيتمّ حذف السطر الخاصّ بالخَيار templatedir كما تمّ سابقَا مع نسخة الخادم المَركزيّ، بالإضافة إلى ذلك سوف يتمّ حذف القسم المُسمى [master] وكافة السطور الّتي تخصّه. إنّ تمكّنت الخوادم من الاتصال بالخادم المَركزيّ Puppet master بالاسم “puppet”، فيُمكن للعُملاء استخدام هذا الاسم للاتصال بالخادم المَركزيّ، أما في حال عدم توفّر الجهاز المَركزيّ تحت الاسم “puppet” فيجب إضافة اسم المجال الكامل FQDN الخاصّ بالخادم المَركزيّ Puppet master، ومن المُستحسن عمل ذلك في جميع الأحوال. [agent] server = puppet.nyc2.example.comبعد الإعدادات السابقة أصبحت نسخة العميل من الأداة Puppet agent جاهزة للعمل، وذلك بتنفيذ الأمر التّالي: sudo service puppet startلن يُظهر تنفيذ الأمر السابق أيّة مُخرجات output في حال أنّ الإعدادات طُبقت بشكل صحيح. يتمّ عند التشغيل الأول للأداة Puppet agent توليد شهادة SSL وإرسال طلب توقيع signing request إلى الخادم المَركزيّ Puppet master، وبعد أنّ يُوقع الخادم المَركزيّ شهادة العميل سيكون الاتصال جاهزًا بينهما. تجدرُ الإشارة هنا أنّه في حال كان هذا العميل هو العميل الأول، فمن المُستحسن محاولة توقيع الشهادة على الخادم المَركزيّ Puppet master قبل إضافة باقي العُملاء، وعندما يتمّ التأكد من أنّ الأمور تجري على ما يُرام، عندها يُمكن إضافة باقي العُملاء من دون التخوف من وقوع مُشكلات مُحتملة مع باقي الخوادم. توقيع طلب العُملاء على الخادم المَركزيّ: تُرسل الأداة Puppet عند تشغيلها للمرّة الأولى على خادم العميل Puppet agent طلب توقيع شهادة إلى الخادم المَركزيّ Puppet master، ولن يتمكّن الخادم المَركزيّ من التحكم بالخادم العميل حتى يوقع على هذه الشهادة. سوف يتمّ توضيح هذه النقطة في الفقرة التّالية. عرض طلبات الشهادة الحاليةيتمّ تنفيذ الأمر التّالي على الجهاز المَركزيّ Puppet master ليَعرض جميع طلبات الشهادة غير المُوقعة: sudo puppet cert listسيُظهر الأمر السابق طلبًا وحيدًا حتّى الآن، وهو للعميل الذي تمّ إعداده سابقًا، وسيبدو بالشكل التّالي، حيثُ الاسم هو اسم المجال الكامل FQDN: "host1.nyc2.example.com" (SHA256) 5F:DB:E0:6D:8B:1F:C8:A3:04:4E:CD:48:6F:9F:D7:89:14:38:FB:5B:EF:2F:09:76:C5:13:A9:E0:4D:D2:C5:FCيجب الانتباه هنا إلى أنّ المُخرج السابق لا يحتوي على إشارة الزائد (+)، وذلك يُشير إلى أنّ هذه الشهادة غير مُوقعة بعد. توقيع الطلبيُستخدم الأمر puppet cert sign لتوقيع طلب شهادة، ويُضاف إلى هذا الأمر اسم الخادم الخاصّ بهذه الشهادة، على سبيل المثال لتوقيع طلب الخادم host1.nyc2.example.com، فسوف يتم تنفيذ الأمر التّالي: sudo puppet cert sign host1.nyc2.example.comالأمر السابق يَعرضُ المُخرَج التّالي، والذي يُشير إلى توقيع طلب الشهادة. Notice: Signed certificate request for host1.nyc2.example.com Notice: Removing file Puppet::SSL::CertificateRequest host1.nyc2.example.com at '/var/lib/puppet/ssl/ca/requests/host1.nyc2.example.com.pem'أصبح بإمكان الخادم المَركزيّ Puppet master بعد توقيع طلب الشهادة من الاتصال والتحكم بهذه النقطة node والتي تنتمي إليها هذه الشهادة المُوقعة. يُمكن استخدام الأمر التّالي لتوقيع جميع الطلبات الحالية وذلك باستخدام الخيار -all. sudo puppet cert sign --allإبطال الشهاداتيحتاج مُدير النظام في بعض الحالات إلى حذف أحد العُملاء من الخادم المَركزيّ، ربما لأسباب تتعلق بتحليل المشاكل، أو لأي سببٍ آخر، حيثُ يُمكن إبطال شهادة العميل من الخادم المَركزيّ باستخدام الخيار clean مع اسم الخادم، كما في المثال التّالي: sudo puppet cert clean hostnameاستعراض جميع الطلبات المُوقعةيُستخدم الأمر التّالي لاستعراض جميع الطلبات المُوقعة وغير المُوقعة sudo puppet cert list –allيَعرض الأمر السابق جميع الطلبات مع الانتباه أنّ الطلبات المُوقعة تُسبق بإشارة الزائد "ns2.nyc2.example.com" (SHA256) E4:F5:26:EB:B1:99:1F:9D:6C:B5:4B:BF:86:14:40:23:E0:50:3F:C1:45:D0:B5:F0:68:6E:B2:0F:41:C7:BA:76 + "host1.nyc2.example.com" (SHA256) 71:A2:D3:82:15:0D:80:20:D4:7E:E3:42:C2:35:87:83:79:2B:57:1D:D5:5A:EC:F6:8B:EE:51:69:53:EB:6B:A1 + "host2.nyc2.example.com" (SHA256) F4:79:A6:7C:27:0C:EA:8E:BC:31:66:FF:F2:01:AB:B1:35:7B:9F:5E:C8:C9:CE:82:EE:E8:2F:23:9F:0C:2B:ED + "puppet" (SHA256) 05:22:F7:65:64:CF:46:0E:09:2C:5D:FD:8C:AC:9B:31:17:2B:7B:05:93:D5:D1:01:52:72:E6:DF:84:A0:07:37 (alt names: "DNS:puppet", "DNS:puppet.nyc2.example.com") الخطوات الأولى مع الأداة Puppetبعد تجهيز بيئة العمل، سيتمّ التركيز في الفقرات التالية على كيفية عمل بعض المُهِمّات أو الواجبات الأساسية للخوادم وذلك باستخدام الأداة Puppet، وذلك في سبيل عرض الخطوط العريضة لهذه الأداة وآلية عملها. كيف تُجمّع الحقائقتجمع الأداة Puppet الحقائق حول جميع العُقد المُرتبطة بها، وذلك باستخدام أداةٍ تُسمى “facter”. تَجمع الأداة Facter جميع المعلومات المُفيدة في إعداد النظام بشكل افتراضيّ، مثل اسم نظام التشغيل، عنواين برتوكول الانترنت IP، ومفاتيح SSH، وغيرها من المعلومات. كما مِن المُمكن إضافة حقائق مُخصّصة حسب الحاجة لأداء بعض الإعدادات الخاصّة. يُمكن الاستفادة من هذه الحقائق المُجمّعة في حالات عديدة. على سبيل المثال، يُمكن إنشاء نموذج إعدادات خادم ويب وتعيين العناوين المُلائمة لمُضيف افتراضي مُحدد دون الآخر، أويُمكن استخدامها في التحكم بمسار الإعدادات، أي تطبيق إعداد معين على حسب حقيقة معينة، فعند معرفة أن النظام هو نظام أوبونتو، فسيكون اسم الخدمة الخاصّة بخادم الويب هي apache2، وفي حال كان نظام التشغيل هو CentOS، فستكون الخدمة الخاصّة بخادم الويب هي httpd. الأمثلة السابقة هي تبسيط لما يُمكن عمله باستخدام هذه الحقائق المُجمّعة. لاستعراض قائمة الحقائق والّتي تمّ جمعها بشكلٍ تلقائيّ على خادم العميل يُمكن استخدام الأمر التّالي: facterكيفيّة تنفيذ مَلفّ البيان الرئيسي The Main Manifestتقوم العُملاء الخاصّة بالأداة Puppet بالاتصال بالخادم المَركزيّ Puppet master دوريًا كل 30 دقيقة تقريبًا، مُرسلةً حقائق factsعن نفسها إليه، بالإضافة إلى سحب فهرس (catalog) مَلفات البيان، والتي هي قائمة مُجمّعة (compiled) للمَوارِد وحالتها المَطلوبة والمُرتبطة مع هذه العُملاء، وتُحدّد هذه القائمة من قِبل مَلفّ البيان الرئيسيّ main manifest، وفيما بعد تُحاول نقاط العُملاء تطبيق التَغَيُّرات لتُلائم الحالة المَطلوبة. يستمر التسلسل السابق بالتكرار طالما أنّ الخادم المَركزيّ يعمل ومُتصل مع نقاط العُملاء. تنفيذ التَغَيُّرات على نقاط العُملاء بشكلٍ يدويٍّ ومُباشر يُمكن المُبادرة بعمل اتصال يدويّ بين أحد نقاط العُملاء والخادم المَركزيّ، رُبما لتسريع عملية التطبيق أو في سبيل تحديد مُشكلة ما، أو لمعرفة كيف سوف يؤثّر مَلفّ البيان على أحد الخوادم دون تطبيقه على جميع الخوادم، ويتمّ ذَلِك عبر بتنفيذ الأمر التّالي على الخادم العميل: puppet agent --testسيقوم الأمر السابق بتطبيق مَلفّ البيان الرئيسي main manifest على الخادم العميل، كما يَعرض هذا الأمر المُخرجات التّالية: Info: Caching certificate_revocation_list for ca Info: Retrieving plugin Info: Caching catalog for host1 Info: Applying configuration version '1423707894' Info: Creating state file /var/lib/puppet/state/state.yaml Notice: Finished catalog run in 0.01 seconds تطبيق مَلفِ بيانٍ كيفيٍ ولمرّة واحدةيُتيح الأمر puppet apply تنفيذ مَلفات بيانٍ اختياريّة لاترتبط بمَلف البيان الرئيسيّ، وعلى نقاط العُملاء مُعينة. sudo puppet apply /etc/puppet/modules/test/init.ppتشغيل مَلفّات البيان بهذا النمط مفيدٌ عندما يكون المُراد اختبار مَلفّ بيان جديد على أحد العُملاء، أو عندما يَكون المُراد تنفيذ مَلفّ البيان لمرّة واحدة فقط، مُثلًا لاستهلال العميل إلى حالة مُعينة. إنشاء مَلفّ بيانٍ رئيسيٍّ مُبسَطتمّت الإشارة سابقًا إلى أنّ مَلفّ البيان الرئيسي على الخادم المَركزيّ من المُفترض تواجده في المسار /etc/puppet/manifests/ وبالاسم site.pp. سيتمّ إضافة بعض التعديلات البسيطة لهذا المَلف: sudo vi /etc/puppet/manifests/site.ppالسطور التّالية تصف مَورِد مَلفّ file resource: file {'/tmp/example-ip': # التصريح عن مَورد مَلفّ ومسار المَلف ensure => present, # التأكد من وجود المَلف mode => 0644, # تحديد صلاحيات المَلف content => "Here is my Public IP Address: ${ipaddress_eth0}.\n", # تحديد مُحتوى المَلف واستخدام الحقائق }يقوم مَلفّ البيان السابق بإنشاء مَلفٍ في المسار /tmp/، والتأكد من وجوده وبالاسم example-ip مع صلاحيات -rw-r--r--، ومُحتوى نصيّ يتضمّن عنوان الـIP الخاصّ بالخادم العميل. بالإمكان إما الانتظار حتّى يقوم الخادم العميل بالاتصال مع الخادم المَركزيّ بشكل آليٍّ، أوتنفيذ الأمر puppet agent –test على أحد نقاط العُملاء. لمُشاهدة التغييرات التي قام بها مَلفّ البيان السابق، وبعد ذلك يُمكن تنفيذ الأمر التّالي على الخادم العميل: Cat /tmp/example-ipوالذي سوف يَعرض السطرَ التّالي مع اختلاف العنوان بطبيعة الحال: Here is my Public IP Address: 10.0.2.15.استهداف عميلٍ مُحددمن المُهم معرفة أنّه بالإمكان تعريف مَورد مُحدد لعميلٍ مُعين دون الآخرين، ولذلك على الخادم المَركزيّ، ومنه المَلف site.pp: sudo vi /etc/puppet/manifests/site.ppسيتمّ إضافة السطور التّالية: node 'ns1', 'ns2' { # تطبيق المَورد التّالي على الخوادم المُحددة فقط file {'/tmp/dns': # التصريح عن مَورد مَلفّ ومسار المَلف ensure => present, # التأكد من وجود المَلف mode => 0644, # تحديد صلاحيات المَلف content => "Only DNS servers get this file.\n", } } node default {} # تطبيق المَوارد على النقاط التي لم تُعرّف بشكل مُحدد.ستتأكّد الأداة Puppet من وجود المَلف /tmp/dns على الخادمين "ns1" و“ns2”، ومن المُمكن تطبيق الأمر puppet agent –test على الخادمين آنفي الذّكر لعدم الانتظار إلى حين الطلب التلقائي من العُملاء. يجدُر الذكر هنا أنّه في حال عدم تعريف مَورد، فإن الأداة Puppet سوف لن تقوم بإجراء أيّة تعديلات على العُملاء، أي في حال حذف المَوارد السابقة من مَلفّ البيان، فإنّ الأداة Puppet لن تَحذف الملفات التي قامت بإنشائها سابقًا، إلا إذا تمّ التصريح بذلك عبر تعديل قيمة ensure إلى absent والّتي تعني غائب أو لا وجود له. في حقيقة الأمر لايُظهر تطبيق الأمثلة السابقة قوة الأداة Puppet وما الذي يُمكنها فعله، ولكنه يُبرهن على الأقل أنّها تعمل كما هو مُخططٌ لها. استخدام الوحدات Modulesتُستخدم الوحدات modules لتجميع المهام في صيغة واحدة، ويتوفّر العديد من هذه الوحدات في مُجتمع Puppet، مع العلم أنّه يُمكن كتابة وحدة جديدة وعدم التقيد بما يوفره المُجتمع من هذه الوحدات. سيتمّ تنصيب وحدة مُعدّة مُسبقًا من موقع Puppet باستخدام الأمر puppetlabs-apache: sudo puppet module install puppetlabs-apacheتحذير: لا يُفترض استخدام الوحدة السابقة في حال وجود خادم الويب Apache، وذلك من شأنه أنّ يُلغي أيّة إعدادات تُدار من قبل الأداة Puppet. يجب الآن تحرير المَلف site.pp، لكي يَستخدم الوحدة المُنصبة (apache). وعلى سبيل المثال سيتمّ اختيار الخادم “host2” لتنصيب خادم الويب Apache لتوضيح المثال: node 'host2' { class { 'apache': } # use apache module apache::vhost { 'example.com': # define vhost resource port => '80', docroot => '/var/www/html' } } ستقوم الأداة Puppet بتنصيب خادم الويب Apache على العميل “host2”، وإعداد مُضيف افتراضيّ “example.com”، مُصغيًا على المنفذ 80، مع document root بالمسار /var/www/html. على الخادم “host2” يُمكن تنفيذ الأمر التّالي لتسريع عمليّة التطبيق: sudo puppet agent --testيَعرض الأمر السابق مُخرجات تُشير إلى تنصيب خادم الويب Apache. بعد استكمال التنصيب، من المُمكن التأكد من عمل خادم الويب بالشكل المطلوب عبر زيارة صفحة الترحيب الافتراضيّة الخاصّة به. خاتمةتمّ التطرّق في هذا الجزء إلى كيفيّة تنصيب الأداة Puppet، وإعدادها إعدادًا أوليًا، وبذلك أصبح بالإمكان التعمّق في المزيد من التفاصيل الخاصّة بهذه الأداة وماتقدمه من تسهيلات لمُدير النظام، وذلك عبر مَلفّات البيان والوحدات الّتي سيتمّ التركيز عليها في الجزء الثاني من هذه السلسلة. ترجمة -وبتصرّف- للمقال How To Install Puppet To Manage Your Server Infrastructure
  18. لا يوجد سعر مُحدّد أو تقريبي، يختلف الأمر على حسب نوعيّة المادّة وجودتها. أتحّدث هنا عن تجربتي الشخصيّة فقط، وليس بصفة أُخرى.
  19. لا مَفرّ من ثلاث، وابدأ بالترتيب التّالي، مع العلم أنّ HTML و CSS ليستا لغات برمجة: HTMLCSSJavaScript
  20. بلا شكّ التصميم الأوّل، حيثُ أنّ التصميم الثّاني يبدو لي "ولادي" إنّ جاز التعبير، ولايوحي بالاحترافيّة. قُم بإجراء تعديلاتك على التصميم الأوّل وبالتوفيق.
  21. ​الكتابة (التدوين) --> زوّار-->إعلانات (تُشاهد أو يُنقر عليها)-->مُعلن (يدفع نقودًا). مُحتوى (قوي)-->زوّار-->مُنتج (كُتيّب أو خدمة ذات قيمة)-->زائر (يدفع نقودًا).
  22. يجب أنّ يكون الحساب على الوقت وليس على عدد الكلمات أو عدد الأسطر، فـ 100 كلمة في خبر تقنيّ، تختلف عن 100 كلمة في مقال تحليلي لتقنيّة مُعينة. الأمر لايقتصر على كتابة المقالات أو الترجمة، بل على أي عمل، من تصميمٍ أوبرمجة، الوقت هو الفاصل في التسعير وليس الكم.
  23. قم بوضع المؤشر cursor في بداية النص المُراد تحديده، ثمّ اضغط على التّالي لتحديد البداية، ومن ثم قم بتحريك المؤشر إلى نهاية النص: Alt-Aقم باستخدام التّالي للبحث والاستبدال، في البداية ستقوم بكتابة الكلمة المُراد البحث عنها، ثمّ كتابة الكلمة البديلة: Ctrl \ قد يكون هناك اختصارات أفضل لا أعلم بها، حيثُ أني استخدم Vim.
  24. في اعتقادي لا إظن أنّ هناك فرق جوهري في اختيار توزيعة دون الأُخرى بالنسبة للتعلّم، ولكن يُمكن القول أنّ مجتمع أوبونتو نشط بشكل أكبر بالنسبة لباقي التوزيعات، ويتوفّر مُحتوى جيد له حتّى على المُستوى العربي. أكثر ما يُهم في تعلّم إدارة الخوادم هو كسر حاجز الخوف في التعامل مع الطرفيّة والأوامر، وستكون باقي الأمور على مايُرام.
  25. العُملاء الّتي تطلب تعديلات متكرّرة نوعان: من لم يعد يرغب في المشروع من الأساس، لسبب أو لآخر، هذا العميل ستجده يُدقّق على كل شيء محاولًا التهرب وخلق الأعذار. العميل الحائر أو المُتردّد، وأغلب الأحوال يكون هذا النوع صاحب خبرة ضعيفة، ولا يُدرك حقيقة الأمور. في جميع الأحوال الحلّ، أولًا التحلّي بالصبر بالتعامل مع هذا النوع من العُملاء، وثانيًا تقديم اتفاقيّة استخدام واضحة تخص هذا الأمر، فمثلًا يُمكن إضافة البنود التّالية إليها، هذه البنود مُقتبسة من تدوينة من مدونة "أنا مُستقلّ" والّتي أنصحك بالاطّلاع عليها:
×
×
  • أضف...