-
المساهمات
26 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
2
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Shadi Habbal
-
أصبحت واجهات REST البرمجية أكثر انتشارًا بين المطوّرين، نظرًا لأنها توفّر واجهة بسيطة، موحّدة وواضحة لخدمات الطرف الثالث third-party مثل Twitter، MailChimp وGitHub. ومع ازدياد شهرة واجهة ووردبريس البرمجية (المتوفرة عبر إضافة) فإن الوقت قد حان لنتعلم حول واجهة HTTP البرمجية في ووردبريس، وكيفية عملها واستخداماتها. ما هي واجهة HTTP في ووردبريس؟ لن يكون من المستغرب القول بأنها طريقة لإرسال واستقبال الرسائل بواسطة HTTP – لغة شبكة الويب. حيث يقوم المتصفح بإرسال واستقبال الرسائل طوال الوقت وبهذا الشكل يتم استقبال صفحات الويب. ويمكن من خلال واجهة REST البرمجية، يمكن باستخدام رسائل HTTP القيام بأشياء أكثر كتعديل منشور، حذف حساب مستخدم أو نشر وصفة جديدة على موقعك. لهذا السبب تعتبر واجهة ووردبريس البرمجية مهمة جدًا، فهي تسمح بفصل التطبيق من جهة المستخدم عن النواة البرمجية الخاصة بووردبريس. ولاستخدامها، تحتاج أن تكون معتادًا على إرسال طلبات HTTP واستقبال الأجوبة، وهذا هو أساس عمل واجهة HTTP البرمجية. وهناك العديد من الطرق لإرسال طلبات HTTP، حيث توفّر واجهة HTTP البرمجية طريقة موحّدة باستخدام مجموعة من التوابع المساعدة والتي سنطّلع عليها بعد قليل. طرق HTTP ومصادرها ترتكز HTTP حول الطرق methods (تسمّى أحيانًا بالأفعال verbs) والمصادر resources. تحدّد المصادر العنصر الذي سيتم تنفيذ العملية عليه، وتحدّد الطريقة نوع العملية التي سيتم تنفيذها. ويعتبر العنوان URL هو المصدر الذي يشير إلى الغرض على شبكة الويب، كمنشور على سبيل المثال. وتوجد العديد من الطرق، لكن الأهم فيها هي GET, POST, PUT و DELETE. ولا بد أن لديك الكثير من الخبرة مع GET فهذه الطريقة هي المستخدمة في الحصول على المصادر، فمثلًا عند استعراض مقال في المتصفح يتم إرسال طلب GET إلى عنوان المقال وليكن مثلًا https://premium.wpmudev.org/blog/using-the-wordpress-http-api/. أما طلبات PUT فتستخدم لتعديل المصادر، وتستخدم طلبات POST لإنشاء مصادر جديدة، وتستخدم طلبات DELETE لحذف مصادر موجودة مسبقًا. ولو كان لدى موقع WPMU DEV واجهة REST برمجية، فربما كان من الممكن أن يقوم المدير بإرسال طلب DELETE لحذف المقال على الرابط https://premium.wpmudev.org/blog/wordpress-http-api، وهذا الأمر مفيد جدًا للمواقع الكبيرة التي تملك برامج إدارة على الهواتف الذكية. مثال عن طلب HTTP بسيط للقيام بإرسال طلب GET بسيط على سبيل التجربة، سنقوم باستخدام التابع wp_remote_get() الذي يملك مُعاملين، المُعامل الأول هو رابط المصدر، والمُعامل الثاني هو مصفوفة اختيارية optional من الخيارات التي من الممكن استخدامها لتحديد بعض التفاصيل. $test = wp_remote_get( 'http://google.com' ); echo "<pre>"; var_dump($test); echo "</pre>"; يقوم المثال السابق بجلب الصفحة الرئيسية لموقع جوجل، ومن ثم يتم طباعة محتوى المتغير test الذي يحوي على جواب الطلب الذي أرسله موقع جوجل – حيث يمكن رؤية جميع العناصر التي يحتويها. تحتوي الترويسات headers على المزيد من المعلومات عن كل رسالة. وقد تطلب منك بعض واجهات REST البرمجية أن تقوم بإرسال معلومات محددة في الترويسات عندما ترسل الطلب. يحتوي الجواب response على رمز الحالة status code وعبارة قد تكون معروفة بالنسبة لك كأخطاء 404، أو خطأ في معالجة الطلب 500 أو تحويل من النوع 301 أو 302. يحتوي موقع W3.org على جميع رموز أخطاء HTTP المعرّفة والمشروحة، ويعتبر مصدرًا مفيدًا إن احتجت أن تعرف ما يعني أي خطأ. بإمكانك أيضا الاطّلاع على هذا المقال على أكاديمية حسوب لتعرف المزيد حول هذه الرّموز: رموز الإجابة في HTTP يحتوي الجسم body على الجواب وهو المكان الذي تحتاج أن تنظر إليه بحثًا عن النتيجة المطلوبة. في حالة المثال السابق، فإننا نحصل على وسوم HTML التي تشكّل الصفحة الرئيسية، ولكن عند التعامل مع واجهات REST البرمجية فمن الشائع أن نحصل على نص بصيغة JSON. وعادة ما تطلب الواجهات البرمجية APIs أن يتم إضافة نص محدّد إلى الجسم عند إرسال طلبات أيضًا. يحتوي قسم cookies على أي كعكات تم استلامها مع الرسالة. كما ترى، فإن إرسال طلب باستخدام واجهة HTTP البرمجية أمر بسيط جدًا. ما يجعل العمل مع HTTP معقّد نوعًا ما هو أن واجهات REST البرمجية قد تكون حساسة جدًا لصيغة البيانات المدخلة (وهو أمر جيّد) لذا فإن تجاوزت سطرًا عند دراسة توثيق الواجهة البرمجية قد ينتهي بك الأمر ببرمجية لا تعمل كما ترغب. العمل مع الواجهات البرمجية أعتقد بأنه من الآمن القول بأن معظمكم سيستخدم HTTP للتعامل مع واجهات REST البرمجية في شبكة الويب، وفي هذه الحالة سنحتاج لاستخدام المعامل الثاني لتحديد بعض الأمور، كالاستيثاق وتجنب بعض الأخطاء الشائعة. لنبدأ بمثال بسيط – استعادة البيانات من لوحة Pinterest. تتطلب جميع الواجهات البرمجية الجيّدة تنفيذ عملية استيثاق للتعريف عن المستخدم الذي يرسل الطلب، لكنّنا سنغش قليلًا في هذا المثال باستخدام مولّد رموز الأمان الخاص بـ Pinterest. بعد إكمال الاستيثاق ستحصل على رمز أمان يمكن استخدامه في المثال التالي، حيث سنقوم بإنشاء طلب لجلب وعرض قائمة بمنشورات Pinterest. $request = wp_remote_get( 'https://api.pinterest.com/v1/boards/marticz/home-office/pins/?access_token=<your access token>' ); $pins = json_decode( $request['body'], true ); if( !empty( $pins['data'] ) ) { echo '<ul>'; foreach( $pins['data'] as $pin ) { echo '<li><a href="' . $pin['url'] . '">' . $pin['note']. '</a></li>'; } echo '</ul>'; } لو قمنا بنسخ المثال السابق ولصقه في صفحة content-page.php في قالب Twenty Fifteen لتجربته فإن النتيجة هو الحصول على لائحة بالمنشورات من لوحة Pinterest حول المكاتب الشخصية في المنزل. لا تنس أن تستبدل <your access token> في المثال السابق برمز الأمان الذي حصلت عليه. يقوم السطر الثاني في المثال بفك ترميز جسم الجواب من JSON إلى شكله الأساسي كمصفوفة ونقوم بإنشاء حلقة loop تقوم بطباعة محتوى عنصر المصفوفة $pins['data']. الاستيثاق يقع العديد من الأشخاص في عثرات في هذه المرحلة لأنها تتطلب خطوة إضافية على الأقل وربما بعض الترويسات الإضافية أيضًا. ولننظر إلى واجهة تويتر البرمجية على سبيل المثال، وتحديدًا إلى الاستيثاق الخاص بالتطبيقات، الذي يمكنك استخدامه لاستيثاق تطبيقك مع تويتر. قراءة التوثيق إن أول خطأ قد يتم ارتكابه هو عدم قراءة التوثيق بشكل جيّد. ولو كنت مبرمجًا متمرسًا في واجهات REST البرمجية فيمكنك القفز مباشرة إلى الجزء حول الاستيثاق، ولو فعلت هذا فقد لا تنتبه إلى سطر يقول: وإهمال هذا الشرط سيؤدي إلى فشل حتمًا في الحصول على نتيجة، على الرغم من أن كل شيء آخر مطبّق بشكل كامل، لذا حتى توفّر على نفسك الحاجة لمراجعة شفرة برنامجك، تأكد من قراءة التوثيق بشكل جيّد وكامل. إضافة ترويسات ومعاملات أخرى بعد اتباع التوجيهات في التوثيق حرفيًّا، قمت بإنشاء طلب POST، ينبغي أن يؤدي إلى توليد رمز أمان للوصول من أجلي، ويبدو الكود على الشكل: $key = base64_encode( urlencode( "n8KP16uvGZA6xvFTtb8IAA:i4pmOV0duXJv7TyF5IvyFdh5wDIqfJOovKjs92ei878" ) ); $request = wp_remote_post('https://api.twitter.com/oauth2/token', array( 'headers' => array( 'Authorization' => 'Basic ' . $key, 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8' ), 'body' => 'grant_type=client_credentials', 'httpversion' => '1.1' )); $token = json_decode( $request['body'] ); echo "<pre>"; var_dump($token); echo "</pre>"; إن الخطوة الأولى هو ترميز رمز أمان الوصول والكلمة السرّية بصيغة URL encoding. قمت أيضًا بإضافة ترويستين، واحدة ترويسة استيثاق تحوي على بيانات الوصول. أما الترويسة الثانية فهي ترويسة نوع المحتوى content type، والتي يطلب توثيق تويتر إضافتها. إضافة لما سبق، قمت بملء جسم الطلب تمامًا كما ذكرت الملاحظة السابقة حول grant_type=client_credentials وتم إضافة إصدار HTTP كما يطلب توثيق تويتر أيضًا. سيحتوي الجواب بالإضافة للعديد من المعلومات الأخرى على رمز أمان الوصول في جسم الجواب، وسنحتاج لرمز الأمان هذا في جميع الطلبات اللاحقة المرسلة إلى الواجهة البرمجية الخاصة بتويتر. تخزين رمز أمان الوصول إن رمز الأمان صالح لبعض الوقت، ويعتبر طلبه مجدّدًا هدرًا غير ضروري عند تحميل كل صفحة أو عندما يحتاج تطبيقك أن يقوم بعملية ما وسيؤدي إلى استهلاك عدد الطلبات المسموح بسرعة. يمكن في ووردبريس استخدام عابرة transient لتخزين قيمة رمز الأمان ومن ثم استخدام العابرة عند كل طلب لاحق للواجهة البرمجية. $token = get_transient( 'twitter_access_token' ); $token = ( empty( $token ) ) ? get_twitter_access_token() : $token; $request = wp_remote_get('https://api.twitter.com/1.1/followers/ids.json?screen_name=danielpataki&count=5', array( 'headers' => array( 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8' ), 'httpversion' => '1.1' )); $token = json_decode( $request['body'] ); سيؤدي إرسال الطلب السابق إلى واجهة تويتر البرمجية إلى عرض 5 من متابعيّ على تويتر (قائمة بسيطة لأرقام حساباتهم Ids). وكما يظهر في المثال السابق، فإنني أقوم بجلب القيمة التي خزّنتها في العابرة فإن لم تكن موجودة سأقوم باستدعاء التابع get_twitter_access_token() للحصول على رمز أمان جديد ومن ثم إضافته إلى العابرة كي أستخدمه في الطلبات اللاحقة. تجدر الإشارة إلى أن هذه الطريقة تهدف فقط إلى إظهار آلية التنفيذ وليست أفضل طريقة للتنفيذ، وكسيناريو أبسط كنت لأقوم بوضع جميع العبارات الشرطية IFs داخل التابع get_twitter_access_token() الذي سيقوم بتنفيذ جميع الشيفرة السابقة ضمنيًا. التوابع المساعدة في واجهة HTTP البرمجية الآن وبعد أن حصلنا على لمحة جيدة حول هدف المقال، دعونا نلق نظرة على التوابع التي ستساعدك في واجهة HTTP البرمجية في ووردبريس. هناك 4 توابع يمكن بواسطتها تنفيذ طلبات: wp_remote_get() wp_remote_post() wp_remote_head() wp_remote_request() ومن الواضح تمامًا وظيفة كل تابع، أما التابع الأخير wp_remote_request() فهو تابع عام يمكنك استخدامه مع أي طريقة HTTP method. أما التوابع الخمسة التالية فتسمح لك بالحصول على جواب على الطلب بسهولة باستخدام توابع قياسية عوضًا عن الخوض في التعامل مع المصفوفات وعناصرها. wp_remote_retrieve_body() wp_remote_retrieve_header() wp_remote_retrieve_headers() wp_remote_retrieve_response_code() wp_remote_retrieve_response_message() أيضًا يبين اسم كل تابع الهدف الوظيفي له بسهولة، وينصح عند الإمكان باستخدام هذه التوابع عوضًا عن التعامل مع المصفوفات يدويًا، حيث ستسمح هذه الطريقة الموحّدة لمطوّرين آخرين بفهم البرمجية بسهولة واستخدام الخطافات hooks إن أصبحت متاحة في المستقبل. الخلاصة كما ترى فإن التعامل مع واجهة REST البرمجية سهل باستخدام واجهة HTTP البرمجية في ووردبريس وبعض توابع ووردبريس كالعبّارات. أنصح بشدّة تجربة هذا الأمر لأن عملية التطوير في ووردبريس تسير بثقة باتجاه العالم المُقاد باستخدام الواجهات البرمجية وعليك أن تقفز إلى الموكب قبل فوات الأوان. إن كان لديك المزيد من الأسئلة حول استخدام واجهة HTTP البرمجية أو لديك بعض الأفكار حول كيفية استخدامها، فلا تتردد بمناقشة الأمر في قسم التعليقات في الأسفل. ترجمة -وبتصرّف- للمقال How to Use the WordPress HTTP API لصاحبه Daniel Pataki.
-
تم بشكل رسمي إطلاق الإصدار 16.04 LTS ذو الدعم طويل الأمد (الملقّب بـ Xerial Xerus) من توزيعة أوبونتو منذ عدّة أسابيع، ويتشوق الكثيرون إلى معرفة المزيد عن التغييرات التي طرأت والميزات الجديدة التي أضيفت، ويمكن القيام بذلك من خلال تثبيت نسخة نظيفة clean install أو تحديث نسخة قديمة من توزيعة لينوكس أوبونتو. سنتابع في المقال كيفية القيام بتحديث توزيعة أوبونتو من الإصدار 14.04 LTS إلى الإصدار الجديد وذلك خطوة بخطوة. تحذير: يجب أخذ الاحتياطات اللازمة وإنشاء نسخة احتياطية للبيانات كالمجلدات والمستندات والصور والكثير من الملفات الموجودة على النظام، ولا يجوز ترك الموضوع للحظ لأن في بعض الأحيان لا تجري عمليات التحديث كما هو متوقّع، وقد تصادف بعض الإشكالات التي قد تؤدي إلى تلف البيانات في حال فشلت عملية التحديث. تحديث توزيعة أوبونتو 14.04 إلى 16.04 على نسخة أوبونتو المكتبية Desktop Edition في البداية سنتحقق من أن النظام يملك آخر إصدار من البرمجيات المثبّتة، ونقوم بذلك من خلال فتح مدير تحديثات أوبونتو Ubuntu Update manager الموجود في لوحة القيادة Dashboard. رسم توضيحي 1 – البحث عن الإصدارات الجديدة لبرمجيات أوبونتو المثبّتة سيقوم مدير التحديثات بفحص النظام للتحقق فيما إذا كانت البرمجيات المثبتة تم تحديثها لآخر إصدار، وعند انتهائه يقوم بعرض قائمة بالبرمجيات التي سيتم تحديثها وتثبيت الإصدار الجديد منها. رسم توضيحي 2 - قائمة بالبرمجيات التي يتوفر إصدارات أحدث منها نقوم بالضغط على زر Install Now لتحميل وتثبيت التحديثات المعروضة. رسم توضيحي 3 - تحميل تحديثات برمجيات أوبونتو بعد انتهاء التحميل، سيتم البدء بتثبيت الإصدارات الجديدة: رسم توضيحي 4 - تثبيت تحديثات برمجيات أوبونتو بعد الانتهاء سيعُرض علينا إعادة التشغيل لإنهاء عملية تثبيت التحديثات، وسنقوم باختيار إعادة التشغيل Restart Now. رسم توضيحي 5 - إعادة التشغيل لإنهاء عملية تحديث البرمجيات أخيرًا، يمكن التحقق من أنه قد تم تثبيت جميع التحديثات على البرمجيات بفتح مدير التحديثات مجددًا ويُفترض أن تظهر الرسالة التالية التي تشير إلى عدم وجود تحديثات جديدة: رسم توضيحي 6 - جميع البرمجيات مثبتة بآخر إصداراتها سنباشر الآن بعملية تحديث التوزيعة، نقوم في البداية بفتح سطر الأوامر وتنفيذ الأمر التالي للبدء بعملية تحديث التوزيعة للإصدار الجديد 16.04 LTS: $ sudo update-manager -d تنبيه: انتبه إلى وجود مسافة ما بين update-manager و d- في الأمر السابق. بعد تنفيذ الأمر، سيطلب النظام إدخال كلمة مرور المستخدم، قم بإدخالها والضغط على مفتاح Enter وسيتم فتح مدير التحديث update-manager كما في الصورة: رسم توضيحي 7 - تحديث أوبونتو إلى الإصدار 16.04 أخيرًا، اضغط على زر Upgrade لتحديث نسخة التوزيعة. تحديث توزيعة أوبونتو 14.04 إلى 16.04 على نسخة أوبونتو الخاصة بالخوادم Server Edition سنقوم بتطبيق ذات الخطوات أيضًا، حيث سنبدأ بتحديث البرمجيات المثبتة من خلال تنفيذ الأمر: $ sudo apt-get update && sudo apt-get dist-upgrade وبعد الانتهاء قم بإعادة التشغيل لإنهاء تثبيت التحديثات: $ sudo init 6 بعد ذلك سنقوم بتثبيت حزمة update-manager-core باستخدام الأمر التالي إذا لم تكن مثبتة مسبقًا على الخادوم: $ sudo apt-get install update-manager-core بعد ذلك، سنقوم بفتح الملف etc/update-manager/release-upgrades/ باستخدام أي محرر نصوص نُفضّله (نستخدم vi في مثالنا)، وسنضيف عبارة Prompt=lts إلى نهايته كما في الصورة التالية: $ sudo vi /etc/update-manager/release-upgrades رسم توضيحي 8 - إعداد مدير تحديثات أوبونتو بعد ذلك، سنبدأ عملية التحديث بتنفيذ الأمر: $ sudo do-release-upgrade -d تنبيه: انتبه أيضًا إلى وجود مسافة ما بين do-release-upgrade و d- في الأمر السابق. رسم توضيحي 9 - عملية تحديث توزيعة أوبونتو 14.04 بعد أن يقوم مدير التحديثات بتحديد الحزم التي سيتم تحديثها وأفضل مصادر لها، سيطلب منك تأكيد العملية لذا سنقوم بالنقر على مفتاح y (الذي يشير إلى كلمة yes) ومن ثم نضغط على مفتاح Enter للبدء بعملية التحديث: رسم توضيحي 10 - تحديث أوبونتو للإصدار 16.04 سيُعرض أثناء عملية التحديث إعادة تشغيل بعض الخدمات، لذا نختار الموافقة yes حينها: رسم توضيحي 11 - إعداد الخدمات أثناء عملية تحديث توزيعة أوبونتو أخيرًا، سيُسأل فيما إذا كنا نرغب بإزالة الحزم القديمة التي تم تحديثها أو استبدالها، وسنقوم بالموافقة بالضغط على مفتاح y ومن ثم Enter. بعد انتهاء عملية التحديث نقوم بإعادة تشغيل الخادوم باستخدام الأمر: $ sudo init 6 ونكون قد انتهينا من تحديث توزيعة أوبونتو للإصدار 16.04 LTS. آمل أن تجدوا هذا الدليل مفيًدا ومساعدًا، وفي حال ظهور مشكلة أثناء العملية نظرًا لاختلاف خبرات المستخدمين أثناء عملية التحديث، فلا تترددوا بالسؤال في قسم التعليقات أدناه. ترجمة -وبتصرّف- للمقال How To Upgrade to Ubuntu 16.04 LTS from Ubuntu 14.04 LTS لصاحبه Aaron Kili.
-
تستخدم المهام المجدولة باستخدام الأداة Cron لجدولة تنفيذ الأوامر في وقت محدد، حيث يمكن إعداد الأوامر أو السكربتات، التي يمكن أن يتم تنفيذها بشكل متكرر في وقت مجدد. يُعتبر Cron أحد أكثر الأدوات إفادة في أنظمة لينكس وشبيهات يونكس، حيث تعمل خدمة cron في الخلفية وتتحقق باستمرار من ملف etc/crontab/، ومجلّدات /.*etc/cron/، كما تتحقق من مجلد /var/spool/cron/. أمر crontab يستخدم أمر crontab لتثبيت، إلغاء تثبيت أو عرض الجداول (ملف إعدادات cron) المستخدم في قيادة خدمة cron في برمجية Vixie Cron. يمكن لكل مستخدم أن يكون لديه ملف crontab خاص به، وعلى الرغم من أنّها عبارة عن ملفّات في var/spool/cron/crontabs/ إلا أنها غير مخصصة ليتم التعديل عليها بشكل مباشر، حيث يجب استخدام الأمر crontab لتعديل أو إعداد أي مهام مجدولة في cron. أنواع ملفات إعدادات cron توجد أنواع مختلفة لملفات الإعدادات: Crontab الخاصة بأنظمة لينكس/يونكس عادةً ما تستخدم من قبل خدمات النظام والمهام المجدولة الحرجة التي تحتاج لصلاحيات مدير النظام root. ويستخدم الحقل السادس (انظر أدناه لمزيد من المعلومات عن الحقول) هو اسم المستخدم الذي سيتم تنفيذ الأمر وفق صلاحياته، وتعطي هذه المرونة إمكانية تنفيذ الأوامر وفق أي مستخدم. Crontab الخاصة بالمستخدم يمكن للمستخدم تثبيت مهامه المجدولة الخاصة باستخدام أمر crontab، ويستخدم الحقل السادس لتحديد الأمر المُراد تنفيذه، ويتم تنفيذ جميع الأوامر وفق المستخدم الذي قام بإنشاء المُهمّة. ملاحظة: يعرض المقال تطبيقات cron المكتوبة من قبل Paul Vixie والمستخدمة في معظم توزيعات لينكس وشبيهات يونكس كالإصدار الرابع الشهير لنظام BSD. إن الصيغة متوافقة مع العديد من تطبيقات خدمة crond. ولكن كيف أقوم بتثبيت وإنشاء مهامي المجدولة الخاصة؟ للقيام بذلك، نقوم بتنفيذ الأمر التالي في سطر الأوامر على أنظمة لينكس وشبيهات يونكس: $ crontab -e إن صيغة الملف الذي سيظهر على النحو التالي: 1 2 3 4 5 /path/to/command arg1 arg2 أو: 1 2 3 4 5 /root/ntp_sync.sh حيث أن: 1: الدقيقة (0-59) 2: الساعة (0-23) 3: اليوم في الشهر (0-31) 4: الشهر (0-12 حيث يمثل 12 شهر ديسمبر) 5: اليوم في الأسبوع (0-7 حيث يمثل الرقم 0 أو 7 يوم الأحد) path/to/command/: هو مسار السكربت أو اسم الأمر المراد جدولة تنفيذه. ويمكن تصوّر الصيغة على النحو الأسهل التالي: مثال على crontab بسيط: ## نفّذ سكربت backupscript كُل 5 دقائق ## */5 * * * * /root/backupscript.sh ## نفّذ سكربت backupscript يوميًا الساعة 1 صباحًا ## 0 1 * * * /root/backupscript.sh ## نفّذ سكربت backupscript شهريًا في اليوم الأول من الشهر في تمام الساعة 3:15 صباحًا ## 15 3 1 * * /root/backupscript.sh ملاحظة: يمكن إدراج تعليقات في ملف crontab بوضع إشارة # في بداية السطر. كيفية استخدام المعاملات operators لابد أنك لاحظت في الأمر الأول من الأوامر السابقة أننا كتبنا */5 بدلًا من 5 فقط. إنّ إشارة / هي إحدى المعاملات وسنرى الآن كيفية استخدام المعاملات في crontab. تسمح المعاملات بتحديد عدة قيم في الحقل الواحد، وهناك 4 معاملات: النجمة (*): يحدد هذا المعامل جميع القيم الممكنة في الحقل الذي استخدمت فيه. فعلى سبيل المثال، استخدام * في حقل الساعة يعني أنه سيتم تنفيذ الأمر في "كل" ساعة خلال اليوم، واستخدامها في حقل الأشهر يعني أنه سيتم تنفيذ الأمر في "كل" شهر من أشهر السنة. الفاصلة (,): يحدد هذا المعامل مجموعة من القيم، على سبيل المثال: "1,5,10,15,20,25"، فلو استخدمنا هذه السلسلة مثلًا في حقل الدقائق لعَنى ذلك أنه سيتم تنفيذ الأمر في الدقيقة الأولى، والخامسة، والعاشرة، والخامسة عشر، والعشرون، والخامسة والعشرون من الساعة. إشارة السالب (-): يحدد هذا المعامل مجالًا من القيم، على سبيل المثال: "5-15"، فلو استخدمنا هذه القيمة في حقل الأيام مثلًا لعَنى ذلك أنه سيتم تنفيذ الأمر في اليوم الخامس، السادس، السابع، .... الرابع عشر، الخامس عشر من كل شهر; وكما نلاحظ فهذا يشبه تمامًا كتابة "5,6,7,8,9,10,11,12,13,14,15" باستخدام معامل الفاصلة (,). الخط المائل الخلفي (/): يحدد هذا المعامل قيمة الخطوة، على سبيل المثال: "0-23/" يمكن استخدامها في حقل الساعة لتحديد أن الأمر سيتم تنفيذه في كُل ساعة، ويمكن استخدام هذا المعامل بعد معامل النجمة (*) فلو أردنا تنفيذ الأمر كل ساعتين فيمكن أن نكتب */2 في حقل الساعة. استخدام الكلمات الخاصة لتوفير الوقت عوضًا عن استخدام الحقول الخمسة الأولى من سطر crontab، يمكن استخدام إحدى الكلمات الخاصة الثمانية والتي لن توفّر الوقت فقط بل ستزيد من سهولة فهم المحتوى. reboot@: نفذ الأمر مرة واحدة عند كل إعادة تشغيل early@: نفذ الأمر مرة واحدة في بداية كل سنة، يماثل كتابة "0 0 1 1 *" annually@: مشابه لـ yearly@ تمامًا monthly@: نفذ الأمر مرة واحدة في بداية كل شهر، يماثل كتابة "0 0 1 * *" weekly@: نفذ الأمر مرة واحدة في بداية كل أسبوع، يماثل كتابة "0 0 * * 0" daily@: نفذ الأمر مرة واحدة في بداية كل يوم، يماثل كتابة "0 0 * * *" midnight@: مشابه لـ daily@ تمامًا hourly@: نفذ الأمر مرة واحدة في بداية كل ساعة، يماثل كتابة "0 * * * *" مثال: # نفذ أمر ntpdate كل ساعة @hourly /path/to/ntpdate المزيد من المعلومات عن ملف etc/crontab/ ومجلدات */etc/cron.d/ يُعدّ ملف etc/crontab/ خاصًا بالنظام، وعادة ما يستخدم من قبل مدير النظام root أو الخدمات لإعداد مهام مجدولة على مستوى النظام ككل، ويجب على المستخدمين استخدام أمر crontab لإعداد مهامهم المجدولة حسبما أوضحنا أعلاه. أمّا /var/spool/cron/ أو /var/cron/tabs/ فهي مجلّدات لملفّات crontab الخاصة بالمستخدم، ويجب إنشاء نسخة احتياطية عنها مع مجلد home الخاص بكل مستخدم. فهم ملف etc/crontab/ الافتراضي يحتوي الملف بشكل افتراضي على ما يلي: SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root HOME=/ # run-parts 01 * * * * root run-parts /etc/cron.hourly 02 4 * * * root run-parts /etc/cron.daily 22 4 * * 0 root run-parts /etc/cron.weekly 42 4 1 * * root run-parts /etc/cron.monthly يتم في البداية تحديد بيئة الصدفة SHELL، وفيما لو لم يتم تحديد البيئة سيقوم cron باستخدام الافتراضية sh. وفي حال لم يتم تحديد قيمة للمتغير PATH، فلن يكون هناك قيمة افتراضية ويتوجب حينها تحديد مسار الأمر أو السكربت المطلوب تنفيذه بشكل مباشر absolute. أما في حال لم يتم تحديد قيمة للمتغير HOME، فسيستخدم cron مسار مجلد home الخاص بالمستخدم الذي يقوم بالتنفيذ. بالإضافة إلى ما سبق، يقوم cron بقراءة الملفات في مجلد /etc/cron.d/، وعادة ما تقوم خدمات نظام مثل sa-update أو sysstat بوضع ملف مهامها المجدولة في هذا المجلّد. يمكن لمدير النظام root أو مستخدم بصلاحيات عالية superuser أن يستخدم هذه المجلّدات لإعداد المهام المجدولة، حيث بالإمكان إسقاط ملفات السكربتات في هذه المجلّدات مباشرة، ويقوم أمر run-parts بتنفيذ السكربتات أو البرامج الموجودة في مجلّد يتم تحديده في ملف etc/crontab/: ضع جميع السكربتات هنا واستدعيها في ملف etc/crontab/ /etc/cron.d/ نفذ جميع السكربتات مرة في اليوم /etc/cron.daily/ نفذ جميع السكربتات مرة في الساعة /etc/cron.hourly/ نفذ جميع السكربتات مرة في الشهر /etc/cron.monthly/ نفذ جميع السكربتات مرة في الأسبوع /etc/cron.weekly/ النسخ الاحتياطي للمهام المجدولة باستخدام cron يمكن استخدام الأمرين التاليين لأخذ نسخة عن المهام المجدولة للمستخدم الذي يقوم بتنفيذ الأمرين، حيث سيتم حفظ قائمة بالمهام المجدولة في الملف المحدد في المسار: # crontab -l > /path/to/file # crontab -u user -l /path/to/file يسمح الأمر الثاني بتحديد اسم المستخدم الذي سيتم عرض المهام المجدولة الخاصة به، ويتوجب أن يملك المستخدم الذي يقوم بتنفيذ الأمر صلاحية لاستعراض المهام المجدولة الخاصة بالمستخدم المذكور، فمثلًا يملك مدير النظام صلاحية تمكّنه من استعراض المهام المجدولة الخاصة بأي مستخدم، ولكن لا يمكن لأي مستخدم استعراض المهام المجدولة الخاصة بمدير النظام ما لم يكن يملك صلاحية بذلك. ترجمة -وبتصرّف- للمقال HOW TO ADD CRON JOBS IN LINUX AND UNIX لصاحبه Duy NguyenViet.
-
يختار كثيرون من مطوري الويب الحديث اليوم استخدام قواعد بيانات NoSQL في مشاريعهم، وعادة ما تكون MongoDB اختيارهم الأول. إنّ إنشاء نسخ احتياطية بشكل دوري أمر مهم إن كنت تستخدم قواعد MongoDB في مشاريع في طور التشغيل وذلك بغرض الحفاظ على البيانات من التلف، ولحسن الحظ، توفّر MongoDB أمرًا بسيطًا ضمن أدواتها لإنشاء واستعادة النسخ الاحتياطية. لفهم كيفية عمل النسخ الاحتياطية دون المساس بقواعد بيانات عملك الخاص، سنبدأ المقال بإنشاء قاعدة بيانات جديدة وإضافة قدر بسيط من البيانات إليها، بعد ذلك سنقوم بإنشاء نسخة احتياطية لهذه القاعدة، ومن ثم حذفها واستعادتها من النسخة الاحتياطية التي قمنا بإنشائها. المتطلبات نظام تشغيل Ubuntu 14.04، مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر sudo. يمكن مراجعة مقال الإعداد الابتدائي لخادوم أوبنتو 14.04 لمزيد من المعلومات، تثبيت وإعداد MongoDB. الخطوة الأولى: إنشاء قاعدة بيانات تجريبية إنّ إنشاء نسخة احتياطية لقاعدة بيانات فارغة ليس أمرًا مفيدًا، لذا سنقوم في هذه الخطوة بإنشاء قاعدة بيانات تجريبية وإضافة بعض البيانات لها. إنّ أسهل طريقة للتعامل مع MongoDB هي عبر سطر أوامرها الذي يمكن فتحه بتنفيذ الأمر mongo في سطر الأوامر العادي. > mongo بعد ذلك سنقوم بإنشاء قاعدة بيانات جديدة سندعوها myDatabase وذلك باستخدام الأمر المساعد use: $ use myDatabasee سنحصل على الخرج التالي نتيجة لتنفيذ الأمر: switched to db myDatabase ينبغي على جميع البيانات في قاعدة MongoDB أن تتبع لمجموعة collection. وبالرغم من ذلك، فليس هناك حاجة لإنشاء مجموعة بشكل خاص، فعند استخدام التابع insert لإدخال بيانات لمجموعة غير موجودة، سيتم إنشاء المجموعة بشكل تلقائي قبل كتابة البيانات. بإمكانك استخدام الشفرة البرمجية التالية لإضافة 3 سندات documents لمجموعة تدعى myCollection باستخدام التابع insert: db.myCollection.insert([ {'name': 'Alice', 'age': 30}, {'name': 'Bill', 'age': 25}, {'name': 'Bob', 'age': 35} ]); وستظهر الرسالة التالية إن تم تنفيذ الشفرة بنجاح: BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 3, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] }) الخطوة الثانية: التحقق من حجم قاعدة البيانات الآن وبعد أن حصلنا على قاعدة مع بعض البيانات فيها، سنقوم بأخذ نسخة احتياطية لها. ولكن حجم النسخ الاحتياطية قد يكون كبيرًا إن كانت لديك قاعدة بيانات كبيرة، وبالتالي حتى نتجنب المخاطرة باستهلاك مساحة التخزين المتبقية في القرص، وبالنتيجة إبطاء الخادوم أو منعه من العمل، فيجب أن نتحقق من حجم قاعدة البيانات قبل البدء بالنسخ الاحتياطي. للقيام بذلك بإمكاننا استخدام التابع stats والتحقق من القيمة التي يعيدها المفتاح dataSize لمعرفة حجم القاعدة مقدّرًا بالبايت. $ db.stats().dataSize; وبالنسبة لقاعدة بياناتنا التجريبية فإن الحجم سيكون رقمًا صغيرًا يبلغ 592 بايت. انتبه إلى أن القيمة التي يعطيها dataSize هي قيمة تقريبية لحجم النسخة الاحتياطية. الخطوة الثالثة: إنشاء النسخة الاحتياطية بإمكاننا استخدام الأمر mongodump والذي سيقوم باستدعاء أداة من الأدوات المرفقة مع MongoDb. سيقوم الأمر mongodump بشكل افتراضي بإنشاء نسخة احتياطية لجميع قواعد البيانات المستخدمة. ولإنشاء نسخة احتياطية لقاعدة بيانات معيّنة، يجب إضافة الخيار -d وتحديد اسم القاعدة. إضافة لذلك، يمكن إعلام mongodump بالمكان الذي نرغب بتخزين النسخة الاحتياطية فيه وذلك باستخدام الخيار -o وتحديد المسار. يتم تنفيذ mongodump من سطر الأوامر العادي لذا سنقوم الآن بإنهاء العمل بسطر أوامر mongo والعودة لسطر الأوامر العادي وذلك بالضغط على مفتاحي Ctrl+D. سنقوم بعد ذلك بتنفيذ الأمر mongodump لإنشاء نسخة احتياطية لقاعدتنا myDatabase وتخزين النسخة في المسار backups/first_backup/~: $ mongodump -d myDatabase -o ~/backups/first_backup إن تم تنفيذ الأمر بنجاح فيفترض أن تظهر الرسالة التالية: 2015-11-24T18:11:58.590-0500 writing myDatabase.myCollection to /home/me/backups/first_backup/myDatabase/myCollection.bson 2015-11-24T18:11:58.591-0500 writing myDatabase.myCollection metadata to /home/me/backups/first_backup/myDatabase/myCollection.metadata.json 2015-11-24T18:11:58.592-0500 done dumping myDatabase.myCollection (3 documents) 2015-11-24T18:11:58.592-0500 writing myDatabase.system.indexes to /home/me/backups/first_backup/myDatabase/system.indexes.bson لاحظ بأنّ النسخة الاحتياطية ليست ملفًّا واحدًا بل هو مجلد يملك الهيكل التالي: first_backup └── myDatabase ├── myCollection.bson ├── myCollection.metadata.json └── system.indexes.bson الخطوة الرابعة: حذف قاعدة البيانات لاختبار النسخة الاحتياطية التي قمنا بالحصول عليها، يمكن إما التوجّه لخادوم آخر يملك نسخة MongoDB أخرى أو حذف قاعدة البيانات التجريبية من الخادوم الحالي، وسنختار الخيار الثاني في المقال. لنقم الآن بفتح سطر أوامر mongo ومن ثم الاتصال بقاعدة البيانات: $ mongo myDatabase سنقوم بحذف قاعدة البيانات باستخدام التابع dropDatabase: $ db.dropDatabase(); إن تم حذف القاعدة بنجاح، ستشاهد الرسالة التالية: { "dropped" : "myDatabase", "ok" : 1 } وللتأكد يمكن استخدام التابع find على المجموعة myCollection وسنرى بأن جميع البيانات المدخلة سابقًا قد اختفت. $ db.myCollection.find(); وبطبيعة الحال فلن يكون هناك أي خرج نتيجة لتنفيذ الأمر لعدم وجود بيانات لإظهارها. الخطوة الخامسة: استعادة قاعدة البيانات من النسخة الاحتياطية لاستعادة قاعدة البيانات التي حصلنا على نسخة احتياطية منها باستخدام الأمر mongodump، سنقوم باستخدام أداة أخرى من أدوات Mongo يسمى mongorestore، ولكن قبل استخدامه قم بالعودة لسطر الأوامر العادي بالنقر على مفتاحي Ctrl+D إن كنت ما تزال في سطر أوامر mongo. إن من السهل استخدام أمر mongorestore حيث يكفي تمرير المسار الذي توجد به النسخة الاحتياطية كما في المثال: $ mongorestore ~/backups/first_backup/ وستظهر رسالة تشبه التالية دلالة على نجاح التنفيذ: 2015-11-24T18:27:04.250-0500 building a list of dbs and collections to restore from /home/me/backups/first_backup/ dir 2015-11-24T18:27:04.251-0500 reading metadata file from /home/me/backups/first_backup/myDatabase/myCollection.metadata.json 2015-11-24T18:27:04.252-0500 restoring myDatabase.myCollection from file /home/me/backups/first_backup/myDatabase/myCollection.bson 2015-11-24T18:27:04.309-0500 restoring indexes for collection myDatabase.myCollection from metadata 2015-11-24T18:27:04.310-0500 finished restoring myDatabase.myCollection (3 documents) 2015-11-24T18:27:04.310-0500 done ولاختبار البيانات التي قمنا باستعادتها، سنقوم بفتح سطر أوامر mongo مجددًا والاتصال بقاعدة myDatabase: $ mongo myDatabase ومن ثم نستخدم الأمر find على المجموعة: $ db.myCollection.find(); فإن سار كل شيء على ما يرام، ينبغي الآن أن تظهر لك البيانات المدخلة سابقًا: { "_id" : ObjectId("5654e76f21299039c2ba8720"), "name" : "Alice", "age" : 30 } { "_id" : ObjectId("5654e76f21299039c2ba8721"), "name" : "Bill", "age" : 25 } { "_id" : ObjectId("5654e76f21299039c2ba8722"), "name" : "Bob", "age" : 35 } الخلاصة تعلّمنا كيفية استخدام mongodump و mongorestore لإنشاء نسخة احتياطية واستعادة واحدة تخص قاعدة بيانات MongoDB. تذكر بأن إنشاء نسخة احتياطية هي عملية شرهة لموارد النظام ويمكن لها أن تخفض من أداء محرك MongoDB، لذا ينصح بأن تتم العملية فقط في الساعات التي تكون فيها الطلبات على القاعدة أقل ما يمكن. ترجمة -وبتصرّف- للمقال How to Create and Use MongoDB Backups on Ubuntu 14.04 لصاحبته Hazel Virdó.
-
- nosql
- نسخ احتياطي
-
(و 3 أكثر)
موسوم في:
-
يعتبر Ansible حلًا مناسبًا لأتمتة الأعمال التقنية البسيطة، فإن وجدت نفسك تقوم بتثبيت ووردبريس بشكل متكرر ومُمل، فقد يوفّر عليك Ansible الكثير من الوقت، وباستخدام بعض الأسطر بلغة YAML (وهي لغة توصيف واضحة ومباشرة) سنقوم بأتمتة عملية تثبيت ووردبريس على خادوم يعمل بنظام تشغيل Ubuntu 14.04، وفق الخطوات بصورة أوتوماتيكية. سنستخدم خادومين: أحدهما الخادوم الباني ويتم تشغيل Ansible عليه، والآخر الذي سنقوم بتثبيت ووردبريس عليه باستخدام Ansible. المتطلبات الأولية قبل المتابعة في المقال، سنحتاج للأمور التالية: خادوم يعمل بنظام تشغيل Ubuntu 14.04. سنقوم بتثبيت Ansible على هذا الخادوم (ونشير إليه في المقال بـ الخادوم الباني). سنقوم بتسجيل الدخول إلى هذا الخادوم وجميع الأوامر والملفّات المذكورة في المقال على هذا الخادوم، خادوم آخر يعمل بنظام تشغيل Ubuntu 14.04. سنقوم بتثبيت ووردبريس عليه باستخدام Ansible (وسنشير إليه في المقال بـ خادوم ووردبريس)، حساب مستخدم عادي -على كِلا الخادومين- لا يملك صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ الأمر sudo، إضافة مفتاح SSH الخاص بالمستخدم -الذي أنشأناه على الخادوم الباني- إلى المفاتيح المصادقة authorized_keys للمستخدم الذي أنشأناه على خادوم ووردبريس، وينبغي تنفيذ هذه العملية على الخادوم الباني ورفع المفاتيح إلى خادوم ووردبريس. تنفيذ أوامر sudo بدون تأكيد باستخدام كلمة مرور إنّ من الأسرع -ولكن أقل أمانًا- تنفيذ أوامر sudo على خادوم ووردبريس بدون الحاجة لإدخال كلمة مرور تأكيد في كل مرّة. لإعطاء المستخدم على خادوم ووردبريس هذه الإمكانية، سنقوم بتعديل ملف sudoers باستخدام الأمر visudo على سطر الأوامر: $ visudo ومن ثم سنضيف السطر التالي في نهاية الملف: sammy ALL=(ALL) NOPASSWD: ALL ملاحظة: لا تنس استبدال اسم المستخدم (sammy في هذه الحالة) باسم المستخدم الموجود لديك، وتأكد من وضع السطر في نهاية الملف حتى لا يتم تجاوزه بالصلاحيات الافتراضية الموجودة في الملف. نصيحة: قم دومًا باستخدام الأمر visudo عند تعديل ملف sudoers، لأن الأمر سيقوم بالتحقق من التعديلات قبل حفظ الملف ويحميك بالتالي من ارتكاب أخطاء في الملف قد تؤدي إلى منعك من الدخول. حالما تنتهي من تنفيذ العملية السابقة سيغدو بإمكانك تنفيذ الأمر التالي على خادوم ووردبريس بدون إدخال كلمة مرور لتأكيده: $ sudo echo "Hello" وفي بقية المقال، تستطيع تنفيذ الأمر ansible-playbook بدون المُعامل K- كي تتجنب الحاجة لإدخال كلمة المرور للتأكيد بشكل يدوي: $ ansible-playbook playbook.yml -i hosts -u sammy الخطوة الأولى: تثبيت Ansible سنقوم الآن بتثبيت Ansible على الخادوم الباني، ونبدأ بتسجيل الدخول عبر SSH إلى الخادوم وتنفيذ الأمر التالي: $ sudo apt-get install ansible -y وتستطيع التأكد من تثبيت Ansible بتنفيذ الأمر: $ ansible --version حيث ينبغي أن يكون الخرج مشابهًا (وليس بالضرورة مطابقًا) لما يلي: ansible 1.5.4 الخطوة الثانية: إعداد بنية الملفات الآن وبعد أن انتهينا من تثبيت Ansible، دعونا نقوم بإعداد بنية الملفات من أجل Ansible playbook. سنقوم بإنشاء مجلّد على النحو التالي: $ cd ~ $ mkdir wordpress-ansible && cd wordpress-ansible سنقوم الآن بإنشاء ملفّين: الأول يدعى playbook.yml (حيث سنقوم بكتابة الأوامر الخاصة بتثبيت ووردبريس فيه) والثاني يدعى hosts (وهذا يُخبر Ansible عن الخواديم التي سيتم تنفيذ الأوامر عليها): $ touch playbook.yml $ touch hosts إنّ من الأفضل فصل الأوامر بحسب الأدوار، ومن الممكن اعتبار الأدوار كأجزاء من الممكن إعادة استخدامها، وسنقوم في هذا المشروع بإنشاء 4 أدوار: server php mysql wordpress سنقوم بإنشاء مجلد الأدوار في الجذر الرئيسي للمجلد الذي أنشأناه سابقًا wordpress-ansible/~ بتنفيذ الأمر التالي: $ mkdir roles && cd roles والآن سنقوم بتجهيز الأدوار باستخدام أداة من أدوات Ansible تدعى ansible-galaxy، حيث سنقوم من أجل كل دور بتنفيذ الأمر ansible-galaxy init كالتالي: $ ansible-galaxy init server $ ansible-galaxy init php $ ansible-galaxy init mysql $ ansible-galaxy init wordpress ستلاحظ بأن هذا الأمر سيقوم بإنشاء هيكل ملفات متكامل لكل دور من الأدوار، وهذه الخطوة هي إحدى الأمور التي ينصح بها في توثيق Ansible. ما يهمّنا غالبًا هو التعامل مع محتوى ملف tasks/main.yml لكل دور. عند الوصول إلى هذه المرحلة سيكون لدينا الهيكل التالي: [.] |_ playbook.yml |_ hosts |_ [roles] |_ [server] |_ ... |_ [php] |_ ... |_ [mysql] |_ ... |_ [wordpress] |_ ... الخطوة الثالثة: إنشاء الـ Playbook سنقوم الآن بكتابة الأوامر التي ستقوم بتثبيت ووردبريس على خادوم ووردبريس. ملف المخزون hosts يُخبر هذا الملف Ansible بالخواديم التي نرغب بتثبيت ووردبريس عليها، ومن الممكن تنفيذ الأوامر للخواديم أو مجموعة الخواديم المعرّفة في ملف المخزون hosts. سنقوم بتحرير ملف hosts باستخدام محرر nano أو أي محرر آخر تفضّله وكتابة التالي: [wordpress] wordpress_server_ip ملاحظة: من الممكن وضع أي عدد نرغب به من العناوين الرقمية IPs تحت مجموعة [wordpress]. سيؤدي هذا إلى تنفيذ الأوامر على جميع الخواديم المذكورة على افتراض أننا نملك صلاحية استخدام هذه الخواديم. سيمكّننا هذا من تثبيت ووردبريس على أي عدد من الخواديم دفعة واحدة. ملف Playbook يمكن اعتبار هذا الملف كتعريف لتطبيق ووردبريس الذي سنقوم بتثبيته. سيحتوي الملف على جميع الأدوار التي قمنا بإنشائها بغرض تجهيز تطبيق مفيد (ووردبريس في حالتنا). سنقوم بداية بتحرير الملف باستخدام محرر nano أو أي محرر آخر ترغب به: $ nano ~/wordpress-ansible/playbook.yml ومن ثم سنضيف المحتويات التالية إلى الملف، والتي ستُخبر Ansible أية أدوار سيتم تنفيذها على أية خواديم (سيتم تنفيذ الأدوار المذكورة في حالتنا على مجموعة العناوين الرقمية المدرجة في مجموعة wordpress المسجّلة في ملف hosts الذي أنشأناه سابقًا): - hosts: wordpress roles: - server - php - mysql - wordpress والآن لنعد إلى الجذر الرئيسي: $ cd ~/wordpress-ansible/ سنتأكد الآن من أنه من الممكن إجراء اتصال ما بين الخادوم الباني وخادوم ووردبريس من خلال تنفيذ ملف playbook الذي لن يقوم بأي شيء سوى التحقق من الاتصال: $ ansible-playbook playbook.yml -i hosts -u sammy -K ستُطالب بإدخال كلمة المرور لتأكيد الأمر، ولا تنس أن تقوم باستبدال اسم المستخدم بالموجود لديك. سيظهر لنا خرج يشبه التالي عند تنفيذ الأمر: ansible-playbook playbook.yml -i hosts -u sammy -K PLAY [wordpress] ************************************************************** GATHERING FACTS *************************************************************** ok: [188.166.68.134] PLAY RECAP ******************************************************************** 188.166.68.134 : ok=1 changed=0 unreachable=0 failed=0 والذي سيؤكد لنا بأن الاتصال قد تم بنجاح، دون أن يتم تنفيذ أي تعديلات لأننا لم نقم بتحديد أي أوامر لتنفيذها حتى الآن. إن فشل تنفيذ الأمر فتأكّد من أن باستطاعتك تسجيل الدخول إلى خادوم ووردبريس من الخادوم الباني باستخدام مفتاح SSH الذي قمت بنسخه في البداية. الخطوة الثالثة: إنشاء الأدوار دور Server سنقوم بداية بتعريف الأوامر التي سيتم تنفيذها على الخادوم ولهذا الغرض سنقوم بتحرير أوامر دور server. ستقوم الأوامر التي سنصرّح عنها بتثبيت جميع البرمجيات التي سنحتاجها على السيرفر الهدف. نبدأ بتنفيذ الأمر التالي: $ nano roles/server/tasks/main.yml قم بإضافة المحتويات التالية وتأكد من وجود سطر واحد فقط يحتوي على --- (حيث يوجد هذا السطر سلفًا بشكل افتراضي): --- - name: Update apt cache apt: update_cache=yes cache_valid_time=3600 sudo: yes - name: Install required software apt: name={{ item }} state=present sudo: yes with_items: - apache2 - mysql-server - php5-mysql - php5 - libapache2-mod-php5 - php5-mcrypt - python-mysqldb سيقوم المحتوى السابق بما يلي: تحديث خبء apt-cache (تنفيذ الأمر apt-get update)، تثبيت Apache ،MySQL ،PHP وبرمجيات أخرى مرتبطة باستخدام apt-get install. وإن كنت مهتمًّا بمعرفة تفاصيل ما نقوم بتثبيته، فيمكنك الاطلاع على هذا المقال حول تثبيت LAMP على Ubuntu 14.04 بشكل يدوي. سنقوم الآن بتنفيذ ansible-playbook مرة أخرى على النحو التالي: $ ansible-playbook playbook.yml -i hosts -u sammy -K ويفترض هذه المرة أن يكون الخرج بما يشبه التالي: ansible-playbook playbook.yml -i hosts -u sammy -K PLAY [wordpress] ************************************************************** GATHERING FACTS *************************************************************** ok: [188.166.68.134] TASK: [server | Update apt cache] ********************************************* ok: [188.166.68.134] TASK: [server | Install required software] ************************************ changed: [188.166.68.134] => (item=apache2,mysql-server,php5-mysql,php5,libapache2-mod-php5,php5-mcrypt,python-mysqldb) PLAY RECAP ******************************************************************** 188.166.68.134 : ok=3 changed=1 unreachable=0 failed=0 وبعد التنفيذ، ينبغي أن تكون قادرًا على استعراض الصفحة الافتراضية لـ Apache عبر فتح العنوان http://wordpress_server_ip في المتصفح. ملاحظة: إن توقّف تنفيذ الأمر بشكل نهائي عند سطر [TASK: [server | Update apt cache فمن المحتمل أن يكون هناك نقص في الصلاحيات المطلوبة على الخادوم الهدف، لذا تأكّد من أن الوصول باستخدام sudo تم إعداده بشكل صحيح على خادوم ووردبريس. دور PHP سنقوم الآن بتجهيز الأوامر التي تستهدف PHP، ولهذا الغرض سنقوم بتحرير الملف الخاص بهذا الدور: $ nano roles/php/tasks/main.yml ومن ثم سنضيف المحتوى التالي (تأكّد من وجود سطر واحد فقط يحتوي على --- في بداية الملف): --- - name: Install php extensions apt: name={{ item }} state=present sudo: yes with_items: - php5-gd - libssh2-php سيقوم المحتوى السابق بتثبيت الملحقات extensions الضرورية لـ PHP وهي: php5-gd و libssh2-php. دور MySQL سنقوم الآن بإعداد قاعدة بيانات MySQL لموقع ووردبريس، وذلك في دور mysql. سنحتاج من أجل القيام بذلك إلى بعض المتغيّرات، والتي من الممكن تخزينها في ملف المتغيرات الافتراضية defaults/main.yml: $ nano roles/mysql/defaults/main.yml سنضيف في الملف اسم قاعدة البيانات، اسم المستخدم الخاص بالقاعدة، كلمة المرور الخاصة بالمستخدم وبنفس الترتيب، ولا تنس أن تستخدم كلمة مرور معقّدة لأغراض أمنية: --- wp_mysql_db: wordpress wp_mysql_user: wordpress wp_mysql_password: wp_db_password والآن نستخدم nano لتحرير ملف المهام: $ nano roles/mysql/tasks/main.yml ونضيف المحتوى التالي: --- - name: Create mysql database mysql_db: name={{ wp_mysql_db }} state=present - name: Create mysql user mysql_user: name={{ wp_mysql_user }} password={{ wp_mysql_password }} priv=*.*:ALL يقوم المحتوى السابق بـ: إنشاء قاعدة بيانات MySQL، إنشاء مستخدم MySQL، إعطاء المستخدم صلاحية الوصول إلى قاعدة البيانات. وكما ترى فسيتم استخدام قيم المتغيرات بشكل تلقائي من ملف defaults/main.yml عند تنفيذ الأوامر. ملاحظة: توفّر أدوات Ansible أداة ansible-vault والتي تسمح بتخزين كلمات المرور بصورة مشفّرة حتى لا تكون قابلة للقراءة في الملف، ولكن الحديث عن هذا خارج إطار حديثنا الآن. دور WordPress والآن نأتي للحظة التي كنا ننتظرها.. تثبيت ووردبريس. نبدأ بتحرير ملف المهام كالمعتاد: $ nano roles/wordpress/tasks/main.yml وسنقوم بنسخ المحتوى التالي إليه: --- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no sudo: yes سيقوم المحتوى السابق بتحميل ووردبريس إلى مجلد tmp/ (ويمكن للحذرين أن ينتبهوا إلى أننا قمنا بتعطيل التحقق من الشهادة الأمنية، لأنه سيمنع عملية التحميل). بعد اكتمال التحميل سنقوم بفك ضغط الملف إلى var/www/، وهو المسار الذي يستخدمه Apache لتخزين محتوى الويب، وبالتالي سنضيف الجزء التالي لمحتوى الملف أيضًا: - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no sudo: yes وبعد أن يتم فك ضغط الملفات، سنقوم بتحديث مسار الجذر الافتراضي DocumentRoot في ملف إعدادات Apache كي يشير إلى موقع ووردبريس: - name: Update default Apache site sudo: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache sudo: yes لاحظ أننا استخدمنا الكتلة notify، والتي نحتاجها عند الرغبة بإعادة تشغيل خدمات بعد أن يتم تنفيذ مهمّة بنجاح، ولا يتم تنفيذ معالجات notify إلا عندما يحصل تغيير على حالة المهمّة. سنقوم بإضافة المعالج الخاص بنا لإعادة تشغيل Apache باستخدام restart apache ويتم ذلك في الملف roles/wordpress/handlers/main.yml: $ nano roles/wordpress/handlers/main.yml نضيف المحتوى التالي: --- - name: restart apache service: name=apache2 state=restarted sudo: yes ويتم تنفيذ هذه المهمّة عندما تتغير حالة المهمّة التي تحتوي على الكتلة notify: restart apache، مما يؤدي إلى إعادة تشغيل الخدمة. إعداد ووردبريس بالعودة إلى roles/wordpress/tasks/main.yml، سنقوم الآن بتجهيز إعدادات موقع ووردبريس، فنقوم أولًا بنسخ ملف الإعدادات config الافتراضي: - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php sudo: yes ومن ثم نقوم بتغيير بعض الثوابت في الملف لتتطابق مع معلومات الاتصال بقاعدة البيانات: - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} sudo: yes حيث ستقوم المهمّة بجلب معلومات الاتصال بالقاعدة من ملف المتغيّرات الافتراضية الذي قمنا بتحريره سابقًا. بعد الانتهاء من الخطوات السابقة بنجاح، سيكون قد أصبح لدينا ملفّين لدور wordpress، وفيما يلي النسخة الكاملة لمحتوى الملفّين.. ملف roles/wordpress/tasks/main.yml: --- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no sudo: yes - name: Update default Apache site sudo: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php sudo: yes - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} sudo: yes ملف roles/wordpress/handlers/main.yml: --- - name: restart apache service: name=apache2 state=restarted sudo: yes ونكون قد انتهينا. لنقم الآن بتشغيل ansible-playbook لآخر مرة لإعداد موقع ووردبريس: $ ansible-playbook playbook.yml -i hosts -u sammy -K وبعد تنفيذ الأمر ينبغي أن نكون قادرين على تصفّح الموقع عبر طلب عنوانه http://your_server_ip في المتصفح ويمكن الآن متابعة إعداد موقع ووردبريس بشكل يدوي عند هذه المرحلة. الخلاصة تهانينا! ستتمكن الآن من تثبيت مواقع ووردبريس على أي عدد من الخواديم التي تعمل بنظام تشغيل Ubuntu باستخدام أمر واحد: $ ansible-playbook playbook.yml -i hosts -u sammy -K وكل ما تحتاج للقيام به هو إضافة العنوان الرقمي IP إلى قائمة الخواديم المستهدفة في ملف hosts والتأكّد من أن الصلاحيات قد تم إعدادها مسبقًا على الخادوم الهدف. تناولنا في المقال بصورة سريعة كيفية استخدام Ansible لتثبيت مواقع ووردبريس بشكل اوتوماتيكي، وقد تكون مهتمًّا ببعض التحسينات الإضافية الممكنة: تعلّم كيفية استضافة أدوارك الخاصة في الـ Ansible Galaxy. أتمتة عملية الإعداد النهائية لموقع ووردبريس حتى لا يكون هناك حاجة للقيام بأي إعداد يدوي للموقع المطلوب إطلاقًا. ترجمة -وبتصرّف- للمقال How To Automate Installing WordPress on Ubuntu 14.04 Using Ansible لصاحبه Christo Crampton.
-
مع ازدياد الحاجة للبُنى ذات الأداء المرتفع والمصمّمة لخدمة الأنظمة الحساسة، ازدادت أهمّية مصطلحات مثل قابلية التوسعة scalability والوفرة العالية availability. وبينما يُعد تحمّل الاستهلاك المتزايد لموارد النظام أمرًا مهمًّا، فإنّ من المهم أيضًا تخفيض زمن توقف الخدمة downtime والقضاء على نقاط التوقّف الحرجة single points of failure، وتمثّل الوفرة العالية جودة تصميم البُنية على مستوى قادر على معالجة هذه الاعتبارات الحساسة. سنناقش في المقال ما تعنيه الوفرة العالية بالضبط وكيف بإمكانها تحسّين جودة البنية الخاصة بك. ما هي الوفرة العالية يستخدم مصطلح الوفرة لوصف الفترة الزمنية التي تتوفر خلالها الخدمة، بالإضافة للوقت المطلوب من قبل النظام للاستجابة لطلبٍ مُرسَل من قبل مستخدم ما. إنّ الوفرة العالية هي جودة النظام أو العنصر الذي يضمن مستوىً عالٍ من الأداء التشغيلي لفترة من الزمن. قياس الوفرة يعبرّ عن الوفرة عادة كنسبة تُمثّل الزمن الذي تكون خلاله خدمة أو نظام ما قيد التشغيل، فتعبّر النسبة 100% مثلًا عن نظام يعمل طوال الوقت دون توقّف أبدًا، بينما تشير النسبة 99% من الوفرة خلال عام واحد إلى أنّ النظام سيعمل طوال العام مع احتمالية انقطاع في الخدمة (إجمالًا) بنسبة 1% أي ما يماثل 3.65 يوم (3 يوم و15 ساعة و36 دقيقة). يتم وضع هذه النسب بالاعتماد على عدة عوامل، بما في ذلك فترات الصيانة المجدّولة والطارئة، بالإضافة إلى الوقت اللازم لاستعادة النظام لوضعه الطبيعي في حال حدوث خطأ. كيف تعمل الوفرة العالية تعمل الوفرة العالية كآلية استجابة عند وقوع مشكلة ما في البنية، وبالرغم من أن مفهومها سهل نظريًا إلا أنّ تنفيذها عمليًّا يتطلب بعض البرمجيات والإعدادات المختصّة. متى تكون الوفرة العالية مهمة تكون الوفرة العالية High Availability مهمّة عند إعداد وتثبيت أنظمة متينة robust، حيث يصبح تخفيض زمن انقطاع الخدمة مسألة بالغة الأهمّية. وبغض النظر عن مدى جودة الأنظمة أو البرمجيات لديك، فقد تقع الأخطاء التي قد تؤدي لتوقف برمجياتك أو خواديمك عن العمل. إنّ تطبيق الوفرة العالية في البنية لديك هو استراتيجية مفيدة لتخفيض الضرر الناتج عن مثل هذه الحوادث، حيث يمكن لأنظمة الوفرة العالية أن تعيد البنية للعمل بصورة طبيعية بشكل أوتوماتيكي. كيف يتم تحقيق الوفرة العالية إنّ إحدى أهداف الوفرة العالية هو القضاء على نقاط التوقّف الحرجة في البنية التحتية infrastructure. إنّ نقطة التوقّف الحرجة A single point of failure هي إحدى العناصر في التكنولوجيا التي تستخدمها والتي تؤدي إلى توقّف الخدمة بشكل كامل في حال خروجها فحسب عن الخدمة. وكمثال على هذا، إنّ أي عنصر يعدّ مُهمًّا لعمل برمجياتك ولا يملك أي بديل عنه يمكن أن يُعتبر نقطة توقّف حرجة. وللقضاء على نقاط التوقّف الحرجة يجب أن يتم تجهيز بديل عن كل طبقة من طبقات النظام. على سبيل المثال، تخيل امتلاكك لبنية تتكون من خادومي ويب متطابقين تمامًا يستخدمان خلف موازن أحمال load balancer. إنّ حركة البيانات التي تصل من المستخدمين سيتم توزيعها بشكل متساوٍ بين الخادومين، ولكن إن توقّف أحدهما عن العمل فسيقوم موازن الأحمال بتحويل جميع البيانات إلى الخادوم الثاني الذي يعمل. إنّ خادوم الويب في هذه الحالة لا يعتبر نقطة توقّف حرجة لأنّ: هناك عنصرًا بديلًا عنه في نفس المستوى، موازن الأحمال قادر على اكتشاف المشكلة في العناصر التي تليه ويقوم بتفادي المشكلة في زمن قصير. ولكن ما الذي قد يحصل في حال توقّف موازن الأحمال عن العمل؟ وفقًا للوصف المقدّم سابقًا الشائع الاستخدام في الحياة العملية، يُعدّ موازن الأحمال نقطة توقف حرجة، والقضاء على نقطة التوقف الحرجة في هذه الحالة هو تحدٍّ صعب على الرغم من أنّ إضافة موازن أحمال ثانٍ أمرٌ ممكن إلا أنّه من غير الواضح أين يُمكن تنفيذ آلية لاكتشاف الخلل الذي قد يطرأ على موازن الأحمال لتفادي المشكلة. إنّ زيادة عدد العناصر المكرّرة البديلة redundant لا يضمن الوفرة العالية، حيث يتوجب تطبيق آلية لاكتشاف الأخطاء واتخاذ الإجراء المناسب عند توقّف أحد العناصر عن العمل. إنّ من الممكن تنفيذ آلية اكتشاف الأخطاء والاستعادة من حالة الفشل وفق منهج عمل يبدأ من الأعلى إلى الأسفل، حيث تكون الطبقة العلوية مسؤولة عن مراقبة الطبقة التي تليها مباشرة بحثًا عن وقوع أخطاء. وفي السيناريو السابق، يُعدّ موازن الأحمال هو الطبقة العلوية وعند توقّف أحد خواديم الويب في الطبقة الدُنيا (التالية)، سيقوم موازن الأحمال بإيقاف حركة البيانات باتجاه الخادوم الخارج عن الخدمة. إنّ هذه الطريقة غير مناسبة على الرغم من بساطتها، حيث لن يكون من الممكن في بعض الحالات تحديد الطبقة العلوية المسؤولة عن مراقبة بعض نقاط التوقّف الحرجة التي تقع في الطبقة التي تليها، كحالة موازن الأحمال في المثال المذكور، وتصبح الآلية -التي يتم إنشاؤها بغرض مراقبة النقاط الحرجة- نقطة حرجة بحد ذاتها. في هذه المرحلة، يصبح من الضروري اتباع منهج موزّع، حيث يتوجب ربط العقد المكرّرة البديلة عن بعضها البعض مع بعضها البعض كعنقود cluster وينبغي أن تكون كل عقدة منها قادرة على اكتشاف الخطأ وتفاديه في العقد المتصلة معها ضمن العنقود. وفي حالة موازن الأحمال، فالأمر أعقد بقليل من ذلك، نظرًا للآلية التي تعمل بها خواديم الأسماء nameservers في DNS، حيث يتطلب الاستعادة من خطأ يحصل في موازن أحمال مكرّر redundant أن يتم إجراء تعديل على سجلّات DNS كي يتم توجيه اسم النطاق domain name إلى عنوان IP لموازن الأحمال الثانوي. إنّ مثل هذا التغيير يحتاج وقتًا ليس بقصير حتى يصبح ساري المفعول على شبكة الإنترنت، مما سيؤدي إلى حصول انقطاع طويل في الخدمة. أحد الحلول لمثل هذه المشكلة هو استخدام موازن أحمال DNS يستخدم خوارزمية Round-Robin، ولكن هذا النهج غير عملي لأنّه يترك احتمالية وقوع خطأ في البرنامج من جهة العميل. إن الحل الأكثر عملية ومتانة هو استخدام أنظمة تسمح بعنونة مرنة للعناوين الرقمية IP، كالعناوين الرقمية العائمة floating IPs. إنّ التبديل بين العناوين الرقمية عند الطلب يُلغي الحاجة للانتظار حتى يتم نشر العنوان الجديد لاسم النطاق عند تغييره على الشبكة، وذلك عبر توفير عناوين رقمية ثابتة يمكن نقلها من عنصر لآخر عند الطلب، حيث يبقى اسم النطاق مرتبطًا بالعنوان الرقمي نفسه، بينما يتم نقل العنوان الرقمي بين الخواديم. يتم تطبيق البنى ذات الوفرة العالية باستخدام العناوين الرقمية العائمة على الشكل التالي: ما العناصر اللازمة لتنفيذ الوفرة العالية هناك عدة عناصر يجب أخذها بعين الاعتبار لتنفيذ الوفرة العالية على أرض الواقع، حيث تعتمد الوفرة العالية على عدة عوامل لا تتوقف عند التطبيق البرمجي فحسب، كـ: البيئة: إن كانت جميع الخواديم موجودة في ذات المنطقة الجغرافية، فيمكن لكارثة طبيعية كالهزات الأرضية أو الفيضانات أن تقضي على النظام كاملًا، وبالتالي يكون من المهم توزيع الأنظمة المكرّرة البديلة على مراكز بيانات مختلفة ضمن مناطق جغرافية متباعدة أمرًا مهمًا لرفع نسبة الوفرة. العتاد الصلب: يجب أن تكون خواديم الوفرة العالية حصينة من الانقطاعات الكهربائية ومشاكل العتاد الصلب كأقراص التخزين وبطاقات الشبكة. العتاد البرمجي: يجب أن تكون البرمجيات وأنظمة التشغيل معدّة لمعالجة الأخطاء الطارئة التي قد تتطلب إعادة التشغيل على سبيل المثال. البيانات: يجب أن تأخذ أنظمة الوفرة العالية احتمالية فقدان البيانات نتيجة مشكلة ما بعين الاعتبار، ففقدان البيانات وأخطائها قد يحدث نتيجة عوامل مختلفة لا تتعلق بمشاكل الأقراص الصلبة فقط. الشبكة: الانقطاعات الطارئة غير المتوقّعة في اتصالات الشبكة تمثّل نقطة توقّف حرجة أخرى في أنظمة الوفرة العالية، ومن المهم تصميم الشبكة التي تخدم أنظمة الوفرة العالية بطريقة تضمن عدم خروجها عن الخدمة في حال حدوث مشكلة في إحدى نقاط التوقّف الحرجة. ما البرمجيات التي من الممكن استخدامها لإعداد أنظمة الوفرة العالية إن كلّ طبقة من طبقات أنظمة الوفرة العالية تحتاج متطلّبات مختلفة في البرمجيات والإعدادات. ولكنّ موازنات الأحمال تعدّ جزءًا ضروريًا على مستوى التطبيقات لإنشاء أي نظام وفرة عالية. يُعدّ برنامج (HAProxy (High Availability Proxy أحد الخيارات الشائعة لتوزيع الأحمال، حيث بإمكانه إدارة توزيع الأحمال على عدّة طبقات، ولمختلف أنواع الخواديم، بما في ذلك خواديم مراكز البيانات. وبالانتقال إلى الأعلى في طبقات النظام، فإنّ من المهم تنفيذ حل معتمد انطلاقًا من المدخل، وهو موازن الأحمال عادة. ولإلغاء نقطة توقّف حرجة كما ذكرنا سابقًا، نحتاج لتنفيذ عنقود مشكّل من موازنات الأحمال التي تستخدم العناوين الرقمية العائمة. يُعدّ كلّ من Corosync و Pacemaker خيارين شائعين لتنفيذ هذا الغرض، ويتوفّران على خواديم Ubuntu و CentOS. الخلاصة إن الوفرة العالية أمرٌ هام، تركّز على ضمان امتلاك النظام أو أحد العناصر لقدرة تشغيل عالية في فترة من الزمن. وقد يبدو تنفيذها للوهلة الأولى أمرًا معقّدًا، ولكنّها تؤمن فوائد كبيرة للأنظمة التي تتطلب اعتمادية متزايدة. ترجمة -وبتصرّف- للمقال What is High Availability لصاحبته Erika Heidi.
-
يُعدّ محرك قواعد بيانات MongoDB أحد أشهر محرّكات قواعد بيانات NoSQL، ويشتهر بمرونته وقابليته للتوسعة وقوّته ومدى اعتماديّته وسهولة استخدامه. سنتحدث في المقال عن كيفية إجراء نسخ احتياطي واستعادة نسخة احتياطية ونقل قاعدة بيانات MongoDB. عند الحديث عن الاستيراد والتصدير في MongoDB فالمقصود التعامل مع البيانات بصيغة مقروءة من قبل البشر، ومتوافقة مع باقي المنتجات البرمجية. بالمقابل، فإن عمليات النسخ الاحتياطي واستعادة النسخ الاحتياطية تُنشئ أو تَستخدم نمط بيانات ثنائية binary خاصّة بـ MongoDB، وتحافظ بالتالي على تناسق وسلامة البيانات إضافة إلى سمات MongoDB الخاصة. بناء على ما سبق، فإنّه من المفضّل استخدام النسخ الاحتياطي عند الحاجة لتهجير migration قاعدة البيانات طالما أن هناك توافقية ما بين النظام المصدر والنظام الهدف. المتطلبات الأولية قبل أن نتابع، يرجى التأكّد من توفر المتطلبات التالية بشكل كامل: نظام تشغيل Ubuntu، مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر sudo. يمكن مراجعة مقال الإعداد الابتدائي لخادوم أوبنتو 14.04 لمزيد من المعلومات، تثبيت وإعداد MongoDB. وعدا عمّا قد يستثنى بوضوح، فإنّ جميع الأوامر التي تحتاج لصلاحيات مدير نظام root في المقال، يجب أن يتم تنفيذها من قبل مستخدم عادي يملك صلاحيات sudo. نسخة قاعدة بيانات MongoDB تجريبية، ويمكن الحصول على واحدة وتثبيتها وفق التعليمات المذكورة في مقال استيراد وتصدير قاعدة بيانات MongoDB في نظام أوبنتو 14.04. تنبيه: يجب تنفيذ جميع الأوامر المذكورة في المقال بصلاحيات المستخدم العادي من خلال أمر sudo ويستثنى من ذلك ما يذكر صراحة أن يتم تنفيذه وفق صلاحيات مدير النظام root. فهم الأساسيات سنحتاج لفهم بعض الأمور قبل أن نتابع أكثر في المقال، وإن كنت تملك بعض الخبرة مع قواعد البيانات العلائقية relational المشهورة مثل MySQL، فربّما تجد بعض التشابه عند العمل مع MongoDB. إنّ أول ما تحتاج معرفته حول MongoDB هو أنها تستخدم صيغتي json و bson (الصيغة الثنائية binary من json) بغرض تخزين المعلومات. إنّ Json هي صيغة مقروءة من قبل البشر وبالتالي مناسبة جدًا لتصدير واستيراد البيانات في نهاية الأمر، ومن الممكن أيضًا التعديل على البيانات المصدّرة باستخدام أيّ أداة تدعم json، بما في ذلك أي محرر نصوص بسيط. يبدو أحد الأمثلة عن مستند json على الشكل التالي: {"address":[ {"building":"1007", "street":"Park Ave"}, {"building":"1008", "street":"New Ave"}, ]} إنّ Json مناسبة جدًا للعمل معها، لكنها لا تدعم جميع أنماط البيانات المتاحة في bson، وهذا يعني بأنّه سيكون لدينا "فقدان في الدقّة" في البيانات عند استخدام json، ولهذا السبب فإنّه من الأفضل استخدام الصيغة الثنائية bson في حالة النسخ الاحتياطي والاستعادة لأنّها ستساعد في استعادة قاعدة بيانات MongoDB بشكل أدق. ثانيًا، ليس هناك داعٍ للقلق حول إنشاء قاعدة البيانات إن لم تكن موجودة أصلًا عند القيام باستعادة نسخة احتياطية، حيث سيتم إنشاؤها بشكل تلقائي. إضافة لذلك، فإنّ هيكل المجموعات collections (التي تُقابل الجداول) في القاعدة -بخلاف محركات قواعد البيانات الأخرى- سيتم إنشاؤها أيضًا بشكل تلقائي عند إدراج insert أول سطر. ثالثًا، إن قراءة وإدراج كمّية كبيرة من البيانات في MongoDB، قد يستهلك مصادر النظام كقدرة المعالج، الذاكرة ومساحة التخزين بشكل كبير جدًا وهذه نقطة حساسة على اعتبار أن MongoDB تُستخدم عادة مع قواعد البيانات الكبيرة والبيانات الضخمة، والحل الأسهل لهذه المشكلة هو تنفيذ عمليات التصدير والنسخ الاحتياطي ليلًا. رابعًا، فقد يكون هناك مشكلة في تناسق البيانات إن كنت تملك خادوم MongoDB معرّض لضغط العمل باستمرار وبالتالي قد تتغير البيانات أثناء عملية التصدير، حيث لا يوجد حل بسيط لهذه المشكلة ولكن في نهاية المقال سنتحدث حول استنساخ البيانات replication. وعلى الرغم من أنه من الممكن استخدام وظائف الاستيراد والتصدير للحصول على نسخة احتياطية أو استعادتها، تبقى هناك طرق أفضل لتضمن دقة البيانات في قاعدة MongoDB، ومن هذه الطرق استخدام الأمر mongodump للحصول على نسخة احتياطية للبيانات، والأمر mongorestore لاستعادة نسخة احتياطية سابقة. الحصول على نسخة احتياطية لقاعدة بيانات MongoDB لنتحدث أولًا عن الحصول على نسخة احتياطية لقاعدة البيانات. يقوم المُعامل db-- في الأمر mongodump بتحديد اسم قاعدة البيانات التي نرغب بالحصول على نسخة احتياطية لها، فإن لم يتم تحديد اسم قاعدة البيانات، سيقوم الأمر بإنشاء نسخة احتياطية لجميع قواعد البيانات التي يديرها محرّك MongoDB. أما لتحديد مسار المجلّد الذي سيتم تخزين النسخ الاحتياطية فيه فنستخدم المُعامل out--. لنرى المثال التالي للحصول على نسخة احتياطية من قاعدة بيانات اسمها newdb ولتخزين النسخة في مجلد var/backups/mongobackups/. نصيحة: من الأفضل أن يتم تخزين كل نسخة احتياطية في مجلد فرعي يُسمّى بتاريخ اليوم الذي تم إنشاء النسخة الاحتياطية فيه، مثل var/backups/mongobackups/01-20-16/ (العشرون من كانون الثاني 2016). لنقم أولًا بإنشاء المجلد الرئيسي الذي سنقوم فيه بتخزين النسخ الاحتياطية لقواعد MongoDB التي نملكها، ونستخدم لذلك الأمر: $ sudo mkdir /var/backups/mongobackups ثم نقوم بإنشاء نسخة احتياطية بالأمر التالي: $ sudo mongodump --db newdb --out /var/backups/mongobackups/`date +"%m-%d-%y"` فإن تم تنفيذ الأمر بنجاح، سيظهر ما يشبه النتيجة التالية على الشاشة: 2016-01-20T10:11:57.685-0500 writing newdb.restaurants to /var/backups/mongobackups/01-20-16/newdb/restaurants.bson 2016-01-20T10:11:57.907-0500 writing newdb.restaurants metadata to /var/backups/mongobackups/01-20-16/newdb/restaurants.metadata.json 2016-01-20T10:11:57.911-0500 done dumping newdb.restaurants (25359 documents) 2016-01-20T10:11:57.911-0500 writing newdb.system.indexes to /var/backups/mongobackups/01-20-16/newdb/system.indexes.bson لاحظ في الأمر الذي قمنا بتنفيذه أننا أدرجنا الجزء التالي "date +"%m-%d-%y الذي يقوم بالحصول على تاريخ اليوم بشكل تلقائي، وبالتالي نحصل على نسخة احتياطية داخل مجلد فرعي /var/backups/mongobackups/01-20-16/، وهذا مناسب جدًا إن قمنا بجدولة الأمر ليتم تنفيذه بصورة اوتوماتيكية. عند الوصول إلى هذه المرحلة نكون قد حصلنا على نسخة احتياطية لقاعدة البيانات المسمّاة newdb في المسار /var/backups/mongobackups/01-20-16/newdb/، وتملك هذه النسخة جميع المعلومات اللازمة لاستعادة حالة القاعدة newdb في حال حصول مشكلة فيها. وكقاعدة عامة، يجب أن يتم الحصول على نسخ احتياطية بشكل دوري، على أساس نسخة احتياطية يومية مثلًا، ويستحسن أن يتم تنفيذ العملية في الوقت الذي يكون نشاط الخادوم أقل ما يمكن، وللقيام بذلك يمكن جدولة تنفيذ الأمر mongodump باستخدام cron حتى يتم تنفيذه بصورة دورية، مثلاً، الساعة 3:03 صباحًا من كل يوم. لتنفيذ ذلك سنقوم بفتح محرّر cron المسمّى crontab على الشكل التالي: $ sudo crontab -e ملاحظة: عندما يتم تنفيذ الأمر sudo crontab فإننا نقوم بتحرير المهام المجدولة الخاصة بحساب المستخدم مدير النظام root. إن هذا مستحسن لأنه في حال جدولة الأمر mongodump ليتم تنفيذه بصلاحيات مستخدم آخر فقد لا يتم التنفيذ بشكل صحيح وخصوصًا إن كانت إعدادات sudo تتطلب تأكيد الأمر بإدخال كلمة المرور. سنقوم في crontab بإدخال السطر التالي: 3 3 * * * mongodump --out /var/backups/mongobackups/`date +"%m-%d-%y"` لاحظ أننا لم نستخدم المعامل db-- في الأمر السابق لأننا نرغب بالحصول على نسخة احتياطية دورية لجميع القواعد التي نملكها. إن تنفيذ النسخ الاحتياطي الدوري سيؤدي مع الوقت إلى استهلاك مساحة التخزين على القرص الصلب، لذا فمن الأفضل أن يتم حذف النسخ الاحتياطية القديمة بصورة دورية أو خفض المساحة التي تستهلكها عبر ضغطها. لحذف النسخ الاحتياطية التي تم الحصول عليها قبل 7 أيام يمكن أن نستخدم الأمر التالي: $ find /var/backups/mongobackups/ -mtime +7 -exec rm -rf {} \; وكما في الأمر المُجدول السابق فمن الممكن التخلص من النسخ الاحتياطية القديمة بصورة دورية عبر تنفيذ الأمر قبل أمر النسخ الاحتياطي، ولأجل هذا سنقوم بإدراج السطر التالي في cron، والذي سيتم تنفيذه الساعة 3:01 صباحًا من كل يوم: 3 1 * * * find /var/backups/mongobackups/ -mtime +7 -exec rm -rf {} \; وبإتمام الخطوات السابقة نكون قد ضمنّا حلًا مناسبًا للنسخ الاحتياطي لقواعد بيانات MongoDB. استعادة نسخة احتياطية لقاعدة بيانات MongoDB إن استعادة نسخة احتياطية سابقة لقاعدة بيانات MongoDB (كالتي حصلنا عليها من الخطوة السابقة) تتم باستخدام الأمر mongorestore والذي يمكّنك من الحصول على نسخة مطابقة تمامًا لبيانات القاعدة كما كانت في لحظة إنشاء النسخة الاحتياطية، متضمنًا ذلك جميع الفهارس وأنماط البيانات، وهذه مسألة مفيدة جدًا إن رغبت بنقل قاعدة البيانات. ومتابعة من المثال السابق، لنرى كيف من الممكن استعادة نسخة احتياطية سابقة. سنقوم باستخدام المُعامل db-- مع الأمر mongorestore لتحديد القاعدة التي نرغب باستعادة النسخة الاحتياطية إليها، كما سنستخدم المُعامل drop-- كي نضمن أن يتم حذف القاعدة القديمة حتى تتم استعادة النسخة الاحتياطية إلى نسخة جديدة من القاعدة لا تحتوي أي مشاكل، وأخيرًا سنقوم بتحديد مسار النسخة الاحتياطية التي نرغب باستعادتها; سيظهر الأمر كاملًا على النحو التالي (لا تنس استبدال المسار بمسار النسخة الموجودة لديك والتي ترغب باستعادتها): $ sudo mongorestore --db newdb --drop /var/backups/mongobackups/01-20-16/newdb/ وسيظهر ما يشبه الخرج التالي على الشاشة في حال تنفيذ الأمر بالشكل الصحيح: 2016-01-20T10:44:47.876-0500 building a list of collections to restore from /var/backups/mongobackups/01-20-16/newdb/ dir 2016-01-20T10:44:47.908-0500 reading metadata file from /var/backups/mongobackups/01-20-16/newdb/restaurants.metadata.json 2016-01-20T10:44:47.909-0500 restoring newdb.restaurants from file /var/backups/mongobackups/01-20-16/newdb/restaurants.bson 2016-01-20T10:44:48.591-0500 restoring indexes for collection newdb.restaurants from metadata 2016-01-20T10:44:48.592-0500 finished restoring newdb.restaurants (25359 documents) 2016-01-20T10:44:48.592-0500 done وفي هذه الحالة نكون قد أنجزنا استعادة نسخة احتياطية للقاعدة على الخادوم ذاته. أمّا لو رغبنا بنقل البيانات من خادوم لآخر باستخدام نفس الطريقة، فكُل ما نحتاجه هو نسخ مجلد النسخة الاحتياطية /var/backups/mongobackups/01-20-16/newdb/ إلى الخادوم الجديد قبل تنفيذ أمر استعادة النسخة الاحتياطية على الخادوم الجديد. الخلاصة تعرّفنا في المقال على أساسيات إدارة بيانات قاعدة MongoDB فيما يخص النسخ الاحتياطي والاستعادة من نسخة احتياطية سابقة، ونقل قاعدة البيانات من خادوم لآخر. إن آلية النسخ المُتماثل للبيانات ليست مهمّة بغرض قابلية التوسعة فحسب، وإنما مهمّة للموضوع الذي نتحدث عنه الآن، حيث تسمح الآلية باستمرارية تشغيل خدمة MongoDB دون توقّف أو انقطاع من خلال خادوم MongoDB ثانوي بينما يتم استعادة نسخة احتياطية على الخادوم الرئيسي في حال حدوث خلل ما فيه. وتعتبر سجلّات التشغيل (operations log (oplog جزءًا من آلية النسخة المُتماثل، حيث تقوم هذه السجلّات بتخزين جميع العمليات التي قامت بتغيير البيانات، ومن الممكن استخدام هذا السجل -كما يستخدم السجل الثنائي binary log في MySQL- بغرض استعادة البيانات بعد آخر نسخة احتياطية. تذكّر بأن النسخ الاحتياطي عادة يتم في فترة متأخرة من الليل، فإن قررت استعادة نسخة احتياطية ليلًا (قبل أن تبدأ عملية النسخ الاحتياطي) فستفقد جميع البيانات الجديدة التي لم يتم الحصول على نسخة احتياطية لها أولًا. ترجمة -وبتصرّف- للمقال How To Back Up, Restore, and Migrate a MongoDB Database on Ubuntu 14.04 لصاحبه Anatoliy Dimitrov.
-
هل قمت من قبل باختيار قالب theme في ووردبريس وبدأت باستخدامه ومن ثم مع الوقت تفاجأت بأنّه غير مناسب للموقع؟ قد لا يكون استبداله في ذلك الوقت أمرًا ممكنًا بعد ما تمّ صرفه من وقت ومال في المشروع، فتجد نفسك عالقًا مع قالب كان من الأفضل لو اخترت واحد آخر عوضًا عنه. إنّ اختيار قالب أمرٌ مهمٌ كاختيار سيّارة، فمن السهل أن تنبهر بجمال وقوّة إحداها وينتهي بك الأمر بسيارة رياضيّة مكشوفة ذات مقعدين بينما ما تحتاجه حقًّا هو سيارة يُعتمد عليها بمقاعد مريحة تكفي لـ 5 أشخاص. لقد وجدت نفسي في هذا المأزق عدّة مرّات من قبل على الأقل، لكنّ التجربة والخطأ علّماني أن أضع نظامًا يعتمد على تحديد متطلبات المشروع وتقييمه ومقارنة القوالب المرشّحة للاختبار قبل أن أتخذ قرارًا. سأشرح الآلية التي أستخدمها عند اختيار قالب وكيف يمكن اعتمادها لزيادة فرص اختيار القالب الأمثل لمشروعك القادم باستخدام ووردبريس. يجب أن تعرف ما الذي تحاول بناءه تجنّب انتقاء قالب قبل أن تحدّد تمامًا ما الذي تحاول بناءه، فبالرغم من أنّ اختيار قالب يُعتبر أمرًا مشوّقًا، ولكنّ التخطيط لمحتوى الموقع هو الجزء الأهم والذي يتطلب أعلى انضباط في عملية بنائه. وحتى يكون موقع الويب مفيدًا، يجب أن نعير الاهتمام إلى اختيار المحتوى أوّلًا، وتحديد الهدف من الموقع، وهيكله العام، والنصوص والعناصر المرئيّة التي سنستخدمها في بنائه، قبل أن نبدأ التفكير باختيار قالب، ويساعد في هذا إنشاء قائمة بجميع ما ستتضمنه صفحات الموقع، وما ستحتويه كل صفحة. كن دقيقًا في التوصيف قدر الإمكان، فعلى سبيل المثال، إن كنت تقوم بإنشاء موقع لأغراض تجارية يحتوي على صفحة تعرض أهمّ موظّفي الشركة، فقد يكون توصيف الصفحة مثلًا: صفحة الموظّفين: الملفات الشخصية لـ 4 موظّفين في الإدارة التنفيذية. كل ملفّ سيتضمن صورة، وصفًا شخصيًّا يتراوح ما بين 125-150 كلمة، وأيقونة أو أكثر لشبكات التواصل الاجتماعي. يمكنك من خلال التوصيف السابق تحديد الميّزات التي ستحتاجها في القالب، ومن ثم عند بحثك عن قالب مناسب، عد لقائمة الميّزات التي قمت بتحديدها واختر القالب التي تدعم معظمها سلفًا، فهي النقطة الأهم في هذه الخطوة، لأنّ إساءة اختيار قالب هو وصفة مضمونة لترهق نفسك عندما تحاول تعديله ليتناسب مع أهدافك التي لم يُصمّم من أجلها أساسًا. إنّ العديد من القوالب المشهورة في فهرس قوالب ووردبريس، كـ Sydney، تعتمد بصورة أساسية على الصور ذات الحجم الكبير وهي مناسبة أكثر لتستخدم كمحفظة أعمال للمصمّمين والوكالات الفنّية، لذا تجنّب اختيار مثل هذه القوالب إن كنت تحاول إنشاء مدوّنة وابحث عن تلك التي صمّمت لتتناسب أكثر مع أغراض التدوين كـ Twenty Sixteen. وقد يُطرح سؤال هنا، هل نستطيع تعديل قالب كـ Sydney ليُصبح مناسبًا للاستخدام في مدوّنة؟ إن هذا ممكن بالطبع لكن ستستغرق الكثير من الوقت والجهد. يجب أن تعلم ما الذي تبحث عنه إنّ ميزانية المشروع والمدة الزمنية المخصصة له لهما الكلمة الفصل في مقدار الوقت الذي تستطيع صرفه في إنشاء الموقع، وهناك 3 فئات للقوالب التي يمكنك أخذها بعين الاعتبار اعتمادًا على متطلبات المشروع وعلى مقدار الوقت الذي يمكنك إمضاؤه بتحسين شكل الموقع النهائي. إن احتجت لبداية نظيفة فيمكنك استخدام قوالب أُطر العمل، كـ Genesis أو Thesis، أو Upfront، فهي منتجات تستطيع استخدامها لبناء أي نوع من المواقع بالاعتماد عليها. ومع بعض التمرّس، ستغدو قادرًا على إنشاء المواقع بسرعة باستخدام قالب إطار العمل المفضّلة لديك. ولكن إن كانت السرعة العامل الأهم، فقد يتوجب عليك تجنّب هذا الأمر والانتقال مباشرة إلى اختيار قالب صُمّم بناءً على إطار العمل الذي تستخدمه لمشروعك، فهناك العديد من القوالب التي تتناسب مع مختلف أنواع المشاريع والتي لا تحتاج إلّا إلى تعديلات قليلة، كالمذكورة سابقًا Sydney أو بناء قالب اعتمادًا على إطار عمل القوالب المُفضّل لديك. أخيرًا، إن لم تكن ترغب ببناء قالب من الصفر باستخدام باستخدام إطار عمل، ولم تتمكن من إيجاد قالب يتناسب تمامًا مع مشروعك، فيمكنك اختيار قالب مصمّم ليكون من السهل التعديل عليه، حيث أنّ هذا الكلام قد ينطبق على القوالب المصمّمة المبنية اعتمادًا على أُطر العمل ولكنه غير صحيح مع القوالب المستقلّة فالبعض منها من السهل تعديله لكنّ الأغلب يصعب معه ذلك دون الوقوع في مشاكل، وسنتناول الحديث عن الطرق التي يمكن اتباعها للتعديل على القوالب في نهاية المقال إن أردت السير في هذا الطريق. تجاهل المحتوى التجريبي عندما ترغب ببناء موقع فإنه لديك مجموعة من المحتويات التي ستستخدمها فيه وستكون مجبرًا على انتقاء الصور، الأشكال، الفيديوهات والنصوص بعناية، حيث سيكون هناك هدف لكل عنصر سيستخدم في الموقع، لكنّ مصمّم القوالب لا يواجه هذه المشكلة فهدفه النهائي هو إغراؤك لاقتناء القالب الخاص به وبالتالي سيعمل على استخدام معظم المزايا المتاحة له ويغرق الموقع بالمحتوى التجريبي demo content ونصوص lorem ipsum والصور الرمزية وما شابه ذلك. لذا وأنت تبحث تأكّد من أن تتجاهل المحتوى المؤقت المستخدم في القالب وركّز على مقدار مناسبتها لمتطلبات مشروعك. انتبه جيدا إلى المزايا التي يقدمها القالب من المهم الانتباه جيّدًا إلى المزايا المقدّمة من القالب (وليس إلى المحتوى التجريبي كما ذكرنا سابقًا)، وبالعودة إلى المثال السابق حول صفحة موظّفي الشركة، ألق نظرة على القالب التي تستعرضه وتأكّد من أنه يُلبّي احتياجك من حيث إنشاء ملفات شخصية بسهولة؟ Zerif Lite هو أحد القوالب الخاصة بـووردبريس والذي يتضمن ميّزة تفيد في هذا الغرض: إنّ بعض أهم عناصر القوالب التي يجب الانتباه إليها تتضمن: شكل قوائم تصفّح الموقع: ستملك عناصر التصفّح درجة من المرونة، لكن تأكّد من أن تصميمها يلبّي احتياجك. فإن احتجت لقوائم كبيرة mega menus فإنشاؤها سيكون أسهل بكثير إن اخترت قالبًا يدعم هذا النوع من القوائم. كيف يتم عرض شعار الشركة: إن كنت تملك شعارًا وعبارة تسويقية فتأكد بأنّهما يتناسبان مع المواقع والأحجام التي تفرضها القالب. تأكّد إن كانت الميّزات مقدّمة من القالب ذاته أو باستخدام مُلحقات plugins: من الأفضل أن تكون الميّزات مقدّمة من إضافات، فحينها ستستطيع المحافظة على معظم المزايا إن قررت تغيير القالب، وبحديثنا عن القوائم الكبيرة mega menus فمن الأفضل أن تستخدم القالب إضافة Max Mega Menu عوضًا عن إدراج الميّزة ضمن تصميم القالب الداخلي. مدى سهولة التعديل على القالب: فهل تفضّل العمل مع محرر مرئي مثل Visual Composer أو محرر Upfront Editor، أو تفضّل كتابة شيفرات CSS يدويًا للتعديل على مظهر الموقع؟ إن كنت تفضّل العمل بطريقة معينة فتأكد من أن القالب تتطابق مع اختيارك، وإحدى الأخطاء التي يجب تجنّبها هي كتابة شيفرات CSS بشكل يدوي في موقع يستخدم محررًا مرئيًّا. احصل على رأي غير منحاز حالما تستقر على مجموعة من القوالب التي تتناسب مع متطلبات مشروعك ومزاياه، فهناك مجموعة من الاختبارات التي تستطيع إجراءها لمقارنة الأداء فيما بينها. إحدى هذه الاختبارات هو إخضاع نسخة تجريبية demo من الموقع لاختبار Pingdom’s Website Speed Test. لا تقلق كثيرًا في البداية حول زمن التنفيذ أو حجم الصفحة إلّا إن ظهرت لك نتائج تنذر بسوء، فزمن التنفيذ يمكن أن يختلف كلّيًا بحسب الاستضافة وطريقة إعدادها والمكان الجغرافي للخادوم، كما يتعلق بالخبء المؤقت (cache) وضغط الصفحات minifying المطبّق على الموقع. إنّ حجم الصفحة للنسخة التجريبية غالبًا ما يكون ناتجًا عن كون النسخة متخمة بالصور والفيديوهات عالية الدقة، لذا فإنّ البيانات الأهم التي يجب الانتباه إليها في هذه المرحلة هي عدد طلبات HTTP التي تظهر والمرتبة النهائية للأداء التي نحصل عليها. إن وجدت بأنّ القالب التي اخترته لا يملك نتائج جيّدة عند تطبيق هذا الاختبار، فاعتبر هذا تحذيرًا بأنّك بحاجة لاختيار إضافة جيّدة للخبء مؤقت وضغط المحتوى كـ Hummingbird عوضًا عن رفض القالب ككل. إنّ أفضل طريقة لاستخدام النتائج أثناء التقييم هو المقارنة فعلى سبيل المثال إن اخترت استخدام Zerif Lite أو OnePress اعتمادًا على النتائج فيمكن منح نقطة إضافية لصالح OnePress على الرغم من أنّ القالبين يملكان نتائج جيّدة متقاربة. ومن الإضافات المناسبة أيضًا للاختبار هي Google PageSpeed Insights، ومرّة أخرى نذكّر بأنّه ليس هناك معيار نتائج معيّن نبحث عنه، حيث يجب اختبار جميع القوالب التي نفضّلها ونأخذ بعين الاعتبار النتائج التي نحصل عليها. يمكن أثناء تنفيذ هذا الاختبار أن نحدّد المشاكل التي تعاني منها القالب التي نختارها في نهاية المطاف ونحاول معالجتها. معاينة الخلفية آخر ما تحتاج للقيام به هو الحصول على بعض المعلومات عمّا سيكون عليه العمل مع القالب، فالعديد منها تسمح بالاطلاع على اللوحة الإدارية، لذا خذ بعض الوقت لإلقاء نظرة وفهم ما سيكون عليه الأمر عندما تعمل معها فإن احتوت على محرّر سحب وإفلات مرئي لعناصر الموقع فخذ بعض الوقت في تجربة ذلك لترى كيف يختلف المظهر الخارجي. أما لو كنت ستقوم بكتابة شيفرات CSS خاصة للتعديل على مظهر القالب فقم باستعراض ملفات CSS التي تستخدمها باستخدام أدوات المطوّر. إن الهدف هو معرفة كم سيكون سهلًا أو صعبًا التعديل على الموقع. هاك بعض الأمور التي تحتاج للتركيز عليها أثناء ذلك: كم عدد أسطر CSS المستخدمة: إنه من غير المستبعد أن تمتلك قالب ما بين مئات لعدة آلاف الأسطر من CSS، وعلى الرغم من أنّها ليست قاعدةً أساسية، فإنّه من الأسهل عادة التعديل يدويًا على شيفرات CSS في القوالب التي تستخدم أقلّ عدد ممكن من قواعد CSS. كم عدد ملفات CSS المستخدمة: معظم القوالب تستخدم قواعد CSS موزّعة على عدّة ملفات، وعلى الرغم من ذلك، فلو أردت القيام بتعديلات يدوية، فكلّما قلّ عدد الملفات كلّما كان ذلك أفضل، فالملفّات الأقل إشارة إلى هيكلة منظّمة أكثر وأسهل للتعديل. كم عدد المرّات التي استخدمت فيها قاعدة !important: رغم أنه من المتوقع نظريًّا أن تقوم معظم القوالب بتجاوز override القواعد الموروثة في CSS بين العناصر عدّة مرات، إلا أنّه في حال وجدت بأن السمة تستخدم هذه القاعدة بضع مئات من المرّات فتوقّع أن يكون التعديل اليدوي عليها أمرًا صعبًا. إن إحدى الطرق التي يمكنك اتباعها لتحديد مدى سهولة التعديل اليدوي على قواعد CSS هي باختيار أحد العناصر الذي ترغب بتعديله ومن ثم تستخدم لوحة المظهر في أدوات المطوّر لتقوم بالتعديل على مظهر العنصر مباشرة وترى مدى سهولة القيام بذلك. الخلاصة تحدّثنا عن العديد من الأمور الواجب مراعاتها عند انتقاء قالب، ولتلخيص ما سبق: نحدّد المحتوى أوّلًا ومن ثم التصميم: ابدأ بتحديد المحتوى وعناصره التي ستستخدمها وسيكون من الأسهل اختيار القالب. حدّد نوع القالب التي تبحث عنه: إطار عمل قوالب، قالب متعدّدة الأغراض للاستخدام كما هو، قالب معدّل. قارن أداء القوالب المرشّحة باستخدام الاختبارات التي ذكرناها. جرّب استخدام المحرّر المرئي المستخدم ضمن القالب أو إطار العمل، أو قم بالاطلاع على قواعد CSS التي تستخدمها القالب إن لم تملك محرّرًا مرئيًّا مدمجًا معها. يجب أن تكون قادرًا الآن على اختيار قالب إطار العمل أو القالب المناسب لمشروعك القادم. كيف تقوم باختيار القوالب لمشاريعك عادة؟ هل هناك معايير أخرى تعتمدها في اختيارها؟ أخبرنا في التعليقات أدناه. ترجمة -وبتصرّف- للمقال How to Pick the Perfect WordPress Theme لصاحبه Jon Penland.
- 2 تعليقات
-
- wordpress
- قوالب ووردبريس
-
(و 3 أكثر)
موسوم في:
-
يُعدّ MongoDB أحد أشهر محركات قواعد البيانات من نوع NoSQL، فهو شهير بمرونته، فعاليّته، موثوقيته وسهولة استخدامه، وسنستعرض في المقال كيفية استيراد وتصدير قواعد بيانات MongoDB. تجدر الإشارة إلى أنّه عند حديثنا عن الاستيراد والتصدير فالمقصود التعامل مع البيانات بصيغة مقروءة من قبل البشر، ومتوافقة مع باقي المنتجات البرمجية. بالمقابل، فإن عمليات النسخ الاحتياطي واستعادة النسخ الاحتياطية تُنشئ أو تَستخدم نمط بيانات ثنائية binary خاصّة بـ MongoDB، وتحافظ بالتالي على تناسق وسلامة البيانات إضافة إلى سمات MongoDB الخاصة. بناء على ما سبق، فإنّه من المفضّل استخدام النسخ الاحتياطي عند الحاجة لنقل/تهجير migration قاعدة البيانات طالما أن هناك توافقية ما بين النظام المصدر والنظام الهدف، وهذا الموضوع خارج إطار حديثنا. المتطلبات الأولية قبل أن نتابع، يرجى التأكّد من توفر المتطلبات التالية بشكل كامل: نظام تشغيل Ubuntu 14.04، مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر sudo. يمكن مراجعة الإعداد الابتدائي لخادوم أوبنتو 14.04 لمزيد من المعلومات، تثبيت وإعداد MongoDB. وعدا عمّا قد يستثنى بوضوح، فإنّ جميع الأوامر التي تحتاج لصلاحيات مدير نظام root في المقال، يجب أن يتم تنفيذها من قبل مستخدم عادي يملك صلاحيات sudo. فهم الأساسيات سنحتاج لفهم بعض الأمور قبل أن نتابع المقال، وإن كنت تملك بعض الخبرة مع قواعد البيانات العلائقية relational المشهورة مثل MySQL، فربّما تجد بعض التشابه عند العمل مع MongoDB. إنّ أول ما تحتاج معرفته حول MongoDB هو أنها تستخدم صيغتي json و bson (الصيغة الثنائية binary من json) بغرض تخزين المعلومات. إنّ Json هي صيغة مقروءة من قبل البشر وبالتالي مناسبة جدًا لتصدير واستيراد البيانات في نهاية الأمر، ومن الممكن أيضًا التعديل على البيانات المصدّرة باستخدام أيّ أداة تدعم json، بما في ذلك أي محرر نصوص بسيط. يبدو أحد الأمثلة عن مستند json على الشكل التالي: {"address":[ {"building":"1007", "street":"Park Ave"}, {"building":"1008", "street":"New Ave"}, ]} إنّ Json مناسبة جدًا للعمل معها، لكنها لا تدعم جميع أنماط البيانات المتاحة في bson، وهذا يعني بأنّه سيكون لدينا "فقدان في الدقّة" في البيانات عند استخدام json، ولهذا السبب فإنّه من الأفضل استخدام الصيغة الثنائية bson في حالة النسخ الاحتياطي والاستعادة لأنّها ستساعد في استعادة قاعدة بيانات MongoDB بشكل أدق. ثانيًا، ليس هناك داعٍ للقلق حول إنشاء قاعدة البيانات إن لم تكن موجودة أصلًا عند القيام باستعادة نسخة احتياطية، حيث سيتم إنشاؤها بشكل تلقائي. إضافة لذلك، فإنّ هيكل المجموعات collections (التي تُقابل الجداول) في القاعدة -بخلاف محركات قواعد البيانات الأخرى- سيتم إنشاؤها أيضًا بشكل تلقائي عند إدراج insert أول سطر. ثالثًا، إن قراءة وإدراج كمّية كبيرة من البيانات في MongoDB، قد يستهلك مصادر النظام كقدرة المعالج، الذاكرة ومساحة التخزين بشكل كبير جدًا وهذه نقطة حساسة على اعتبار أن MongoDB تُستخدم عادة مع قواعد البيانات الكبيرة والبيانات الضخمة، والحل الأسهل لهذه المشكلة هو تنفيذ عمليات التصدير والنسخ الاحتياطي ليلًا. رابعًا، فقد يكون هناك مشكلة في تناسق البيانات consistency إن كنت تملك خادوم MongoDB معرّض لضغط العمل باستمرار وبالتالي قد تتغير البيانات أثناء عملية التصدير، حيث لا يوجد حل بسيط لهذه المشكلة ولكن في نهاية المقال سنتحدث حول استنساخ البيانات replication. استيراد المعلومات إلى قاعدة بيانات MongoDB لنتعلّم كيفية استيراد المعلومات إلى قاعدة بيانات MongoDB، سنقوم باستخدام عيّنة قاعدة بيانات معروفة حول المطاعم. إنّ القاعدة بصيغة json ويمكن تحميلها باستخدام الأمر wget بالشكل التالي: $ wget https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/primer-dataset.json وحالما ينتهي التحميل ستحصل على ملف حجمه 12 ميغابايت يُدعى primer-dataset.json في المجلّد الذي قمت بتنفيذ الأمر فيه. سنقوم باستيراد البيانات من هذا الملف إلى قاعدة بيانات جديدة سنسمّيها newdb وضمن جدول سنسمّيه restaurants. للقيام بعملية الاستيراد سنستخدم الأمر mongoimport على الشكل التالي: $ sudo mongoimport --db newdb --collection restaurants --file primer-dataset.json ويُفترض أن تكون نتيجة تنفيذ الأمر السابق على الشكل التالي: 2016-01-17T14:27:04.806-0500 connected to: localhost 2016-01-17T14:27:07.315-0500 imported 25359 documents وكما يظهر في الناتج السابق، فقد تم استيراد 25359 مستند، ولأننا لم نكن نملك قاعدة بيانات باسم newdb، فقد قام محرّك MongoDB بإنشائها بشكل تلقائي، وللتأكّد من نجاح عملية الاستيراد سنقوم بالاتصال بقاعدة البيانات newdb على الشكل التالي: $ sudo mongo newdb سنلاحظ عند تنفيذ الأمر بأن شكل مِحرف سطر الأوامر قد تغيّر، مما يشير إلى نجاح الاتصال بقاعدة البيانات، وللتحقق الآن من عدد المستندات التي تم استيرادها، سنقوم بتنفيذ الأمر التالي: > db.restaurants.count() ويفترض أن تكون النتيجة 25359، وهو مطابق تمامًا لعدد المستندات المستوردة. وللتحقق بشكل أفضل من نجاح الاستيراد، سنقوم باختيار المستند الأول من مجموعة المطاعم بتنفيذ الأمر التالي: > db.restaurants.findOne() وينبغي أن تكون النتيجة على الشكل التالي: { "_id" : ObjectId("569beb098106480d3ed99926"), "address" : { "building" : "1007", "coord" : [ -73.856077, 40.848447 ], "street" : "Morris Park Ave", "zipcode" : "10462" }, "borough" : "Bronx", "cuisine" : "Bakery", "grades" : [ { "date" : ISODate("2014-03-03T00:00:00Z"), "grade" : "A", "score" : 2 }, ... ], "name" : "Morris Park Bake Shop", "restaurant_id" : "30075445" } إنّ مثل هذا التحقق قد يظهر أيّ مشاكل في محتوى المستندات أو ترميزها أو ما شابه ذلك، فصيغة json تستخدم ترميز UTF-8 ويجب أن تكون البيانات المصدّرة والمستوردة بهذا الترميز. تذكّر هذا الأمر دومًا عند القيام بتحرير ملفات json بشكل يدوي، وفيما عدا ذلك فإنّ محرك MongoDB سيتولّى الأمر عنك بشكل تلقائي. أخيرًا، للخروج من سطر أوامر MongoDB نقوم بتنفيذ الأمر exit على الشكل: > exit وسيتم الخروج والعودة إلى سطر أوامر النظام كمستخدم عادي. تصدير المعلومات من قاعدة بيانات MongoDB كما ذكرنا سابقًا، فإنّه من الممكن الحصول على بيانات مقروءة ومفهومة عند القيام بتصدير المعلومات من قاعدة MongoDB، وتكون صيغة الملف المصدّر بشكل افتراضي هي json، ولكن من الممكن أيضًا الحصول على البيانات في ملف بصيغة (csv (comma separated value. نستخدم الأمر mongoexport لتصدير البيانات من قاعدة MongoDB، ويسمح أمر التصدير باختيار قاعدة بيانات، مجموعة من المجموعات collection، حقل من الحقول، وحتّى استخدام استعلام من أجل التصدير. وكمثال بسيط على أمر التصدير mongoexport، سنقوم بتصدير مجموعة المطاعم من قاعدة newdb التي قمنا باستيرادها سابقًا، ويبدو الأمر على النحو التالي: $ sudo mongoexport --db newdb -c restaurants --out newdbexport.json حيث قمنا في الأمر السابق باستخدام المُعامل db-- لتحديد القاعدة، والمُعامل c- لتحديد المجموعة، والمُعامل --out لتحديد اسم الملف الذي سيتم تصدير البيانات إليه، وستكون نتيجة تنفيذ الأمر السابق بشكل ناجح على النحو التالي: 2016-01-20T03:39:00.143-0500 connected to: localhost 2016-01-20T03:39:03.145-0500 exported 25359 records ويظهر الأمر السابق أنه قد تم تصدير 25359 مستند، وهو مماثل تمامًا لعدد المستندات التي قمنا باستيرادها سابقًا. قد نحتاج في بعض الأحيان إلى تصدير جزء من مجموعة، وبالأخذ بعين الاعتبار هيكل ومحتوى مستند المطاعم بصيغة json، سنقوم بتصدير معلومات جميع المطاعم التي تحقق الشرط الذي يقول بأنها موجودة في المنطقة الإدارية المسمّاة Bronx والتي تقدّم الطعام الصيني. للحصول على هذه المعلومات بشكل مباشر في حال كنّا متصلين بقاعدة MongoDB من خلال سطر أوامر MongoDB، فسنقوم بالاتصال بقاعدة البيانات مجددًا: $ sudo mongo newdb ومن ثم سنستخدم الاستعلام: > db.restaurants.find( { borough: "Bronx", cuisine: "Chinese" } ) وسيتم عرض النتيجة مباشرة، وللخروج من سطر أوامر MongoDB سننفّذ الأمر exit كما ذكرنا سابقًا. أمّا لتصدير البيانات من سطر أوامر النظام دون أن نكون متصلين بقاعدة البيانات مسبقًا، فسنقوم بتمرير الاستعلام السابق كمُعامل لأمر mongoexport باستخدام المُعامل q- على الشكل التالي: $ sudo mongoexport --db newdb -c restaurants -q "{ borough: 'Bronx', cuisine: 'Chinese' }" --out Bronx_Chinese_retaurants.json لاحظ في الأمر السابق بأنّا قمنا باستخدام علامات الاقتباس الفرديّة ' داخل علامات الاقتباس الزوجيّة " لأنّ هذا شرط من شروط كتابة الاستعلام في سطر الأوامر، ولو احتجنا لاستخدام علامات اقتباس زوجيّة أو إشارة $ فسنحتاج لتخطي المحارف الخاصة باستخدام \ بإدراجها قبل المحرف الخاص في الاستعلام. إن تمت عملية التصدير بنجاح فينبغي أن تكون النتيجة على الشكل التالي: 2016-01-20T04:16:28.381-0500 connected to: localhost 2016-01-20T04:16:28.461-0500 exported 323 records تُظهر النتيجة السابقة بأنّ هناك 323 سجل قد تم تصديره، ويمكن إيجادها ضمن ملف Bronx_Chinese_retaurants.json الذي قمنا بتحديده. الخلاصة تعرفّنا في المقال على أساسيات استيراد وتصدير المعلومات من وإلى قاعدة بيانات MongoDB. إنّ عملية الاستنساخ replication مفيدة في حالة التوسعة، ولكنّها مهمة أيضًا للنواحي التي تحدثنا عنها، حيث تسمح باستمرارية تشغيل خدمات MongoDB دون انقطاع عبر خادوم MongoDB ثانوي بينما نقوم باستعادة نسخة احتياطية إلى الخادوم الرئيسي عند حدوث فشل. إن جزءًا من عملية الاستنساخ هو سجل العمليات (oplog)، الذي يقوم بتسجيل جميع العمليات التي تقوم بتغيير البيانات، ويمكن استخدام هذا السجل كما في MySQL، لاستعادة البيانات بعد أن تكون آخر عملية نسخ احتياطي قد بدأت. تذكّر بأن عمليات النسخ الاحتياطي تحصل في الليل عندما يكون نشاط قاعدة البيانات في حدّه الأدنى، وإن قررت استعادة نسخة احتياطية لقاعدة البيانات في الفترة المسائية (أي قبل أن تبدأ عملية النسخ الاحتياطي الليلية) فإنّك ستفقد بذلك جميع التعديلات التي تمت على القاعدة منذ آخر عملية نسخ احتياطي. ترجمة -وبتصرّف- للمقال How To Import and Export a MongoDB Database on Ubuntu 14.04 لصاحبه Anatoliy Dimitrov.
-
يُعدّ Nginx خادوم ويب مفتوح المصدر يتسّم بالسرعة والاعتمادية، كسب شعبيّته نتيجة حجم الذاكرة القليل الذي يستهلكه، وقابليته الكبيرة للتوسعة، وسهولة إعداده، ودعمه لمعظم البروتوكولات المختلفة. ويعتبر بروتوكول HTTP/2 الجديد نسبيًا أحد البروتوكولات التي يدعمها خادوم Nginx، الأمر الذي تم منذ أقل من عام مضى، وتعتبر الميّزة الرئيسية في HTTP/2 هي سرعة نقله العالية للمحتويات الغنيّة بالمعلومات في مواقع الويب. سيساعد المقال على تثبيت وإعداد خادوم Nginx سريع وآمن مع دعم لبروتوكول HTTP/2. المتطلبات الأولية قبل أن نبدأ، سنحتاج للأمور التالية: نظام تشغيل Ubuntu 14.04، مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر sudo. يمكن مراجعة الإعداد الابتدائي لخادوم أوبونتو 14.04 لمزيد من المعلومات، نطاق موقع، ويمكن شراء واحد من موقع Namecheap أو الحصول على واحد مجانًا من موقع Freenom، تأكّد من أنّ النطاق يشير إلى عنوان نظام التشغيل الذي ستستخدمه عبر الإنترنت، وستساعدك مقالة إعداد اسم مضيف مع DigitalOcean إن احتجت لمساعدة، شهادة SSL رقميّة، ويمكن إنشاء واحدة بشكل يدوي، أو الحصول على واحدة مجانًا من Let’s Encrypt، أو شراء واحدة من مزوّد آخر. هذا كل شيء، فإن كانت لديك جميع المتطلبات المذكورة، فأنت جاهز للبدء. الفرق ما بين HTTP 1.1 و HTTP/2 إن HTTP/2 هو الإصدار الجديد من بروتوكول نقل النصوص الفائقة HTTP، الذي يستخدم على الشبكة العنكبوتية لإيصال محتويات صفحات الويب من الخوادم إلى المتصفّحات، وهو أول تحديث ضخم طرأ على HTTPمنذ حوالي عقدين، حيث تم إطلاق الإصدار HTTP 1.1 عام 1999 حينما كانت الصفحات عبارة عن ملف HTML مستقل مع أنماط CSS ضمنيّة (أي مكتوبة ضمن مستند HTML وليست مستوردة من ملف خارجي). لقد تغيّرت شبكة الإنترنت بشكل متسارع في السنوات الستة عشر الأخيرة، وأصبحنا الآن نواجه صعوبة مع المحدودية التي يفرضها HTTP 1.1، حيث يَحُدّ البروتوكول من سرعة النقل الممكنة لمعظم مواقع الويب الحديثة لأنه يقوم بتحميل أجزاء الصفحة وفق مبدأ الطابور queue (بمعنى أنه يجب أن ينتهي تحميل كل جزء قبل أن يبدأ تحميل الجزء التالي له)، ويحتاج موقع ويب حديث وسطيًّا حوالي 100 طلب ليتم تحميل الصفحة(كل طلب يمثّل صورة، ملف js، ملف css، إلخ). يقوم بروتوكول HTTP/2 بحل هذه المشكلة لأنّه يقوم بتقديم تغييرات جذرية تتمثل في: تحميل جميع الطلبات على التوازي، وليس على التسلسل كما في مبدأ الطابور، ضغط ترويسة HTTP، نقل الصفحات عبر الشبكة بصيغة ثنائية binary، وليس كنصوص text، وهذا أكثر فعالية، قدرة الخادوم الآن على "دفع" البيانات قبل أن يطلبها المستخدم، مما سيحسّن من السرعة للمستخدمين الذين يعانون من بطء في الإرسال. وعلى الرغم من أن بروتوكول HTTP/2 لا يتطلب التشفير، إلا أن مطوّري أشهر متصفّحين، Google Chrome و Mozilla Firefox، صرّحوا بأنه -لدواع أمنيّة- سيتم دعم بروتوكول HTTP/2 في اتصالات HTTPS الآمنة فقط، ولهذا السبب إن قررت تثبيت خواديم تدعم HTTP/2 فيجب عليك الانتقال إلى استخدام HTTPS. الخطوة الأولى: تثبيت الإصدار الأخير من Nginx تم طرح دعم HTTP/2 في إصدار Nginx 1.9.5، ولسوء الحظ فإنّ المستودع الافتراضي في نظام Ubuntu متأخر عن إدراج آخر إصدار ويقوم حاليًّا بتوفير الإصدار 1.4.6. لكن لحسن الحظ فإن مطوّري Nginx لديهم مستودع apt خاص على نظام Ubuntu، حيث بالإمكان الحصول دومًا على آخر إصدار متوفّر. لإضافة المستودع الخاص إلى قائمة مستودعات apt لدينا، نحتاج أولًا للحصول على مفتاح التوقيع الرقمي الخاص بالمستودع، وهذا إجراء أمني يضمن بأن الحزم البرمجية التي سنحصل عليها من هذا المستودع صادرة عن المطوّرين الحقيقين وموقّعة منهم. سنقوم بتنفيذ الأمر التالي في سطر الأوامر: $ wget -qO - http://nginx.org/keys/nginx_signing.key | sudo apt-key add - بعد ذلك، سنقوم بإضافة المستودع إلى قائمة مصادر الحزم البرمجية، بتنفيذ الأمر التالي: $ sudo echo -e "deb http://nginx.org/packages/mainline/ubuntu/ `lsb_release -cs` nginx\ndeb-src http://nginx.org/packages/mainline/ubuntu/ `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list الآن وبعد أن أصبح نظام الحزم (الذي يدعى apt في نظامي Ubuntu و Debian) يعلم عن توفّر المستودع الجديد، سنقوم بتحديث قائمة الحزم البرمجية المتوفّرة وأخيرًا سنقوم بتثبيت الإصدار الأخير من Nginx: $ sudo apt-get update $ sudo apt-get install nginx ويمكن التحقق من رقم الإصدار بتنفيذ الأمر: $ sudo nginx -v حيث ينبغي أن يكون الخرج مشابهًا لـ nginx version: nginx/1.9.x. سنقوم في الخطوات التالية بتغيير الإعدادات الافتراضية في Nginx ليقوم بتخديم موقع الويب الخاص بنا. الخطوة الثانية: تغيير منفذ التنصّت الافتراضي سنقوم أولًا بتغيير رقم المنفذ من 80 إلى 443، وذلك بفتح ملف الإعدادات: $ sudo nano /etc/nginx/conf.d/default.conf ملاحظة: في حال ظهر خطأ يخبرك بأنه لم يتم التعرّف على الأمر nano، فتأكّد من تثبيت محرر النصوص nano وحاول مجدّدًا. ينبغي أن نخبر Nginx برقم المنفذ الذي يجب عليه تلقّي الاتصالات عبره، وهو المنفذ 80 افتراضيًا، المنفذ القياسي في بروتوكول HTTP. سنبحث في ملف الإعدادات عن السطر التالي: listen 80; سنقوم بتغيير المنفذ إلى 443 لأن HTTP/2 لن يعمل مع معظم المستخدمين إذا بقي يقوم بإرسال البيانات عبر المنفذ 80، كما أشرنا سابقًا إلى أنه مدعوم فقط عبر المنفذ 443 على متصفحات Chrome و Firefox.سنستبدل السطر السابق بـ: listen 443 ssl http2; لاحظ أننا أضفنا كلمة ssl و http2 في نهاية السطر، وتخبر هذه المتغيّرات Nginx بأن يستخدم بروتوكول HTTP/2 مع المتصفحات التي تدعم البروتوكول الجديد. الخطوة الثالثة: تغيير اسم الخادوم يأتي اسم الخادوم server_name بعد السطر السابق الذي يحوي على listen، وسنقوم بإعلام Nginx أيّ نطاق سيرتبط مع ملف الإعدادات. سنستبدل الاسم الافتراضي localhost الذي يعني بأن ملف الإعدادات مسؤول عن جميع الطلبات الواردة، وسنضع مكانه اسم النطاق الحقيقي، كـ example.com على سبيل المثال: server_name example.com; سنقوم الآن بحفظ التغييرات بالضغط على CTRL+O ومن ثم نضغط CTRL+X للخروج من محرر nano. الخطوة الرابعة: إضافة المسار إلى شهادات SSL الأمنية سنقوم بإعداد Nginx الآن ليستخدم الشهادات الأمنية اللازمة لـ HTTPS، وإن لم تكن تعلم ما هي الشهادة الأمنية أو لم تكن تملك واحدة فيرجى مراجعة المقالات المذكورة في قسم المتطلبّات الأولية في بداية المقال. لنقم أولًا بإنشاء مجلّد لحفظ الشهادات الأمنية فيه داخل مجلد إعدادات Nginx: $ sudo mkdir /etc/nginx/ssl سنقوم الآن بنسخ ملف الشهادة وملف المفتاح الخاص private key إلى داخل المجلد الجديد، وبعد ذلك سنقوم بتغيير أسماء الملفات لتظهر بوضوح أي نطاق ترتبط معه (تساعد هذه الخطوة في المستقبل على توفير الوقت والجهد إن امتلكت أكثر من نطاق واحد). لا تنسى استبدال example.com باسم النطاق الخاص بك. $ sudo cp /path/to/your/certificate.crt /etc/nginx/ssl/example.com.crt $ sudo cp /path/to/your/private.key /etc/nginx/ssl/example.com.key سنقوم بإضافة سطر جديد الآن إلى ملف الإعدادات ضمن كتلة server لتعريف مسارات الشهادة الرقمية مع مفتاحها الخاص ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; الخطوة الخامسة: تحويل جميع طلبات HTTP إلى HTTPS ينبغي الآن أن نخبر Nginx بأننا نرغب بتوفير المحتوى عبر HTTPS فقط إن استلم طلب HTTP عوضًا عن ذلك. سنقوم في نهاية ملف الإعدادات بإنشاء كتلة server جديدة لتحويل جميع طلبات HTTP إلى HTTPS، ومرة أخرى لا تنس استبدال النطاق باسم النطاق الخاص بك، ستكون الكتلة الجديدة على الشكل التالي: server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; } لاحظ في الكتلة السابقة كيف أنّ Nginx عند استلامه لطلبات HTTP تخص النطاق example.com عبر المنفذ 80، فإنّه سيقوم بتحويل الطلب إلى HTTPS على نفس المسار المطلوب، مستخدمّا التحويل من النمط301 (moved permanently). سيصبح شكل ملف الإعدادات (إن تجاهلنا الأسطر الخاصة بالتعليقات) على النحو التالي: server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name example.com; location / { try_files $uri $uri/ =404; } ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_dhparam /etc/nginx/ssl/dhparam.pem; } server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; } سنقوم الآن بحفظ ملف الإعدادات بالضغط على CTRL+O ومن ثم الخروج من محرر nano بالضغط على CTRL+X. الخطوة السادسة: تحميل ملف الإعدادات الجديد في ذاكرة Nginx لتطبيق التغييرات التي قمنا بها، سنحتاج لإعادة تشغيل خادوم Nginx: $ sudo service nginx restart وللتحقق من أن كل شيء سار على ما يرام، سنقوم بفتح المتصفح واستعراض النطاق الذي أعددناه مع Nginx، فإن كانت الإعدادات صحيحة، يجب أن يتم تحويل الطلب إلى HTTPS بشكل تلقائي، وللتأكد مما إذا تم استخدام البروتوكول الجديد فسنقوم بفتح أدوات المطوّر (في متصفح كروم يمكن فتحها من خلال قائمة View > Developer > Developer Tools)، ومن ثم نعيد تحميل الصفحة من جديد (View > Reload This Page)، ثم من خلال لسان Network، سنضغط بالزر الأيمن للفأرة على سطر رأس الجدول ونختار Protocol. يجب الآن أن يظهر عمود جديد عنوانه Protocol ستتمكن من خلاله من رؤية أن البروتوكول المستخدم هو h2 (الذي يرمز إلى بروتوكول HTTP/2) في حال تم الإعداد بشكل صحيح. إلى هنا سيكون Nginx قد أصبح قادرًا على تخديم المحتوى باستخدام بروتوكول HTTP/2، ولكن تبقى هناك بعض الأمور التي ينبغي إعدادها قبل استخدام الخادوم في بيئة التشغيل. الخطوة السابعة: تحسين Nginx لتقديم أداء أفضل سنقوم الآن بفتح ملف الإعدادات مجدّدًا لضبط إعدادات Nginx لتقديم أفضل أداء وحماية. تفعيل Connection Credentials Caching بالمقارنة مع HTTP، فإن HTTPS يتطلب وقتًا أطول نسبيًا لإنشاء اتصال ما بين الخادوم والمستخدم، ولتقليل الفرق في سرعة تحميل الصفحة، سنقوم بتفعيل ميّزة Connection Credentials Caching وهذا يعني بأنه عوضًا عن إنشاء جلسة عمل جديدة عند طلب كل صفحة، سيقوم الخادوم باستخدام نسخة خبء cache لمعلومات المصادقة. لتفعيل الميّزة، سنقوم بإضافة السطرين التاليين إلى نهاية كتلة http في ملف الإعدادات: ssl_session_cache shared:SSL:5m; ssl_session_timeout 1h; يقوم المتغيّر ssl_session_cache بتحديد حجم الخبء الذي سيحتوي على معلومات الجلسة، حيث يمكن لـ 1MB أن يقوم بتخزين معلومات 4000 جلسة عمل، وبالتالي ستكون القيمة الافتراضية 5MB أكثر من كافية لمعظم الحالات، ولكن إن كنت تتوقع أن يكون هناك حركة مرور كثيفة على الموقع، فيمكنك زيادة القيمة وفقًا لذلك. يحدّد المتغير ssl_session_timeout من الوقت الذي تكون ضمنه جلسة العمل فعّالة داخل الخبء، ولا ينبغي أن تكون هذه القيمة كبيرة (أكثر من ساعة)، وإلى جانب ذلك فإن تخفيضها كثيرًا سيخفض من الفائدة المرجوّة أيضًا. تحسين باقات التشفير Cipher Suites باقات التشفير هي مجموعة من خوارزميات التشفير التي تصف كيف ينبغي أن يتم تشفير البيانات المنقولة. يملك بروتوكول HTTP/2 قائمة كبيرة من خوارزميات التشفير القديمة وغير الآمنة التي يجب تجنّب استخدامها. سنقوم باستخدام مجموعة تشفير معتمدة من قبل جهات عملاقة مثل CloudFlare. لا تسمح هذه المجموعات باستخدام خوارزمية MD5 في التشفير (التي تم إثبات أنها غير آمنة في عام 1996، وبالرغم من ذلك، فما تزال منتشرة حتى يومنا هذا). سنقوم بإضافة السطرين التاليين بعد ssl_session_timeout: ssl_prefer_server_ciphers on; ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; تفعيل ميزة (Strict Transport Security (HSTS على الرغم من أنّا قمنا بتحويل جميع طلبات HTTP إلى HTTPS في إعدادات Nginx، فينبغي علينا أيضًا أن نقوم بتفعيل ميّزة Strict Transport Security لتجنّب الحاجة لإخبار Nginx بعملية التحويل بأنفسنا أساسًا. عندما يصادف المتصفح ترويسة HSTS، فلن يحاول الاتصال بالخادوم عبر HTTP التقليدي مجدّدًا قبل مضي فترة من الوقت، ومهما حصل، سيعمل على تبادل البيانات عبر اتصالات HTTPS مشفّرة. تساعد هذه الترويسة على حمايتنا من هجمات تخفيض البروتوكول. كل ما نحتاجه هو إضافة السطر التالي في ملف الإعدادات: add_header Strict-Transport-Security "max-age=15768000" always; يحدّد المتغير max-age القيمة التي يجب على المتصفح خلالها ألا يحاول التواصل مع الخادوم إلا عبر بروتوكول HTTPS، وهذه القيمة ممثّلة بالثواني وبالتالي فإن القيمة 15768000 تساوي 6 أشهر. وبشكل افتراضي فإن هذه الترويسة لن يتم إضافتها إلى الطلبات الموجّهة للنطاقات الفرعية، فإن كنت تملك نطاقات فرعية وترغب أن يتم تطبيق HSTS عليها جميعًا فيجب إضافة المتغير includeSubDomains حينها إلى نهاية السطر على الشكل التالي: add_header Strict-Transport-Security "max-age=15768000; includeSubDomains: always;"; لا تنس حفظ الملف الآن بالضغط على CTRL+O ومن ثم إغلاقه بالضغط على CTRL+X إن كنت تستخدم محرر nano. الخطوة الثامنة: رفع حماية تبادل المفاتيح الأمنية إن الخطوة الأولى في إنشاء اتصال آمن هو تبادل المفاتيح الخاصة بين الخادوم والعميل، وتكمن المشكلة في هذه العملية في أنّه حتى تلك اللحظة فالاتصال غير مشفّر بينهما وبالتالي فالبيانات المتبادلة يمكن التنصّت عليها من طرف ثالث. لهذا السبب، سنحتاج لاستخدام خوارزمية Diffie-Hellman-Merkle في تبادل المفاتيح. يستخدم Nginx بشكل افتراضي مفتاح DHE) Ephemeral Diffie-Hellman) بطول 1024 بت، والذي يمكن فك تشفيره بسهولة نسبيًا، وللحصول على أمان أعلى فينبغي علينا إنشاء مفتاح DHE خاص أكثر أمنًا. للقيام بذلك سنقوم بتنفيذ الأمر التالي في سطر الأوامر: $ sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048 تنبيه: يجب أن يتم إنشاء مُعاملات DH في المجلد الذي قمنا بتخزين الشهادات الأمنية فيه، وفي المقال قمنا بتخزين الشهادات في المسار /etc/nginx/ssl/. إن السبب وراء هذا هو أن Nginx يقوم دومًا بالبحث عن مفتاح DHE الخاص بالمستخدم في مجلد الشهادات الأمنية ويستخدمه إن وُجد. تحدّد القيمة 2048 في الأمر السابق طول المفتاح الذي نرغب بإنشائه، حيث سيكون مفتاح بطول 2048 بت أكثر أمنًا وينصح به من قبل مؤسسة موزيلّا، ولكن إن كنت تسعى خلف أقصى درجة أمان، فيمكنك استخدام مفتاح بطول 4096 بت. ستأخذ عملية إنشاء المفتاح حوالي 5 دقائق، ويمكنك أثناء ذلك الاسترخاء وارتشاف بعض القهوة. لتطبيق التغييرات التي قمنا بها على ملف الإعدادات، لا تنسى أن تقوم بإيقاف وإعادة تشغيل خادوم Nginx: $ sudo service nginx restart الخلاصة أصبح اتصال SSL الخاص بك أكثر أمنًا وقابلًا للاستخدام لنقل المعلومات الحساسة، ولكن إن أردت اختبار قوته الأمنية فقم بزيارة Qualys SSL Lab وبتشغيل اختبار على خادومك، حيث ينبغي أن تحصل على نتيجة A+إن كان كلّ شيء معدّ بشكل صحيح. هذا كلّ شيء، أصبح خادوم Nginx الخاص بك جاهزًا للاستخدام، وكما ترى فإن بروتوكول HTTP/2 هو حل رائع لتحسين سرعات نقل البيانات ومن السهل استخدامه كما أظهرنا في المقال. ترجمة -وبتصرّف- للمقال How To Set Up Nginx with HTTP/2 Support on Ubuntu 14.04 لصاحبه Sergey Zhukaev.
-
تحدد صلاحيّات الملفّات من يستطيع قراءة، إنشاء، تحرير ملف و/أو فتحه، وهذه العملية مهمّة في ووردبريس، لأنها قد تحتاج إلى إمكانية إنشاء ملفات جديدة في مجلد wp-content الّلازمة لعمل بعض الوظائف. إن عدم امتلاك ملفات الموقع للصلاحيات الضرورية والكافية يفتح المجال للآخرين للتطفّل على ملفّات موقعك، وقد لا يحميك تعيين الصلاحيات بشكل صحيح من جميع الهجمات الإلكترونية، لكنه سيساعدك في جعل موقعك أكثر أمانًا، حيث سيكون إجراءً أمنيًّا آخر يضاف إلى إجراءاتك الأمنية الحالية. يحتوي توثيق ووردبريس على بعض المعلومات حول صلاحيات الملفات الضرورية لـ ووردبريس، لكن قد يكون من الصعب متابعته لأنّه لا يشرح التفاصيل، لذا يهدف المقال إلى شرح تفاصيل صلاحيات الملفات والمجلّدات وكيفية تغييرها بغرض رفع أمان الموقع. كيف تبدو صلاحيات الملفات؟ توجد فئتان يجب أخذهما بعين الاعتبار عند التحدّث عن صلاحيات الملفّات: العمليّات ومستخدمو العمليّات. العمليّات وهي العمليات التي من الممكن تنفيذها على الملفّات: القراءة Read: تسمح بقراءة محتوى ملف فقط، ويتم تمثيلها بالحرف r كما سنرى لاحقًا. الكتابة Write: تسمح بإنشاء ملف جديد و/أو تعديل محتوى ملف موجود مسبقًا، ويتم تمثيلها بالحرف w. التنفيذ Execute: تعطي إمكانية تنفيذ الملف بغرض تشغيله كبرنامج أو سكربت، ويتم تمثيلها بالحرف x. ملاحظة: يجب الانتباه إلى عدم الخلط ما بين عمليّتي القراءة والتنفيذ، فالأولى تسمح بقراءة محتوى ملف (سواء كان ملف نصّي، أو صورة، أو برنامج حتّى) ولكنّها لازمة وغير كافية لتنفيذ محتوى الملف إن كان برنامجًا، فحينها يجب أن يمتلك ملف البرنامج إمكانيّتي القراءة والتنفيذ كي يكون بالإمكان تشغيله كبرنامج. أما مستخدمو العمليات فهم: المستخدم User: وهو مالك الملف owner، المجموعة Group: ويمكن أن تضم مستخدمين آخرين لهم صلاحية الوصول إلى الملفات التي تختارها والتي لهذه المجموعة صلاحية الوصول إليها; الطرف الثالث World: أي مستخدم آخر عدا ما ذُكر. ويمكن تمثيل صلاحيات الملفّات كمجموعات متتالية من الأرقام على الشكل rwxrwxrwx-: الرقم الأول rwx: صلاحيات الوصول الخاصة بمالك الملف user (أو owner). الرقم الثاني rwx: صلاحيات الوصول الخاصة بالمجموعة group. الرقم الثالث rwx: صلاحيات الوصول الخاصة بالطرف الثالث world. وللحصول على قيمة الرقم الخاص بِكلّ مجموعة سنقوم اعتمادًا على النظام الثنائيّ binary باستنباط الجدول التالي: نظام rwx الثُنائي binary القيمة بالنظام العُشري decimal إمكانيّة Read/Write/Execute 000 0 001 1 تنفيذ فقط 010 2 كتابة فقط 011 3 كتابة + تنفيذ 100 4 قراءة فقط 101 5 قراءة + تنفيذ 110 6 قراءة + كتابة 111 7 قراءة + كتابة + تنفيذ فاستنادًا للجدول السابق فإن أعلى صلاحية rwxrwxrwx- يمكن منحها بالنظام العُشريّ هي 777 حيث يكون لكلٍّ من المالك، المجموعة والطرف الثالث جميعهم، إمكانية القراءة والكتابة والتنفيذ، وبنفس الشكل يمكن القول بأنّ أقلّ صلاحية rwxrwxrwx- يمكن منحها (إلى جانب عدم وجود أيّ صلاحية على الإطلاق) هي 444، حيث يملك الجميع إمكانية القراءة فقط. لا تخف فهناك طريقة سهلة لتذكر الصلاحيات، فعلى سبيل المثال لو أردنا إعطاء مالك الملف كامل الصلاحيات والحدّ من صلاحيات باقي المستخدمين، فنقوم بما يلي: المستخدم User – سيملك إمكانية القراءة (4)، الكتابة (2) والتنفيذ (1)، فتكون قيمة الصلاحية النهائية (1+2+4=7) المجموعة Group – ستملك إمكانية القراءة (4) والكتابة (2)، فتكون قيمة الصلاحية النهائية (4+2=6) الطرف الثالث World – سيملك إمكانية القراءة فقط (4). إذًا، تصبح صلاحية الملف النهائيّة 764 أو rwxrw-r-- في هذا المثال، ولكنّ هذه الصلاحية غير مثاليّة لملفات مدوّنات ووردبريس، فقد تلاحظ بأن صلاحيات الملفّات تبدو مختلفة قليلًا عند التحقق منها عبر SSH أو FTP، كما في الصورة: تذكّر بأن الـ - (hyphen) في صيغة صلاحيّات الملفّات تمثّل غياب إمكانية ما، عدا أوّل - إلى أقصى اليسار والتي تبيّن فيما إذا كانت الصلاحية لملف أو مجلّد، فإن كانت لمجلّد حلّ محلّها الحرف d، الحرف الأول من كلمة directory. تجدر الإشارة إلى أنّ المحرف الأول إلى اليسار قد يملك قيمًا مختلفة عن الحرف d ولكن يندر أن تصادف هذا في ووردبريس. وكما ذكرنا سابقًا فإنّ كلّ مجموعة تمثّل الإمكانيات المسموحة لكل مجموعة مستخدمين، فإن أخذنا الصلاحية التالية rwxr-xr-x- فإنّ الـ - في أقصى اليسار تخبرنا بأنّ هذه صلاحية ملف، أما الـ rwx التي تليها فتخبرنا بأنّ المستخدم مالك الملف يملك إمكانية القراءة والكتابة والتنفيذ، بينما تملك مجموعة المستخدمين المالكة للملف إمكانية القراءة والتنفيذ، وأخيرًا يكون لباقي المستخدمين إمكانية القراءة والتنفيذ أيضًا، فإن قُمنا بتحويل نمط الصلاحية هذا إلى الشكل الرقمي لحصلنا على القيمة 755. من الجدير بالذكر بعد هذا الشرح المطوّل بأنّ الصلاحية 777 تعطي جميع المستخدمين كامل الصلاحيات وهذا غير مناسب أمنيًّا ويجب عدم استخدامه لمواقع ووردبريس على الأقل، وفي الوقت ذاته فإنّ الصلاحية 444 لن تكفي ليعمل موقع يستخدم ووردبريس. ما الصلاحيات اللازمة لمواقع ووردبريس؟ إن قمت بتنصيب ووردبريس بنفسك فإنّ الصلاحيات ستكون معدّة بشكل صحيح غالبًا، ولكن إن كنت تحصل على رسائل خطأ بصلاحيات الوصول أو كان موقعك معدًّا من قبل شخص آخر، فإنّ الوقت مناسب لمراجعة صلاحيات الملفّات. تختلف الصلاحيات المطلوبة باختلاف الإضافات plugins التي قد تستخدمها في موقعك والتي تتبع لطبيعة عمل الـ plugin، وستعتمد صلاحية الملفات والمجلّدات على إعدادات استضافتك، فإن كنت تستخدم خادومًا خاصًا بك بالكامل (dedicated server) فإنّ بالإمكان استخدام الصلاحيات التالية بشكل آمن تبعًا لما يذكره توثيق ووردبريس: للمجلّدات – 755 للملفّات – 644 أمّا الملفّات الأكثر خصوصية كملف الإعدادات الخاصة بـ ووردبريس والذي يتضمن معلومات حسّاسة wp-config.php، فيمكن استخدام الصلاحية 600 معه، ويستثنى من ذلك ملف htaccess. والذي يحتاج موقع ووردبريس للوصول إليه ليتم تحديث محتواه بشكل اوتوماتيكي، فينصح باستخدام الصلاحية 644 معه أو الصلاحية الأكثر أمنًا 604 في معظم الحالات. كيف يمكن التحكم بصلاحيات الملفات؟ يمكن إيجاد صلاحيات الملفات المذكورة على أنظمة لينكس/يونكس فقط، فإن فرضنا أنّ الاستضافة مزوّدة بلوحة تحكّم cPanel فعندها للوصول إلى صلاحيات الملفات نتوجّه بعد تسجيل الدخول إلى: Files > File Manager وعند ظهور نافذة اختيار المجلّد الرئيسي، نضغط زر Go أسفل النافذة. بعد ظهور صفحة إدارة الملفات، نختار أيّ ملف ثم نضغط على أيقونة Change Permissions في أعلى الصفحة. ستظهر الآن نافذة منبثقة تحوي على صلاحيات الملف أو المجلّد الذي قمنا باختياره، والتي يمكن من خلالها التعديل عليها: إضافة لما سبق فإنّ بالإمكان التعديل على الصلاحيات عبر برنامج إدارة الملفّات باستخدام FTP، فمثلًا باستخدام FileZilla بعد إتمام الاتصال، يمكن الوصول إلى صلاحيات الملف بالضغط بالزر الأيمن على الملف أو المجلّد المطلوب واختيار File permissions: حيث ستظهر نافذة يمكن خلالها التعديل على الصلاحيات كالمعتاد أيضًا: وأخيرًا يمكن التعديل أيضًا على الصلاحيات عبر سطر الأوامر من خلال SSH بعد تسجيل الدخول، باستخدام الأمر التالي: للمجلّدات find /path/to/your/wordpress/install/ -type d -exec chmod 755 {} \; للملفّات find /path/to/your/wordpress/install/ -type f -exec chmod 644 {} \; سيقوم الأمر السابق بإعادة ضبط صلاحيات جميع المجلّدات في المسار المحدّد لتأخذ الصلاحية 755 وجميع الملفّات لتأخذ الصلاحية 644، وبالطبع لا تنس التأكّد من إدخال مسار تثبيت ووردبريس بشكل صحيح قبل التنفيذ. الخلاصة قمنا بتغطية الأساسيات الخاصّة بصلاحيات الملفات الّلازمة لعمل ووردبريس وكيفية تغييرها من خلال لوحة تحكم cPanel أو من خلال بروتوكوليّ FTP و SSH، لكن يبقى تحديث إصدار ووردبريس أمرًا ضروريًّا من الناحية الأمنيّة، فإنّ هذا يضمن بأنّ صلاحيات الملفات سيتم ضبطها بشكل تلقائيّ إلى الوضع الأمثل. إن كنت تفضّل استخدام الإضافات، فهناك 3 منها يمكنك تجربتها: Triagis® WordPress Security Evaluation SECURE BulletProof Security حيث تقوم هذه الإضافات بالتحقّق من صلاحيات الملفات وتخبرك إن كان هناك إعدادات غير مقبولة. هل احتجت من قبل لإصلاح صلاحيات الملفات لديك؟ شاركنا تجربتك عبر التعليقات في الأسفل. ترجمة -وبتصرّف- للمقال Understanding File Permissions and Using Them to Secure Your Site لصاحبته Jenni McKinnon.
-
- permissions
- ووردبريس
- (و 5 أكثر)
-
تعتمد سرعة عرض صفحة ويب على حجم جميع الملفات المرتبطة بالصفحة والتي يجب تحميلها من قبل المتصفح، وبالتالي فتخفيف حجم الملفات المطلوبة يمكن أن يسرّع من عرض صفحة الويب، ويوفّر الكثير من المال على الأشخاص الذين يدفعون مقابل عرض الحزمة bandwidth المستهلكة. يعدّ gzip من البرامج المشهورة المستخدمة في ضغط البيانات، وبالإمكان إعداد خادوم Nginx لاستخدام gzip لضغط الملفات التي يتم تخديمها من قبل الخادوم قبل إرسالها للمتصفحات والتي ستقوم بدورها بفك الضغط عن الملفّات (تدعم جميع المتصفحات المشهورة فك ضغط gzip ويفترض أن تدعم -معظم- المتصفحات عمومًا هذه العملية) دون أي خسارة في دقة البيانات بعد فك الضغط، مستفيدة بذلك من تخفيف حجم البيانات المتبادلة ما بين خادوم الويب والمتصفح. ونظرًا لاختلاف الطرق التي تعمل بها خوارزميات الضغط عمومًا، وآلية عمل خوارزمية gzip خصوصًا، فإنّ بعض الملفات يمكن ضغطها بنسبة أكبر من بعضها الآخر. فعلى سبيل المثال، يتم ضغط الملفات النصيّة text بصورة جيّدة جدًا حيث قد تكون نتيجة الضغط أصغر بحوالي مرّتين من الحجم الأصلي. ومن ناحية أخرى، فالصور من نوع JPEG و PNG تأتي مضغوطة سلفًا بطبيعة الخوارزمية المنتجة لها وبالتالي لن نحصل على الكثير من الفائدة بعد تطبيق ضغط gzip عليها، وعلى اعتبار أن ضغط الملفّات يستهلك الكثير من مصادر الخادوم، فمن الأفضل أن يتم ضغط الملفّات التي تملك نسبة ضغط عالية. سنناقش في المقال كيفية إعداد خادوم Nginx المثبت على نظام تشغيل Ubuntu 14.04 ليستخدم gzip في الضغط لتخفيف حجم المحتوى المرسل إلى متصفّحي الموقع. المتطلبات الأولية نحتاج الأمور التالية قبل المتابعة: نظام تشغيل Ubuntu 14.04، مستخدم عادي بدون صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ أمر sudo، يمكن مراجعة الإعداد الابتدائي لخادوم أوبونتو 14.04 لمزيد من المعلومات، نسخة Nginx مثبّته على النظام، ويمكنك اتباع هذا المقال لتثبيت Nginx للقيام بذلك. الخطوة الأولى: إنشاء ملفات تجريبية سنقوم في هذه الخطوة بإنشاء عدّة ملفات تجريبية في الجذر الافتراضي للمواقع المدارة من Nginx لاختبار ضغط gzip. ولتحديد الملف الذي سيتم تخديمه عبر الشبكة، يكتفي Nginx بالاعتماد على لاحقة الملف لتحديد نمط MIME الخاص به، عوضًا عن القيام بقراءة ترويسته وذلك بغية تنفيذ العملية بأسرع وقت ممكن. ونتيجة لهذا التصرّف فإن محتوى الملف لا يعود مهمًّا ويصبح من الممكن خداع Nginx بجعله يعتقد أن ملفًا فارغًا عبارة عن صورة، وملفًا آخر عبارة عن مستند css. في إعداداتنا التالية، لن يقوم Nginx بضغط الملفّات الصغيرة جدًا، لذا سنقوم بإنشاء ملفّات تجريبية يبلغ حجمها 1 كيلوبايت تمامًا. سيسمح هذا السيناريو بالتحقق فيما إذا كان Nginx يقوم بضغط الملفات التي من المفترض به القيام بضغطها. لنقم بإنشاء ملف بحجم 1 كيلوبايت وتسميته test.html في الجذر الرئيسي الافتراضي للمواقع المدارة من Nginx وذلك باستخدام أمر truncate عبر سطر الأوامر، كما في المثال التالي: $ sudo truncate -s 1k /usr/share/nginx/html/test.html لنقم بإنشاء المزيد من الملفّات التجريبية بنفس الطريقة: ملف صورة jpg، ملف css، وملف js. $ sudo truncate -s 1k /usr/share/nginx/html/test.jpg $ sudo truncate -s 1k /usr/share/nginx/html/test.css $ sudo truncate -s 1k /usr/share/nginx/html/test.js الخطوة الثانية: التحقق من التصرّف الافتراضي لـ Nginx سنقوم الآن بالتحقق من كيفية تصرّف Nginx عند ضغط الملفات التي قمنا بإنشائها توًّا. لنتحقق مما إذا سيتم تخديم ملف test.html بعد الضغط، سنقوم في الأمر التالي بطلب الملف من خادوم Nginx، ونخبره بأنّه لا مشكلة لدينا في الحصول على محتوى مضغوط باستخدام gzip وذلك بتمرير ترويسة HTTP مناسبة (Accept-Encoding: gzip). $ curl -H "Accept-Encoding: gzip" -I http://localhost/test.html سنحصل في جواب الخادوم على ما يشبه النص التالي: HTTP/1.1 200 OK Server: nginx/1.4.6 (Ubuntu) Date: Tue, 19 Jan 2016 20:04:12 GMT Content-Type: text/html Last-Modified: Tue, 04 Mar 2014 11:46:45 GMT Connection: keep-alive Content-Encoding: gzip ويمكن في السطر الأخير ملاحظة وجود ترويسة (Content-Encoding: gzip) والتي تخبرنا بأن المحتوى الذي حصلنا عليه قد تم ضغطه باستخدام gzip، ولكن كيف حصل ذلك دون أن نقوم بتفعيل gzip أولًا في Nginx؟ إنّ السبب خلف هذا هو أن الضغط باستخدام gzip مفعّل بشكل تلقائي في نسخة Nginx على نظام Ubuntu 14.04 بإعداداته الافتراضية. على الرغم من ذلك، فإن Nginx لن يقوم إلا بضغط ملفات HTML فقط، بينما يتم تخديم باقي أنواع الملفّات بدون ضغط، ويمكن التحقق من ذلك بطلب صورة بنفس الطريقة السابقة: $ curl -H "Accept-Encoding: gzip" -I http://localhost/test.jpg وسنحصل على رد مختلف قليلًا عن السابق: HTTP/1.1 200 OK Server: nginx/1.4.6 (Ubuntu) Date: Tue, 19 Jan 2016 20:10:34 GMT Content-Type: image/jpeg Content-Length: 0 Last-Modified: Tue, 19 Jan 2016 20:06:22 GMT Connection: keep-alive ETag: "569e973e-0" Accept-Ranges: bytes حيث نلاحظ عدم وجود ترويسة (Content-Encoding: gzip) وهذا يعني أن الملف تم إرساله لنا بدون ضغط. يمكن تنفيذ الاختبار ذاته مجدّدًا مع ملف test.css ومرّة أخرى سنحصل على الملف بدون ضغط. HTTP/1.1 200 OK Server: nginx/1.4.6 (Ubuntu) Date: Tue, 19 Jan 2016 20:20:33 GMT Content-Type: text/css Content-Length: 0 Last-Modified: Tue, 19 Jan 2016 20:20:33 GMT Connection: keep-alive ETag: "569e9a91-0" Accept-Ranges: bytes الخطوة الثالثة: تغيير إعدادات ضغط gzip في خادوم Nginx سنقوم الآن بتغيّير إعدادات Nginx ليتم ضغط ملفّات من أنواع أخرى عدا عن HTML، والتي من الممكن الاستفادة من نسبة الضغط المطبّقة عليها. سنقوم بفتح ملف إعدادات Nginx باستخدام محرر nano أو أي محرر آخر تفضّل استخدامه: $ sudo nano /etc/nginx/nginx.conf ومن ثم سنبحث عن كتلة إعدادات gzip التي ستبدو كما يلي: . . . ## # `gzip` Settings # # gzip on; gzip_disable "msie6"; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; . . . نلاحظ في الإعدادات السابقة أن الضغط بواسطة gzip مفعّل بشكل افتراضي بواسطة توجيه gzip on، بينما معظم الإعدادات الإضافية تم تعطيلها بإشارة التعليقات # في بداية السطر. سنقوم بإجراء بعض التعديلات على هذه الإعدادات مثل: تفعيل الإعدادات الإضافية من خلال حذف إشارة التعليقات # في بداية الأسطر، إضافة توجيه gzip_min_length 256; الذي يخبر Nginx ألّا يقوم بضغط الملفات التي يصغر حجمها عن 256 بايت، فهذا الحجم الصغير جدًا لن يحقق الفائدة المرجوّة بعد الضغط، ▪ إضافة توجيه gzip_types مع المزيد من أنماط الملفّات كخطوط الويب، الأيقونات والصور من نوع SVG. بعد إجراء التعديلات المذكورة سيبدو مقطع الإعدادات الجديد على النحو التالي: . . . ## # `gzip` Settings # # gzip on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_min_length 256; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; . . . قم بحفظ الملف وإغلاقه وتطبيق التعديلات من خلال إعادة تشغيل خادوم Nginx باستخدام الأمر: $ sudo service nginx restart الخطوة الرابعة: التحقق من الإعدادات الجديدة سنقوم الآن بالتحقق من أنّ الإعدادات التي قمنا بتغييرها وإضافتها تعمل على النحو المطلوب، ويمكن القيام بذلك من خلال إعادة تنفيذ الاختبارات المذكورة في الخطوة الثانية عبر استخدام أمر curl على كلّ من الملفّات التجريبية والتحقق من وجود ترويسة Content-Encoding: gzip في الخرج: $ curl -H "Accept-Encoding: gzip" -I http://localhost/test.html $ curl -H "Accept-Encoding: gzip" -I http://localhost/test.jpg $ curl -H "Accept-Encoding: gzip" -I http://localhost/test.css $ curl -H "Accept-Encoding: gzip" -I http://localhost/test.js من المفترض الآن أن تكون جميع الملفّات مضغوطة وتظهر ترويسة Content-Encoding: gzip في الخرج، عدا ملف الصورة test.jpg، وتكون الإعدادات المطبّقة صحيحة والاختبار ناجحًا إن تحقق هذا. الخلاصة إن تغيّير إعدادات Nginx لاستخدام ضغط gzip عملية سهلة جدًا لكن الفوائد المحقّقة ستكون كبيرة، فستوفّر الكثير على الزوّار الذين يملكون اتصالات محدودة بعرض الحزمة، وبالإضافة إلى ذلك ستحصل على تقييم أفضل في محرّكات البحث مثل Google من خلال تحقيق سرعة عرض أعلى للصفحة، حيث أن عامل سرعة عرض الصفحة بدأ يأخذ حيّزًا مهمًا من عملية التقييم في المواقع الحديثة وخوارزمية الضغط gzip هي خطوة كبيرة باتجاه تحسين النتيجة. ترجمة -وبتصرّف- للمقال How To Add the gzip Module to Nginx on Ubuntu 14.04 لصاحبه Mateusz Papiernik.
-
إنّ Trackback طريقة ممتازة للناشرين عبر ووردبريس لمشاركة أفكارهم ونقاشاتهم مع الكتّاب الآخرين من خلال منشوراتهم، ويمكن اعتبارها كتعليق يأتي من خارج المُدوّنة فإن قام موقع ما (لا يستخدم ووردبريس) بنشر مقال يحوي على رابط لأحد منشوراتك فإنّه من الممكن لصاحب المقال أن يرسل لك تنبيهًا على منشورك في مدوّنتك يظهر كاقتباس للنصّ المحيط بالرابط. أمّا Pingbacks فلا تختلف كثيرًا عمّا سبق فيما عدا كونها خاصّة بـ ووردبريس حصرًا، والتنبيهات التي يتمّ إرسالها تحدث بشكل أوتوماتيكيّ، ولكن يشترط في حالة Pingback أن تستخدم المدوّنتين منصّة التدوين ووردبريس وأن تكون ميّزة Pingback مفعّله على كلا المدوّنتين إمّا على مستوى المدوّنة ككل أو على مستوى المنشور الذي تمّ الإشارة إليه. إن تمّ السماح بـ Trackback و Pingback فإن رابطًا واقتباسًا للنص إضافةً إلى اسم المقال سيظهران على شكل تعليق على منشورك في مدوّنتك كما يبدو في الصورة التالية: للأسف فإنّ هذه الميّزة تغري الكثير من أصحاب المنشورات والإعلانات غير المرغوب بها (spam)، ولكن لحسن الحظ فإنّ هناك طرقًا سهلة لمنع استغلال الميّزة لأغراض السبام بشكل نهائيّ، وهذه الطرق متوافقة مع كل من WordPress و WordPress Multisite. سنذكر فيما يلي بعض النصائح وقائمة بأكثر الإضافات plugins المجّانيّة حداثة وفعاليّة، لِخفض حجم السبام المزعج الذي يصلك بنسبة كبيرة جدًّا. قد نجد أنّ معظم التنبيهات التي تصلنا عبارة عن سبام، وبالتالي إن رغبنا بإيقاف الميّزة بشكل نهائيّ فإنّ بالإمكان القيام بذلك عبر لوحة التحكّم الإداريّة دون أيّ إضافات أو جهد، وللقيام بذلك نتوجه إلى صفحة: Settings > Discussion وأسفل العنوان الأول Default article settings، نلغي تفعيل الخيار المسمّى (Allow link notifications from other blogs (pingbacks and trackbacks كما في الصورة: لا تنس الضغط على زرّ الحفظ Save Changes أسفل الصفحة لتطبيق التغييرات، وبعد القيام بذلك لن تحصل بعد اليوم على أيّ تعليقات من خلال trackbacks، ولكن إن لم ترغب بتضييع الفرصة بالحصول على بعض التنبيهات حول مقالات حقيقية قد يهمّك المشاركة في مناقشتها فإنّ من السهل الاستعانة ببعض الإضافات التالية. Hide Trackbacks تعمل هذه الإضافة كبديل عن إيقاف ميّزة trackback بشكل نهائيّ، فهي تسمح باستمرارية الحصول على التنبيهات ولكنّها تقوم بإخفاء تلك التعليقات وتمنعها من الظهور في قسم التعليقات تحسّبًا. لا يتطلّب تثبيت هذه الإضافة أيّ جهد أو المزيد من الإعدادات بعد التثبيت فهي ستقوم بعملها مباشرة بعد تفعيلها بإخفاء التعليقات التي تأتي من خلال trackbacks، وتبقى هذه التعليقات مرئيّة لصاحب المدوّنة عبر لوحة التحكّم الإداريّة. بهذه البساطة، فإن زوّار المدونة لن يروا أيّ سبام مزعج وتبقى لك إمكانيّة الحصول على تنبيهات تخبرك بأنّه قد تم ذكر مقالك في موقع ما. Topsy Blocker تعمل هذه الإضافة بإحدى طريقتين حيث تحاول تحليل محتوى التنبيه الذي يصل لمعرفة إن كان المصدر موثوقًا أم لا عبر التحقّق من قائمةٍ على موقع topsy.com فإن ظهر المصدر على تلك القائمة تم اعتباره سبام مزعجًا. ملاحظة: تجدر الإشارة إلى أنّ موقع topsy.com كان خارج الخدمة أثناء ترجمة هذا المقال. تقوم الإضافة أيضًا بالتحقّق من مصدر التعليق الذي يأتي فإن لم يكن صادرًا عن الموقع الذي يشير إليه تم اعتباره سبام. تملك هذه الإضافة نسبة فعاليّة عالية إلى جانب سهولة تثبيتها، كما أنّ الإعدادات التي يمكن الوصول إليها عبر المسار: Settings > Simple TB Validation بسيطة وواضحة. إنّ الإعدادات الافتراضية تعمل بشكل ممتاز في معظم الحالات، ولكن من الممكن الاختيار فيما إن أردنا ترشيح (filter) التنبيهات من خلال عناوين IP أو من خلال كيفيّة ظهور رابط منشورك عندما تصل التنبيهات، فيمكن الاختيار بين عنوان النطاق الرئيسيّ أو العنوان الدائم permalink للمنشور، كما يمكن الاختيار فيما لو رغبنا بحذف التعليقات التي يتم تصنيفها كسبام مزعج أو إلغاء نشرها بانتظار المراجعة. تأتي هذه الإضافة كبديل عن الإضافة الأصليّة باسم Simple Trackback Validation وبالتالي إن كنت تستخدم الإضافة القديمة فيجب إلغاء تثبيتها أولًا ومن ثمّ تثبيت Topsy Blocker. Antispam Bee تعدّ هذه الإضافة من الإضافات المعروفة لمستخدمي ووردبريس الذين يزيد عددهم عن 200,000 مستخدم نشط، ولا ينتهي عملها عند ترشيح التعليقات الناتجة عن trackback بل تتعدى ذلك إلى فحص التعليقات الأخرى بحثًا عن أيّ تعليقات سبام. إنّ من السهل تثبيت هذه الإضافة كما في الإضافات الأخرى المذكورة، ويمكن الوصول إلى خياراتها عبر: Settings > Antispam Bee وغالبًا ما تكون الإعدادات الافتراضيّة للإضافة كافية لمعظم المواقع، ويمكن أيضًا تنشيط الخيار الذي يسمح للإضافة بمقارنة التعليقات مع قاعدة بياناتها بحثًا عن سبام محتمل. إلى جانب ما سبق، يمكن إيقاف التعليقات والـ trackback بحسب الدولة، الأمر الذي قد يكون مناسبًا إن كان الموقع مخصّصًا لمجتمع محلّي على سبيل المثال. تتمتع الإضافة بمزايا أخرى مما يجعلها ذات فعالية عالية ومجانيّة. WP-SpamShield Anti-Spam تساعد هذه الإضافة المميّزة على حمايتك بصورة كبيرة باعتمادها رموز التحقق CAPTCHA وطرقًا أخرى للتأكّد من أن التعليق يأتي من شخص حقيقي لا من برمجيات مؤتمتة، لكنّ الزوّار قد لا يكونوا سعيدين جدًا بذلك. فيما عدا ذلك، فإن البرمجيات المؤتمتة التي تنتقل من موقع لآخر بهدف إغراقه بالسبام المزعج يتم إيقافها بسهولة ويسر مع هذه الإضافة لكونها تعمل كجدار ناريّ ضدّها. وكما في معظم الإضافات السابقة، فبالإمكان تثبيت الإضافة بسهولة والتعديل على خياراتها عبر المسار: Settings > WP-SpamShield كما أنها تملك توثيقًا غنيًّا يهدف إلى مساعدتك بالحصول على أفضل حماية ممكنة. تقوم الإضافة بمنع السبام المزعج بشكل تلقائي حتى لا تضطرّ إلى تصفح عشرات التنبيهات بحثًا عن التعليقات المفيدة وتنبيهات trackbacks. وبشكل افتراضي فإنّ جميع ما يتم تصنيفه كسبام سيتم إلغاؤه من النشر بانتظار الموافقة عليه. قد تكون خيارات الإضافة بسيطة لكنّها رغم ذلك تبقى إحدى الإضافات الفعّالة. الخلاصة باستخدام النصائح والإضافات المذكورة سابقًا، ستنتهي المعاناة من السبام المزعج الذي يصل عبر ميزة trackback. ما هي الطرق التي تفضّلها للحد من السبام المزعج على موقعك؟ شارك معنا تجربتك. ترجمة -وبتصرّف- للمقال How to Stop WordPress Trackback and Pingback Spam لصاحبته Jenni McKinnon.
-
إنّ السجلّات logs أمر ضروري لحل مشاكل تثبيت Redis، وقد تتساءل عن مكان تواجد هذه السجلّات أو عن المكان الذي يقوم Redis بتخزين السجلّات فيه على نظام Ubuntu. عند تثبيت Redis بالطريقة الافتراضية باستخدام apt-get على Ubuntu 14.04 فسيقوم Redis بإنشاء سجلّاته في المسار var/log/redis/redis-server.log/. لاستعراض آخر 10 أسطر في سجلّات redis، نقوم بتنفيذ الأمر التالي: $ sudo tail /var/log/redis/redis-server.log لاحظ في الأمر السابق استخدامنا لـ sudo نظرًا لأننا نحتاج لصلاحيات أعلى لنتمكن من قراءة سجلّات redis. أما في حال تثبيت Redis من ملفّات الشيفرة المصدرية على Ubuntu 14.04، فسيقوم بتخزين السجلّات في المسار var/log/redis_6379.log/. ولاستعراض آخر 10 أسطر نستخدم الأمر: $ sudo tail /var/log/redis_6379.log التحقق من السجلات المؤرشفة يقوم Redis بأرشفة ملفّات السجلّات القديمة، ولاستعراض قائمة الملفّات المتوفرة ننفذ الأمر: $ ls /var/log/redis فسيظهر الخرج بما يشبه التالي: redis-server.log redis-server.log.1.gz ولاستعراض آخر 10 أسطر من سجل مؤرشف نحتاج أولًا أن نقوم بفك ضغطه، ونستخدم gunzip لفك ضغط الملفات من نوع gz، كما في الأمر التالي: $ sudo gunzip /var/log/redis/redis-server.log.1.gz انتبه: يقوم gunzip بفك ضغط ملفات gz وحذف الملف الأساسي المضغوط، لذا إن كنت تريد المحافظة على الأرشيف المضغوط توفيرًا للمساحة واستعراض محتويات الملف المضغوط بشكل مؤقت فقم بنسخه إلى المسار المؤقت tmp/ وقم بفك ضغطه هناك. ومن ثم ننفذ الأمر tail مع الملف الذي نحصل عليه: $ sudo tail /var/log/redis/redis-server.log.1 البحث عن ملفات السجلات باستخدام أمر find إن لم تكن ملفّات السجلّات في المسارات المذكورة السابقة، فمن الممكن تنفيذ عملية بحث واسعة باستخدام الأمر find في المسار var/logs/ على الشكل التالي: $ find /var/log/* -name *redis* أو البحث في كامل النظام. قد تأخذ عملية البحث بهذا الشكل بعض الوقت إن كنت تملك الكثير من الملفّات، وقد تظهر لك بعض التحذيرات حول عدم كفاية الصلاحيات للبحث في بعض المسارات، وهذا أمر طبيعي، بالرغم من أنّنا نتجنب أسوأ مسارين للبحث فيهما وهما proc/ و sys/ باستعمال المعامل prune-. سيظهر تنفيذ الأمر التالي جميع الملفّات التي تحوي على كلمة redis في اسمه، بما في ذلك ملفات التثبيت: $ find / -path /sys -prune -o -path /proc -prune -o -name *redis* تحديد مسار تخزين السجلات في ملف إعدادات Redis نستطيع تغيير مسار تخزين ملفات السجلّات وذلك بتغيير المسار في ملف الإعدادات redis.conf، ويتواجد الملف غالبًا في المسار etc/redis/redis.conf/ نقوم بفتح الملف بمحرر نصوص مثل nano أو أي محرر آخر تفضّله: $ sudo nano /etc/redis/redis.conf ونبحث عن السطر الذي يبدأ بـ logfile ونقوم بتغيير المسار الذي يظهر فيه إلى المسار الجديد، كما بالإمكان تغيير اسم ملف السجل الأساسي: logfile /var/log/redis/redis-server.log التحقق من سجلات systemd باستخدام journalctl في Ubuntu 15.04 والإصدارات الأحدث منه قد نحتاج أن نتحقق من سجلّات Redis التي يقوم بالتقاطها سجل النظام systemd (يستخدم نظام Ubuntu 15.04 والأحدث منه سجل النظام systemd، بينما يستخدم Ubuntu 14.04 سجّلات Upstart بشكل افتراضي). الخلاصة لتتعلّم المزيد حول إعدادات Redis، يرجى قراءة هذا المقال حول إعداد عنقود Redis cluster. ترجمة -وبتصرّف- للمقال How To Find Redis Logs on Ubuntu لصاحبته Sharon Campbell.
-
يسمح تحويل الطلبات بإرسالها من عنوان URL إلى آخر تلقائيًا، وهي طريقة عملية لإرسال الزوار وعناكب محركات البحث إلى عنوان URL مختلف عن العنوان الأصليّ المطلوب، ويمكّن من الحفاظ على تقييم محركات البحث لعنوان معيّن، كما يساعد في الحفاظ على أيّة زيارات محتملة لمحتوى قديم من خلال تحويلها إلى المحتوى الجديد بعد أن تمّ تحديثه. سنستعرض كيفية إنشاء تحويلات 301 (أو ما يُعرف أيضًا بـ 301 Redirect)مع بعض الطرق التي يُمكن استخدامها للحفاظ على محتوى حديث للموقع من أجل تقييم SEO أعلى، ومثالًا عن استخدامنا تحويل 301 على مدوّنتنا لرفع معدّل الزيارات. ما هي أنماط التحويل المتوفرة؟ يوجد أنماط مختلفة للتحويل تحمل الرموز (301، 302، 307) بالإضافة إلى تحديث الصفحة باستخدام وسم meta. 1. التحويل 301 (301 Redirect) تحويل دائم للطلبات من عنوان لآخر، يسمح بتمرير 90-99% من عصير الروابط (قوّة التقييم) القادمة من محركات البحث لعنوان ما إلى العنوان الجديد، حيث يشير الرقم 301 إلى رمز حالة HTTP، التي تخبر محركات البحث بأنّ الصفحة قد نُقلت. إنّ هذا التحويل هو الأفضل لتحويل الطلبات من رابط لآخر في معظم الحالات. 2. التحويل 302 تحويل مؤقّت لطلبات عنوان ما لعنوان آخر، يقوم بتمرير 0% من عصير الروابط (قوّة التقييم) محرك البحث إلى العنوان الجديد، ويفضّل تجنّب استخدامه في معظم الحالات. 3. التحويل 307 الإصدار البديل عن تحويل 302 المتوفّر في الإصدار 1.1 لبروتوكول HTTP. 4. وسم meta نوع من أنواع التحويل الذي يمكن تنفيذه في المتصفّح لدى العميل مباشرة عوضًا عن تنفيذه على مستوى الخادوم. إنّ من الأفضل بشكل عام استخدام التحويل من النمط 301 عند القيام بتحويل طلبات عنوان لآخر بهدف المحافظة على تقييم محرّكات البحث. لماذا قد نحتاج للتحويل 301 (301 Redirect)؟ يستحسن استخدام التحويل 301 بهدف المحافظة على الزوّار وعلى تقييم محركات البحث لعنوان ما، فإعادة جواب من الخادوم يحمل رمز التحويل 301 هو إشارة واضحة للمتصفّح ومحرّكات البحث بأنّ الصفحة قد انتقلت من هذا العنوان بشكل نهائي. ستقوم محركات البحث بتفسير ذلك بأنّ الصفحة لم تنتقل إلى عنوان جديد فحسب، ولكنّ المحتوى -أو نسخة أحدث منه- يمكن إيجاده على العنوان الجديد، عندها يتم نقل قوّة التقييم من العنوان الأصليّ إلى العنوان الجديد. إنّ استخدام التحويل 301 بالشكل الصحيح له القدرة على إعادة تنظيم أيّ هيكلة سيّئة للموقع، بالإضافة إلى حلّ مشكلة المحتوى القديم ورفع جودة تجربة الزائر، كلّ ذلك مع المحافظة على قوّة التقييم. اكتشفنا في أحد الأشهر الماضية بأنّ إحدى المنشورات القديمة التي تعود لعام 2011 وأخرى لعام 2012، كانت تحصل على معدّل زيارات مرتفع، لذا قرّرنا استخدام هذه التقنيّة على سبيل التجربة، لذا أنشأنا مقالًا جديدًا بتاريخ 2 ديسمبر 2013، وقمنا بتحويل الطلبات من المقالات القديمة إلى المنشور الجديد وخلال ذلك الشهر حتى 31 ديسمبر، حصل المنشور الجديد على أكثر من 13,000 زيارة من محرّكات البحث فقط، تتضمن الزيارات تلك التي تمّ تحويلها من المقالات القديمة إليه. لم يكن الوقت ليكون أفضل من ذلك، فلم يكن محتوى المقال مناسبًا لفترة نهاية العام فحسب بل كان المقال من أفضل المقالات في ذلك الشهر بحسب عدد الزيارات، فقد تمكّنا من تحويل معظم الزيارات من المقالات القديمة إلى المحتوى الجديد مُعْلمين بذلك كلًّا من الزوّار ومحرّكات البحث بأنّ لدينا مقالات ذات محتوى جديد ومناسب. إنشاء التحويل باستخدام الإضافات إضافة Redirection تسمح إضافة Redirection بإدارة التحويل من النمط 301 ومتابعة أي أخطاء 404 تظهر عند طلب محتوى غير موجود، وتعمل الإضافة عبر ووردبريس فقط دون الحاجة للوصول إلى ملف htaccess. أو أيّ من إعدادات خادوم أباتشي. تتمتع الإضافة بميّزة عظيمة هي إحصائيات التحويل التي تسمح لك بمشاهدة عدد المرّات التي تمّ فيها تنفيذ تحويل لعنوان مطلوب، وآخر مرّة تمّ فيها ذلك، ومن كان صاحب الطلب (زائر أم محرّك بحث) وأين كان يوجد العنوان الذي تمّ طلبه قبل التحويل. إضافة SEO Redirection تسمح إضافة SEO Redirection بإعداد تحويل سريع للطلبات باستخدام الأنماط 301, 302 و307، كما يمكنك مراقبة أخطاء 404 التي تشير إلى محتوى غير متوفّر وتسمح بتحويل الطلبات تلك إلى عناوين أخرى، وتتميّز الإضافة بأنّه من السهل جدًّا إنشاء التحويل حيث يكفي إدخال العنوان القديم والجديد الذي ترغب بتحويل الزيارات إليه وأخيرًا نوع التحويل (301, 302, 307) الذي ترغب باستخدامه. إضافة Quick Page/Post Redirection تسمح إضافة Quick Page/Post Redirect بإرسال الزيارات من عنوان لآخر على ذات النطاق أو على موقع آخر، وتتمتع بالكثير من الخيارات المتاحة التي تسمح بإنشاء التحويل ونمطه، استيراد وتصدير لوائح التحويل، خيارات التجاوز override أو حذف كلّ عمليات التحويل التي تمّ إضافتها. إنشاء التحويل باستخدام htaccess. وتبقى هذه الطريقة من أبسط الطرق لإنشاء تحويل 301 من خلال إنشاء ملف htaccess. في الجذر الرئيسي للموقع -إن لم يكن الملف موجودًا مسبقًا- حيث أنّ هذه الطريقة سهلة وسريعة ومناسبة لمحرّكات البحث، لكن تذكّر بأنّ هذه الطريقة تعمل فقط مع خوادم أباتشي Apache. لتحويل زيارات صفحة واحدة: Redirect 301 /oldpage.html http://www.yoursite.com/newpage.html Redirect 301 /oldpage2.html http://www.yoursite.com/folder/ أمّا لتحويل جميع زيارات الموقع: Redirect 301 / http://newsite.com/ وتعدّ هذه الطريقة مناسبة جدًا في حال قمت بحجز نطاق جديد وترغب بتحويل زيارات الموقع القديم إلى الجديد شريطة أن تحافظ على مسارات الروابط النسبيّة كما هي، حيث يؤدي طلب الرابط من الشكل www.oldsite.com/helloworld إلى تحويل الزائر إلى www.newsite.com/helloworld . الخلاصة يفيد تحويل الزيارات من النمط 301 إن كنت تملك مجموعة من المنشورات القديمة والتي ترغب بأن تقوم بتحويل زياراتها إلى محتوى جديد للمحافظة على قوّة التقييم الخاص بها; كما يمكن استخدامه مع محرّكات البحث لإبلاغها بأنك تحافظ على محتوى جديد لموقعك. توفّر الإضافات المتاحة طرقًا سهلة لإنشاء التحويلات لموقعك، ولكن إن رغبت باستخدام الطريقة التقليدية فيمكنك اعتماد التحويل باستخدام ملف htaccess. ترجمة -وبتصرّف- للمقال Creating 301 Redirects With WordPress and How it Boosted Our Traffic لصاحبته Raelene Morey.
-
تحدّثنا في المقال السّابق عن البحث الدلالي، كيفية عمله ولماذا نحتاجه، وسنتحدث في هذا الجزء عن استخدام وتحسين البحث الدلالي في ووردبريس. كيفية تحسين البحث الدلالي في ووردبريس الآن وبعد أن تطرّقنا إلى بعض التفاصيل حول ماهية البحث الدلالي، وكيفية عمله، ولماذا يجب علينا الاهتمام به، يمكن أن نبدأ بالتركيز على الطرق التي يمكننا بها تحسين موقع ووردبريس الخاص بنا وفقًا لذلك. وقد تم تقسيم العملية إلى عدد من الخطوات الرئيسية. 1. فكر بالمستخدم النهائي إن الجزء الأكبر من تحسين البحث الدلالي يدور حول ما يريده المستخدم النهائي، وقد تحدّثنا عن ذلك في الجزء الأول. ولكن من وجهة نظر قابلة للتنفيذ فإنّه من المهم أن تأخذ بعض الوقت للتفكير فيما يريده جمهورك المستهدف. فكّر فيما يأمل أن يجده زائرك المثالي عندما يصل إلى موقع الويب الخاص بك. بعد ذلك، يجب عليك أن تأخذ بعين الاعتبار ما قد يبحثون عنه كي تحسّن من فرصة ظهور موقعك في نتائج البحث. قد يستغرق هذا الأمر قليلًا من التفكير للاقتراب من الجواب ولكن النتيجة النهائية ستجعل موقع الويب الخاص بك يفهم احتياجات زوّارك لأنه قد تم إنشاؤه بعد الأخذ بعين الاعتبار ما يريده الجمهور وتوقّعاتهم منه. إنّ الفكرة خلف البحث الدلالي هو معرفة ما يريده المستخدم وتقديم نتائج البحث والمحتوى الذي يحقق تلك التوقّعات. 2. أنشئ محتوى دقيقا وواضحا وفقًا لـ Neil Patel، فتحسين البحث الدلالي يعني التأكّد مرّتين من دقّة ووضوح كل جزء من المحتوى الذي تنشره، ونقتبس عنه: إنّ هذا يعني بأن كل مقال تنشره يجب أن يكون مركّزًا، ويحافظ على رسالته، ويقدّم المعلومات الواضحة للزوار. تذكّر: كلّما زادت كمية المعلومات ذات الصلّة التي تدرجها في المحتوى، كلّما كان من المحتمل أن ترتفع نسبة تقييم موقعك نتيجة لاحتوائه على كلمات مفتاحية وعبارات واستعلامات مناسبة. 3. التحكم بأساسيات SEO بشكل كامل كل هذا الحديث عن نتائج البحث الدلالي قد يجعلك تعتقد أن الكلمات المفتاحية لا تهم على الإطلاق وهذا غير صحيح أبدًا. إنّ الكلمات المفتاحية ما تزال مهمّة ولكن لم تعد بأهميتها سابقًا. مع ذلك، فتحسين المحتوى الخاص بك يمكن أن يكون مفيدًا لزيادة تركيز المحتوى الخاص بك لتصبح مناسبة أكثر لقرائك. إن من المهم أن تحقّق أقصى قدر من التأثير في كل صفحة أو منشور من خلال استثمار جميع المعلومات التي تؤثر على تقييم SEO. إن هناك العديد من الملحقات التي تستطيع مساعدتك لتحقيق هذا بسهولة، لكننا نميل إلى استحسان All-In-One SEO Pack عادة. 4. إعطاء عمليات البحث المكونة من عدة كلمات أهمية أعلى إن فهم واستخدام عمليات البحث المُكوّنة من عدّة كلمات (long tail keyword) أمر مهم، على الرغم من أن هذا قد يتناقض مع ما ذكرته سابقًا حول أهمية الكلمات المفتاحية، والسبب في هذا أنها مشتقة من عمليات البحث التي يقوم بها الأشخاص والتي ترتبط بكلماتك المفتاحية الأساسية. وبطبيعتها، فهي ذات طبيعة سياقية. إن تحسين عمليات البحث هذه في الواقع هو واحدة من الأسباب الأولى لارتباط SEO بالبحث الدلالي من الأساس. وكونك صاحب موقع ويب، فإن بإمكانك استخدام عمليات البحث الطويلة (ذوات الكلمات المفتاحية الكثيرة) لتضمن بأن محركات البحث تعرف بالضبط ما الذي تتحدث عنه. إن عمليات البحث الطويلة تعطي سياقًا للمحتوى الخاص بك وتظهر العلاقة بين الأفكار المختلفة المعروضة بداخلها لمحركات البحث. لذا، إن كنت تملك موقعًا حول أشكال الرقص، فإن من المفيد أن تذكر أسماء الرقصات المختلفة ضمن المحتوى، وعبر إدراج كلمات مثل "The Robot" في محتواك، فجوجل سيعلم ضمن سياق الحديث بأنك تتحدث عن الرقصة المسمّاة بهذا الاسم وأنك لا تتكلم عن الروبوتات. إن الجزء الأفضل حول تحسين الكلمات المفتاحية الطويلة بأنك لا تحتاج للتفكير مطوّلًا حولها، فغالبًا ما يكون كافيًا تضمين جملة من المحتمل أن يتم البحث عنها بشكل طبيعي. 5. استخدام مخطط الترميز تُعرف schema markup بترميز البيانات الهيكلية والتي تعطي أساسًا محرّكات البحث المزيد من المعلومات كي يظهر موقعك في نتائج البحث المشتقة من السياق بصورة أكبر. ستحتاج أن تضيف البيانات الدلالية إلى موقعك إن أردت أن تحصّل فوائد البحث الدلالي، وقد يبدو هذا مُعقّدًا في البداية، ولكن لا داع للقلق، فلن تحتاج أن تعيد بناء الموقع من البداية، فهناك الكثير من الملحقات المتوفرة التي تساعد في اختصار العمل على الخطوات التي سنذكرها لاحقًا. أما في الوقت الحالي، فمن المهم الحديث عن واحدة من الملحقات تحديدًا التي تساعد في إضافة schema markup إلى موقعك، وتدعى هذه الإضافة بـ Schema Creator لشركة Raven. إن من السهل استخدام هذا الملحق والذي يُضيف نموذجًا إلى موقعك يتم ملؤه تلقائيًا ببيانات مصغّرة microdata من موقع Schema.org في منشوراتك وصفحاتك، وتستطيع إدراج البيانات التي تنشؤها باستخدام رمز مختصر shortcode كما يمكنك تحرير البيانات بعد إدراجها، وتغيير شكلها، ويضيف الملحق أيقونة Schema Creator في المحرّر المرئي لتسهيل العملية عليك. كل ما تحتاج القيام به هو أن تختار ما نوع الـ schema الذي تريد إنشائه: شخص، منتج، حدث، مؤسسة، فيلم، كتاب أو عرض وجهة نظر. يمكنك أيضًا استخدام أداة البيانات الهيكلية ضمن أدوات مشرفي المواقع من جوجل لإنشاء schema markup لموقع ووردبريس الخاص بك، وهذا قد يكون أفضل حل إن كنت تتوقع أن تملك الكثير من المحتوى. مجموعة من الملحقات المفيدة إن محاولة تحسين الموقع بنفسك للاستفادة من البحث الدلالي بالشكل الأمثل يبدو أمرًا مُعقّدًا، وبالتالي قد تجد من الأسهل استخدام بعض الملحقات المفيدة لمساعدتك في هذا الصدد. 1. All-In-One SEO Pack إن All-In-One SEO Pack هو ملحق SEO كامل، يجعل من السهل استكمال جميع المهام المرتبطة بـ SEO. وتشمل على دعم لـ خرائط XML و Google Analytics وتساعد على توليد العناوين المتقدّمة، تحسين أنواع المنشورات المخصصة، توليد وسوم meta بشكل أوتوماتيكي، تعيين عناوين مخصصة وأوصاف meta، والمزيد. كما أن الملحق متوافق مع العديد من الملحقات الأخرى، وتساعد في القضاء على المحتوى المكرر، وتشمل على Nonce Security، وتم ترجمتها لـ 57 لغة. تتوفر نسخة مجانيّة وأخرى تجارية وتحتوي الأخيرة على مدير مزايا، دعم خرائط فيديوهات XML، التحكم على مستوى الفئة، الوسوم، تصنيفات SEO خاصة، دعم لـ WooCommerce والمزيد، مقابل 75$ في السنة. 2. Semantic Tags يركّز ملحق Semantic tags المجاني خصيصًا على الجانب الدلالي عبر مساعدتك على تحسين آلية فهم جوجل للعلاقة بين محتوياتك. بعد تثبيت الملحق، سيصبح من الممكن لك أن تقوم بإضافة وتعديل الوسوم في منشوراتك وصفحاتك. سيساعدك هذا على إنشاء وسوم دلالية تملك معنى أعمق من الوسوم التقليدية التي تضيفها في الصفحات والمنشورات، كما أن بإمكانك ربط المحتوى بالمزيد من المصادر باستخدام هذه الوسوم لتوفير سياق أغنى لمحتواك. 3. WordLift ملحق WordLift مجاني يستحق أن يؤخذ بعين الاعتبار، يُسهّل من عملية تنظيم الصفحات والمنشورات، حيث تسمح بإضافة "حقائق" إلى كل صفحة أو منشور على شكل نص وصورة، لتساعد على تحسين هيكلة موقعك، كما تقوم بنشر المحتوى بصيغة Linked Open Data لتجعله أكثر قابلية للأرشفة من قبل محركات البحث. يضيف هذا الملحق تعقيبات دلالية إلى محتواك ويساعد على تحسين التدفّق من خلال إعطاء النصائح حول المعلومات، الصور، والروابط. وفي الواقع فستقوم باقتراح صور وأشكال مجانية لتضاف إلى المحتوى لتساعد على تنظيمه وتحسين السياق لتجربة تصفّح أفضل وتضمن بأن الشريحة الأهم من الزوّار سيتمكنون من إيجاد موقعك بسهولة أكبر. 4. Kaimbo يعتبر ملحق Kimbo أحد حلول البحث الدلالي المجانية لووردبريس والذي يسمح بتحسين سياق المحتوى. يقوم الملحق بالتأشير على (highlights) الكلمات المفتاحية والأفكار، وتقدم وظيفة بحث دلالية متقدّمة لزوار الموقع، وتقوم بزحف آني على المحتوى لتضمن بأن يتم أرشفة موقعك بشكل اوتوماتيكي. يقوم الملحق أيضًا بأرشفة ملفات PDF لتجعل البحث ضمنها ممكنًا، ويملك قاعدة معلومات ضخمة تساعد على فهم الأفكار المرتبطة بعمليات البحث، كما يملك خاصية ذكية للإكمال التلقائي، والمزيد من المزايا كالإحصائيات والتثبيت بنقرة واحدة. 5. Add Meta Tags يسهّل Add Meta tags عملية تحسين البحث الدلالي من خلال إنشاء معلومات meta حول المحتوى بشكل أوتوماتيكي، لتمكّن من مشاركتها بسهولة مع المواقع الاجتماعية وتؤهلها لأرشفة أفضل في محركات البحث. يقوم الملحق بتوليد عنوان meta ووصف وكلمات مفتاحية ومخططات Open Graph ومعلومات Schema.org إضافة إلى JSON+LD وبطاقات Twitter. الخلاصة قد يبدو البحث الدلالي مُعقّدا ومخيفًا في البداية ولكن آمل بعد قراءة المقال أن يكون قد أصبح لديك فهم أفضل لما يعنيه وكيفية عمله وكيف يمكن استخدامه لتحسين موقع ووردبريس الخاص بك على صورة أفضل وفقًا لذلك. في نهاية المطاف، ستكافؤ جهودك من خلال جعل موقعك أكثر قابلية للعثور عليه من قبل الجمهور المستهدف وهذا بالتأكيد أمر جيّد. هل بذلت جهودًا لتحسين البحث الدلالي في موقعك؟ هل نسيت ذكر شيء حول الأمر؟ شاركونا تجاربكم في التعليقات أدناه. ترجمة -وبتصرّف- للجزء الثاني من مقال Using Semantic Markup with WordPress to Improve Your Search Results لصاحبته Brenda Barron.
-
تظهر بعض الأخطاء الشائعة بكثرة عند محاولة رفع ملفات إلى خادوم باستخدام بروتوكول FTP، وتذهب الأسباب إلى أبعد من أن تكون نتيجة خطأ في إدخال عنوان الخادوم، اسم المستخدم، كلمة المرور أو رقم المنفذ. هذا المقال موجّه إليك إن كنت تستطيع الاتصال بـ FTP محليًّا فقط، أو كنت تواجه مشكلة انقطاع الاتصال باستمرار، حيث سنلقي نظرة على الطرق المتوفرة لإصلاح أكثر 3 أخطاء شيوعًا. 1. لا يمكن إجراء الاتصال إطلاقا قد يحصل أن يبقى الاتصال غير ممكنًا حتّى بعد التحقق من أنّ بيانات الاتصال صحيحة، وتكون الخطوة الأولى باتجاه الحل هي التحقّق من نمط الإرسال في الإعدادات، هل هو سلبي passive أم نشط active؟ سنستخدم FileZilla كمثال لتوضيح الفكرة، فبعد فتح البرنامج نضغط على "تحرير Edit" في القائمة العُلويّة، ونختار "إعدادات Settings". في النافذة التي ستظهر لنا، نقوم باختيار "FTP" ضِمن "الاتصال Connection" وذلك في شجرة الخيارات التي تظهر جانبًا، للتحقّق فيما إذا كان الاتصال في النمط passive أو active، فإن كان النمط سلبيّ passive (وهو الافتراضي) فقم بتغييره إلى النمط النشط active، أو العكس كما في الصورة: لنختر الآن العنصر المسمّى "النمط السلبي Passive mode" في القائمة، ونقوم بتفعيل خيار "رجوع كامل إلى النمط النشط Fall back to active mode"، فإن كان الخيار نشطًا، قم بتفعيل الخيار الثاني بدلًا عنه "استخدام عنوان IP الخارجي بدلًا من ذلك Use the server’s external IP address instead"، وتأكّد من ألّا تقوم بتفعيل الخيار الثاني المذكور إلّا إذا اخترت نمط الاتصال السلبيّ passive سابقًا، تبيّن الصورة التالية الخطوات المذكورة: لا تنس الضغط على زر "حسنًا OK" في الزاوية اليمنى السفلية لحفظ تغييراتك، ومن ثم حاول الاتصال بالخادوم مجدّدًا. 2. خطأ "العديد من الاتصالات Too Many Connections" إن كنت قادرًا على الاتصال بالخادوم دون مشاكل، لكنّ الاتصال يستمر بالانقطاع عند محاولة رفع أو تنزيل ملفّات، فقد يكون هناك عدة أسباب لذلك، ومنها ظهور خطأ يخبرك بوجود العديد من الاتصالات، فهو يرجّح غالبًا أنّ إعدادات خادومك لا تسمح إلا بعدد قليل من الاتصالات عبر FTP، وقبل أن نبادر إلى إصلاح الخطأ، تأكّد بأنّك قمت بإنهاء اتصالك الحالي عبر FTP قبل المتابعة وإلا ستمضي ساعات في محاولة إصلاحه. وبهدف التوضيح، سنستخدم لوحة تحكّم الخادوم WHM كمثال حول إصلاح هذه المشكلة. فبعد تسجيل الدخول في WHM، نتوجه من الصفحة الرئيسية إلى صفحة "إعدادات الخدمة Service Configuration"، ومنها إلى "إعدادات خادوم إف تي بي FTP Server Configuration"، حيث سنرفع عدد الاتصالات المسموحة في حقل الحدّ الأعلى للاتصالات وحقل الحدّ الأعلى للاتصالات لكل IP، وستكون الأمور بخير طالما أنّ هذين الرقمين أعلى مما كانوا عليه من قبل. عادة ما أقوم بوضع الرقم 100 في كل حقل لأكون بأمان، ولا تنس أن تضغط على "حفظ Save" في أسفل الصفحة لتخزين التغييرات. يتطلب دخول لوحة تحكم WHM أن تملك صلاحية مدير النظام root، فإن لم تملك هذه الصلاحية قم بالاتصال بمزوّد خدمة الاستضافة واشرح المشكلة لهم لمساعدتك. حان الوقت الآن لإيقاف الاتصالات الحاليّة يدويًا، وسنوضّح كيف يتم ذلك عبر لوحة تحكّم العميل cPanel. فبعد تسجيل الدخول إلى الّلوحة، نتوجّه إلى قسم الملفّات ونضغط زر "إدارة جلسات إف تي بي FTP Session Control". سنقوم في الصفحة التي تظهر لنا، بإغلاق جميع الاتصالات المعروضة بالضغط على زرّ × الأحمر الموجود على جانب كل سطر، وبعد الانتهاء نضغط زرّ إعادة التحميل reload لتحديث القائمة والتأكّد من عدم تبقّي أيّة اتصالات. هنا يكمن الجزء الذي يكون من المهمّ فيه أن تكون قد أنهيت اتصالك الحالي في البرنامج الذي تستخدمه للاتصال عبر FTP كما أشرت سابقًا، فلو لم تقم بذلك سلفًا، ستجد المزيد والمزيد من الاتصالات التي تظهر لديك في القائمة عند كل تحديث لها، الأمر الذي قد يضيع لك الكثير من الوقت قبل أن تكتشف السبب. وحتى لا تتفاجأ، فمن الطبيعيّ أن تجد العديد من الاتصالات التي ستضطر لإنهائها، خصوصًا إن كنت تواجه هذه المشكلة تحديدًا، لذا تأكّد من أنّك قمت بإنهاء جميع الاتصالات حتى آخر واحد منها. لنعد الآن إلى FileZilla ونضغط على "تحرير Edit" في القائمة، ومن ثمّ "إعدادات Settings" وأخيرًا نختار عنصر القائمة المسمّى "عمليات الإرسال Transfers"، ونتأكد من أنّ قيمة "أقصى عمليّات متزامنة للإرسال Maximum simultaneous transfers" ليست كبيرة وعادة ما تكون هذه القيمة إما 1 أو 2. لا تنس أن تقوم بحفظ أيّ تغييرات قد أجريتها أيضًا. يجب أن تكون الآن قادرًا على إجراء اتصال وتحميل أو تنزيل بعض الملفّات، ولكن إن بقيت تعاني من مشاكل، فعد مجدّدًا إلى "عمليات الإرسال Transfers" وتأكّد فيما إذا كان الحدّ من عمليات التحميل والرفع المتزامنة إلى حوالي 5 أو 10 سيساعد في حلّ المشكلة، فهو يساعد في بعض الحالات النادرة رغم أنّه غير ضروري عادةً. 3. خطأ في إرسال ملف أثناء رفعه إن كنت تستلم رسالة خطأ غريبة عادة عند محاولة رفع الملفات، فإنّ سببها معظم الوقت هو الوصول إلى الحدّ الأقصى لحجم الملف المسموح رفعه. لحسن الحظ فإنّ من السهل تصحيح هذه المشكلة إن كنت تملك صلاحية مدير للنظام ولكن إن لم تكن فسيتوجّب عليك الاتصال بمزوّد خدمة الاستضافة لإجراء التصحيح. لنرى كيف يتم التصحيح باستخدام لوحة تحكم WHM. نتوجّه أولًا إلى "إعدادات الخادوم Server Configuration" في القائمة ثمّ إلى صفحة "محرّر إعدادات بي اتش بي PHP Configuration Editor". بعدها نختار "النمط المتقدّم Advanced mode" في أعلى الصفحة لتظهر جميع الإعدادات المتاحة، كما في الصورة: سنجد إلى الأسفل قليلًا خيارين هما "post_max_size" و "upload_max_filesize"، سنقوم بزيادة الرقم الموجود في الحقلين إلى أيّ قيمة نرغب بها ولكن تذكّر فقط بأنه في حال وضع قيمة كبيرة جدًا فسنخاطر بأن نتجاوز مساحة التخزين المخصصة من مزوّد خدمة الاستضافة. أستخدم عادة القيمة 3000M (التي تعني 3000 ميغابايت) وأجدها مناسبة لي، لكنّي أعلم مسبقًا بأنّي أملك مساحة التخزين الكافية لها، لذا فإن استخدام القيمة 120M - 320M تبدو عمليّة أكثر بشكل عام. لا تنس ضغط زرّ "حفظ Save" في أسفل الصفحة عند الانتهاء، ومن ثمّ حاول مجدّدًا رفع ملفّاتك ويفترض أن تتم العمليّة بنجاح، ولكن في حال لم يحدث ذلك، فتأكّد مجدّدًا من أنّ حجم كلّ ملف من الملفات التي تحاول رفعها أقل من القيمة التي اخترتها. الخلاصة من المحتمل جدًّا أن تضطرّ إلى اتباع الخطوات الثلاثة السابقة للوصول إلى النتيجة المرجوّة، ولكن إن استمرت المشكلة، فإنّ هذا هو الوقت المناسب للاتصال بمزوّد خدمة الاستضافة لمساعدتك، فقد تكون المشكلة متعلّقة بالخادوم لديهم. من المهمّ جدًّا في حال رفع ملفّات موقع ويب، التحقّق فيما إذا كان الموقع يعمل عند طلبه عبر شبكة الإنترنت، فإن لم يكن كذلك فسيكون لديك مشاكل أخرى يتطلب معالجتها أولًا. فيما عدا ما ذكرناه، فقد أصبح لديك ما تحتاجه لنقل ملفّاتك عبر FTP دون أخطاء. ترجمة -وبتصرّف- للمقال 3Common WordPress FTP Upload Errors and How to Fix Them لصاحبته Jenni McKinnon.
-
تغيّر محركات البحث طريقة عملها باستمرار، فخلال بضع سنوات انتقلنا من خوارزميات البحث عن كلمة في نص بشكل مباشر، إلى خوارزميات البحث الدلالي semantic search التي تقوم بإعطاء الأولوية للسياق context عوضًا عن مطابقة كلمات البحث تمامًا. لقد ولّت تلك الأيام التي كنا نقوم فيها بحشو الكثير من الكلمات في خانة البحث في مواقع محركات البحث للحصول على نتائج، ولو أردنا أن نحصل على أعلى تقييم وعدد نقرات ممكن، فنحتاج أن نبدأ بالتفكير باستخدام الترميز الدلالي Semantic Markup. إنّ كلّ شيء متعلق بالسياق context، ولو أردت من موقعك أن يعمل بشكل جيّد مع كل ما تتيح جوجل من ميّزات، فعليك أن تجري بعض التعديلات على كيفية تقديم موقعك لمحركات البحث، وستحتاج أيضًا للتفكير بشكل مختلف حول كيفية إنشاء المحتوى. ما هو البحث الدلالي Semantic Search؟ يشير البحث الدلالي إلى العملية التي تقوم بها محرّكات البحث والتي تستخدم عدّة مصادر في إعداد نتائج البحث، فما تقوم به أساسًا هو استخراج المعلومات من عدّة قواعد بيانات لتجميع أفضل نتائج بحث مُمكنة وأكثرها ارتباطًا بالسياق، في أيّ وقت. ويعرّف البحث الدلالي وفقًا لموقع Techopedia بـ: وعلى اعتبار وجود كمية ضخمة جدًّا من البيانات عند عرض نتائج البحث، فإنّ البحث الدلالي يخطو خطوة إضافية مُقارنة بالبحث التقليدي الذي يستخدم الكلمات المفتاحية، ويخوض إلى مستوى أعمق من مجرّد البحث عن الكلمات المُدخلة. وفقًا لـ Croud.com، فإنّ البحث الدلالي يقوم بهذا عبر محاولة فهم "هدف استعلام البحث ضمن سياق محدّد"، وتقوم محركات البحث الآن بهذا عبر التعلّم مما يقوم المستخدمون بالبحث عنه لإيجاد صلات بين عمليات البحث الفرديّة. فعلى سبيل المثال، إن قمت بالبحث عن primary election results (نتائج الانتخابات الأوّلية) في الولايات المتحدة الأمريكية البارحة، وقمت اليوم بالبحث عن كلمة primary ، فسيقوم محرك البحث جوجل غالبًا بعرض نتائج الانتخابات الأولية كحالة محتملة لأنه يعلم ما الذي تقصده. إضافة لما سبق، فليس هناك علاقة ما بين البحث الدلالي وتطور الذّكاء الاصطناعي، فالبحث الدلالي ليس نوعًا من الذكاء الاصطناعي، رغم وجود بعض الشبه في كيفية قيام الخوارزميات بالتعلّم والتأقلم لعرض نتائج بحث للمستخدمين بناء على ما قام المستخدم بالبحث عنه من قبل. إنّ ما يقوم به محرك البحث جوجل طوال الوقت من تصحيح تلقائي للأخطاء الإملائية المرتكبة في استعلام البحث هو مثال آخر على البحث الدلالي: لقد كانت هذه الوظيفة متاحة قبل أن يظهر البحث الدلالي في تحديث Google Hummingbird عام 2013 بوقت طويل. وبعد ذلك التحديث، بدأنا نرى المزيد من النتائج الحَدسيّة كإمكانية سؤال جوجل عن عاصمة ولاية كاليفورنيا: وإنّه لأمرٌ مثيرٌ أن يكون من الممكن توفير نتائج متعلقة بالسياق بالاعتماد على عمليات بحث سابقة، كاستخدام خدمة Google Now على الهاتف المحمول عبر الأوامر الصوتية، كما تظهره الصورة التالية حيث قمت بطرح السؤال "متى أعلنت ولاية؟" مباشرة بعد سؤالي السابق، فحصلت على إجابة تتعلق بولاية كاليفورنيا تحديدًا. إنّ من الممكن إِمضاءَ اليوم في طرح المزيد من الأمثلة ولكنّي أعتقد بأن الأمثلة المطروحة كافية لإيصال فكرتي حتّى الآن. ولكن، كيف يعمل البحث الدلالي؟ لقد بدأت جوجل تعير الاهتمام إلى معاني الجمل والنصوص كاملة منذ أن طُرح تحديث Hummingbird عوضًا عن معنى كُل كلمة تشكّل الجملة أو النص، فقد غدا كل شيء متعلقًا بالسياق، ولم يكن للبحث الدلالي أن يظهر لو لم يتم وضع خوارزميات قادرة على اكتشاف الهدف من استعلامات البحث، لذا فإن النتائج لم تعد متعلّقة بتطابق الكلمات المستخدمة في البحث مع تلك الموجودة في النصوص، وإنما أصبحت تعتمد على دلالاتها. يوضّح Techopedia الأمر بطريقة أخرى: إنّ هذا ما نعرفه عن كيفية قيام جوجل بتوفير نتائج البحث الدلالية، وبصراحة فنحن لا نعلم الكثير حول الأمر، فالشركة كتومة جدًّا حول تفاصيل خوارزميتها وهذا أمر متوقّع، فبينما نعلم أن نتائج البحث الدلالية تتأثر بما قمت بالبحث عنه سابقًا، فقد يكون هناك الكثير من العوامل الأخرى التي لا نعلم عنها أيّ شيء إطلاقًا. نحن نعلم بأن جوجل تتعلم الكثير من خلال عمليات البحث التي يقوم بها كل مستخدم، لذا فإنّ النتائج التي نحصل عليها لا تتعلق فقط بعاداتنا في البحث (رغم أنّ لها وزنًا كبيرًا في التأثير على نتائج البحث الخاصة بنا) بل تتأثر أيضًا بعادات البحث الخاصة بمستخدمين آخرين استخدموا بحث جوجل في السابق، والروابط التي قاموا بنقرها، وما قاموا بالبحث عنه قبل كل استعلام جديد، وما قاموا بالبحث عنه بعد كل استعلام جديد، إضافة إلى عادات أخرى تخُص كلّ مستخدم. وكما قلت، فإنّ الكثير من العوامل التي لا نعلم عنها شيئًا قد تدخل في تخصيص نتائج البحث، ولكن فقط لكوننا لا نعلم كلّ شيء عن كيفية عمل البحث الدلالي، فهذا لا يعني بأنه لا يجب القيام بأيّ شيء مما من شأنه تعزيزه إيجابًا، فالنتائج التي تظهر لنا بعد تسجيلنا الدخول في خدمات جوجل وتلك التي تظهر بعد تسجيل الخروج تخبرنا بأنّ هذه الفكرة ممكنة. لماذا نحتاج إلى تحسين البحث الدلالي منذ إطلاق مشروع Hummingbird منذ عدة سنوات مضت، كان هناك انتعاش في أهمّية تحسين البحث الدلالي، وكأي مشروع، لم يبادر الكثيرون إلى اعتناق التقنية في البداية. وليس هناك وقت أفضل أساسًا من الحاضر للقفز على موكب البحث الدلالي. فأولًا، يبدو أنه باق وليس مجرد أمر عرضي عابر، وثانيًا، مع القليل من الجهد الإضافي في عالم تحسين البحث الدلالي فأنت تضمن بأن يقدم موقع الويب الخاص بك أداء أفضل. الفوائد المتوقعة من تحسين عملية البحث الدلالي 1. تحسين المرتبة في محركات البحث تحدّث Matt Cutts من قبل بأنّ إضافة البيانات الدلالية لموقع الويب الخاصة بك (الأمر الذي سنتحدث عنه لاحقًا) لن يقوم بتحسين رتبتك في محركات البحث، ولكنه يضمن بأن يكون المحتوى الخاص بك مرئيًّا على أوسع نطاق مُمكن لدى سياق الجمهور المعنيين، ويضمن بأنّ الأشخاص الذين يبحثون عن المحتوى الخاص بك، سيتمكنون من العثور عليه. 2. تحسين نسبة النقر على الروابط إنّ جمالية تحسين البحث الدلالي هو أنه يضمن أن تظهر الروابط إلى موقع الويب الخاص بك في نتائج البحث بالطريقة الأكثر جاذبية، حيث تبدو نتيجة البحث التقليدية مثل الصورة التالية: بينما تظهر نتائج البحث المحسّن كالشكل التالي: يدعى هذا الشكل بالقصاصة الغنيّة بالمعلومات rich snippet وعلى الرغم من أنها قد مرّت ببعض التعديلات إلا أنها ما تزال مستخدمة بكثرة ويمكن أن تشمل أشياء مثل: الوصلات الداخلية breadcrumbs الصور التقييم تضمن هذه البيانات الدلالية بأن يتم تقديم المحتوى الخاص بك تمامًا كما ترغب فيه على وسائل الإعلام الاجتماعية، فمواقع التواصل الاجتماعي مثل Facebook, Twitter, Google+ وLinkedIn تملك هياكل البيانات الدلالية الخاصة بها والتي تستطيعُ أن تقوم بملئها وعادة ما تشمل حقولًا للعنوان، وصف meta، كلمات مفتاحية وصورة. هذا يعني بأنّه لو أراد أحد مشاركة مقالك على Twitter، فالنص والرابط والصورة المرفقة سيتم تضمينها بشكل تلقائي، مما يعطيك إمكانية التحكّم بكيفية تسويق محتوياتك عبر شبكة الإنترنت بالكامل، وهو أمرٌ رائع. 3. تحسين إمكانية الوصول للمحتوى هناك فائدة رائعة من تحسين البحث الدلالي هي أنّ الوصول إلى موقعك يغدو أكثر يسرًا، فمنشوراتك وعناوين الصفحات ستكون أكثر وضوحًا وإيجازًا، إضافة إلى توصيفها. هذا يعني أنّ المستخدمين ذوي الاحتياجات الخاصة سيكونون قادرين على الوصول إلى موقعك بسهولة أكبر عبر قارئات الشاشات، ولا يعني هذا بأنّ جهودك في هذا الصدد يجب أن تتوقف عند هذا الحد. إنّ تحسين البحث الدلالي هو مجرد خطوة أولى كبيرة نحو تحقيق هذه الغاية. 4. الأخذ بعين الاعتبار نية المستخدم كما ناقشنا سابقًا، فتحسين البحث الدلالي يعني التفكير فيما يريده المستخدم النهائي بشكل افتراضي، وبينما قد تملك أفضل بيانات دلالية في الوسط الذي تنشط به، فإنّ عدم وجود محتوى ذي صلة بالسياق يمكن أن يضر بك. ومن جانب آخر، فالتفكير في البحث الدلالي ونوايا المستخدم أثناء عملية إنشاء المحتوى يعني أنك سوف تنشر بطبيعة الحال محتوى أكثر فائدة وصلة لقرائك. في المقال القادم سنتحدّث عن كيفية استخدام وتحسين البحث الدّلالي على مدوّنات ووردبريس. ترجمة -وبتصرّف- للجزء الأول من مقال Using Semantic Markup with WordPress to Improve Your Search Results لصاحبته Brenda Barron.
-
- 3
-
- الترميز الدلالي
- البحث الدلالي
- (و 3 أكثر)
-
يوجد الكثير من المقالات التي تتحدث عن السّير الذاتية، وللتّميّز قليلًا عن تلك المقالات سأحاول أن أعطيك بعض النصائح العمليّة حول كيفية جعل السيرة الذاتية تبدو أكثر جاذبية، وكيف تضع نفسك في مرتبة النجم بدلًا من مرتبة "المبرمج الجيّد". قد تأخذ العملية عدة سنوات حتى تتمكن من زيادة زَخم سيرتك الذاتية، ولكن عندما تنتهي، ستصبح قادرًا على المطالبة بـ 100$ إضافيّة في السّاعة لقاء عملك دون أن تواجه أي تردّد من عملائك في دفع ذلك المبلغ. صفحة واحدة سيرة ذاتية واحدة فقط كان ينطبق عليها هذا الوصف من كلّ عشرة سير ذاتيّة كانت تصلني كلّ يوم، بينما كانت البقيّة تستهلك ثلاث صفحات أو أكثر، ما يجعلها تبدو أقلّ احترافيّة بكثير، فإن لم تستطع وصف نفسك في صفحة واحدة ستتولد الشكوك حول مهاراتك، وهذا أمرٌ يجب ألا يحصل لمهندسي البرمجيات software engineer خصوصًا، حيث يجعلك تبدو غير قادر على تحييد الأمور غير الهامّة والتركيز على ما يهم حقًّا، وإنّه لَمِنَ المملّ قراءة ثلاث صفحات حول نفس المُبرمج. لذا، حاول جاهدًا دون استثناءات الالتزام بهذه القاعدة، فسيرتك الذاتيّة كالملخّص التنفيذي لمنتج تحاول تسويقه، أو مُلصق دعائي، يجب أن تكون قصيرة ومباشرة، فإمّا أن يقوم أصحاب العمل بشراء المنتج أو رميه بعيدًا، فهم لا يرغبون بقراءة سيرة ذاتية; إنّهم يرغبون باتخاذ قرار حول شراء مهاراتك أو تجاهلها، وكلّما زاد عدد الصفحات قلّت معها فرصتك. لا تكذب مهما فعلت بسيرتك الذاتيّة فلا تكذب أبدًا حول أيّ كلمة فيها. تستطيع أن تخفي نصف الحقيقة أو أن تعيد صياغتها كيفما شئت، تستطيع أن تكتم معلومات عن نفسك، لكن لا تكذب أبدًا، فأنت لا تعلم من سيقرأها وفي أيّ مكتب سينتهي بها الحال. كن مستعدًّا لتوضيح كلّ كلمة ذكرتها فيها. لو قُلتَ مثلًا: أنا "خبير JavaScript"، فكن جاهزًا لشرح أهمّ الميّزات الجديدة في الإصدار 6 من ECMAScript. إن لم تستطع، فلا تستخدم كلمة "خبير". الفكرة تكمن في أن تكون جاهزًا لإثبات كلّ كلمة عند الحاجة. صورة جذابة لك في أعلى الصفحة إن رغبت بالعمل معهم فسيرغبون بمعرفة من قد يعملون معه، لذا فصورتك الشخصيّة هي عنصر أساسي من السيرة الذاتيّة، فحاول أن تجعلها تبدو احترافيّة حتى لو اضطررت للدفع مقابلها. ركّز جيّدًا على جودة صورتك فهي عنصر هامّ جدًا. لا حاجة للتّذكير بذلك، لكنه يجب عليك أن تظهر مبتسمًا في هذه الصّورة، ولتكن الصّورة عفويّة فلا داع للتكلّف وارتداء بذلة رسميّة، يكفيك مثلًا قميص مع خلفية مرحة. يجب أن تظهر سعيدًا ومرتاحًا، فليس بالضرورة أن تجاهد لجعلهم يقبلون توظيفك، عليك أن تجعلهم يشعرون بالرّغبة في توظيفك من تلقاء أنفسهم، هذه هي الرسالة التي ستحاول إرسالها لهم من خلال صورتك، تمامًا كما في مواقع التعارف الاجتماعية. لا حاجة لكل من "الهدف Objective" و "اللقب Title" "كبير مطوّر برمجيات"، "مبرمج جافا محنّك"، "اختصاصي تكنولوجيا معلومات موهوب" ... إلخ، إن هذه الألقاب مملّة ولا تسوقّك جيّدًا فهم يعلمون من أنت من خلال قراءتهم لسيرتك الذاتية. إلى جانب هذا، فإنّك تحدّ من نفسك ضمن إطار هذا اللقب، فقد يرغبون بإيجاد نائب مدير القسم الهندسي بينما تقول سيرتك "مهندس برمجيّات". إنّ عدم التطابق الواضح هذا سينقص من فرصك بالعمل لديهم. اسمك هو ما يجب أن يكون العنوان في السيرة الذاتيّة. باقة كبيرة من المهارات يبيّن هذا القسم لأصحاب الوظيفة أين يقع "ثِقَلك التقنيّ"، ويجب أن يحوي على لائحة قصيرة جدًّا من المهارات لا تتجاوز 12 بندًا. فمن غير الممكن أن تكون خبيرًا في MySQL ،PostgreSQL ،Oracle ،MS SQL في الوقت ذاته; وقد تظن لبرهة أن وجود الكثير من المهارات يُعطي الانطباع بأنّك خبير، بينما في الواقع يُفهم من ذلك بأنّك لا تُتقن أيّ شيء، وهو أمرٌ عليك تجنّبه. ولكن كيف تنتقِ المهارات التي ستذكرها؟ عليك بدون مبالغة إيجاد أفضل ما تَبرَع فيه من مهارات وتضعه في ذلك القسم، تأكّد من أنّ المهارات المذكورة على ذات المستوى في التصنيف، فعلى سبيل المثال Java و AngularJS لا يجب أن يوضعا بجانب بعضهما البعض، فـ Java على مستوى أعلى من AngularJS، وبالتالي قد تكتب "Java و SQL و HTTP" أو "AngularJS و Spring Framework و Web Sockets". نصيحتي هي ألّا تصف مهاراتك وصفًا شموليًّا قبل أن تصبح رمزًا معروفًا، فـ Java تبدو مناسبة كمهارة في السيرة الذاتية لـ Jon Skeet، لأنّه بدون شكّ يعرف كلّ شيء عن عالم Java، ومشهودٌ له بذلك. أما لو كان لديك خبرة 3 سنوات فكيف لك أن "تتقن Java"؟ ربما تعرف استخدام بضعة مئات من الصفوف فيها فحسب، لهذا السبب فإنّه من الأفضل أن تذكر الأجزاء التي تتقنها في Java تحديدًا. وكما ذكرت سابقًا، كن دقيقًا في وصف مهاراتك قدر ما أمكنك. ملفك الشخصي على StackOverflow.com بغضّ النظر عن كل ما يُقال عنه، فقد أصبح StackOverflow المنصّة الأساسية -بحكم الواقع- التي تطرح فيها الأسئلة والأجوبة التقنيّة، فتواجدك وتقييمك المرتفع هناك سيرسل رسالة واضحة لصاحب عملك -المحتمل- بأنّك نجم (أو نجم صاعد). لن تجد هناك الكثير ممن حصل على 100 ألف نقطة تقييم أو أكثر، فلم لا تصبح أحدهم. وحتّى لو لم تكن تملك حسابًا على StackOverflow بعد، أنشئ واحدًا الآن وأمضِ ساعة واحدة بالإجابة على الأسئلة الجديدة كلّ يوم لعدة أشهر، وستحصل على 1000 نقطة تقييم أو أكثر، إن اعتبرنا أنّك كنت مساهمًا لا متفرّجًا فقط. هذا كاف في البداية، ولا تنس أن تضع رابط صفحة حسابك في سيرتك الذاتية. قد لا تكون قادرًا على الإجابة مباشرة، حينها اقرأ إجابات الآخرين، قم بالتعليق عليها، حاول إثراءها، وصحّح ما أمكنك، لتكن عضوًا نشيطًا في المجتمع. ملفك الشخصي على GitHub من يستطيع إنكار أن GitHub قد أصبح المنصّة الأساسية للبرمجياّت مفتوحة المصدر. ولكونك مطوّر برمجيات من العصر الحديث، فيجب أن يكون لديك حساب عليه كي تملك أثرًا واضحًا في عالم البرمجيّات مفتوحة المصدر إن أردت التسويق لنفسك بسعر أعلى. ولكن لماذا قد تهتم بهذا الأمر؟ إن مساهمتك في عالم البرمجيّات مفتوحة المصدر، سيمكّن صاحب عملك المحتمل بأن يرى ما يظنّه السوق في برمجياتك وفيك أنت، ووجودك فيه هو ضمانة له، تزيل خوفه من أن يرتكب خطأً بتوظيفك، فلا بدّ أنّ أحدهم قد شاهد شيفراتك البرمجيّة، وربما حصلت على بعض الثناء على مشاريعك أو قام أحدهم بالتصويت لها. بالنتيجة، ستجعلهم يشعرون بارتياح لاختيارك. لن تحتاج لصرف الكثير من الوقت على المصادر المفتوحة لتكون من "النخبة"، يكفي أن تشارك في تلك البرمجيّات التي تستخدمها أنت، فإن كنت تستخدم Sinatra في عملك، ألق نظرة على شيفرتها المصدريّة وستجد الكثير من الأجزاء التي يمكن إجراء إضافات أو تحسينات عليها. اعرض مساعدتك أو قم ببساطة بإرسال طلبات الجذب pull requests الخاصة بك هنا وهناك. إلى جانب هذا، أضف منتجاتك ومشاريعك الخاصة وسوّق لها، وستذهل لمقدار المستخدمين والمتابعين الذين ستحصل عليهم خلال عدّة سنوات بهذا العمل. الشهادات يعتقد البعض بأنّ الشهادات غير مهمّة، وهذا قد يكون صحيحًا في بعض الحالات، ولكنّ سيرتك الذاتيّة يجب أن تحوي بعضًا منها، فهناك شهادات من اليسير الحصول عليها ببضعة أسابيع من الدراسة وبضع مئات الدولارات، حينها لن تبقى مجرّد مبرمج Java وإنّما مبرمجًا معتمدًا، وليس هناك الكثير منهم. نعم هناك ملايين مبرمجي Java حول العالم ولكنّ نسبة قليلة منهم فقط من يمتلكون شهادة مبرمج معتمد، وبغضّ النظر عمّا إن كنت تعتقد بأهميّة تلك الشهادات أم لا، احصل عليها. تجنّب المواقع التي تدور حول اعتمادياتها شبهات مثل BrainBench وغيره. صحيح بأنك تستطيع أن تحصل على شهادة معتمدة منها ولكن لا تذكرها في سيرتك الذاتيّة فهذا سيثبت فقط بأنّك فخور بإنجازك المشبوه، وهذه إشارة غير جيّدة. أسماء وأرقام حقيقية عليك أن تكون حذرًا مع هذه النّقطة. بداية، عليك أن تبحث في ماضيك عن أسماء مشهورة أو أرقام كبيرة. على سبيل المثال، منذ 10 سنوات كنت أساعد شركة ناشئة في كتابة برمجيّة كانت IBM أحد مستخدميها، وعلى الرغم من أنّ IBM توقّفت عن استخدام هذه البرمجيّة بعد بضعة أشهر ، إلّا أنّها استخدمتها فعلًا، وبالتالي يمكن أن أكتب في سيرتي بأنّي: "كتبت برمجيّة لـ IBM"، فهل أكون كاذبًا؟ لا. وإن سُئلت عمّا قمت به بالضبط لـ IBM، سأكون قادرًا على الشرح. في معظم الحالات لن أُسأَل، ولكنّ فرصتي بأن يتمّ وضع سيرتي الذاتيّة في أعلى الكومة ستصبح أكبر. تستطيع القيام بذات الأمر مع الأرقام، إليك قصة حقيقية أخرى. منذ بضعة سنوات، كنت أساعد شركة في إعداد Continuous Integration Pipeline، ولم يكن الأمر صعبًا، لكنّ الشركة كانت تحصل على 5 ملايين زيارة يوميًّا عبر موقعها. وعلى الرغم من أنّه لم يكن لي علاقة بالحصول على هذا الرقم، لكنّي عملت في الشركة لبضعة أشهر، وبالتالي يمكنني أن أقول في سيرتي: "قمت بإعداد Continuous Integration Pipeline لمتجر إلكتروني ذي 5 ملايين زيارة يوميّة"، وفي حال سؤالي عن التفاصيل سأتمكّن من إعطائها لهم، لأنّي لا أكذب. استخدم هذه التقنية بحذر دون أن تكذب، ولا تخشَ من ذلك، فسيرتك الذاتيّة تحتاج لأسماء وأرقام كبيرة. المدونة أنشئ مدوّنتك الخاصة وابدأ بالكتابة عن إنجازاتك اليوميّة، وعن الشيفرات البرمجيّة التي تكتبها وتقرأها، وعمّا تشاهده في المكتب، وعن أفكارك ومشاريعك، وعن الكتب التي تقرأها. إن أردت أن تتقاضى أجرًا كبيرًا فستحتاج أن تملك مدوّنة قطعًا. وليس بالضرورة أن تكون المدوّنة مشهورة، فلا تعر انتباهًا للأرقام، لكن يجب أن تكون معدّة ومصمّمة بشكل جيّد. لا تستخدم WordPress أو Blogger أو Tumblr. عوضًا عن ذلك وما أفعله شخصيًّا، أنصحك باستخدام خدمات توليد الصفحات الثابتة مثل Jekyll وقم باستضافتها على صفحات GitHub. وإلى جانب كون هذا إضافة قيّمة إلى سيرتك، فإن الكتابة المنتظمة ستساعدك في ترتيب أفكارك، مشاريعك وقراراتك. هذا ما أجنيه شخصيًّا على الأقل من مدوّنتي. التعليم سأكتفي في هذا المجال بأن أذكر مستوى شهادتي، "ماجستير" أو "بكالوريوس" يكفي، وليس هناك حاجة لأذكر متى تخرّجت أو من أي مؤسسة تعليمية، فأستطيع ذكر ذلك لاحقًا عند سؤالي، ولكنّ هناك استثناءان لهذه القاعدة. بداية، إن كنت تملك شهادة دكتوراه فاذكر هذا في سيرتك فهي مهمّة وقيّمة لعدم وجود الكثير من حملتها في وسط المبرمجين. ثانيًا، إن كنت خريج جامعة مشهورة مثل ستانفورد، معهد ماسوستش للتكنولوجيا، أو شبيه ذلك، فاذكرها أيضًا. المؤتمرات يجب عليك أن تُلقي بعض المحاضرات هنا وهناك بشكل متواصل، ولكن حتّى تغدو قادرًا على الوصول إلى المؤتمرات الكبيرة، قم بذلك في أيّ مكان آخر يقبلون بك فيه. فمثلًا تستطيع إنشاء حساب على موقع lanyrd (أو ما شابهه) وتحقق باستمرار أيّ المؤتمرات تبحث عن متحدّثين وقم بإرسال طلبك وستفاجئ بأن بعضهم سيقبلون بعض أفكارك. إن العناوين الأسهل للبدء بها هي الحديث عن خبرتك العملية مع بعض التقنيّات والأدوات الحديثة، كسبيل المثال "كيف يساعدنا Docker في تحسين الإنتاج" أو "خمسة مشاكل لدى تنصيب Apache Spark"، أو أن تصف ما قمت بإنجازه على مشروع عملت عليه مؤخّرًا، فلا يهمّنا حقًّا ما تتحدث عنه. ما يهمّنا هو أن تصبح معروفًا، فإن قبلك السوق، فصاحب العمل سيثق بك أكثر. هذا تمامًا ما تحتاجه لتتمكن من طلب أجرة أعلى. تاريخ مسيرتك المهنية كصاحب شركة، لا يهمني شخصيًّا تاريخك المهنيّ على الإطلاق. على العكس من ذلك، فلو لم تشغل من قبل وظيفة بدوام كامل، ربما أكون مهتمًا بالعمل معك أكثر، لكنّ هذا رأيي فقط، لأنّي أؤمن حقًّا بأنّ المكاتب الحديثة والوظائف بدوام كامل تحوّل المبرمجين إلى عبيد (لا مبرمجين فقط). أما باقي أصحاب الشّركات الأخرى فقد يفكّرون أو غالبًا يفكّرون بطريقة مختلفة، لهذا السبب عليك أن تذكر في أيّ الشركات أمضيت السنوات العشرة الماضية من حياتك، وأنصح بإبقاء هذه القائمة قصيرة، حتى لو عملت في 8 شركات في السنوات العشرة الأخيرة فلا تذكر هذا، 3 تكفي، هذا سيظهر لهم بأنّك عبد جيّد لديك ولاء لسيّدك السابق (لم تغيّر عملك كثيرًا). هذا ما يرغبون برؤيته، لأنهم يخطّطون لشرائك ليكونوا أسيادك الجدد. ACM, IEEE, JUG والعضويات الأخرى إن هذه العضويّات لا تعني شيئًا إطلاقًا إلّا أن تثبت بأنّك عضو في هذه المجتمعات. وكما في معظم ما ذكرناه سابقًا، سيثق بك صاحب العمل أكثر إن كان السوق يثق بك. إنّ هذه العضويّات لا تعني أبدًا أن أحدًا يعترف بك، نظرًا لأنك تحصل عليها بدفع رسوم سنويّة فقط. ولكن، طالما أنّك تدفع هذه الرسوم بخلاف كثيرين، فإنّ هذا يجعلك أكثر وثوقيّة من الآخرين. الهوايات أعتقد بأنّ المعلومات عن الهوايات مهمّة، ويجادل البعض في هذا، لكنّي أعتقد بأن لمسة شخصيّة بينك وبين صاحب العمل المحتمل لها دور هام، فلا تنس أنّ هناك شخصًا حقيقيًا على الطرف الآخر، يقرأ سيرتك الذاتيّة، وسترغب بأن تعجبه، حتّى يكون مرتاحًا عند اتخاذ قرار توظيفك. ساعده في اتخاذ القرار بسرعة. إن كنت تحبّ التزلّج، إطعام القرود في حديقة الحيوان، فاذكر ذلك. كن مبتكرًا، لا تكن مملًّا، تمامًا كمواقع التعارف الاجتماعي. التصميم كيف يجب أن تبدو سيرتك الذاتيّة ذات الصفحة الواحدة؟ يجب أن تُظهِر شخصيتك من خلال سيرتك الذاتية، تجنّب بالتالي استخدام القوالب الجاهزة التي يمكنك تحميلها مجّانًا. قم بإنشاء قالبك الخاص، وحتى لو لم تكن قادرًا على التصميم، فاطلب المساعدة من صديق يستطيع. تذكّر حقًّا بأنّ كل ما تحتاج القيام به هو اختيار نوع الخط، قياسه وبضعة ألوان خفيفة هنا أو هناك. إن سيرتك الذاتيّة هي المنتج الذي تريد تسويقه، فأنت من صَنَعَها، أنت من رعيتها واهتممت بها، فإن كانت مجرّد مستند Word بالقالب القياسيّ ستجعلهم يشعرون بأنّك لم تهتم بما يكفي بها، فإن لم تهتم بأمر صغير كهذا، فكيف ستهتم بإنشاء برمجياتهم؟ بالتالي، لا تهمل جماليّة سيرتك الذاتية، ولا تجعلها متكلّفة، يمكنك أن تجعلها بسيطة جدًا لكنها يجب أن تمثّلك، وأن تكون قد بذلت من أجلها الاهتمام الكافي. ترجمة -وبتصرّف- للمقال Pimp Up Your Resume لصاحبه Yegor Bugayenko. حقوق الصورة البارزة: Designed by Freepik.
- 2 تعليقات
-
- 1
-
- stackoverflow
- resume
-
(و 5 أكثر)
موسوم في:
-
لم تعد الصور الرمزيّة لحسابات المستخدمين أمرًا جديدًا ويندر أن تجد برنامجًا لا يسمح لمستخدميه بعرض صورة للمستخدم في صفحته الشّخصية مثلًا أو نحو ذلك، وقد ظهرت من عدّة سنوات فكرة أن يكون للمستخدم صورة رمزية يمكنه استخدامها في الكثير من المواقع والخدمات دون أن يحتاج في كلّ مرّة إلى اختيارها ورفعها، وهذا ما تمّ فعلًا في مشروع أطلق عليه اسم Gravatar اختصارًا للصورة الرمزيّة المتعارف عليها عالميًّا Globally Recognized Avatar. إنّ إضافة صورة Gravatar إلى شريط التصفّح في مشروع مبني بـ Laravel من أكثر الأعمال سهولة فلا تتطلب العملية أكثر من 4 خطوات بسيطة، ويعود الفضل في هذا إلى فريق CreativeOrange، الذين يمكن زيارة صفحة مشروعهم لقراءة الإرشادات الأصليّة، فيما إذا طرأت تغييرات ما. الخطوة الأولى لنقم بتحميل نسخة من الحزمة المطلوبة باستخدام Composer عبر سطر الأوامر: composer require creativeorange/gravatar ~1.0 أو من الممكن التعديل على ملف composer.json وإضافة اسم الحزمة والإصدار المطلوب إلى لائحة الحزم المطلوبة: "require": { "creativeorange/gravatar": "~1.0" } وفي حال تعديل الملف، فيتوجّب علينا أن نقوم بتنفيذ الأمر التّالي من سطر الأوامر ليتمّ تحديث المشروع وتحميل الحزمة: composer update الخطوة الثانية نحتاج الآن لإضافة مزوّد خدمة Service Provider إلى ملف app/config/app.php في مصفوفة providers بالشّكل: 'providers' => [ // Other Service Providers // ... App\Providers\AppServiceProvider::class, // ... // Other Service Providers ], ملاحظة: لا تنس الفاصلة في نهاية السطر إن لم تدرج السطر في نهاية المصفوفة. نلاحظ فيما سبق بأننا استخدمنا الصيغة الخاصة بـ PHP 5.6 وهي الصيغة القياسية لمصفوفة providers في الإصدار 5.* من Laravel. الخطوة الثالثة لنقم الآن بإضافة إختصار في مصفوفة aliases في ملف app.php ذاته: 'aliases' => [ // ... 'Gravatar' => Creativeorange\Gravatar\Facades\Gravatar::class, // ... ], نلاحظ بأن كلّ ما احتجنا لإضافته في الخطوتين السابقتين هو سطر واحد فقط، وهذا من الأمور المميّزة في معمارية Laravel، حيث أنّ حزّم Service Providers كأحجار البناء في التطبيق البرمجيّ ويمكن ملاحظة مدى سهولة استخدامها في البرنامج، فلا يتطلّب الأمر أكثر من سطرين. أصبح الآن بالإمكان استخدام الصفّ Gravatar في البرنامج بسهولة من خلال الواجهة التي حصلنا عليّها، الأمر الذي يمكن القيام به على النحو التالي: use Gravatar; لكن لن نحتاج لاستخدامه بهذا الشكل في مثالنا. الخطوة الرابعة من المحتمل أن الاستخدام الأسهل للإضافة Gravatar يكون عبر إدراجها مباشرة في عرض View، كالصّفحة الرّئيسية كأن تكون عنصر قائمة في شريط التصفّح الرئيسي العلويّ. سنحتاج بداية للتحقّق فيما إذا قد تمّ تسجيل الدخول أولًا أم لا، ويمكن ذلك باستخدام ()Auth::check المتاحة للاستخدام دومًا عند الحاجة لها، كما في الشّكل: @if (Auth::check()) // أظهر العنصر @endif تستخدم الشّيفرة السابقة الصّيغة القياسية لنظام القوالب Blade والذي نحتاج لمعرفة استخدامه عند اختيار إطار العمل Laravel، وتسمح صيغة blade بالمزج ما بين شيفرات HTML و PHP بسهولة عند الاستخدام، دون الحاجة لاستخدام وسوم البدء الخاصّة بـ PHP، من خلال إدراج التعليمات ما بين الأقواس {{ .. }} كما يظهر في الكود البرمجيّ التالي: @if (Auth::check()) <li> <img src="{{ Gravatar::get(Auth::user()->email) }}" style="height:50px; width:50px; border-radius:50%;"> </li> @endif والآن لنأخذ الجزء الأهمّ ما بين الأقواس ولنقم بتوضيحه: Gravatar::get(Auth::user()->email) يؤدّي استدعاء التابع ()get من الصنفّ Gravatar إلى إعادة مسار نصيّ بصيغة URL لصورة gravatar بعد أن نقوم بتزويده ببريد إلكترونيّ، ونظرًا لأنّا نرغب بعرض صورة حساب المستخدم النشط في البرنامج فإنّ بالإمكان الحصول على البريد الإلكتروني للحساب من الكائن object الذي يعيده استدعاء التابع ()Auth::user الذي يحمل معلومات عن المستخدم صاحب جلسة العمل النشطة. قد لا يكون قياس الصّورة التي نحصل عليها مناسبًا لنا، ولحلّ هذه المشكلة يمكن تغيير القياس الافتراضيّ المطلوب من خلال تعديل قيمة المتغيّر size في المصفوفة default في الملف vendor/creativeorange/gravatar/config/gravatar.php: 'default' => array( 'size' => 80, 'fallback' => 'mm', 'secure' => false, 'maximumRating' => 'g', 'forceDefault' => false, 'forceExtension' => 'jpg', ), وهناك العديد من القيم الافتراضية التي يمكن تغييرها لتتناسب مع احتياجاتنا في هذا الملف، كالصّورة الافتراضيّة التي يتم عرضها في حال لم يكن للمستخدم صورة Gravatar، أو طلب الصورة بصيغة مختلفة عن JPG، وغير ذلك. ترجمة -وبتصرّف- للمقال Laravel 5.1 Gravatar Plugin لصاحبه Bill Keck.
-
سنتناول في هذا المقال الأسئلة العشرة الأكثر تكرارًا حول Git والحلول المتعلقة بها. ستساعد هذه الحلول في تجاوز بعض العقبات عند استخدام Git. 1. كيف أقوم بتحرير رسالة إيداع commit خاطئة في Git؟ وهو سؤال يطرح بكثرة من طرف كل من بدأ لتوّه باستخدام Git. لتحرير رسالة إيداع commit خاطئة قمنا بكتابتها، نستخدم الأوامر التالية: git commit --amend سيقوم الأمر بفتح المحرّر الذي سيسمح بتغيير أحدث إيداع. إن أردنا تحرير رسالة الإيداع مباشرة عبر سطر الأوامر، يمكننا القيام بذلك باستخدام الأمر: git commit --amend -m "الرسالة الجديدة" 2. كيف أتراجع عن آخر إيداع commit كاملا؟ للتراجع عن إيداع بعض الملفّات نقوم في البداية بإلغاء آخر إيداع باستخدام الأمر: git reset --hard HEAD~1 سيقوم هذا الأمر بنقل مؤشر الرأس HEAD إلى الإيداع قبل الأخير. بعد ذلك، نقوم بعرض حالة جميع الملفات مرّة أخرى باستخدام الأمر: git status وأخيرًا، نضيف الملفات التي نودّ إضافتها إلى الإيداع باستخدام الأمر: git add ... 3. كيف أتراجع عن إضافة ملف git add؟ للتراجع عن إضافة بعض أو كل الملفّات إلى منطقة الإدراج بالأمر المذكور، نستخدم أحد الأوامر التالية: للتراجع عن ملف وحيد: git reset <FileName> للتراجع عن جميع الملفّات: git reset 4. كيف أحذف تفرع branch (محلي أو بعيد)؟ لحذف تفرّع محلّي، نستخدم الأمر: git branch -d yourLocalBranchName ولحذف تفرّع بعيد، نستخدم الأمر: git push origin --delete yourRemoteBranchName 5. كيف أحذف ملفات محلية من التفرع الحالي لحذف جميع الملفّات المحلّية التي لا نرغب بإيداعها أو الحفاظ عليها في مجلّد العمل، نستخدم الأمر: git clean -f أو: git reset --hard 6. كيف أعيد تسمية تفرع محلي؟ لإعادة تسمية تفرّع محلّي، لدينا حالتان: إعادة تسمية لتفرّع الحالي: git branch -m newBranchName إعادة تسمية تفرّع آخر ليس التفرّع النّشط الحالي: git branch -m oldBranchName newBranchName 7. كيف أنشئ تفرعا بعيدا remote Git branch؟ لإنشاء تفرّع بعيد، نقوم أوّلًا بإنشاء تفرّع محلّي: git checkout -b newBranchName ومن ثم نقوم بدفع التفرّع الذي أنشأناه إلى الخادم البعيد: git push origin newBranchName 8. كيف أغير الرابط الخاص بمستودع بعيد remote Git repository؟ لتغيير الرابط الخاص بمستودع بعيد (لنفترض أنه التفرّع origin) نستخدم الأمر التالي: git remote set-url origin newURL 9. كيف أغير اسم من قام بالإيداع؟ يمكن تغيير اسم من قام بالإيداع في سجلّ المُستودع باستخدام السكربت التالي المأخوذ من مقالات موقع github.com: git filter-branch --env-filter ' an="$GIT_AUTHOR_NAME" am="$GIT_AUTHOR_EMAIL" cn="$GIT_COMMITER_NAME" cm="$GIT_COMMITTER_EMAIL" if[ "$GIT_COMMITTER_EMAIL" = "your@email.to.match" ] then cn="New Committer Name" cm="New Committer Email" fi if[ "$GIT_AUTHOR_EMAIL" = "your@email.to.match" ] then an="New Author Name" am="New Author Email" fi export GIT_AUTHOR_NAME="$an" export GIT_AUTHOR_EMAIL="$am" export GIT_COMMITTER_NAME="$cn" export GIT_AUTHOR_EMAIL="$cm"' 10. كيف أستنسخ مستودعا في مجلد معين؟ لاستنساخ مستودع في مجلّد معيّن، نحتاج إمّا: الانتقال بمسار سطر الأوامر إلى داخل ذلك المجلّد وتنفيذ الأمر: git clone <URL> أو ننفّذ الأمر: git clone <URL> <yourFolderName> حيث أن yourFolderName هو اسم/مسار المُجلّد المعني بالأمر. ترجمة -وبتصرّف- للمقال Top 10 frequently asked questions on Git لصاحبه Hemant Joshi.
-
السلام عليكم، تأكد من أنك بداية لا تستخدم أي إضافة أو مكافح فيروسات قد يمنع تنفيذ شفرات XSS كنوع من الحماية (مثل NoScript وسواها). الرابط الخاص بموقعك لا يعمل، يبدو أن الاستضافة قامت بحظره أو إزالته. قم أيضًا بوضع قيمة للـ cookie في المستند قبل محاولة سرقتها.. الصفحة بشكل افتراضي لا تملك أي cookie فمن الطبيعي ألا تحصل على أي قيمة لا تنس الاطلاع أيضًا على جوابي في سؤالك السابق حول الاستغلال بدون استخدام document.location
- 1 جواب
-
- 1
-
السلام عليكم أعتقد أن سبب المشكلة لديك يكمن في هذا السطر $dbse = mysqli_connect("localhost", "root", "root", "dbname") or die (mysql_error()); تأكّد من أن تنفيذه يعطيك object في $dbse وأن الاتصال يتم فعلًا. قم بإضافة السطر التالي بعده مباشرة وتأكد من أنه obj وليس string. var_dump($dbse); exit(); والسلام عليكم ورحمة الله وبركاته
-
استخدم التالي لإنشاء حقلين لإدخال الملفات في جهة العميل <form id="upload" method="post" action="" enctype="multipart/form-data"> <div id="drop"> Drop Here <a>صورة</a> <input type="file" name="up[]" id="file1" multiple /> <input type="file" name="up[]" id="file2" multiple /> </div> <ul> <!-- The file uploads will be shown here --> </ul> </form> كما تلاحظ، لقد قمت باستخدام مصفوفة بنفس الاسم في الـ name attribute للحقلين. الآن من جهة PHP سيكون بإمكانك الوصول لمواصفات الملف الأول عبر: $_FILES['up']['name'][], $_FILES['up']['tmp_name'][], $_FILES['up']['size'][], $_FILES['up']['type'][] وللملف الثاني $_FILES['up']['name'][1], $_FILES['up']['tmp_name'][1], $_FILES['up']['size'][1], $_FILES['up']['type'][1] تذكّر بأننا نتعامل مع مصفوفة، فالـ index=0 يمثّل الملف file1 والـ index=1 يمثّل الملف file2 دومًا لأن هذا هو الترتيب الذي حدّدناه في جهة HTML. السلام عليكم ورحمة الله وبركاته.
- 2 اجابة
-
- 1