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

عبد اللطيف ايمش

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

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

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

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

    63

كل منشورات العضو عبد اللطيف ايمش

  1. تتوفر عدِّة «أدوات بناء» (build tools) تعمل على تسهيل عملية تطوير مواقع الويب وأتمتة المهام الروتينية مثل «تصغير» (minify) ملفات JavaScript و HTML و CSS والصور، وتحويل ملفات LESS و SASS إلى CSS، والتحقق مباشرةً من صحة البنية اللغوية لملفات JavaScript والكثير من الأمور التي ستغيّر من طريقة عملك وتجعلها أكثر سرعةً وكفاءة. سنشرح في درسنا هذا إحدى أدوات البناء المشهورة وهي الأداة Gulp بالإضافة إلى أساسيات استخدامها، شرحًا مدعمَّا بالأمثلة العملية. ملاحظة مهمة: هذا الدليل كتب من أجل الإصدار 3 من Gulp وهنالك بعض الاختلافات والتغييرات الجوهرية في الإصدار 4. لذلك، إن كنت تستعمل الإصدار 4، فهذا الدليل ليس لك لأنه هنالك بعض الدوال والواجهات البرمجية التي لن تعمل مع ذلك الإصدار. ما هي أداة البناة Gulp؟ أدوات البناء هو أمر حديث العهد ولم ينتشر إلا منذ بضعة سنوات. كانت ملفات ‎.sh التي تكتب بلغة Bash أحد أشهر أدوات البناء غير المباشرة وغير المخصصة المستعملة آنذاك لكتابة التعليمات وأتمتة بعض المهام الروتينية المحدودة مثل مراقبة الملفات وتحديثها. هذه الملفات تعمل مع الصدفة shell التي تأتي مدمجة مع أنظمة التشغيل. انتشرت أدوات بناء أخرى مثل Ant و Gradle ولكنهما كانتا ضمن عالم جافا وتحتاجان إلى استعمال لغة XML لضبطهما وهي اللغة التي لا يحبها مطوري الويب عدا عن تعلم لغة جديدة لا يألفونها. اللغة التي يحبها مطورو الويب هي جافاسكربت وهنا جاءت أداتا البناء Gulp و Grunt لسد هذه الفجوة. تتفوق أداة البناء Gulp على منافستها Grunt بأنها أسرع بكثير لأنها تنفذ المهام على التوازي (على عكس Grunt) كما أنها تمرر الملفات المفتوحة عبر مجاري Streams داخلية. أضف إلى ذلك أن اللغة المستعملة في ضبط مهام Gulp هي جافاسكريبت بالتأكيد وهي اللغة التي يحبها مطورو الويب كثيرًا. المتطلبات المسبقة سيجري العمل على نظام التشغيل أوبنتو 18.04 ويجب أن تكون قد ثبَّت Node.js و npm مسبقًا. إن لم تكن Node.js مثبتةً لديك، فابدأ بتثبيتها هي ومدير الحزم npm عبر الأمر التالي: sudo apt update sudo apt install nodejs للتحقق من عملية التثبيت (وللتأكد من الإصدار المثبت مسبقًا لديك)، نفذ الأمر التالي: nodejs --version يجب أن ترى ناتجًا شبيهًا بالناتج التالي: v8.10.0 ولتكون قادرًا على تنزيل وتثبيت حزم npm، تحتاج إلى تنزيل npm (مدير حزم Node.js) إن لم يكن مثبَّتًا لديك: sudo apt install npm تحقق من عملية التثبيت (أو الإصدار المثبت مسبقًا) عبر الأمر التالي: npm --version يجب أن ترى ناتجًا شبيهًا بالناتج التالي: 3.5.2 أنت الآن جاهز لإكمال هذا الدليل! تثبيت Gulp يمكن تثبيت Gulp عبر مدير الحزم npm الذي تحدثنا عنه منذ قليل، بشكل سهلٌ للغاية فكل ما عليك فعله هو تنفيذ الأمر الآتي في سطر الأوامر لتثبيت Gulp 3 لعموم النظام: npm install gulp@3.9.0 ثم عليك تهيئة مجلد المشروع الذي ستعمل عليه. نفِّذ الأمر الآتي في مجلد المشروع: npm init عليك الآن تثبيت Gulp في المشروع وإضافته إلى الاعتماديات (أي devDependencies): npm install --save-dev gulp أصبح Gulp مثبتًا في مشروعك وجاهزًا للاستخدام. البنية الهيكلية للمشروع الذي سنعمل عليه مرونة Gulp تسمح لنا باستخدامه بغض النظر عن بنية المجلدات التابعة للمشروع، كل ما يلزمك هو فهمٌ صحيحٌ كاملٌ لآلية عمله مما يسمح لك بتعديله لتلبية احتياجاتك. سنعتمد في مقالتنا البنية الآتية للمجلدات: |- app/ |- css/ |- fonts/ |- images/ |- index.html |- js/ |- scss/ |- dist/ |- gulpfile.js |- node_modules/ |- package.json هذه بنيةٌ بسيطة نستعمل فيها مجلد app لاحتواء ملفات التطوير، بينما المجلد dist (اختصار للكلمة «distribution») سيحتوي على الملفات الإنتاجية. كتابة أول مهمة من مهام Gulp عندما نُشغِّل Gulp من سطر الأوامر، فسيبحث عن وجود الملف gulpfile.js في مجلد المشروع. سيُخبِر هذا الملف Gulp ما هي الإضافات التي يجب تحميلها وما هي المهام التي يجب القيام بها. علينا إذًا إنشاء الملف gulpfile.js وتضمين gulp في بدايته كما يلي: var gulp = require('gulp'); عبارة require السابقة ستخبر Node أن تبحث في مجلد node_modules عن حزمة باسم gulp، وعند العثور عليها فستُسنَد محتوياتها إلى المتغير gulp. يمكننا الآن البدء بكتابة «مهمّة Gulp» (أي Gulp task) بالاستفادة من المتغير gulp. البنية الأساسية لمهمّة Gulp هي: gulp.task('task-name', function() { // سنضع الشيفرات هنا }); task-name تشير إلى اسم المهمّة، والتي ستُستعمَل في أي مكانٍ تريد تشغيل هذه المهمّة فيه. نستطيع تشغيل هذه المهمة بتمرير اسمها كوسيط للأمر gulp في سطر الأوامر (أي تنفيذ gulp task-name). لنجرِّب ما سبق بإنشائنا للمهمّة hello في ملف gulpfile.js السابق (الذي يحتوي على عبارة require) والتي ستطبع الجملة Hello World: gulp.task('hello', function() { console.log('Hello World'); }); يمكننا تشغيل هذه المهمة بتنفيذ الأمر gulp hello في سطر الأوامر، لا تنسَ الانتقال إلى مجلد المشروع (عبر الأمر cd في لينكس أو ماك، أو dir في ويندوز) قبل تنفيذ الأمر. مخرجات الأمر السابق هي: user@linuxbox:~/gulp-test$ gulp hello [18:34:41] Using gulpfile ~/gulp-test/gulpfile.js [18:34:41] Starting 'hello'... Hello World [18:34:41] Finished 'hello' after 127 μs حسنًا، لا تكون مهام Gulp بهذه البساطة، حيث تحتوي عادةً على دالتين تابعتين للكائن gulp بالإضافة إلى استخدام إضافة (plugin) أو أكثر من إضافات Gulp. هذا مثالٌ عن البنية العامة لمهمّات Gulp: gulp.task('task-name', function () { //الحصول على الملفات التي يجب إجراء عمليات عليها // gulp.src باستخدام الدالة return gulp.src('source-files') .pipe(aGulpPlugin()) // ومن ثم تمريرها إلى إضافة .pipe(gulp.dest('destination')) // وإخراج الملف إلى المجلد الهدف }) كما هو واضح، تتطلب المهام المفيدة في gulp دالتين هما gulp.src و gulp.dest. الدالة gulp.src تخبر Gulp ما هي الملفات التي يجب تطبيق المهمة عليها، بينما الدالة gulp.dest تخبر Gulp أين يجب إخراج الملفات بعد تنفيذ المهمّة. يَستخدم Gulp المجاري (streams) التي توفرها node.js، وهذا يسمح بتمرير البيانات التي ستُعالَج عبر الأنابيب (pipes) وهذا ما تفعله الدالة ‎.pipe()‎؛ لشرحٍ تفصيليٍ عن المجاري في node.js، فأحيلك إلى هذه المقالة. سنشرح كيفية الاستفادة من Gulp عبر استعماله لتحويل ملفات Sass إلى ملفات CSS. تحويل ملفات Sass إلى CSS عبر Gulp نستطيع استخدام إضافة باسم gulp-sass لتحويل ملفات Sass إلى CSS. عليك تثبيت الإضافة gulp-sass في مشروعك باستخدام الأمر npm install كما فعلنا سابقًا مع gulp. يفضل أيضًا استخدام الخيار ‎--save-dev لكي تُضاف الحزمة gulp-sass إلى devDependencies في ملف package.json وهذا يسهل نسخ الملف إلى مشروع آخر وتثبيت نفس الاعتماديات (عبر الأمر npm install فقط): npm install gulp-sass –save-dev علينا الآن تضمين الحزمة gulp-sass عبر require من مجلد node_modules كما فعلنا أول مرة مع gulp كي نتمكن من استخدام الإضافة: var gulp = require('gulp'); // gulp-sass تضمين إضافة var sass = require('gulp-sass'); يمكننا استخدام gulp-sass بوضع الدالة sass()‎ بدلًا من aGulpPlugin()‎ في المثال السابق. ولمّا كان الغرض من المهمّة هو تحويل ملفات Sass إلى CSS فلنسمِّها sass: gulp.task('sass', function(){ return gulp.src('source-files') .pipe(sass()) // gulp-sass استخدام إضافة .pipe(gulp.dest('destination')) }); علينا توفير ملفات مصدرية بصيغة sass -ومجلد لإخراج الناتج فيه- إلى المهمّة sass، لنبدأ بإنشاء الملف styles.scss في مجلد app/scss، ومن ثم سنضع مسار هذا الملف في الدالة gulp.src في مهمّة sass. ونريد أيضًا إخراج ملف styles.css النهائي إلى مجلد app/css الذي سيكون هو مجلد الوجهة (destination) لدالة gulp.dest. gulp.task('sass', function(){ return gulp.src('app/scss/styles.scss') .pipe(sass()) .pipe(gulp.dest('app/css')) }); سنختبر المهمّة sass الآن للتأكد من عملها عملًا صحيحًا، لكن قبل ذلك علينا استخدام دالة من دوال Sass ضمن ملف styles.scss. // styles.scss .testing { width: percentage(5/7); } إذا نفَّذتَ الأمر gulp sass في سطر الأوامر، فيجب أن يُنشَأ الملف styles.css في مجلد app/css، مع تبديل الدالة percentage(5/7)‎ وتحويلها إلى 71.42857%‎. /* styles.css */ .testing { width: 71.42857%; } تحققنا أنَّ المهمّة sass تعمل بشكلٍ سليم. أحيانًا نحتاج إلى بناء أكثر من ملف ‎.scss وتحويلها إلى ملفات CSS في نفس الوقت، وسنحتاج حينها إلى استخدام «محارف التحديد» (Globs). محارف التحديد في Node تسمح لك محارف التحديد بتمرير أكثر من ملف إلى الدالة gulp.src، وهي شبيهة بالتعابير النمطية (regular expressions) لكنها تُستعمَل خصيصًا لمسارات الملفات. عند استخدامك لمحرف تحديد (glob) فسيتحقق جهازك من أسماء الملفات والمسارات المُحدَّدة بالنمط المستخدم، فإن تمت مطابقة النمط فسيُضاف الملف إلى الدالة gulp.src. أغلبية الأنماط التي نستعملها مع Gulp تنضوي تحت لواء الأنماط الآتية: النمط ‎*.scss: رمز النجمة * هو محرفٌ خاصٌ يُطابِق أيّة ملف في المجلد المعيّن. وفي مثالنا ستُطابَق جميع الملفات التي تنتهي باللاحقة ‎.scss في المجلد الرئيسي للمشروع. النمط ‎**/*.scss: هذه حالةٌ أعم من المثال السابق، حيث ستتم مطابقة أيّة ملفات تنتهي باللاحقة ‎.scss في المجلد الرئيسي للمشروع وفي جميع المجلدات الفرعية الموجودة فيه. النمط ‎!not-me.scss: الرمز ! يعني أنَّ على Gulp استثناء هذا النمط من الملفات المُحدَّدة، وهذا مفيدٌ إن شئتَ أن تستثني ملفًا من التحويل؛ وفي مثالنا سنستثني الملف not-me.scss. النمط ‎*.+(scss|sass): إشارة الزائد + والأقواس ()‎ ستسمح لأداة Gulp بمطابقة عدِّة أنماط معًا، والتي سيُفصَل بينها بمحرف الخط العمودي |. وفي مثالنا سيُطابِق Gulp جميع الملفات التي تنتهي باللاحقة ‎.scss أو ‎.sass في المجلد الرئيسي للمشروع. بعد تعلمنا لمحارف التحديد، أصبح بإمكاننا وضع التعبير app/scss/**/*.scss بدلًا من app/scss/styles.scss، وبهذا ستُطابَق جميع الملفات التي لها اللاحقة ‎.scss في المجلد app/scss أو أيّ مجلدٍ فرعيٍ موجودٍ داخله. gulp.task('sass', function() { // scss الحصول على جميع الملفات التي تنتهي باللاحقة // app/scss والموجودة في المجلد return gulp.src('app/scss/**/*.scss') .pipe(sass()) .pipe(gulp.dest('app/css')) }) سيُضمَّن أيّ ملف Sass موجود في مجلد app/scss تلقائيًا في مهمّة sass المُعدَّلة. فلو أضفتَ ملف print.scss إلى المشروع، فستلاحظ توليد الملف print.css في مجلد app/css تلقائيًا. حسنًا، تمكّنا من تحويل جميع ملفات Sass إلى ملفات CSS بأمرٍ وحيد، لكن السؤال الآن هو: ما الفائدة من المهمّة التي أنشأناها إن كنا سنحتاج إلى تطبيق الأمر gulp sass يدويًا في كل مرة نرغب فيها بتحويل ملفات Sass إلى CSS؟ لحسن الحظ، يمكننا أن نخبر Gulp أن يُشغِّل المهمّة sass تلقائيًا في كل مرة يُحفَظ فيها أحد تلك الملفات، وهذا ما ندعوه «المراقبة» (watching). مراقبة التغييرات في ملفات Sass يوفِّر لنا Gulp الدالة watch لمعرفة إن حُفِظَ أحد الملفات. الشكل العام لدالة watch هو: gulp.watch('files-to-watch', ['tasks', 'to', 'run']); إذا أردنا مراقبة جميع ملفات Sass وتشغيل المهمّة sass عندما يحفظ أحد تلك الملفات، فعلينا أن نضع app/scss/**/*.scss بدلًا من files-to-watch ونضع ['sass'] بدلًا من ['tasks', 'to', 'run']: gulp.watch('app/scss/**/*.scss', ['sass']); وفي أغلبية الأوقات سنحتاج إلى مراقبة أكثر من نوع من الملفات في آنٍ واحد، ويمكننا إنشاء مجموعة من عمليات المراقبة مع بعضها ضمن مهمّة باسم watch: gulp.task('watch', function(){ gulp.watch('app/scss/**/*.scss', ['sass']); // عمليات المراقبة الأخرى }) إذا جرّبتَ تنفيذ الأمر gulp watch الآن، فسترى أنَّ Gulp قد بدأ مراقبة الملفات فوريًا. user@linuxbox:~/gulp-test$ gulp watch [21:10:00] Using gulpfile ~/gulp-test/gulpfile.js [21:10:00] Starting 'watch'... [21:10:00] Finished 'watch' after 12 ms وأنَّ Gulp سيُنفِّذ المهمّة sass عندما تحفظ أحد ملفات ‎.scss، جرِّب الآن فتح الملف styles.scss السابق وإضافة أيّ شيء إليه وحفظه، ثم انظر إلى ناتج Gulp: abd@linuxbox:~/gulp-test$ gulp watch [21:10:00] Using gulpfile ~/gulp-test/gulpfile.js [21:10:00] Starting 'watch'... [21:10:00] Finished 'watch' after 12 ms [21:12:03] Starting 'sass'... [21:12:03] Finished 'sass' after 69 ms ما رأيك أن نخطو خطوةً إلى الأمام ونجعل Gulp يُعيد تحميل الصفحة عندما نحفظ أحد ملفات ‎.scss لكي يظهر تأثير تغيير الصفحة مباشرةً على المتصفح، وذلك بالاستعانة بأداة Browser Sync. تحديث الصفحة آنيًا باستخدام Browser Sync يُسهِّل Browser Sync من تطوير الويب بإنشاء خادوم ويب الذي يساعدنا على تحديث الصفحات آنيًا عند تغييرها. وله ميزاتٌ أخرى، مثل مزامنة الأحداث بين أكثر من جهاز. لنبدأ أولًا بتثبيت الأداة Browser Sync كالمعتاد: npm install browser-sync –save-dev علينا بعدئذٍ أن نُضمِّن Browser Sync عبر التعليمة require: var browserSync = require('browser-sync').create(); سنحتاج إلى إنشاء مهمّة باسم browserSync للسماح لأداة Gulp بتشغيل خادوم ويب باستخدام Browser Sync، ولأننا سنُنشِئ خادوم ويب، فعلينا أن نُحدِّد للخادوم ما هو المجلد الرئيسي للموقع، والذي هو في حالتنا المجلد app: gulp.task('browserSync', function() { browserSync.init({ server: { baseDir: 'app' }, }) }) علينا أيضًا تغيير المهمّة sass قليلًا لكي يتمكن Browser Sync من تحديث أنماط CSS في المتصفح عندما تُشغَّل المهمّة sass: gulp.task('sass', function() { return gulp.src('app/scss/**/*.scss') .pipe(sass()) .pipe(gulp.dest('app/css')) .pipe(browserSync.reload({ stream: true })) }); انتهينا الآن من ضبط الأداة Browser Sync، لكن علينا تشغيل المهمّتَين watch و browserSync في نفس الوقت لكي تُحدَّث الصفحة آنيًا. من غير المقبول فتح نافذَتي سطر أوامر وتشغيل gulp browserSync في إحداها و gulp watch في الأخرى، لذا لنجعل Gulp يشغِّلهما معًا بإخبار المهمّة watch أنَّه يجب إكمال المهمّة browserSync قبل السماح بتنفيذ watch. يمكننا فعل ذلك بتمرير وسيطٍ ثانٍ إلى المهمّة watch. الشكل العام هو: gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){ // ... }) وفي حالتنا هذه سنضيف المهمّة browserSync: gulp.task('watch', ['browserSync'], function (){ gulp.watch('app/scss/**/*.scss', ['sass']); // عمليات المراقبة الأخرى }) علينا أيضًا أن نتأكد أنَّ المهمّة sass ستعمل قبل watch لكي يتم تحويل أيّة ملفات sass حُفِظَت قبل تشغيل Gulp إلى ملفات CSS. gulp.task('watch', ['browserSync', 'sass'], function (){ gulp.watch('app/scss/**/*.scss', ['sass']); // عمليات المراقبة الأخرى }); إذا شغَّلتَ gulp watch في سطر الأوامر، فسيُشغِّل Gulp المهمّتين sass و browserSync ثم بعد إكمالهما ستُشغَّل المهمّة watch. ستجد في الناتج رابط URL شبيه بالرابط الآتي http://localhost:3000 الذي إذا فتحته في نافذة المتصفح، فسترى صفحة app/index.html التي يجب أن يكون محتواها شبيهًا بما يلي: <!doctype html> <html> <head><link rel="stylesheet" href="css/styles.css"></head> <body></body> </html> شغِّل الآن المتصفح وادخل إلى الرابط السابق وستعرض أمامك صفحة فارغة، ولتجربة التحديث الآني للصفحة، فافتح ملف styles.scss وأضف لونًا للخلفية (مثلًا: body {background-color: red;} واحفظ الملف وستجد أنَّ الصفحة قد حُدِّثَت تلقائيًا! ما رأيك الآن أن نضيف قليلًا على المهمّة السابقة ونراقب تغيير ملفات HTML أو JavaScript (بالإضافة إلى ملفات ‎.sass) ومن ثم إعادة تحميل الصفحة حينها؟ يمكننا فعل ذلك بإضافة عمليتَي مراقبة، واستدعاء الدالة browserSync.reload عند حفظ الملف: gulp.task('watch', ['browserSync', 'sass'], function (){ gulp.watch('app/scss/**/*.scss', ['sass']); // تحديث الصفحة عند حفظ هذه الملفات gulp.watch('app/*.html', browserSync.reload); gulp.watch('app/js/**/*.js', browserSync.reload); }); حتى الآن قمنا بثلاثة أمور: تشغيل خادوم ويب للتطوير تحويل ملفات Sass إلى CSS إعادة تحميل الصفحة في المتصفح عند حفظ الملفات سنشرح في القسم الآتي كيفية تحسين الملفات الملحقة بصفحات الويب، وسنبدأ بتحسين ملفات CSS و JavaScript. تحسين ملفات CSS و JavaScript يُجري المطورون مهمّتَين عندما يحاولون تحسين ملفات CSS و JavaScript: تصغير الملفات وجمعها في ملفٍ واحد. إحدى المشاكل التي يواجهها المطورون عند أتمتة هذه العملية هي الصعوبة في جمع السكربتات بترتيبٍ صحيح. لنقل أننا أضفنا 3 وسوم script في صفحة index.html: <body> <script src="js/lib/a-library.js"></script> <script src="js/lib/another-library.js"></script> <script src="js/main.js"></script> </body> هذه السكربتات موجودة في مجلدين مختلفين، ومن الصعب جمعها باستخدام الإضافات التقليدية مثل gulp-concatenate؛ لكن لحسن الحظ، تأتي إضافة gulp-useref لتحل لنا هذه الإشكالية. تجمع إضافة gulp-useref أيّ عدد من ملفات CSS أو JavaScript إلى ملفٍ وحيد بالبحث عن تعليق يبدأ بالتعبير ‎<!--build:‎ وينتهي بالتعبير <‎!--endbuild--‎> الشكل العام له هو: <!-- build:<type> <path> --> ... HTML Markup, list of script / link tags. <!-- endbuild --> النوع <type> يمكن أن يكون إما js أو css أو remove. من الأفضل تحديد نوع type للملفات التي تحاول جمعها؛ وإذا ضَبطتَ type إلى remove فسيَحذف Gulp الشيفرةَ المُحدَّدةَ ولن يولِّد ملفًا. أما <path> فيشير إلى مسار الملف الذي سيولّد. إذا أردتَ أن يكون ملف JavaScript المولَّد في مجلد js باسم main.min.js فستبدو الشيفرة كالآتي: <!--build:js js/main.min.js --> <script src="js/lib/a-library.js"></script> <script src="js/lib/another-library.js"></script> <script src="js/main.js"></script> <!-- endbuild --> لنضبط الآن إضافة gulp-useref في ملف gulpfile.js. علينا أولًا تثبيت الإضافة ثم تضمينها في الملف. نفِّذ الأمر الآتي للتثبيت: npm install gulp-useref –save-dev أضف السطر الآتي إلى ملف gulpfile.js: var useref = require('gulp-useref'); تهيئة المهمّة useref شبيهة بتهيئة المهام الأخرى التي أنجزناها من قبل. هذه هي الشيفرة: gulp.task('useref', function(){ return gulp.src('app/*.html') .pipe(useref()) .pipe(gulp.dest('dist')) }); إذا شغّلتَ مهمّة useref الآن فسيأخذ Gulp ملفات JavaScript المُحدَّدة وسيجمعها في ملف dist/js/main.min.js. لكن الملف لم يُصغَّر (minified) إلى الآن، وعلينا استخدام إضافة gulp-uglify لفعل ذلك. وسنحتاج أيضًا إلى إضافة تدعى gulp-if لكي نُصغّر ملفات JavaScript دونًا عن غيرها. تثبيت الإضافة: npm install gulp-uglify --save-dev الشيفرة التي سنضيفها إلى ملف gulpfile.js: var uglify = require('gulp-uglify'); var gulpIf = require('gulp-if'); gulp.task('useref', function(){ return gulp.src('app/*.html') .pipe(useref()) // JavaScript التصغير إذا كان الملف .pipe(gulpIf('*.js', uglify())) .pipe(gulp.dest('dist')) }); يجب أن يولِّدَ Gulp الملفَ main.min.js في كل مرة تشغِّل فيها المهمّة useref. إحدى الأمور الرائعة التي لم أخبرك عنها بعد هي أنَّ إضافة gulp-useref ستحوِّل جميع السكربتات الموجودة بين ‎<!--build:‎ و <‎!--endbuild--‎> إلى ملف JavaScript وحيد الذي يُشير إلى js/main.min.js وذلك في صفحة index.html، أي أنَّ ملف index.html الناتج سيكون شبيهًا بما يلي: <!doctype html> <html> <head></head> <body> <script src="js/main.min.js"></script> </body> </html> سنستعمل نفس الطريقة لجمع ملفات CSS: <!--build:css css/styles.min.css--> <link rel="stylesheet" href="css/styles.css"> <link rel="stylesheet" href="css/another-stylesheet.css"> <!--endbuild--> يمكننا أيضًا تصغير ملف CSS الناتج، لكننا بحاجة إلى تثبيت الإضافة gulp-cssnano: npm install gulp-cssnano الشيفرة التي سنضيفها إلى ملف gulpfile.js: var cssnano = require('gulp-cssnano'); gulp.task('useref', function(){ return gulp.src('app/*.html') .pipe(useref()) .pipe(gulpIf('*.js', uglify())) // CSS التصغير إذا كان الملف .pipe(gulpIf('*.css', cssnano())) .pipe(gulp.dest('dist')) }); ستحصل الآن على ملف CSS وملف JavaScript وحيد ومُصغّر في كل مرة تُشغِّل فيها المهمّة useref. تحسين دعم المتصفحات لخاصيات CSS وشيفرة JavaSctipt نبدأ بتحسين دعم خاصيات CSS عبر مختلف المتصفحات. فمن المؤكد أنك رأيت شيفرة CSS مكتوبة بالشكل التالي: .navigation { display: -webkit-box; display: -ms-flexbox; display: flex } ولابد أنك استصعبت - أثناء كتابة شيفرة CSS - البحث عن دعم كل خاصية من خاصيات CSS لمختلف المتصفحات وتساءلت عن وجود أداة تضيف السوابق الخاصة بدعم الخاصيات في المتصفحات الأخرى مثل ‎-webkit-box و ‎-ms-flexbox. الحل بسيط جدًا وهو استعمال الإضافة gulp-autoprefixer الموجودة لهذا الغرض. نفذ الأمر التالي لتثبيت هذه الإضافة: npm install gulp-autoprefixer --save-dev أضف السطر الآتي إلى ملف gulpfile.js: const autoprefixer = require('gulp-autoprefixer'); تهيئة واستعمال هذه الإضافة - مع الإضافة gulp-sass والإضافة browser-sync التي تحدثنا عنهما في الأعلى - يكون بالشكل التالي: gulp.task("styles", function() { gulp .src("app/css/**/*.scss") .pipe(sass().on("error", sass.logError)) .pipe(autoprefixer({ // دعم آخر إصدارين للمتصفح browsers: ["last 2 versions"] }) ) .pipe(gulp.dest("css")) .pipe(browserSync.stream()); }); نحصل بذلك على شيفرة CSS السابقة عند كتابة: .navigation { display: flex } فقط لتصبح الشيفرة مدعومة على كافة المتصفحات التي لا تدعم خاصيات CSS محدَّدة مثل التي رأيناها للتو. ملاحظة: إن أردت استعمال الإضافة gulp-autoprefixer مع الإضافة gulp-cssnano (وإضافات أخرى)، فيمكنك استعمالهما سوية عبر استعمال الإضافة gulp-postcss. تمرر هذه الإضافة شيفرة CSS إلى عدة إضافات مع تحليل الشيفرة مرةً واحدةً مما يزيد من سرعة تنفيذ العملية. var postcss = require('gulp-postcss'); var gulp = require('gulp'); var autoprefixer = require('autoprefixer'); var cssnano = require('cssnano'); gulp.task('css', function () { // CSS تحديد الإضافات المراد استعمالها مع شيفرة var plugins = [ autoprefixer({browsers: ['last 2 version']}), cssnano() ]; return gulp.src('app/css/*.css') .pipe(postcss(plugins)) .pipe(gulp.dest('./dest')); }); اطلع على توثيق الإضافة الرسمي لمزيد من الأمثلة وكيفية الاستخدام. ننتقل الآن إلى تحسين دعم شيفرة JavaScript وأتحدث الآن عن دعم ميزات ES6 عبر مختلف المتصفحات. الحقيقة أن الميزات التي يوفرها الإصدار ES6 (أو ECMAScript 6) مغرية جدًا لجميع مطوري الويب ولكن نقص الدعم في مختلف المتصفحات والإصدارات القديمة هو من أكبر العقبات أمام الاستفادة من تلك الميزات. انطلاقًا من ذلك، جاءت فكرة وجود محول يدعى transpiler والذي يحول من لغة برمجية معينة إلى برمجية أخرى (في حالتنا من ECMAScript 6 إلى ES2015 أو ما قبلها). المحول الذي سنختاره هنا هو المحول الشهير Babel JS الذي يحوي الكثير من الميزات والمدعوم بقوة من قبل المجتمع. سنستعمل الإضافة gulp-babel لهذا الغرض. ثبت الإضافة عبر الأمر التالي: # Babel 6 npm install --save-dev gulp-babel # Babel 7 npm install --save-dev gulp-babel@next @babel/core أضف الشيفرة التالية إلى ملف gulpfile.js: var babel = require("gulp-babel"); gulp.task("default", function () { return gulp.src("app/js/*.js") // تحويل الشيفرة إلى الإصدار الأقدم .pipe(babel()) .pipe(gulp.dest("dist")); }); تنبيه: احرص على استدعاء babel()‎ قبل إجراء أية عملية تصغير أو ضغط على شيفرة JavaScript. تحسين الصور أظن أنك ستتوقع أننا سنحتاج إلى تثبيت إضافة لمساعدتنا في موضوع تحسين الصور، وهي gulp-imagemin. الضغط الذي ستوفره هذه الإضافة هو الضغط غير الفَقُود (lossless compression). npm install gulp-imagemin –save-dev يمكننا تصغير صورة png و jpg و gif وحتى svg باستخدام إضافة gulp-imagemin. لننشِئ مهمّة images لهذا الغرض: var imagemin = require('gulp-imagemin'); gulp.task('images', function(){ return gulp.src('app/images/**/*.+(png|jpg|gif|svg)') .pipe(imagemin()) .pipe(gulp.dest('dist/images')) }); ولأن كلُّ نوعٍ من أنواع الصور سيُحسّن بطريقةٍ مختلفة، فربما ترغب بإضافة بعض الخيارات إلى imagemin لتخصيص كيفية تحسين الصورة. على سبيل المثال، يمكننا إنشاء صورة GIF متداخلة (interlaced) بضبط قيمة الخيار interlaced إلى ture. gulp.task('images', function(){ return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)') .pipe(imagemin({ interlaced: true })) .pipe(gulp.dest('dist/images')) }); إن كانت تريد إجراء عملية ضغط فقود (lossy compression)، والذي سيخفّض حجم الصورة بشكل كبيرة على حساب الجودة، فاستعمل الإضافة imagemin-pngquant. npm install imagemin-pngquant –save-dev خيار الضغط الذي توفره هذه الإضافة يتمتع بالذكاء والذي يدعى PNG quantization (توضيح صور PNG)، إذ يعمل على اللعب بالألوان التي يراها دماغنا على أنها تقريبًا متماثلة محولًا الصورة إلى حجم 256 أو 8 بت للألوان. أفضل شيء في هذه الإضافة هو أنها لن تعدل أي شيء على الصور إن لم تتحقق حدود معينة متعلقة بالجودة. سنعدل على المثال السابق لاستعمال pngquant()‎ مع imagemin بالشكل التالي: var imagemin = require('gulp-imagemin'); gulp.task('default', function() { return gulp.src('app/images/*') .pipe(imagemin({ progressive: true, use: [pngquant()] })) .pipe(gulp.dest('dist/images')); }); على أي حال، عملية تحسين الصور هي عمليةٌ بطيئةٌ للغاية، ولا ترغب في تكرارها إلا إذا كان ذلك ضروريًا، ويمكننا تخزينها مؤقتًا باستخدام إضافة gulp-cache. npm install gulp-cache –save-dev الشيفرة التي سنضيفها إلى ملف gulpfile.js: var cache = require('gulp-cache'); gulp.task('images', function(){ return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)') // تخزين الصور المُحسّنة مؤقتًا .pipe(cache(imagemin({ interlaced: true }))) .pipe(gulp.dest('dist/images')) }); انتهينا تقريبًا من عمليات التحسين، وبقي مجلدٌ أخير يجب علينا نقله من مجلد app إلى dist وهو مجلد الخطوط. لمزيد من التفاصيل حول تحسين الصور في موقعك، ننصحك بالإطلاع على مقال «دليلك الشامل لتحسين أداء الصور على موقعك». نسخ الخطوط إلى مجلد dist لن تحتاج الخطوط إلى أيّة عمليات تحسين، وكل ما علينا فعله هو نسخها إلى مجلد dist. يمكننا نسخ الملفات باستخدام Gulp ببساطة باستخدام الدالتين gulp.src و gulp.dest دون أيّة إضافات: gulp.task('fonts', function() { return gulp.src('app/fonts/**/*') .pipe(gulp.dest('dist/fonts')) }) سينسخ Gulp مجلد fonts من app إلى dist في كل مرة تشغِّل فيها الأمر gulp fonts. أصبحت لدينا ست مهام مختلفة في ملف gulpfile.js، ويجب علينا استدعاؤها يدويًا باستخدام سطر الأوامر. ربما نفكّر بربط المهام جميعًا إلى أمرٍ وحيد، لكن قبل ذلك لننظر إلى كيفية حذف الملفات المولّدة تلقائيًا. حذف الملفات المولدة تلقائيًا لمّا كنّا نولِّد الملفات تلقائيًا، فعلينا أن نتأكد أنَّ الملفات التي لم تعد مستخدمةً لن تبقَ موجودةً دون علمنا. سنحتاج إلى استخدام del لمساعدتنا في ذلك. npm install del –save-dev الدالة del تأخذ مصفوفةً من محارف التحديد (globs) التي تخبرها ما هي المجلدات التي يجب حذفها. يمكننا استخدامها كمهمّة في Gulp كما فعلنا من قبل: var del = require('del'); gulp.task('clean:dist', function() { return del.sync('dist'); }) سيَحذف Gulp المجلد dist في كل مرة تُشغِّل فيها الأمر gulp clean:dist. ملاحظة: لا حاجة أن نقلق من حذف مجلد dist/images لأنَّ إضافة gulp-cache خزَّنت نسخةً مؤقتةً من الصور في نظامك. ستحتاج إلى إنشاء مهمّة منفصلة لحذف النسخة المؤقتة وليكن اسمها cache:clear: gulp.task('cache:clear', function (callback) { return cache.clearAll(callback) }) جمع مهام Gulp مع بعضها ما فعلناه إلى الآن هو إنشاء مجموعتين منفصلتين من مهمات Gulp. الغرض من المجموعة الأولى هو المساعدة في التطوير، حيث حوّلنا ملفات Sass إلى CSS، وراقبنا تغيرات الملفات، وأعدنا تحميل الصفحة في متصفح الويب وقت الحاجة. أما المجموعة الثانية فكانت لتحسين الملفات الملحقة بالصفحة، حيث جهّزنا جميع الملفات للموقع الإنتاجي، وذلك بدمج ملفات CSS و JavaScript وتصغيرها، وتحسين الصور ونسخ الخطوط من app إلى dist. لقد وضعنا أول مجموعة من المهمات في بُنية يمكن تشغيلها باستخدام الأمر gulp watch: gulp.task('watch', ['browserSync', 'sass'], function (){ // ... }) أما المجموعة الثانية فتستخدم لإنشاء الموقع الإنتاجي، وهي تتضمن المهمات clean:dist و sass و useref و images و fonts. يمكننا إنشاء مهمة باسم build التي ستجمع كل ما سبق في مهمة واحدة. gulp.task('build', [`clean`, `sass`, `useref`, `images`, `fonts`], function (){ console.log('Building files'); }) للأسف لا يمكننا كتابة المهمّة build بهذه الطريقة لأن Gulp سيشغِّل المهمات المُمرَّرة كوسيطٍ ثانٍ إلى الدالة task معًا وليس بالترتيب. فهنالك احتمالٌ أن ينتهي تنفيذ المهمات useref أو images أو حتى fonts قبل إكمال المهمّة clean التي تُسبِّب حذف كامل مجلد dist! لذا لضمان أنَّ المهمات ستُنفَّذ بترتيبٍ صحيح، فسنحتاج إلى استخدام إضافة خارجية باسم Run Sequence: npm install run-sequence –save-dev وهذه هي البنية العامة لطريقة تشغيل سلسلة من المهمّات: var runSequence = require('run-sequence'); gulp.task('task-name', function(callback) { runSequence('task-one', 'task-two', 'task-three', callback); }); عندما تستدعى المهمّة task-name فسيُشغِّل Gulp المهمّة task-one أولًا، وبعد انتهاء تنفيذها سيُشغِّل المهمة task-two، ثم task-three وهكذا. تسمح لك إضافة Run Sequence بتشغيل المهمات معًا إذا وضعتَها في مصفوفة: gulp.task('task-name', function(callback) { runSequence('task-one', ['tasks','two','run','in','parallel'], 'task-three', callback); }); في هذه الحالة، سيُشغِّل Gulp المهمّة task-one، وبعد انتهاء تنفيذها فسيُشغِّل جميع المهمات الموجودة في المصفوفة معًا، وجميع المهمات الموجودة في المصفوفة يجب أن ينتهي تنفيذها قبل تنفيذ task-three. لذا يمكننا الآن إنشاء مهمة التي تُشغِّل المهمّة clean:dist أولًا، ثم تتبعها بقية المهمات: gulp.task('build', function (callback) { runSequence('clean:dist', ['sass', 'useref', 'images', 'fonts'], callback ) }) ولجعل الملف متناسقًا، فسنستخدم نفس الطريقة مع أوّل مجموعة من المهمات، وسنستخدم الاسم default كاسمٍ للمهمّة: gulp.task('default', function (callback) { runSequence(['sass','browserSync', 'watch'], callback ) }) لماذا اخترنا الاسم default؟ لأنّ المهمّة ذات الاسم default ستُشغَّل إن كَتبتَ الأمر gulp دون تمرير اسم المهمة له، مما يوفِّر عليك بعض الوقت :-) . الخلاصة بدأنا درسنا ونحن لا نعرف شيئًا عن Gulp، ثم كتبنا مهمةً بسيطةً لتحويل ملفات Sass إلى CSS ومراقبة ملفات HTML و JS، وتعلمنا كيف نشغِّل تلك المهمّة في سطر الأوامر باستخدام الأمر gulp. ثم بنينا بعد ذلك مهمّةً ثانيةً، ألا وهي build، والتي تُنشِئ المجلد dist لكي يحتوي على ملفات الموقع الإنتاجي، وحوّلنا ملفات Sass إلى CSS وأجرينا عمليات تحسين على ملحقات الصفحة، ونسخنا المجلدات الضرورية إلى مجلد dist؛ وتمكنّا من تنفيذ كل ما سبق بأمرٍ وحيد وهو gulp build. في النهاية، أنشأنا المهمّة clean التي تحذف المجلد dist وبالتالي سنحذف أيّة ملفات غير مستخدمة في الموقع. لا تقف عند هذا الحد! Gulp واسع جدًا وإمكانياته لا تنتهي، وأرى أنَّ عليك تصفّح الإضافات الخاصة به والموجودة في الموقع الرسمي، وعليك الاستعانة بتوثيق API إن أردت رؤية توثيق دوال Gulp. المصادر تعتمد هذه المقالة اعتمادًا أساسيًا على مقالة Gulp for Beginners لصاحبها Zell Liew قائمة بالمقالات التي تتحدث عن Gulp المجاري (streams) في Node مقالة Automate Your Tasks Easily with Gulp.js لصاحبها Justin Rexroad
  2. وفرنا في أكاديمية حسوب دليلًا للمبتدئين لتعلم البرمجة بالتفصيل، يمكنك الاطلاع عليه من الرابط الآتي: https://academy.hsoub.com/programming/general/تعلم-البرمجة-r662/
  3. "أريد تعلم البرمجة لكنني لا أعرف من أين أبدأ!" هذه هي أكثر عبارة تتردد على سمعي من حديثي العهد بالبرمجة، إذ يأتيني هذا السؤال مرارًا وتكرارًا؛ وفي كل مرة أحاول أن أجيب عنه في سياقه، أجد أنني أضيف معلومات جديدة على إجاباتي السابقة، لذا قررت كتابة هذا المقال بعنوان "تعلم البرمجة" لعله يفيد الراغبين في تعلم تطوير التطبيقات في بدء رحلتهم مع تعلم البرمجة من الصفر. جدول المحتويات حرصًا على تنظيم المقالة ولتسهيل الوصول إلى القسم الذي تريده بسهولة، سنذكر هنا جدول المحتويات باختصار: ما هي البرمجة؟ لماذا تتعلم البرمجة؟ ما عليك معرفته لتصبح مبرمجًا الأدوات اللازمة للبدء في تعلم البرمجة لماذا هناك العديد من لغات البرمجة؟ مفاهيم البرمجة مصادر تعلم البرمجة تطوير واجهات المستخدم تطوير الواجهات الخلفية تعلم تطوير تطبيقات الجوال تطوير الألعاب تطوير الأنظمة المدمجة تطوير تطبيقات سطح المكتب كيفية اختيار لغة البرمجة التي تناسبك نصائح لتعلم البرمجة ما هي البرمجة؟ البرمجة هي عملية تقسيم مهمة معينة يراد تنفيذها عبر الحاسوب إلى أجزاء صغيرة ومترابطة وقابلة للتنفيذ بأوامر بسيطة. بعد ذلك، يجري كتابة هذه الأوامر والتعليمات بإحدى لغات البرمجة، والتي هي وسيلة للتخاطب مع الحاسوب. إليك المثال العملي التالي الذي يشرح ماهية البرمجة: إن كنت تتوقع زيارة صديق لك اليوم، واتصل بك ليقول لك: "أنا واقف بجانب الحديقة ولا أعرف كيف أصل إلى منزلك". أنت عادةً تمر كل يوم من جانب الحديقة وتعرف الطريق بينها وبين منزلك شبرًا بشبر. برأيك هل ينفع إن قلت له: "منزلي معروف وقريب من الحديقة وأنا كل يوم أمر من جانبها"؟ لا، بالتأكيد. تحتاج إلى أن تقسِّم المشكلة إلى أجزاء تمثل خطوات بسيطة يستطيع صديقك فهمها وتنفيذها. مثلًا، أخبره أن ينفذ الأوامر التالية: "سر إلى الأمام عشرة أمتار" ثم "اتجه إلى اليمين" ثم "سر إلى نهاية الشارع" ثم "اتجه إلى اليسار". أخبره بعد ذلك: "عُدَّ الأبنية الموجودة على اليسار حتى تصل إلى البناء الرابع" ثم "اصعد إلى الطابق الثاني" ثم "اطرق على الباب الذي سيظهر أمامك". مبارك! بهذه الطريقة، تستطيع أن تدل صديقك على منزلك بدقة. البرمجة هي الشيء نفسه تمامًا. فهل ترى التعابير المكتوبة بين قوسين؟ إنها التعابير التي تكتب بإحدى لغات البرمجة والتي تخاطب الحاسوب بدلًا من صديقك السابق. لغات البرمجة هي مجموعة من المفردات والقواعد اللغوية التي تشكل لغةً وسيطةً للتخاطب مع الحاسوب وأمره بتنفيذ تعليمات وأشياء محدَّدة. فلا الحاسوب يفهم لغة البشر ولا البشر يفهمون لغة الحاسوب، لذا كان هنالك حاجة ملحة لوجود لغة وسيطة يفهمها كلاهما؛ نتيجةً لذلك، انبثق مفهوم لغة البرمجة. بعبارة أخرى، لو أردنا أن نقول للحاسوب "افعل كذا"، فسنحتاج إلى لغةٍ مشتركةٍ بيننا وبينه ليفهم ما نبتغيه، وهنا يأتي دور لغات البرمجة، إذ يمكنك أن تعدّ لغات البرمجة على أنها وسيط بين المبرمج والحاسوب. يهتم المبرمج بالتفكير في تسلسل الخطوات التي على الحاسوب القيام بها لإتمام العمل المطلوب منه (مثل حساب العمر اعتمادًا على تاريخ الولادة)، ثم كتابة هذه الخطوات بترتيب منطقي بإحدى لغات البرمجة. ربما لاحظتَ في الجملة السابقة أن جزءًا من مهمة المبرمج هو التفكير المنطقي، وهذا يجعلنا ننتقل إلى السؤال الشائع "هل أستطيع تعلم البرمجة وأصبح مبرمجًا؟" أو "هل أنا مؤهل لأصبح مبرمجًا؟". لماذا تتعلم البرمجة؟ يبدو أن تعلم البرمجة من الصفر ليس بالصعوبة التي توقعتها، لكنك تريد حافزًا يجعلك تتعلم البرمجة. تسمع كثيرًا أن البرمجة هي مجال المستقبل، وأن وظائف المبرمجين ستكتسح مجال التوظيف في السنوات القادمة؟ أستطيع أن أؤكد لك ذلك، كما أنَّ وظائف البرمجة هي من أعلى الوظائف دخلًا. فلو كنت تريد بدء مشوارك الاحترافي وتريد عملًا مستقرًا وذا دخلٍ ممتاز، فإن تعلم البرمجة والعمل بها هو أفضل خيارٍ أمامك. وظائف البرمجة مريحة عمومًا، فالعمل كله مكتبي أمام حاسوب في بيئة مريحة ومناسبة، وأغلبية الشركات تتبع نظام العمل 40 ساعة في الأسبوع (أي 5 أيام لمدة 8 ساعات يوميًا)، ولا تغفل عن قدرتك على العمل عن بعد من خلال الانترنت أو كمستقل في أوقات فراغك. تعلم البرمجة سيوسع أفق تفكيرك كثيرًا، خصوصًا أن تعاملك مع الحاسوب يتبع إلى التفكير المنطقي، وستجد أن البرمجة ستسهل لك القيام بأمور أخرى في الحاسوب. ما عليك معرفته لتصبح مبرمجًا يتردد الكثيرون في تعلم البرمجة متذرعين بأن مستواهم في الرياضيات ليس ممتازًا، وهذا ليس صحيحًا، فصحيحٌ أنَّ هنالك أمور تعترضك أثناء أداء عملك كمبرمج تتطلب خبرة في الرياضيات، إلا أنَّه قد تمر عليك فترات طويلة لا تحتاج فيها إلى مسائل رياضية. كل ما يلزمك للبدء في تعلم البرمجة هو الأساسيات التي يعرفها الجميع. إلى حين اعتراضك أية مسألة أو مشكلة تتطلب مهارة في الرياضيات، هنالك الكثير من المصادر والمراجع التي تستطيع الرجوع إليها آنذاك. بعبارة أخرى، أجِّل هذا الأمر قليلًا ولا تخف. الأهم من ذلك هو أن تكون قادرًا على التفكير بشكل منطقي. التفكير المنطقي التفكير المنطقي هو المهارة التي تجمع كافة المبرمجين تحت مظلة واحدة، وهي أساس كتابة الخوارزميات، إذ يجب أن تكون قادرًا على اكتساب هذه المهارة وتطويرها. الخوارزميات كلمة "الخوارزميات" هي الكلمة المرعبة التي ينفر منها البعض، فكل ما يتخيلونه عند ذكرها هو الرياضيات المعقدة والمعادلات الطويلة والرموز العجيبة، لكن الأمر بسيط جدًا؛ فالخوازرميات هي تطبيقٌ للتفكير المنطقي في خطوات متسلسلة واضحة تمامًا لحل مشكلة ما. لكي أوضِّح لك أن الخوارزميات ليست أمرًا معقدًا، سأخبرك بكيفية كتابة برنامج يسأل المستخدم عن سنة ميلاده، ثم يعيد عمره الحالي بالسنوات. الخطوة الأولى: إظهار رسالة نصية نطلب فيها من المستخدم إدخال تاريخ ميلاده. الخطوة الثانية: تخزين سنة الميلاد التي أدخلها المستخدم. الخطوة الثالثة: الحصول على السنة الحالية. الخطوة الرابعة: طرح مدخلات المستخدم من السنة الحالية. الخطوة الخامسة والأخيرة: إظهار الناتج. ما سبق هو خوارزمية بسيطة تتألف من خطوات متسلسلة، لكن إذا أمعنا النظر فيها سنجد خللًا في حال أدخل المستخدم تاريخًا أكبر من التاريخ الحالي، أي لو أدخل 2050 مثلًا بدلًا من 1995. عندها سيصبح العمر المعاد من الخوارزمية سالبًا، ويمكننا أن نحل هذه الإشكالية منطقيًا بوضع شرط يمنع المستخدم من إدخال تاريخ أكبر من التاريخ الحالي. إطارات العمل كلمة أخرى شائعة جدًا في عالم البرمجة هي "إطارات العمل" frameworks، إطارات العمل هي مجموعة من الشيفرات البرمجية التي تسهل على المبرمج إنشاء التطبيقات، بتوفير وحدات جاهزة تقدم خدمات مثل تسجيل المستخدمين، وإرسال البريد الإلكتروني، والتعامل مع قواعد البيانات. أي يمكنك أن تعدّها أدوات برمجية تساعدك في برمجة تطبيقك وتسهِّل لك فعل ذلك. الأدوات اللازمة للبدء في تعلم البرمجة تحتاج إلى حاسوبٍ بمواصفات جيدة (ليس من الضروري أن يكون من أفضل الحواسيب، وإنما أن يمتلك مقدارًا جيدًا من الذاكرة العشوائية). لا ننصح بمواصفات معينة أو نظام تشغيل معين، استعمل ما يحلو لك وما ترى نفسك معتادًا عليه (سواءً كان ويندوز أو لينكس أو ماك). ستحتاج أيضًا إلى اتصالٍ جيد بالإنترنت للوصول إلى المواد التعليمية، ولتنزيل البرمجيات والمكتبات اللازمة للتطوير. أما بخصوص أدوات التطوير، فستحتاج إلى برمجية لكتابة الشيفرات، وهنالك نوعان رئيسيان لها: المحررات النصية: مثل Visual Studio Code أو Atom أو Sublime Text أو Bracktes أو Notepad++‎. وهذه المحررات النصية تكون بسيطة في أغلبها، وتوفر ميزات أساسية مثل تلوين الشيفرات، وبعض ميزات الإكمال التلقائي، وتدعم أغلبيتها إضافات لزيادة وظائفها. وظيفة هذه المحررات النصية عمومًا هي تعديل الشيفرات بسهولة وسرعة. ننصحك بتجربة Visual Studio Code لشهرته حاليًا وكثرة إضافاته ودعمه الممتاز من شركة Microsoft. بيئات التطوير المدمجة: مثل Visual Studio و Eclipse و Android Studio و NetBeans و Apple Xcode وغيرها. وهذه البيئات توفر ميزات أكثر بكثير من المحررات النصية، مثل تشغيل الشيفرات وتنقيحها (debugging) وميزات التحكم بالإصدارات والاتصال بقواعد البيانات وخلاف ذلك. لماذا هناك العديد من لغات البرمجة؟ قد تتساءل، لماذا هناك العديد من لغات البرمجة؟ أليست هذه اللغات كلها تنفذ الهدف ذاته؟ لماذا لا يكون هنالك لغة موحدة بين المبرمجين والحاسوب؟ الحقيقة أنّه توجد لغة برمجة واحدة ولكن ليست إحدى اللغات التي تراها أمامك في الصورة. اللغة التي نشير إليها هي "لغة الآلة" التي يستطيع معالج الحاسوب قراءتها وفهمها. أتتساءل ما هي لغة الآلة وكيف تبدو؟ إليك مقطعًا منها: معلومٌ أنّ معالج الحاسوب لا يفهم شيئًا سوى الأصفار والواحدات، وهذه اللغة -أي لغة الآلة- هي تمثيل للأصفار والواحدات بطريقة تخبر الحاسوب بما يجب عليه فعله. الجدير بالذكر أن هذه اللغة عصية الفهم على البشر، إذ حتى إن استطعت كتابة شيفرة مثل الشيفرة الموضحة بالصورة (كما في السنوات الأولى من بداية اختراع الحاسوب)، لن يفهمها الآخرون ولن يستطيع أحد التعديل على الشيفرة وتطويرها لاحقًا باستثنائك. سعيًا لإيجاد لغة قريبة من لغة البشر، انقسمت لغات البرمجية إلى قسمين: لغات البرمجة منخفضة المستوى، ولغات البرمجة عالية المستوى وذلك تبعًا لمدى قربها من لغة الآلة أو لغة البشر على التوالي. أي أنّ لغات البرمجة منخفضة المستوى هي اللغات الأقرب للغة الآلة آنفة الذكر مثل لغة التجميع، ولغات البرمجة عالية المستوى هي اللغات الأقرب للغة البشر مثل لغة بايثون وجافا. تنفيذ البرامج المكتوبة بلغات برمجة عالية المستوى الحديث عن اللغات عالية المستوى واللغات منخفضة المستوى يقودنا إلى الحديث عن كيفية تنفيذ المعالج للشيفرة المكتوبة بلغة عالية المستوى لا يفهمها المعالج (أليس هذا ما تفكر به الآن؟). عرفنا أن المعالج يفهم الأوامر والتعليمات المكتوبة بلغة منخفضة المستوى (لغة الآلة)، إذ مَثَلُ هذه العملية كمَثَلِ شخصٍ أجنبي تعلم اللغة العربية وبدأ التحدث مع ناطقٍ باللغة العربية، إذ يمكن لهما التواصل مباشرةً - ليخبر كل منها ما يريد من الآخر فعله - دون وسيط. أمَّا مَثَلُ كتابة برنامج بلغة عالية المستوى أقرب إلى لغة البشر والطلب من الحاسوب تنفيذه كمثل ناطق باللغة الهندية يريد التخاطب مع ناطق باللغة العربية دون أن يفقه أحدهما لغة الآخر. في هذه الحالة، لن يستطيع أحدهما فهم ما يتكلم به الآخر وستفشل عملية التواصل. قد تقول: لماذا لا يحضران مترجمًا يترجم ما يقوله كل منها للآخر؟ حسنًا، هذا ما يحصل تمامًا عندما يراد تنفيذ برنامج بلغة لا يفهمها معالج الحاسوب. في اللغات البشرية، هنالك نوع واحد من المترجمين يعرفه الجميع للترجمة من لغة إلى آخرى؛ أما في لغات البرمجة، هنالك نوعان من المترجمين بين اللغات هما: المفسر، والمترجم. بناءً على ذلك، تنقسم لغات البرمجة إلى لغات مفسرة ولغات مترجمة. (من الآن وصاعدًا، كلما ذكرنا لغات البرمجة، فنحن نشير إلى لغات البرمجة عالية المستوى.) المفسر (interpreter): وهو برنامج خاصٌ يفسِّر الشيفرة المصدرية لبرنامج مكتوب بلغة عالية المستوى سطرًا بسطر ويحولها إلى لغة منخفضة المستوى لينفذها الحاسوب مباشرةً. المترجم (compiler): وهو برنامج خاصٌ يحوِّل الملفات المصدرية لبرنامج مكتوب بلغة عالية المستوى إلى ملف تنفيذي مكتوب بلغة الآلة دفعةً واحدةً، ثم يمكن تشغيل الملف التنفيذي على الحاسوب للقيام بالمهمة المطلوبة. لماذا يوجد الكثير من لغات البرمجة عالية المستوى؟ الآن وبعد أن عرفت الفرق بين لغة الآلة ولغة البشر، لربّما ما زلت تتساءل عن كثرة اللغات البرمجية عالية المستوى المتوافرة وعدم وجود لغة واحدة. نستطيع القول أنك خطوت خطوةً جيدةً للأمام إذ أصبحت الآن أكثر دقة. جواب سؤلك هو أنّ كل لغات البرمجة تُستخدم لتحويل فكرة منطقية إلى سلسلة أوامر يمكن للحاسوب أن ينفذها. فعلى سبيل المثال لا الحصر يمكنك استخدام أي من Ruby أو Java أو Python أو C#‎ أو Go أو JavaScript لبناء موقع ويب. لكن يمكنك أن تعدّ لغات البرمجة على أنها أدوات، وكل أداة تسهّل مهمة دونًا عن أخرى. فعلى سبيل المثال، السيارة والحافلة والدراجة والمحراث الزراعي كلها وسائط نقل، لكنها مختلفة الاستخدام؛ فلا يمكنك أن تذهب وعائلتك لقضاء إجازة صيفية مستخدمين المحراث الزراعي، كما لا يمكنك استخدام سيارة سباق في مدينة مكتظة ذات شوارع ضيقة للذهاب بها إلى العمل. مع أن آلية عمل هذه المركبات متشابهة. والأمر سيانٌ بالنسبة إلى البرمجة. خلاصة القول أنّ هنالك لغات برمجة متخصصة بإنشاء تطبيقات سطح المكتب، وأخرى متخصصة بإنشاء تطبيقات الجوال، وأخرى تستعمل خصيصًا لمواقع الويب، وأخرى لبرمجة العتاد، وهذا ما يحيلنا إلى الحديث عن مجالات البرمجة واللغات الأنسب لكلٍ منها. مفاهيم البرمجة "حسنًا، اقتنعتُ أن البرمجة مناسبة لي وليست صعبة كما كنتُ أتخيل، من أين أبدأ طريقي في تعلم البرمجة إذًا؟" قبل الإجابة عن السؤال السابق، سآخذ وقتي لأشرح لك بعض المفاهيم الخاصة بالبرمجة، ثم سنتحدث عن مجالات العمل فيها وما المسار الأفضل لتعلمك كلًا منها. أنت تعلم أن البرنامج هو سلسلة أوامر ينفذها الحاسوب لحل مشكلة ما، والبرنامج نفسه مكتوب بلغة يفهمها الحاسوب تسمى لغة الآلة. من الأمور الملحوظة التركيز كثيرًا على لغة البرمجة ذاتها أثناء بداية تعلم البرمجة. سأخبرك حقيقةً صادمةً: "لغة البرمجة التي تستعملها ليست بتلك الأهمية التي تتوقعها"، أنا لا أقول لك أن جميع لغات البرمجة متماثلة أو تُستعمل لنفس الاستعمالات، لكن لا تركِّز كثيرًا على تعلم كيفية الكتابة في لغة برمجة ما وتهمل المفاهيم البرمجية التي تقف وراءها. المتغيرات والثوابت عليك أن تتعرف على مفهوم المتغيرات variables المستعمل في جميع لغات البرمجة، والذي يعني إسناد قيمة ما إلى رمز أو كلمة وتخزين هذه القيمة في الذاكرة. فلو أردنا أن نخزن العبارة "Hello World" في متغير ما فنكتب شيئًا شبيهًا بما يلي: var variable_name = "Hello World"; أي أننا نسند الجزء الموجود على يمين إشارة المساواة إلى المتغير المذكور على يسار إشارة المساواة. يمكننا أن نستنتج من اسم "المتغيرات" أن قيمتها قابلة للتغيير خلال تنفيذ البرنامج، فيمكننا في مكانٍ ما من الملف المصدري أن نعيد تعريف المتغير السابق بكتابة: var variable_name = "New value"; أما الثوابت فهي تتشابه مع المتغيرات في كثيرٍ من النواحي، إلا أنك لا تستطيع إعادة تعريف قيمتها بعد تعريفها أول مرة. قد تستفيد من الثوابت عندما تكون متأكدًا تمامًا من عدم تغيير القيمة خلال فترة تنفيذ البرنامج. فلو أردنا تعريف ثابت اسمه pi يحتوي على القيمة 3.14 (والتي سنعرف أنها لن تتغير مطلقًا)، فيمكننا أن نكتب: const pi = 3.14; وإذا حاولتَ تغيير قيمة الثابت بعد تعريفه فستحصل على رسالة خطأ. الشروط تدعم جميع لغات البرمجة تعريف شروط تُنفَّذ في حالات معينة. ففي الخوازرمية السابقة التي شرحنا فيها حساب العمر، يمكننا أن نكتب الشرط بالعربية كما يلي: إذا كان (تاريخ الميلاد أكبر من التاريخ الحالي): نقول للمستخدم أن هنالك خطأ وإلا: سنحسب العمر بطرح تاريخ الميلاد من التاريخ الحالي وإذا أردنا كتابتها بإحدى لغات البرمجة فستبدو شبيهةً بما يلي: if ( user_birth > current_year ) { // ERROR! } else { age = current_year - user_birth; } لا تلقِ للأقواس بالًا، فهي جزء من لغة البرمجة، وقد تختلف من لغة لأخرى، وليست موضع اهتمامنا حاليًا. حلقات التكرار ماذا لو كانت لدينا قاعدة بيانات فيها أكثر من مستخدم ولكل مستخدم تاريخ ميلاد. لا تقل لي سنأخذ التواريخ يدويًا وندخلها إلى البرنامج! هذا مضيعةٌ للوقت، والصواب هو إنشاء حلقة تكرار تأخذ قيمة تاريخ الميلاد الخاص بكل مستخدم ثم تحسب عمره كما أسلفنا في القسم السابق. دعنا نعدل الخوارزمية البسيطة لنضيف تكرارًا فيها: ما أجمل البرمجة! تخيل لو كان عندك ألف مستخدم، وكان عليك حساب أعمارهم، يمكنك بضغطة زر أن تحسبها كلها. الدوال الدالة function هي مجموعة من التعليمات البرمجية التي تقبل مدخلات وتعيد القيمة المطلوبة. تكون الدوال عادةً قصيرةً وتقوم بمهمة وحيدة فقط. فمثلًا لو أردنا تعريف دالة باسم divide تقبل عددين، وتعيد ناتج قسمة العدد الكبير على الصغير، فيمكننا أن نكتب الخورزمية الآتية: مصادر تعلم البرمجة للمبتدئين أول ما سيتبادر إلى ذهنك بعد قرارك تعلم البرمجة هو من أين سأتعلم؟ هنا يأتي دور القسم التعليمي المتكامل في حسوب ليقدم للمبتدئ (والمحترف على حدٍ سواء) محتوى علمي مميز ومبسط. تزخر أكاديمية حسوب بالمحتوى البرمجي عن تعلم البرمجة للمبتدئين وحتى الخبيرين أي على كافة المستويات، ستجد فيها أقسامًا تشرح لغات البرمجة وتقنياتها كلها. ولدينا قسم للأسئلة البرمجية التي يمكنك أن تطرح فيه سؤالك وسيجيب عليه أحد أفراد مجتمع أكاديمية حسوب. أضف إلى ذلك أن الأكاديمية توفر قسمًا للدورات المتخصصة التي تبدأ معك من الصفر وحتى احتراف لغة البرمجة التي تريد تعلمها مع كادر من المدربين المختصين الذي يقدمون لك المساعدة ويجيبون عن جميع استفساراتك. وهنالك قناة للأكاديمية على يوتيوب ننشر فيها دوريًا دروسًا قصيرةً عن تساؤلات محددة ومفاهيم البرمجة وخلافه. لا تنسَ الاشتراك في قناة الأكاديمية لتصلك الفيديوهات الجديدة. ماذا لو أردتَ التعمق أكثر في لغة معيّنة؟ تأتي هنا موسوعة حسوب التي توفِّر توثيقًا عربيًا كاملًا وعالي الجودة، مدعّمًا بالأمثلة لمختلف لغات البرمجة وتقنيات تطوير الويب والجوال. ستكون الموسوعة مرجعًا تعود إليه في مسيرتك البرمجية، وتستعين بها لمعرفة التفاصيل الدقيقة عن لغات البرمجة. فأنت لست مضطرًا لحفظ كل شيء في لغة البرمجة، إذ حتى المبرمجين المختصين ذوي الخبرة يعودون إلى التوثيقات بين الفينة والأخرى أثناء عملهم. لننطلق الآن للتحدث عن مجالات البرمجة الأساسية وما اللغات والتقنيات المستعملة فيها. تطوير واجهات المستخدم يبدأ أغلبية المطورين مشوارهم من خلال تعلم تطوير واجهات المستخدم عند اتخاذ قرارهم لدخول مجال تطوير وبرمجة مواقع الويب، وذلك لسهولة اللغات المستعملة في هذا المجال. هدف هذا المجال هو تطوير صفحات الويب التي تعرض محتوى مختلف مواقع الويب، وهي الصفحات التي تراها عند زيارتك لموقع أكاديمية حسوب أو موسوعة حسوب أو مستقل أو أي موقع آخر. تتألف صفحة الويب من مجموعة من المكونات، وتُكتَب هذه المكونات باستخدام لغة HTML، وبعد كتابة البنية الهيكلية للصفحة سنأتي على تنسيقها باستخدام لغة CSS، وهي اللغة المستعملة لإضفاء شكل وهيئة على عناصر HTML. أي أن عناصر HTML تصف محتوى الصفحة (مثل الترويسات والقوائم والمحتوى الرئيسي والفقرات والروابط والصور والفيدوهات)، وقواعد CSS تُعرِّف كيف يجب أن تبدو هذه العناصر (سواءً من ناحية الألوان أو المساحات أو الخلفيات أو الخطوط أو خلاف ذلك). تأتي لغة JavaScript مكملةً لهما وتستعمل لإعطاء بعض عناصر الصفحة صفاتٍ تفاعلية، مثل شريط متحرك من الصور أو قوائم تظهر عند وقوع حدث معيّن ...إلخ. هنالك تقنيات كثيرة تستعمل في تسهيل إنشاء الواجهات الأمامية وسنذكر بعضها: إطار Bootstrap لتسهيل تنسيق عناصر الصفحة. مكتبة jQuery لتسهيل التعامل مع عناصر الصفحة باستخدام JavaScript. لغة Sass لإنشاء ملفات CSS بسرعة وسلاسة. أدوات بناء مثل Webpack الذي يسهِّل تحويل الملفات المصدرية للتطبيق إلى النسخة النهائية التي ستعرَض للمستخدم. لتعلم تطوير واجهات المستخدم، ننصحك بالتسجيل في دورة تطوير واجهات المستخدم المقدمة من أكاديمية حسوب، والتي تحتوي على 58 ساعة فيديو تتوزع على سبعة مسارات تعليمية تشرح أمثلة عملية تطبيقية شرحًا مفصلًا. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب لتتعرف على توثيق لغات البرمجة المذكورة، وذلك للاطلاع على تفاصيل وأمثلة أكثر عن كل جزئية من الجزئيات المشروحة في دورة تطوير واجهات المستخدم. اللغات والتقنيات المستخدمة في تطوير واجهات المستخدم: HTML و CSS و JavaScript و Bootstrap و Sass و jQuery و Webpack. تطوير الواجهات الخلفية قد تتساءل: ماذا يعني تطوير الواجهات الخلفية (backend)؟ وما الفرق بينه وبين تطوير واجهات المستخدم (frontend)؟ الفرق بينهما هو أن الواجهات الخلفية هي البرمجيات التي تُنفَّذ على الخوادم وتجري عمليات عليها مثل التعامل مع قواعد البيانات والملفات والخدمات الخارجية، أما واجهات المستخدم فهي الصفحات التي تظهر على شاشة الزائر في متصفحه. سأطرح عليك الخيارات المتاحة أمامك للبدء في مجال تطوير الواجهات الخلفية، وجميع اللغات المذكورة هنا هي لغات ناجحة وقوية ولا يهم أي لغة تختار منها، المهم أن تتطلع على شيفرات بسيطة من كل لغة وتتخذ قرار تعلمها، واحذر من تضييع وقتك في التنقل بين لغات البرمجة والبحث عن أفضلها، فكلُ لغةٍ ممتازةٌ في مجالها. تعلم البرمجة باستخدام لغة PHP بعد تبيان الفرق بين واجهات المستخدم والواجهات الخلفية، يمكن القول بأن أشهر لغة لتطوير الواجهات الخلفية هي لغة PHP، وتتفوق على اللغات المنافسة لها أضعافًا مضاعفة. تعلم البرمجة بلغة PHP أمر سلس، فهي لغة سهلة التعلم وبسيطة الشكل، والمجتمع حولها كبير وتطويرها مستمر. هذه اللغة هي خيار استراتيجي لمن يريد الدخول إلى مجال تطوير الواجهات الخلفية. هنالك عدد من البرمجيات المكتوبة بلغة PHP مثل ووردبريس WordPress ودروبال Drupal وميدياويكي MediaWiki (التي تشغِّل ويكيبيديا وموسوعة حسوب) وغيرها الكثير؛ إضافةً إلى عددٍ كبير من إطارات العمل مثل Laravel و Zend و CodeIgniter و Symfony و CakePHP و Yii وغيرها، وهذا ما يدل على إمكانيات اللغة الكبيرة والمجتمع الكبير الذي يحيط بها. لتعلم تطوير الواجهات الخلفية باستخدام PHP، ننصحك بالتسجيل في دورة تطوير تطبيقات الويب باستخدام PHP المقدمة من أكاديمية حسوب، والتي تحتوي على 56 ساعة فيديو تتوزع على أحد عشر مسارًا تعليميًا تبدأ بأساسيات لغة البرمجة PHP للمبتدئين، مرورًا بشرح أمثلة عملية تطبيقية بالتفصيل، ووصولًا لتطوير التطبيقات باستخدام إطار العمل Laravel، وشرح تطوير ووردبريس. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق لغة PHP وإطار العمل Laravel. اللغات والتقنيات المستخدمة في تطوير تطبيقات الويب باستخدام PHP هي: PHP و Laravel وقواعد البيانات (مثل MySQL و PostgreSQL وغيرها). تعلم البرمجة باستخدام لغة روبي - Ruby إذا كنتَ تبحث عن لغةٍ أنيقة وسهلة الاستعمال فستجد ضالتك في لغة روبي Ruby فهي من أجمل اللغات وأسلسها كتابةً، وهي لغة برمجة عامة يمكن استخدامها لتطوير مختلف أنواع التطبيقات ومن ضمنها تطوير تطبيقات الويب. ذاع صيت روبي في تطوير الويب بعد نشر إطار العمل Ruby on Rails (يشار إليه اختصارًا "ريلز"). هنالك إطارات عمل أخرى مثل Sinatra لكن يبقى ريلز أشهرها. لتعلم تطوير الواجهات الخلفية باستخدام روبي، ننصحك بالتسجيل في دورة تطوير تطبيقات الويب باستخدام روبي المقدمة من أكاديمية حسوب، والتي تحتوي على 20 ساعة فيديو تتوزع على أربعة مسارات تعليمية تشرح أمثلة عملية تطبيقية شرحًا مفصلًا، وتشرح تطوير التطبيقات باستخدام إطار العمل ريلز. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق لغة روبي وإطار العمل ريلز. اللغات والتقنيات المستخدمة في تطوير تطبيقات الويب باستخدام روبي: روبي و ريلز وقواعد البيانات (مثل MySQL و PostgreSQL وغيرها). تعلم البرمجة باستخدام لغة جافا سكربت - JavaScript نعم! تستعمل JavaScript في تطوير الواجهات الخلفية أيضًا. الفضل يعود لبيئة Node.js التي تسمح للمطورين باستخدام JavaScript لكتابة برمجيات تعمل من جهة الخادم وذلك لتوليد صفحات ويب ديناميكية قبل إرسالها إلى المتصفح، وتستطيع Node.js التعامل مع الملفات وقواعد البيانات ومختلف أنظمة الشبكات وخدمات أنظمة التشغيل. هل يوجد أجمل من استخدام نفس اللغة لبرمجة الواجهات الأمامية لمواقع الويب والواجهات الخلفية؟ وكل ذلك باستخدام لغة سهلة التعلم والاستعمال ومدعومة دعمًا ممتازًا من المجتمع. تعلم لغة JavaScript لتطوير الواجهات الخلفية من خلال التسجيل في دورة تطوير التطبيقات باستخدام JavaScript المقدمة من أكاديمية حسوب، والتي تحتوي على 55 ساعة فيديو تتوزع على تسعة مسارات تعليمية تشرح أمثلة عملية تطبيقية شرحًا مفصلًا، وتشرح تطوير الواجهة الخلفية باستخدام Node.js. أثناء مشاهدتك للدورة، يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق لغة JavaScript وبيئة العمل Node.js. اللغات والتقنيات المستخدمة في تطوير تطبيقات الويب باستخدام JavaScript: لغة JavaScript وبيئة Node.js وإطار العمل Express.js وقواعد البيانات (مثل MongoDB و MySQL و PostgreSQL وغيرها). تعلم البرمجة باستخدام لغة بايثون - Python لغة بايثون متعددة الاستعمالات، ويمكن عدّها على أنها أسهل لغة برمجة على الإطلاق، إذ تبدو شيفرتها البرمجية كأنها مقالة مكتوبة باللغة الإنكليزية. إذا أردتَ لغةً سهلةً ومدعومةً دعمًا ممتازًا ولها أطر عمل كثيرة فأنت تبحث عن لغة بايثون. الخيارات المتاحة أمامك هي إطار العمل جانغو (Django) وفلاسك (Flask) وغيرها، يمكنك تعلم لغة البرمجة بايثون لتطوير الواجهات الخلفية من خلال قراءة سلاسل المقالات عن تعلم بايثون في قسم البرمجة في أكاديمية حسوب، ثم الانتقال إلى تعلم إطار العمل جانغو أو فلاسك. يمكنك أن تعود إلى موسوعة حسوب للاطلاع على توثيق لغة بايثون. تعلم لغة بايثون لتطوير الواجهات الخلفية من خلال التسجيل في دورة تطوير التطبيقات باستخدام Python المقدمة من أكاديمية حسوب، والتي تحتوي على 44 ساعة فيديو تتوزع على خمسة مسارات تعليمية تشرح أساسيات لغة بايثون للمبتدئين، ثم تطبق عمليًا بأمثلة واقعية، وتشرح إطار العمل جانغو Django وفلاسك Flask. اللغات والتقنيات المستخدمة في تطوير تطبيقات الويب باستخدام بايثون: لغة بايثون وإطارات العمل المبنية عليها (مثل جانغو وفلاسك) وقواعد البيانات (مثل MySQL و PostgreSQL وغيرها). تعلم تطوير تطبيقات الجوال ازداد عدد تطبيقات الجوال لأنظمة أندرويد و iOS ازديادًا كبيرًا في الفترة الماضية، وأصبح لكل شركة أو خدمة تطبيق خاص بها يسهِّل على مستخدميها الوصول إلى الخدمات التي توفرها. النظامان الرئيسيان المسيطران على سوق الجوال حاليًا هما أندرويد ثم iOS. يمكن برمجة تطبيقات أندرويد بلغة Java أو Kotlin (أو غيرهما) وبرمجة تطبيقات iOS باستخدام Swift (وغيرها). ستكتشف أنَّ عليك تطوير تطبيقين منفصلين تمامًا، واحد لهواتف أندرويد وآخر لهواتف iOS، وذلك يسبب زيادةً في حجم العمل المطلوب وصعوبةً في إدارة التغييرات. بسبب ذلك، ظهر مفهوم "التطبيقات متعددة المنصات"، وهي تطبيقات تعمل على نظام أندرويد و iOS دون أي تعديلات، وذلك باستخدام تقنيات مشتركة وهي في الغالب تقنيات الويب. أي أصبح بإمكان مطوري الويب الاستفادة من معلوماتهم في تطوير تطبيقات الجوال باستخدام منصات مثل آيونيك Ionic. تسمح آيونيك Ionic للمبرمجين بالتعامل مع مختلف وظائف الجهاز باستخدام لغة JavaScript، مثل الوصول إلى الموقع الجغرافي، والتقاط صور بالكاميرا، والتعامل مع الملفات وخلاف ذلك. طوِّرت في الفترة الماضية تقنيات أخرى مبنية على JavaScript مثل React Native المبنية على مكتبة React.js والتي تسمح للمطورين بكتابة تطبيقات أصيلة باستخدام تقنيات الويب. تستطيع تعلم تطوير تطبيقات الجوال عبر Ionic وعبر React Native من خلال التسجيل في دورة تطوير التطبيقات باستخدام لغة JavaScript المقدمة من أكاديمية حسوب، والتي تحتوي على 55 ساعة فيديو تشرح أمثلة عملية تطبيقية شرحًا مفصلًا. وكالعادة يمكنك أثناء مشاهدتك للدورة أن تعود إلى موسوعة حسوب للاطلاع على التوثيقات اللازمة. اللغات والتقنيات المستخدمة في تطوير تطبيقات الجوال: Java و Swift و Kotlin و Ionic و React Native وغيرها. تطوير الألعاب تطوير الألعاب هو المجال الذي يحلم جميع مستخدمي الحاسوب بالدخول إليه. فالأغلبية تعرفوا على الحاسوب من خلال ألعاب الفيديو ومن ثم بدؤوا برحلة الاستكشاف عن البرمجة والتطوير. أغلب من يجيب عن تطوير الألعاب يقول "عليك بتعلم لغة C++‎" لكن دعني أفصِّل لك الأمر قليلًا. برمجة الألعاب تتطلب عملًا كثيرًا من فريق عمل كبير، مدعوم من شركة تجارية. من الصعب على مطوِّر وحيد أن ينشئ لعبة كاملة من الصفر دون فريق. تُطور أغلبية الألعاب باستخدام محرِّك (engine) والذي يسهِّل الأمر على المطورين ويتيح بيئة تطوير مناسبة للألعاب، ويتيح الميزات الأساسية لجميع الألعاب مثل التحكم بالكاميرا ونمذجة الشخصيات ثلاثية الأبعاد وتحريكها والأمور الفيزيائية الأخرى. هنالك عدد كبير من محركات تطوير الألعاب، ومن المرجح أنك شاهدت شعارها في الألعاب التي لعبتها من قبل، ومن أشهرها: Unreal Engine و Unity. يمكن التعامل مع هذه المحركات باستخدام عدِّة لغات، مثل C++‎ (وهي أشهرها)، وجافا (خصوصًا للألعاب على هواتف أندرويد) وحتى يمكن استخدام JavaScript في التعامل مع بعضها. تذكر أنّ الألعاب غير محدودة بتطبيقات سطح المكتب أو الهواتف، فهنالك ألعاب كثيرة تعمل على المتصفحات باستخدام تقنيات HTML5 و JavaScript. اللغات والتقنيات المستخدمة في تطوير الألعاب: C++‎ و Java و JavaScript ومحركات Unity و Unreal Engine. تطوير الأنظمة المدمجة الأنظمة المدمجة هي أنظمة حاسوبية شبيهة بالحاسوب ولكنها لا تملك كل ميزات الحاسوب الذي تراه أمامك الآن. بعبارة أخرى، النظام المدمج هو حاسوب صغير مبرمج لأداء مهام محددة فقط ومدمج ضمن الجهاز أو البيئة المراد استخدامه فيها. أنت الآن محاط بالكثير من الأنظمة المدمجة الآن مثل جهاز مقياس مستوى المياه وجهاز التحكم بالتلفاز وجهاز إنذار الحريق وأجهزة المراقبة ...إلخ. حتى إشارات المرور وتنظيم السير وألعاب الأطفال الآلية تصنَّف على أنها أنظمة مدمجة. هل سمعت أيضًا بمصطلح "إنترنت الأشياء"؟ إنترنت الأشياء هو نظام مدمج متصل بالإنترنت. نعم، بهذه البساطة! لابد الآن أن يتبادر إلى ذهنك الساعات والثلاجات والغسالات الذكية وطائرات الدرون وأنظمة المراقبة عن بعد وأنظمة البيوت الذكية، إذ كلها أمثلة على إنترنت الأشياء. كيفية برمجة الأنظمة المدمجة أشهر وأكثر لغة برمجة تستعمَل في برمجة الأنظمة المدمجة وإنترنت الأشياء هي لغة C (أي لغة سي) وكل اللغات المشتقة منها (مثل‎ لغة أردوينو C). تُستعمَل لغة C++‎ كثيرًا في هذا المجال، إذ تعدُّ لغة ذات مستوى أعلى من لغة C لدعمها للبرمجة كائنية التوجه. أضف إلى ذلك أنه بدأ حديثًا استعمال لغة بايثون في برمجة تطبيقات الأنظمة المدمجة مع أنها لم ترتبط تقليديًّا بهذا المجال سابقًا. صحيح أنَّ لغة بايثون ليست بقوة لغة C و C++‎ في هذا المجال إلا أنها تستمد ميزاتها وفعاليتها من المكتبات الهائلة المتوافرة فيها. بعيدًا عن C وبايثون، تستعمل في مجال الأنظمة المدمجة أيضًا لغات أخرى تنضوي ضمن "لغات توصيف العتاد" (Hardware Description Languages)؛ لغتي VHDL و Verilog هما من أشهر لغات توصيف العتاد المستعملة في هذا المجال. تُستعمَل مثل هذه اللغات في برمجة "مصفوفة البوابات المنطقية القابلة للبرمجة" (FPGA أي Field Programmable Gate Array). أخيرًا، قد تجد بعض المراجع تشرح برمجة الأنظمة المدمجة بلغة أخرى تدعى "لغة التجميع" (Assembly Language) التي تصنف من اللغات منخفضة المستوى. يتطلب تعلم البرمجة باستخدام هذه اللغة فهمًا واسعًا بمعمارية وحدة التحكم المركزية والمعالج بالمجمل لأنها أقرب لغة يفهمها الحاسوب. الانتقال إلى هذه اللغة قد يكون في مستويات متقدمة من تعلمك لبرمجة الأنظمة المدمجة وتطبيقات إنترنت الأشياء. من ميزات البرمجة بهذه اللغة هي التحكم الواسع بالعتاد والمعالج الذي لا توفره لغات أخرى. يقال أن هذه اللغة صعبة بعض الشيء ومعقدة، ولكن لا أرى ذلك! قد يكون سبب قول ذلك هو أن لغة التجميع هي لغة منخفضة المستوى وأقرب شيء إلى لغة الآلة ولا يستطيع من يلقي نظرة على شيفرة مكتوبة فيها فهمها مطلقًا إن لم يعرفها. تطوير تطبيقات سطح المكتب مجال تطوير تطبيقات سطح المكتب كالمحيط الواسع؛ إن لم تملك بوصلة وتعرف إلى أين تريد الاتجاه، ستضيع فيه حتمًا. هنالك الكثير من أنظمة التشغيل أشهرها - وأكثرها سيطرةً على السوق حاليًا - هي: نظام التشغيل ويندوز، ولينكس، وماك (macOS)، ويملك كل نظام تشغيل تطبيقات مكتبية خاصة به. لذلك، يجب عليك أولًا -قبل الدخول إلى سوق برمجة تطبيقات سطح المكتب- تحديد نظام التشغيل المستهدف. أي يجب الإجابة على السؤال التالي: هل يستهدف تطبيقك نظام تشغيل محدد، أم تريد لتطبيقك أن يعمل على عدة أنظمة تشغيل في آن واحد؟! بعد تحديد نظام التشغيل المستهدف، اطلع على اللغات المفضل استعمالها في ذلك النظام لبرمجة تطبيقاته؛ فعلى سبيل المثال، اللغات C و C++‎ و C#‎ و VB.NET هي الأكثر استعمالًا في برمجة تطبيقات نظام التشغيل ويندوز، واللغات C و C++‎ و Bash هي الأكثر استعمالًا في برمجة تطبيقات توزيعات نظام التشغيل لينكس. أمَّا نظام الشغيل ماك، فينفرد باستعمال لغة Objective-C. حسنًا، دعني أخبرك الحقيقة، كل لغة برمجة عامية الغرض يمكن استعمالها في برمجة التطبيقات، إذ أشهر اللغات التي تُدرَّس أكاديميًّا في هذا المجال هي لغة جافا (Java). لا يخفى على القارئ دخول لغة بايثون بقوة على هذا المجال نظرًا لامتلاكها الكثير من المكتبات الرائعة وسهولة صياغتها. دخلت مؤخرًا لغة جافاسكربت على سوق برمجة تطبيقات سطح المكتب عبر إطار العمل Electron (إلكترون)، إذ توظف في هذا المجال تقنيات تطوير الويب (HTML و CSS و JavaScript ...إلخ.). بدأ هذا الإطار ينتشر كالنار في الهشيم مما دفع شركات كبيرة لتطوير تطبيقات سطح المكتب الخاصة بها باستعمال هذا الإطار ومنها شركة Slack التي استعملت هذا الإطار لتطوير تطبيقها المكتبي. أعلم أنك الآن تشعر بالضياع من كثرة لغات البرمجة والتقنيات المستعملة في هذا المجال؛ معك حق، فقد أخبرتك بذلك منذ قليل. دخول هذا السوق يحتاج منك تحديد هدفك منه بالضبط. هل لديك فكرة تطبيق وتريد إنشاءه والربح منه؟ هل تريد العمل لدى شركة محددة؟ ما هي مواصفات التطبيق الذي تريد إنشاءه أو تريد العمل على تطويره؟ كل ذلك يلعب دورًا في تحديد لغة البرمجة الأنسب لك لتعلمها. في النهاية، إن تعلمت أساسيات البرمجة وأتقنت العمل على لغة برمجية محددة، سيسهل عليك الانتقال إلى لغة برمجة أخرى، إذ أغلب لغات البرمجة تشبه بعضها بعضًا من ناحية المفهوم والمضمون وتختلف بعض الشيء من ناحية الصياغة والشكل. لذلك، اطمئن من هذه الناحية. كيفية اختيار لغة البرمجة التي تناسبك يمكنك اختيار لغة البرمجة اعتمادًا على المجال الذي تحب العمل فيه، سألخص لك مسار التعلم لمختلف مجالات العمل: العمل كمطور ويب full-stack: يعني ذلك تعلم تطوير واجهات المستخدم، وتطوير الواجهات الخلفية. يمكن التخصص بمجال واحد من هذين المجالين فقط، إذ يُطلَب كثيرًا في سوق العمل مبرمجين متخصصين في واجهات المستخدم أو الواجهات الخلفية. العمل كمطور تطبيقات للهواتف المحمولة: يمكنك تعلم برمجة تطبيقات أندرويد أو iOS كلًا على حدة، أو استعمال تقنيات مثل كوردوفا للتطوير لكلا النظامين معًا. العمل كمطور تطبيقات سطح المكتب: يمكنك البدء بالتخصص في تطوير تطبيقات مكتبية لنظام تشغيل محدَّد (مثل نظام التشغيل ويندوز أو لينكس) عبر تعلم لغة البرمجة المستعملة في ذاك المجال (كما أشرنا إلى ذلك في قسم تطوير تطبيقات سطح المكتب)؛ خيار آخر هو تعلم اللغات والتقنيات التي تمكنك من تطوير تطبيقات عابرة للمنصات (تعمل على عدة أنظمة تشغيل) مثل استعمال إطار العمل Electron. العمل كمطور للأنظمة المدمجة والأنظمة الذكية: لغة C هي أساس هذا المجال، سواءً كنتَ تتعامل مع المتحكمات مباشرةً، أو تتعامل مع شريحة مثل أردوينو (والتي تمتلك لغةً مشتقةً من C). يساعدك هذا الفيديو على معرفة المعايير التي من خلالها ستتمكن من اختيار لغة البرمجة التي تتناسب مع تطلعاتك وأهدافك المستقبلية. نصائح لتعلم البرمجة مشوار تعلم البرمجة من الصفر طويل وشائق، وجميل ومسلٍ، لكنك قد تصاب بالإحباط في بداية طريقك لكثرة الأمور التي عليك الإلمام بها، لذا جهزت إليك النصائح الآتية من تجربتي في البرمجة: حدد هدفك من تعلم لغة البرمجة وسوق العمل الذي تريد دخوله واجعله واقعيًا. بدون هدف، أبشرك بأنك ستتخلى عن فكرة تعلم البرمجة بعد حين. انتبه إلى أن يكون هدفك واقعيًا وقابلًا للقياس والتجزيء على مراحل. بدون ذلك، ستفشل من أول عقبة وتترك تعلم البرمجة. أعرف نفسك جيدًا ونقاط قوتك وضعفك. كلنا لديه نقاط قوة وضعف، ولكن المفلح من عمل على ترميم وتحسين نقاط ضعفه في المجال الذي يرغب بتعلمه. رشح دورة واحدة وكتابًا واحدًا وابدأ بقراءة الكتاب ومتابعة الدورة تدريجيًّا ثم انتقل بعد الانتهاء إلى دورة أخرى وكتاب آخر، إذ سيجنبك ذلك التشتت بين الدورات الكثيرة والكتب العديدة. الشيء الذي أفعله قبل بداية تعلم شيء جديد هو ترشيح قائمة من عدة كتب ودورات ثم ترتيب هذه الكتب والدورات بحسب جودتها ومدى بساطتها وتعقيدها. أرقم الكتب والدورات وأبدأ بالخيار الأول منها. أحدد الوقت التقريبي الذي يأخذه كل خيار لدراسته وأجدول الخيارات البقية على رزنامتي الخاصة. لا تأخذ العلم إلا ممن تثق بعلمه، فالكثير من المبتدئين يحاولون مساعدة غيرهم وقد يضعون معلومات مغلوطة دون قصد. طبق ما تعلمته مباشرة، وأنشئ أي شيء من كل أمر جديد تتعلمه حتى لو كان رسمة بسيطة أو شيفرة من عدة أسطر فقط. فرحة إنجاز شيء مما تعلمته تدفعك لتعلم المزيد والاستمرار في طلب العلم. نظم وقتك بورقة وقلم، حدد بداية كل أسبوع خطةً لسائره والتزم بتنفيذها. أخبر أصدقائك أن لديك إلتزام وأمور مهمة عليك إنجازها. خصص وقتًا للاستراحة بالطبع ولا تنسَ نصيبك منها. في نهاية كل أسبوع، وازن مدى الإنجاز الذي حققته ومدى تطبيق الخطة التي وضعها وحاول أن تصل النسبة إلى 100%. أنصحك بقراءة ومتابعة استراتيجيات تنظيم الوقت ورفع الإنتاجية. تمرس على حل المشكلات وتحدى نفسك باستمرار وتابع المسابقات البرمجية واشترك بها إن استطعت، أنصحك بقراءة مقالة حل المشكلات وأهميتها في احتراف البرمجة بعد هذه المقالة. لا تنسَ أن تكافئ نفسك في كل مرة تنهي فيها كتابًا أو تكمل العمل على مشروع. لا تنسَ حظك من الاستراحة، لأن طريق البرمجة قد يكون له بداية ولكن النهاية بعيدة ومتعبة -مثله مثل أي مجال آخر-. في النهاية أرجو لك كل التوفيق في مشوارك البرمجي. وأرجو منك أن تشاركنا تجربتك في تعلم البرمجة، لعل غيرك يستفيد منها. اقرأ أيضًا كيف تتعلم البرمجة المدخل الشامل إلى تعلم علوم الحاسوب المرجع الشامل إلى تعلم لغة بايثون تعرف على أعلى تخصصات البرمجة أجرا تعلم لغة HTML قواعد البرمجة ما هي فوائد تعلم البرمجة؟ أسهل لغات البرمجة أهمية البرمجة
  4. على الرحب والسعة. الحل هو سحب الرصيد ثم شراء الدورة عبر paypal.
  5. وعليكم السلام ورحمة الله وبركاته، أهلًا بك. كانت هذه الخدمة موجودة ولم تعد متاحةً للأسف.
  6. توفِّر JavaScript إمكانية بناء كائن Date جديد، وإذا أمعنت النظر في المعاملات التي يقبلها هذا الكائن، فستلاحظ أنَّ مجال «اليوم» بين 1 إلى 31. لاحظ أنَّه عند استدعاء الدالة البانية Date مع أكثر من وسيط، وكانت القيم أكبر من مجالها المنطقي (مثلًا: استخدمنا 13 مكان الشهر أو 70 مكان الدقائق أو 0 مكان «اليوم») فستُعدّل قيمة التاريخ بما يوافق ذلك. لذا سنستعمل 0 مكان «اليوم» عند بناء الكائن كما يلي: var dateNow = new Date(); var lastDayOfMonth = new Date(dateNow.getFullYear(), dateNow.getMonth() + 1, 0).getDate(); console.log(lastDayOfMonth); ما سبق سيُنشِئ كائن Date جديد للسنة الحالية، وللشهر القادم، ولليوم 0، ولمّا كان أول يوم في الشهر هو 1 وليس 0، فسيؤخذ آخر يوم من الشهر الذي يسبق الشهر الماضي (أي الشهر الحالي). راجع توثيق الدالة البانية Date والدالة getFullYear والدالة getMonth والدالة getDate في موسوعة حسوب للمزيد من المعلومات.
  7. إحدى المهارات الأساسية والمهمة التي عليك أن تتقنها هي القدرة على استيراد وتصدير قواعد البيانات، إذ تستطيع أخذ نسخ احتياطية لقواعد بياناتك وتستعيدها عند الحاجة، أو يمكنك الاستفادة منها لنقل البيانات إلى خادوم جديد أو بيئة تطوير مختلفة. إجراء عملية تصدير من قواعد بيانات MySQL و MariaDB هو أمرٌ بسيطٌ، وسنشرحه في هذا الدرس إضافةً إلى شرح طريقة استيراد النسخة الاحتياطية. المتطلبات المسبقة لتصدير أو استيراد قواعد بيانات MySQL ستحتاج إلى: وصول إلى خادوم لينكس يستعمل قواعد بيانات MySQL أو MariaDB. قاعدة بيانات مع معلومات المستخدم القادر على إجراء عمليات عليها. تصدير قاعدة البيانات تُستعمَل الأداة mysqldump لتصدير قواعد البيانات إلى ملفات SQL نصية، ويمكن بسهولة نقل تلك الملفات كيفما تشاء. ستحتاج إلى معرفة اسم قاعدة البيانات نفسها وإلى اسم المستخدم وكلمة المرور لحسابٍ يملك امتيازاتٍ تسمح –على الأقل– بأذونات القراءة الكاملة على قاعدة البيانات. استعمل الأمر الآتي لتصدير قاعدة البيانات: mysqldump -u username -p database_name > data-dump.sql username هو اسم المستخدم الذي يستطيع الوصول إلى قاعدة البيانات database_name هو اسم قاعدة البيانات التي نريد تصديرها data-dump.sql هو مسار الملف الذي نريد حفظ مخرجات عملية التصدير إليه لن يعرض الأمر السابق أيّة مخرجات مرئية، لكن يمكنك النظر في محتويات الملف data-dump.sql لتتأكد من وجود ملف SQL سليم فيه باستعمال الأمر: head -n 5 data-dump.sql يجب أن تبدو المخرجات (التي تظهر أوّل خمسة أسطر من الملف) كما يلي، يجدر بالذكر أنَّ الملف الآتي هو ناتج عملية تصدير قاعدة بيانات باسم database_name: -- MySQL dump 10.13 Distrib 5.7.16, for Linux (x86_64) -- -- Host: localhost Database: database_name -- ------------------------------------------------------ -- Server version 5.7.16-0ubuntu0.16.04.1 إذا حدثت أيّة أخطاء أثناء عملية التصدير، فسيعرضها mysqldump على الشاشة مباشرةً. استيراد قاعدة البيانات لاستيراد ملف SQL مُصدَّر إلى قاعدة بيانات MySQL أو MariaDB، فعليك أولًا إنشاء قاعدة بيانات جديدة التي ستستضيف البيانات المستوردة. سجِّل دخولك إلى عميل قواعد البيانات بحساب المستخدم root أو أي حساب آخر له امتيازات كافية لإنشاء قواعد بيانات جديدة: mysql -u root -p ستنتقل الآن إلى سطر الأوامر الخاص بقواعد MySQL، أنشِئ الآن قاعدة بيانات جديدة وليكن اسمها new_database: CREATE DATABASE new_database; يجب أن تشاهد الناتج الآتي الذي يدل على نجاح إنشائها: Query OK, 1 row affected (0.00 sec) اخرج الآن من عميل MySQL بكتابة الأمر exit أو بالضغط على الزرين Ctrl+D، وبعد عودتك إلى سطر الأوامر ستستطيع استيراد الملف باستخدام الأمر الآتي: mysql -u username -p new_database < data-dump.sql username هو اسم المستخدم الذي يستطيع الوصول إلى قاعدة البيانات new_database هو اسم قاعدة البيانات التي نريد استيراد البيانات إليها data-dump.sql هو مسار الملف الذي نريد استيراد محتوياته لن تظهر أية مخرجات إذا نجح تنفيذ الأمر السابق، لكن إن حدثت أخطاء خلال العملية فسيظهرها الأمر mysql على الشاشة. يمكنك التأكد من استيراد قاعدة البيانات بتسجيل الدخول إلى عميل MySQL مجددًا وتفحص البيانات، يمكن فعل ذلك بتحديد قاعدة البيانات الجديدة عبر USE new_database ثم كتابة الأمر SHOW TABLES;‎ أو ما شابهه. الخلاصة أصبحت تعلم كيف تصدِّر قواعد بيانات MySQL إلى ملفات وكيف تستوردها مجددًا. هنالك خياراتٌ أخرى متاحةٌ للأمر mysqldump التي تُعدِّل سلوك هذا الأمر عند تصدير قواعد البيانات، والتي يمكنك التعرف عليها في صفحة التوثيق الرسمي. ترجمة –وبتصرّف– للمقال How To Import and Export Databases in MySQL or MariaDB لصاحبه Mateusz Papiernik
  8. برمجية Jenkins هي خدمة أتمتة مفتوحة المصدر الغرض منها هو أتمتة المهام التقنية المتكررة التي تتعلق بدمج وتوفير البرمجيات. برمجية Jenkins مكتوبة بلغة Java ويمكن تثبيتها من حزم أوبنتو أو بتنزيل وتشغيل ملف WAR (الذي هو مجموعة من الملفات التي تُنشِئ تطبيق ويب كامل ليعمل على خادومك). سنُثبِّت Jenkins في هذا الدرس بإضافة مستودع حزم دبيان الخاص بها، ثم بتثبيت الحزم اللازمة عبر الأداة apt-get من ذاك المستودع. المتطلبات المسبقة سنحتاج إلى خادوم أوبنتو 16.04 فيه حساب مستخدم ليس جذرًا وفيه جدار ناري وذلك باتباع التعليمات الواردة في درس «الإعداد الابتدائي لخادوم أوبنتو 14.04](https://academy.hsoub.com/devops/servers/الإعداد-الابتدائي-لخادوم-أوبنتو-1404-r4/)»، ننصح باستعمال 1 غيغابايت من ذاكرة RAM على الأقل؛ راجع صفحة Choosing the Right Hardware for Masters لمزيدٍ من المعلومات حول العتاد اللازم لتثبيت Jenkins. يمكنك المتابعة مع هذا الدرس بعد إعداد الخادوم. الخطوة الأولى: تثبيت Jenkins الإصدار المتوافر في مستودعات أوبنتو الرسمية يكون قديمًا ومتأخرًا عن الإصدار الحالي لمشروع Jenkins؛ وللاستفادة من آخر التحديثات والميزات فسنستخدم الحزم المُصانة من قِبل مشروع Jenkins نفسه. علينا أولًا إضافة مفتاح المستودع إلى النظام: wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add - بعد إتمام إضافة المفتاح بنجاح فستظهر كلمة OK في الطرفية؛ ثم سنضيف بعد ذلك عنوان مستودع دبيان إلى ملف sources.list الموجود في الخادوم: echo deb http://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list بعد تنفيذ الخطوتين السابقتين، علينا تحديث فهرس الحزم عبر الأمر: sudo apt-get update ثم نثبّت Jenkins مع اعتمادياته كلها، بما فيها بيئة تشغيل Java: sudo apt-get install jenkins يمكننا الآن تشغيل خادوم Jenkins بعد تثبيته مع اعتمادياته. الخطوة الثانية: بدء تشغيل خادوم Jenkins سنستخدم الأداة systemctl لتشغيل Jenkins: sudo systemctl start jenkins ولعدم إظهار الأمر systemctl لأية مخرجات، فسنستخدم الخيار status لعرض حالة الخدمة للتأكد أنها قد بدأت دون مشاكل: sudo systemctl status jenkins إذا جرى كل شيءٍ على ما يرام، فيجب أن تشير المخرجات أنَّ الخدمة تعمل حاليًا وستُشغَّل تلقائيًا عند الإقلاع: ● jenkins.service - LSB: Start Jenkins at boot time Loaded: loaded (/etc/init.d/jenkins; bad; vendor preset: enabled) Active:active (exited) since Thu 2017-04-20 16:51:13 UTC; 2min 7s ago Docs: man:systemd-sysv-generator(8) بعد تشغيل خادوم Jenkins، علينا الآن تعديل قواعد الجدار الناري للسماح بالوصول إلى خدمة Jenkins من متصفح الويب لإكمال ضبطه المبدئي. الخطوة الثالثة: فتح المنفذ في الجدار الناري يعمل خادوم Jenkins افتراضيًا على المنفذ 8080، لذا سنفتحه باستخدام ufw: sudo ufw allow 8080 يمكننا رؤية القاعدة الجديدة بالتحقق من حالة جدار UFW الناري: sudo ufw status يجب أن نلاحظ أنَّ التراسل الشبكي إلى المنفذ 8080 متاحٌ من كل الشبكات: Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere 8080 ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) 8080 (v6) ALLOW Anywhere (v6) بعد أن ثبتنا Jenkins وضبطنا الجدار الناري للسماح بالوصول إليه من جميع الشبكات، فسنكمل في الخطوة التالية الضبط المبدئي له. الخطوة الرابعة: ضبط خدمة Jenkins علينا لضبط خدمة Jenkins أن نزور صفحته على المنفذ الافتراضي 8080 مستعملين اسم نطاق الخادوم أو عنوان IP الخاص به كما يلي: http://ip_address_or_domain_name:8080. سنستعمل الأمر cat في نافذة الطرفية لعرض كلمة المرور: sudo cat /var/lib/jenkins/secrets/initialAdminPassword انسخ كلمة المرور المكومة من 32 محرفًا ورقمًا من الطرفية وألصقها في حقل «Administrator password» ثم اضغط على زر «Continue»، ثم ستظهر لك صفحة تعرض خيارين لتثبيت الإضافات المقترحة أو تحديد إضافات معيّنة. اضغط على خيار «Install suggested plugins» الذي سيبدأ عملية التنزيل مباشرةً: بعد إكمال التثبيت سيُطلَب منك ضبط أوّل حساب مستخدم، وصحيح أنَّ من الممكن تخطي هذه الخطوة والإكمال باستعمال المستخدم admin مع كملة المرور المبدئية التي استعملناها أعلاه، لكن من الأفضل إنشاء مستخدم جديد. ملاحظة: الاتصالات المنشأة إلى خادوم Jenkins غير مشفرة، لذا ستُرسَل البيانات النصية كما هي دون أي تشفير، لذا أنصحك باتباع ما ورد في هذا الدرس لإعداد تشفير SSL مع خادوم Jenkins، مما يحمي بيانات المستخدم والمعلومات التي ترسَل عبر واجهة الويب. بعد ضبط أوّل حساب للمدير فستُعرَض لك صفحة فيها «Jenkins is ready!‎»: اضغط على زر «Start using Jenkins» للانتقال إلى لوحة التحكم الرئيسية لخادوم Jenkins: تهانينا، لقد ثبتنا خادوم Jenkins بنجاح. الخلاصة ثبتنا في هذا الدرس برمجية Jenkins من الحزم التي يوفرها المشروع، ثم بدأنا الخدمة وفتحنا منفذًا في الجدار الناري، وأنشأنا حسابًا جديدًا للمدير؛ وتستطيع الآن أن تستكشف Jenkins. ترجمة –وبتصرّف– للمقال How To Install Jenkins on Ubuntu 16.04لصاحبته Melissa Anderson
  9. عندما تصون مستودعًا لمشروع مفتوح المصدر، فأنت تأخذ راية القائد، فلو كنتَ مؤسس أحد المشاريع التي أطلقتها للعموم ليستخدموها ويشاركوا فيها، أو كنت تعمل في فريقٍ وكنت تصون جانبًا من جوانب المشروع، فأنت تقدم خدمةً مهمةً إلى مجتمع التطوير. وعلى الرغم من أنَّ المساهمات في المشاريع مفتوحة المصدر تكون عادةً عبر طلبيات pull وهي أمرٌ بالغ الأهمية للحفاظ على جودة البرمجيات وفائدتها للمستخدمين النهائيين، لكن المساهمين في المشروع ليس لهم نفس تأثير من يقوم بصيانته ويبلور الشكل العام للمشروع؛ فالصائنون يشاركون في صلب تطوير المشاريع مفتوحة المصدر، إذ يديرون المشروع وينظموه يوميًا ويطوروه، ويتفاعلون مع المستخدمين ويوفرون المعلومات اللازمة للمساهمين. سنستعرض في هذا المقال بعض التلميحات عن صيانة المستودعات العامة للمشاريع مفتوحة المصدر. فالمسؤولون عن المشاريع مفتوحة المصدر عليهم مسؤوليات كبيرة تقنية وغير تقنية، والعمل كصائن للمشروع يعطي الفرصة للتعلم من الآخرين، وأخذ خبرة في إدارة المشاريع، ويسمح بمراقبة مراحل نمو المشروع وكيف أصبح المستخدمون العاديون مساهمين فعالين فيه. اكتب توثيقًا مفيدًا سيزيد التوثيق سهل الفهم (والذي سيؤدي إلى جعل البرنامج سهل الاستخدام) من قاعدة مستخدميك، ويساعد في تحويل المستخدمين إلى مساهمين في مشروعك. عندما تفكر بالشيفرات التي تكتبها أثناء تطويرك للمشروع، وتكتب بعض الملاحظات الجانبية لتساعدك في دمج مختلف أجزاء مشروعك مع بعضها بعضًا، فسيسهل عليك البدء بكتابة التوثيق أثناء عملية التطوير؛ أو ربما تقرر أن تكتب التوثيق قبل برمجة التطبيق، متبعًا بذلك منهجية «التطوير الموجه بالتوثيق» (documentation-driven development) التي تقول أنَّ عليك كتابة توثيق ميزات المشروع أولًا ثم برمجة تلك الميزات اعتمادًا على توثيقها. هنالك بضعة ملفات عليك وضعها في المجلد الرئيسي لمشروعك بجانب الشيفرات وهي: - ملف README.md الذي يوفر ملخصًا عن المشروع وأهدافه. - ملف CONTRIBUTING.md الذي يحتوي على تعليمات المساهمة في المشروع. - رخصة مشروعك، والتي ستشجِّع الناس على المساهمة في موقعك، أرجو أن تراجع مقالة كيف تختار رخصة مفتوحة المصدر لبرامجك. قد يأخذ التوثيق أشكالًا عدِّة، لذا عليك أن تضع نوعية المستخدمين المحتملين ومجال المشروع في الحسبان، فمن الممكن أن يأتي التوثيق بمختلف الأشكال ويكون موجهًا نحو فئات مختلفة من مستخدمي المشروع. قد تقرر استخدام شكل أو أكثر من الأشكال الآتية اعتمادًا على مجال عملك: دليل عام لتعريف المستخدمين بالمشروع الدروس التعليمية لعرض مختلف حالات الاستخدام الأسئلة الشائعة (FAQ) للإجابة عن أكثر التساؤلات شيوعًا بين المستخدمين مقالات عن استكشاف الأخطاء التي قد يواجهها المستخدمون وكيفية إصلاحها مرجع للواجهة البرمجية (API) للتطبيق تسمح للمستخدمين معرفة معلومات عن الواجهة البرمجية بسرعة ملاحظات الإصدار (release notes) التي تُذكَر فيها العلل المعروفة والتغييرات التي حدثت في كل إصدار الميزات المستقبلية لتتبع وشرح ما هي الميزات التي ستأتي في إصدارات مستقبلية. تسجيل مقطع فيديو لتعريف المستخدمين بمشروعك عبر الوسائط المتعددة. قد تلائم بعض أشكال التوثيق السابقة مشروعك أكثر من غيرها، لكن توفير أكثر من شكل للتوثيق سيساعد مستخدمي مشروعك أن يفهموا كيف يتفاعلون معك فهمًا أعمق. عليك عند كتابة التوثيق أو تسجيل مقطع فيديو أن تكون واضحًا قدر الإمكان، ومن الأفضل ألّا تكون عندك افتراضات مسبقة عن القدرات التقنية لمستخدمي مشروعك، ومن الأفضل أن تتبع منهجية Top-Down عند تأليف التوثيق، أي أن تشرح بداية الأمر ما الذي تفعله البرمجية بشكل عام (مثلًا: أتمتة أمور إدارة النظام، أو بناء موقع إلكتروني …إلخ.) قبل التعمق في التفاصيل. وصحيحٌ أنَّ اللغة الإنكليزية هي اللغة الرائدة في عالم التقنية، لكن أبقِ في ذهنك مَن هم المستخدمون المتوقعون وما هي لغتهم الأم؛ فاللغة الإنكليزية هي خيارٌ جيدٌ إذا كانت لديك قاعدة مستخدمين واسعة ومن مختلف البلدان، لكن ضع في بالك أنَّ عدد كبيرًا ممن سيقرؤون توثيقك لا تكون اللغة الإنكليزية هي لغتهم الأم، لذا حاول استخدام لغة سهلة لا تُسبِّب لبسًا عند القراء، وإذا كان مشروعك موجّه لمنطقة أو لغة معيّنة مثل برنامج للتعرف على الكلام العربي فأنصحك حينئذٍ أن توفر التوثيق باللغة العربية. حاول أن تكتب التوثيق كما لو كنتَ تكتب لأحد المساهمين الجدد الذين يريدون أن يطلعوا على حالة المشروع، فلا تنسَ أنَّك تريد أن يتحول المستخدمون العاديون إلى مساهمين. تنظيم «القضايا» القضايا (issues) هي طريقةٌ تستعمل لتتبع أو التبليغ عن العلل، أو لطلب ميزات جديدة لتضاف إلى البرنامج. توفِّر خدمات استضافة مستودعات المشاريع مفتوحة المصدر مثل GitHub و GitLab و Bitbucket طرائق لتتبع القضايا التي تُنشِئها وتسمح للمستخدمين بإنشائها. فمن المتوقع عند إطلاق مشروعك مفتوح المصدر أن تُفتَح عدِّة قضايا من قِبل مجتمع المستخدمين، لذا سيمثِّل تنظيم ووضع أولويات لهذه القضايا أمرًا مهمًا لتبيان خارطة الطريق لما عليك فعله للمشروع مستقبلًا. ولأنَّ أي مستخدم يستطيع أن يفتح قضية، فلن تكون جميع القضايا لتبليغ العلل أو لطلب الميزات، فقد تأتيك أسئلة عبرها، أو قد تأتي طلبات لتحسينات صغيرة على واجهة المستخدم مثلًا. فمن الأفضل تنظيم هذه القضايا في أفضل شكل ممكن ومحاولة التواصل مع المستخدمين الذين أنشؤوها. يجب أن تمثِّل القضايا مهامًا محددة عليك تنفيذها برمجيًا، لذا عليك تنظيمها حسب أهميتها. يجب أن يكون هنالك حدود للوقت والعمل الذي تنفقه أنت أو المساهمون في المشروع للقضايا المفتوحة فيه، ويمكنكم التعاون على اتخاذ القرارات والخروج بخطة قابلة للتنفيذ، وعندما تعلم أنَّك غير قادر على حل مشكلة معيّنة في الإطار الزمني المتاح لك، فيمكنك التعليق عليها وإخبار المستخدم أنَّك قرأت المشكلة وستفعل ما بوسعك تجاهها، وقد تستطيع أن تخبره بالوقت المتوقع للنظر في أمر هذه المشكلة مرةً أخرى. أما لطلبات الميزات أو التحسينات، فيمكنك أن تسأل الشخص الذي أنشأ القضية إن كان يستطيع المساهمة في الشيفرة لتطبيق هذه الميزة، يمكنك توجيه المستخدمين إلى ملف CONTRIBUTORS.md أو إلى أيّة صفحات أخرى من التوثيق. ولأن الأسئلة لا تمثِّل عادةً مهامًا محدَّدة، فالتعليق على السؤال لتوجيه المستخدم بلباقة إلى صفحة التوثيق هو خيارٌ ممتاز لإبقاء تفاعلك مع المستخدم احترافيًا ولطيفًا؛ وإذا لم يحتوي التوثيق على جوابٍ لهذا السؤال فحان الوقت لإضافة التوثيق الملائم، وتعبِّر عن شكرك للمستخدم لأنه دلّك على موضع النقص في التوثيق. إذا كنتَ تستقبل عددًا كبيرًا من الأسئلة عبر القضايا، فربما تفكر بإنشاء صفحة الأسئلة الشائعة (FAQ) في التوثيق، أو صفحات ويكي أو منتدى لتتيح للآخرين المساعدة والمشاركة في الإجابة عن الأسئلة. وفي كل مرة يبلِّغ فيها أحد المستخدمين عن مشكلة، فحاول أن تكون لطيفًا معه قدر الإمكان، فتفاعل المستخدمين معك يعني أنَّ المشروع قد أعجبهم ويريدون جعله أفضل. محاولة تنظيم القضايا ستجعل مشروعك محدثًا دومًا وسيشعر المستخدمون أنهم يأثرون فيه، لذا احذف القضايا التي تقع خارج نطاق مشروعك أو القضايا القديمة، وضع أولويات للبقية لكي يكون تقدمك في المشروع مستمرًا. حفِّز المساهمين كلما رحّبتَ بالمساهمين الجدد وكافأتهم على جهودهم لوجدت أنَّك تحفِّز مساهمين جدد ليشاركوا في مشروعك، ولكي تجذب المساهمين إلى المشروع فاحرص على تضمين ملف CONTRIBUTING.md في المجلد الرئيسي لمستودعك، وإشارة إلى ذاك الملف في README.md. إذا أردتَ كتابة ملف جيد للمساهمين الجدد فيجب أن يتضمن كيفية بدء العمل على المشروع كمطوِّر، فقد تكتب دليلًا يوضح ذلك خطوةً بخطوة، أو قائمةً من الأمور التي يجب على المطورين اتباعها وتنفيذها، شارحًا كيف يمكن أن يدمجوا الشيفرة التي كتبوها بشيفرة المشروع عبر طلبية pull. إضافةً إلى توثيق كيفية المساهمة في المشروع، فلا تنسَ أن تبقي شيفرات المشروع منظمة وسهلة القراءة، فإذا كانت الشيفرة سهلة الفهم وفيها تعليقات كثيرة تشرح ما تفعله وطريقة استخدامها موحدة ومتناسقة مع بعضها بعضًا فسيساهم ذلك في تحفيز المساهمين المحتملين على المشاركة في المشروع. أقترح أيضًا أن تبقي على قائمة بالمساهمين، فيمكنك أن تجذب المساهمين عبر إضافتهم إلى القائمة بغض النظر عن حجم مشاركتهم (حتى تصحيح الأخطاء اللغوية هو مشاركة ومساهمة فعالة في المشروع، ويمكن أن تؤدي إلى مزيدٍ من المساهمات مستقبلًا). وهذا يعني أنَّك تقدِّر عمل المساهمين في المشروع وتشير إليهم أمام جميع مستخدمي مشروعك، مما يحمِّس بقية المستخدمين على المشاركة. ابنِ مجتمعًا حول مشروعك بتمكين مستخدميك عبر التوثيق وبالتجاوب مع القضايا وبتحفيزهم للمشاركة، فأنت في طريقك لبناء مجتمع حول مشروعك المفتوح المصدر، فالمستخدمون السعيدون بتجاوبك معهم والذين تعدُّهم على أنهم مساهمون سيحاولون الترويج مشروعك ما استطاعوا. إضافةً إلى ما سبق، يمكنك الترويج لمشروعك بمختلف السبل: التدوين تسجيل ونشر فيديوهات تعريفية إنشاء قائمة بريدية النشاط على مواقع التواصل الاجتماعي التعاون مع المشاريع الشبيهة أو المتعلقة بمشروعك والترويج لها. عليك أن تُناسِب ترويجك للمشروع مع مجاله وعدد أعضاء الفريق الفعالين والمساهمين الذين يعملون معك. فعندما ينمو المجتمع حول مشروعك، فيمكنك أن توفِّر مساحة أكبر للمساهمين والمستخدمين والقائمين على المشروع ليتفاعلوا، بعض تلك الخيارات تتضمن: برمجيات الويكي التي توفِّر توثيقًا مصانًا من المجتمع المنتديات لمناقشة الميزات المحتملة وللإجابة على الأسئلة قائمة بريدية للتفاعل مع المجتمع عبر البريد الإلكتروني ضع ببالك قاعدة مستخدمي مشروعك ومجاله بما في ذلك عدد الأشخاص القائمين عليه والموارد المتاحة لك قبل أن تتوسّع في المجالات السابقة، واستشر مجتمعك عن الخيار الأفضل قبل الإقدام عليه. وأهم من ذلك كله أن تكون لطيفًا معهم وتريهم أنَّك تهتم بهم عبر تفاعلك معهم، أعلمُ أنَّ الاتسام بصفة اللباقة طوال الوقت ليس أمرًا سهلًا، لكن ستؤتي أُكلها على المدى البعيد. الخلاصة يلعب صائن المستودع دورًا مهمًا في مجتمع البرمجيات مفتوحة المصدر الكبير. وصحيحٌ أنَّ هذا الدور يأخذ وقتًا وعملًا كبيرًا، لكن الخبرة التي تكتسبها خلال هذا العمل ستفيدك كمطوِّر وكمساهم، ولا تنسَ أنَّ الصائن اللطيف واللبق سيساعد في دفع عجلة تطوير المشروع الذي يهتم لأجله. ترجمة –وبتصرّف– للمقال Maintaining Open-Source Software Projects لصاحبته Lisa Tagliaferri. حقوق الصورة البارزة محفوظة لـ Freepik
  10. إذا طبّقنا بضعة انتقالات (transitions) على عناصر الصفحة فقد تؤدي إلى نتيجة رائعة إذا خططنا لها جيدًا، وسنتعلم في هذا المقال كيف نستخدم الانتقالات لدب الحياة في محتوى الصفحة، وسنخطط ونبني تأثيرات مرور الفأرة فوق العناصر لتبدو بأجمل مظهر. الانتقالات أم الحركات الانتقالات (transitions) رائعة للانتقال بسلاسة من حالة إلى أخرى (والعودة إلى الحالة الأصلية مجددًا) في المتصفح، وقد تبدو أنها بديلٌ أبسط من الحركات (animation) التي تستعمل keyframes و animation، لكن لكلٍ ميزاتها وفوائدها. فمثلًا، لن تستفيد من الانتقالات إذا كنت تريد حدوث حركة عند تحميل الصفحة، أو إذا أردتَ أن تستمر الحركة طوال الوقت؛ أما إذا كانت لديك حالتين وأردتَ التحريك بينهما بسهولة فستستفيد حينئذٍ من الانتقالات. إذا كنتَ مهتمًا بالفروقات بين الانتقالات والحركات فأنصحك بمراجعة هذه المقالة. سنبني في هذا الدرس مشهدًا من الفضاء وسنضيف إليه تأثير مرور الفأرة فوقه لعرض بعض المعلومات الإضافية عن الكوكب، وسنفِّكر بحالتَي العناصر وما هي الخاصيات التي سنستخدمها للحصول على انتقال سلس وجميل. يمكنك الاطلاع على المثال الكامل لأخذ فكرة عن ما سنفعله. See the Pen &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/qmNgXW/&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/qmNgXW/&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;Planet hover effect part 3: with transition&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; by Donovan Hutchinson (&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;@donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;) on &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;CodePen&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;. ضبط الحالتين أكثر الأمور التي تأخذ وقتًا وجهدًا عند إنشاء الانتقالات هي الحالة الأولية والحالة النهائية للعنصر، فيجب أن نُفكِّر كيف سيبدو العنصر قبل تطبيق الانتقال وماذا يجب أن يتغيّر في مظهره بعد حدوث الانتقال. عندما أُنشِئ الانتقالات المعقدة نسبيًا فلا أهتم بالحركة نفسها إلى أن يعجبني مظهر العناصر في الحالتين، ومن هذا المنطلق فسنهتم بالخاصيات التي سنستخدمها في حالة hover لأن هذه الخاصيات ستخضع إلى حركة. قبل الخوض في موضوع الانتقالات فلنضبط الحالتين أولًا. حالة البداية سيكون كوكب الأرض في منتصف المشهد بدايةً، وسيدور القمر حوله. شيفرة HTML تتضمن عنصر article الذي نضع فيه عنصرَي earth و moon، لاحظ أنَّ عنصر moon موجود داخل حاوية باسم moon-container لأنها ستساعدنا بموضع القمر لاحقًا. <article class="earth-demo"> <div class="earth"> <img src="https://cssanimation.rocks/images/random/earth.png"> </div> <div class="moon-container"> <div class="moon"> <img src="https://cssanimation.rocks/images/random/moon.png"> </div> </div> </article> هذه هي أنماط CSS التي سنستخدمها، سنجعل موضع العنصر earth مساويًا للقيمة absolute وسنستخدم الدالة calc لتوسيط الأرض رأسيًا وأفقيًا. .earth { position: absolute; top: calc(50% - 100px); left: calc(50% - 100px); } وسنُحدِّد موضع الصورة ونعطيها طولًا وعرضًا: .earth img { height: 200px; position: absolute; top: 0; left: 0; width: 200px; } وسنفعل المثل تقريبًا للقمر، إذ سنبدأ بوضع الحاوية في منتصف الشاشة: .moon-container { position: absolute; top: calc(50% - 25px); left: calc(50% - 25px); } ثم سنضبط أبعاد القمر ونُطبِّق الحركة spin عليه (والتي سنعرِّفها لاحقًا)، وهذا ما سيجعل القمر يدور حول الأرض. .moon { animation: spin 20s linear infinite; background: none; height: 50px; pointer-events: none; transform-origin: 25px; width: 50px; } عند هذه المرحلة سيكون القمر متموضعًا في منتصف الشاشة وفوق الأرض، لذا لنستخدم الخاصية transform لتحريك القمر إلى خارج الحاوية الخاصة بعيدًا عن الأرض. .moon img { height: 50px; transform: translateX(-160px) translateY(-160px); width: 50px; } هذا يعني أنَّ عنصر moon سيدور فوق الأرض، لكن الصورة ستدور حول الأرض. لنضف الآن حواف مدورة للعنصر لكي تظهر حواف الأرض والقمر بدقة وسنستعمل الخاصية box-shadow لإعطائهما توهجًا أزرقًا: .earth img, .moon img { border-radius: 50%; box-shadow: 0 0 12em 1em rgba(110, 140, 200, .6); } في النهاية، سنُعرِّف الحركة spin لتدوير القمر، وهذه الحركة بسيطة، إذ سندوِّر القمر حول المحور Z بزاوية 360 درجة. @keyframes spin { to { transform: rotateZ(360deg); } } هذا هو ناتج هذه المرحلة: See the Pen &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/aWZPeP/&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/aWZPeP/&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;Planet hover effect part 1: initial stage&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; by Donovan Hutchinson (&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;@donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;) on &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;CodePen&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;. عرض المزيد من المعلومات نريد أن نظهر معلومات مفيدة حول كوكب الأرض عند مرور الفأرة فوقه، ربما ستساعد هذه المعلومات الفضائيين في معرفة بعض الأمور الأساسية عن كوكبنا قبل أن يزورونا :-) . علينا قبل ضبط حالة hover أن نضيف هذه المعلومات، وسنبدأ بإضافة عنصر div ذي المعرِّف more-info الذي يحتوي على بعض النصوص: <article class="earth-demo"> <div class="earth"> <div class="more-info"> <h1>Earth</h1> <ul> <li>Third planet from the Sun</li> <li>Atmosphere: 21% oxygen</li> <li>Liquid water on surface</li> <li>Only planet that has life (that we know of)</li> </ul> </div> <img src="https://cssanimation.rocks/images/random/earth.png"> </div> <div class="moon-container"> <div class="moon"> <img src="https://cssanimation.rocks/images/random/moon.png"> </div> </div> </article> أضفنا هذه المعلومات داخل حاوية earth لأننا نريد جعلها جزءًا من التأثير، أي عند مرور الفأرة فوق النص فسيبقى على الشاشة. سنضيف بعض أنماط CSS إلى عنصر more-info: .earth .more-info { background-image: linear-gradient(to bottom, rgba(10,10,10,1), black); border-radius: 1em; color: #fff; opacity: 0; padding: 1em; transform-origin: 0 0; transform: scale(.8); width: 400px; } .earth .more-info h1 { margin: 0 0 1em; text-align: right; } ضبطنا هنا لون الخلفية والحواف المنحنية والحاشية وعرض العنصر، وغيّرنا قياسه قليلًا باستخدام transform وضبطنا transform-origin إلى الزاوية العليا اليسرى لكي يتغيّر قياسه بدءًا من تلك النقطة. خاصية opacity للعنصر more-info تساوي الصفر أي أنَّ العنصر شفاف تمامًا ولن يكون مرئيًا، وقد نضيف الخاصية visibility لكي نضمن أنَّ المحتوى لا يتداخل مع بقية العناصر، لكننا لن نفعل ذلك في مثالنا هذا. إنشاء انتقال للخاصيات المطلوبة عندما نضبط تأثير الانتقال فمن المهم أن نأخذ الأداء بالحسبان، فبعض الخاصيات مثل الارتفاع والحاشية (padding) وحجم الخط و background-position لن يكون أداؤها جيدًا إذا أجرينا تأثير الانتقال عليها، والسبب وراء ذلك هو أنَّها تجعل المتصفح يُعيد حساب الكثير من التفاصيل في تخطيط الصفحة عندما تتغير. لذا من الأفضل استخدام الخاصيتين opacity و transform عند إجراء حركات لأن أداءها جيد ولا تسبب «تعليق» في المتصفح. سنستخدم في هذا المثال الخاصيتين opacity و transform إذ سيُصغَّر العنصر more-info قليلًا باستخدام transform وكان شفافًا تمامًا (قيمة opacity تساوي الصفر). أما في حالة hover فسنغيّر شفافية العنصر more-info لكي يصبح مرئيًا وسنزيح الكوكب إلى الجانب. حالة مرور الفأرة فوق العناصر لنبدأ بضبط حالة ‎.earth:hover، إذا كنتَ ستستخدم Sass فيمكنك اختصار الكثير من الشيفرات التي سنكتبها، لكنني سأستخدم CSS في هذا الدرس. لنحرِّك الكوكب جانبًا بادئ الأمر: .earth:hover img { transform: translateX(-75px) translateY(-75px) scale(.5); } خاصية transform السابقة ستدفع الكوكب إلى اليسار بمقدار 75 بكسل وستصغره إلى 50% من حجمه. لنقم بشيءٍ مشابه إلى القمر: .earth:hover ~ .moon-container { transform: translateX(-75px) translateY(-75px) scale(.5); } .earth:hover ~ .moon-container img { transform: translateX(-140px) translateY(-140px); } نفّذنا خدعةً هنا إلى صورة القمر ألا وهي استخدام transform لتقريبه إلى الأرض. لنُظهِر الآن العنصر more-info: .earth:hover .more-info { opacity: 1; transform: none; } ضبطنا الشفافية إلى 1 وهذا يعني أنَّ العنصر أصبح ظاهرًا، وضبطنا الخاصية transform إلى none وهذا يعني أنَّ العنصر سيعود إلى حجمه الطبيعي. هذه هي النتيجة الحالية، مرر الفأرة فوق الكوكب لتشاهد مربع المعلومات. See the Pen &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/bWezpR/&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/bWezpR/&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;Planet hover effect part 2: basic hover effect&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; by Donovan Hutchinson (&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;@donovanh&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;) on &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;CodePen&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;. تطبيق تأثير الانتقال لقد أنجزنا الأمور الصعبة، وكل ما بقي علينا لنفعل هو إخبار المتصفح كيف سيتنقل بين الحالتين. ولحسن الحظ لن نحتاج إلى كتابة شيفرات طويلة، وإنما يمكن فعل ذلك بخاصية CSS وحيدة: .earth-demo * { transition: all 4s cubic-bezier(0,1.5,.3,1); } لنشرح القاعدة السابقة بالتفصيل. تُطبَّق القاعدة السابقة على كل العناصر الموجودة داخل عنصر earth-demo (وذلك باستخدام رمز النجمة *). ثم سنطبِّق تأثير الانتقال transition لجميع الخاصيات بمدة 4 ثواني وباستخدام دالة التوقيت cubic-bezier، وهذه الدالة ستبدأ بسرعة ثم تتباطأ حتى النهاية، وفي النهاية ستتخطى القيم المُحدَّدة في الحالة hover ثم ستعود إلى القيم التي ضبطناها. وقبل أن ننظر إلى النتيجة النهائية، فدعنا نضيف تأخيرًا بسيطًا إلى عناصر القائمة، فمن الجميل أن تظهر عناصر القائمة تلو بعضها بتأثيرٍ حركيٍ جميل. يمكننا فعل ذلك باستخدام الخاصية transition-delay. تأخير تأثير الانتقال سنضبط بدايةً شفافية تلك العناصر إلى الصفر، أي سيكونوا غير مرئيين قبل أن يبدأ تأثير الانتقال. .earth-demo h1, li { opacity: 0; } وعندما يبدأ الحدث hover فسنُظهرهم جميعًا: .earth-demo:hover h1, li { opacity: 0; } علينا الآن تأثير ظهور عناصر القائمة الأربعة، وذلك باستخدام المُحدِّد nth-child: .earth-demo:hover li:nth-child(1) { transition-delay: 0s; } .earth-demo:hover li:nth-child(2) { transition-delay: 0.2s; } .earth-demo:hover li:nth-child(3) { transition-delay: 0.4s; } .earth-demo:hover li:nth-child(4) { transition-delay: 0.6s; } الشيفرة السابقة ستُضيف تأخيرًا إلى كل عنصرٍ من عناصر القائمة، ولأننا استخدمنا المُحدِّد * فيما سبق فهذا يعني أنَّ كل عنصر من هذه العناصر سيُطبَّق عليه تأثير الانتقال، وكل ما علينا تحديده هو زمن التأخير. هذه هي النتيجة النهائية: See the Pen &amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/qmNgXW/&amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh/pen/qmNgXW/&amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;gt;Planet hover effect part 3: with transition&amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;gt; by Donovan Hutchinson (&amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io/donovanh&amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;gt;@donovanh&amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;gt;) on &amp;amp;amp;amp;amp;amp;amp;amp;lt;a data-cke-saved-href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;#39; href=&amp;amp;amp;amp;amp;amp;amp;#39;https://codepen.io&amp;amp;amp;amp;amp;amp;amp;#39;&amp;amp;amp;amp;amp;amp;amp;amp;gt;CodePen&amp;amp;amp;amp;amp;amp;amp;amp;lt;/a&amp;amp;amp;amp;amp;amp;amp;amp;gt;. لقد فعلناها! حركة معقدة نسبيًا أنجزناها باستخدام خاصية transition وحيدة. تعلمنا في هذا الدرس كيف نخطط ونبني مثالًا متكاملًا يستخدم الانتقالات لإنشاء حركات معقدة، وحرصنا أن تكون الانتقالات سلسلة وتبدو بشكلٍ جميل. الخلاصة الخدع البسيطة التي نقوم بها عبر الحركات والانتقالات هي التي تجعل موقعنا مميزًا وجميلًا ترجمة –وبتصرّف– للمقال Transitions in space لصاحبه Donovan Hutchinson
  11. بروتوكول نقل الملفات FTP (اختصار للعبارة File Transfer Protocol) هو بروتوكول شبكي كان شائعًا جدًا فيما قد سلف لنقل الملفات بين الخادوم والعميل، لكن استبدلته الطرائق الأكثر أمانًا وسرعةً لنقل الملفات، فكثيرٌ من مستخدمي الإنترنت يتوقعون تنزيل الملفات مباشرةً من متصفح الويب عبر بروتوكول http (أو https)، أما مستخدمي سطر الأوامر فيستعملون بروتوكولات أكثر أمانًا مثل scp أو sFTP. لكن ما يزال بروتوكول FTP مستخدمًا في التطبيقات القديمة أو للحالات التي لها متطلبات خاصة، فلو كنتَ تستطيع اختيار ما هو البروتوكول الذي ستستخدمه، فأنصحك بالنظر في بقية الخيارات الحديثة؛ لكن إذا كنت تحتاج إلى استخدام FTP فخادوم vsftpd هو خيارٌ ممتازٌ إذ إنَّ أداءه ممتاز وآمن ومستقر، ويوفِّر قدرًا كبيرًا من الحماية ضد كثيرٍ من المشاكل الأمنية الموجودة في خودايم FTP الأخرى، إضافةً إلى أنه الخادوم الافتراضي لخدمة FTP للعديد من توزيعات لينكس. سنتعلم في هذا الدرس كيفية ضبط خادوم vsftpd للسماح للمستخدمين برفع ملفاتهم إلى مجلد المنزل الخاص بهم باستخدام بروتوكول FTP مع تأمين معلومات الدخول عبر تشفير SSL/TLS. المتطلبات المسبقة خادوم أوبنتو 16.04 مع وصول إلى مستخدم يملك امتيازات الجذر عبر الأمر sudo: إذ سنُطبِّق الأوامر المذكورة في هذا الدرس عبر مستخدمٍ ليس جذرًا لكنه يمتلك امتيازات الجذر عبر الأمر sudo. يمكنك إنشاء مستخدم له امتيازات الجذر باستخدام الأمر sudo باتباع درس «الإعداد الابتدائي لخادوم أوبنتو 14.04](https://academy.hsoub.com/devops/servers/الإعداد-الابتدائي-لخادوم-أوبنتو-1404-r4/)». يمكننا أن نبدأ بتطبيق هذا الدرس بعد أن يكون الخادوم جاهزًا. الخطوة الأولى: تثبيت vsftpd سنبدأ بتحديث فهرس الحزم في خادومنا ثم تثبيت خادوم vsftpd: sudo apt-get update sudo apt-get install vsftpd عند إكمال التثبيت، فسننسخ ملف الضبط الافتراضي لنأخذ نسخةً احتياطيةً منه، ولنعدِّل الضبط كما نشاء. sudo cp /etc/vsftpd.conf{,.orig} بعد أن أخذنا نسخةً احتياطيةً من ملف الضبط، فحان الوقت الآن لإعداد الجدار الناري. الخطوة الثانية: فتح المنافذ الضرورية في الجدار الناري سنتحقق أولًا من حالة الجدار الناري لنرى إن كان مفعلًا أم لا، فإذا كان مفعلًا فعلينا السماح باتصالات FTP عبره لكي لا نواجه مشاكل عندما نجرِّب الخادوم. sudo ufw status نجد من الناتج الآتي أنَّ خدمة SSH مسموحٌ لها فقط: Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) لاحظ أنَّ الناتج قد يكون مختلفًا عندك، فقد لا توجد أيّة قواعد لجدارك الناري أو لديك قواعد إضافية. ولمّا كان الجدار الناري لا يسمح إلا لاتصالات SSH فعلينا إضافة قواعد للسماح لاتصالات FTP، وسنحتاج إلى فتح المنفذين 20 و 21 لخدمة FTP، والمنفذ 990 لنستعمله لاحقًا عندما نضبط تشفير TLS، والمنافذ من 40000 إلى 50000 كمنافذ غير المباشرة (passive ports) التي نخطط لضبطها لاحقًا في ملف الضبط: sudo ufw allow 20/tcp sudo ufw allow 21/tcp sudo ufw allow 990/tcp sudo ufw allow 40000:50000/tcp sudo ufw status يجب أن تبدو قواعد الجدار الناري كما يلي: Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere 990/tcp ALLOW Anywhere 20/tcp ALLOW Anywhere 21/tcp ALLOW Anywhere 40000:50000/tcp ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) 20/tcp (v6) ALLOW Anywhere (v6) 21/tcp (v6) ALLOW Anywhere (v6) 990/tcp (v6) ALLOW Anywhere (v6) 40000:50000/tcp (v6) ALLOW Anywhere (v6) يمكننا الانتقال إلى الخطوة التالية بعد تثبيتنا لخادوم vsftpd وفتح المنافذ الضرورية. الخطوة الثالثة: تهيئة مجلد المنزل للمستخدم سنُنشِئ في هذا الدرس مستخدمًا جديدًا، لكن قد يكون لديك مستخدم موجود في نظامك ويحتاج إلى وصول FTP، وسنحرص على الحفاظ على وصول المستخدم إلى بياناته، لكن مع ذلك أنصحك بإنشاء مستخدم جديد إلى أن تضبط الخادوم وتجرّبه. سنُنشِئ بدايةً مستخدمًا جديدًا للتجربة: sudo adduser sammy أسنِد كلمة المرور إلى الحساب عند طلبها، ويمكنك تجاهل بقية الأسئلة بالضغط على زر Enter. تكون خدمة FTP أكثر أمانًا إذا كان المستخدمون محدودين بمجلدٍ معيّن، ويمكن لخادوم vsftpd فعل ذلك باستخدام chroot، فعند تفعيل chroot للمستخدمين المحليين، فلن يسمح لهم بالوصول إلى شيءٍ خارج مجلد المنزل الخاص بهم افتراضيًا، لكن خادوم vsftpd يحاول تأمين المجلد بعدم السماح بالكتابة عليه من قبل المستخدم (عبر سطر الأوامر)، ولا بأس بذلك للمستخدمين الجدد الذين يجب أن يتصلوا عبر FTP فقط، لكن إذا كان لدينا مستخدم موجود مسبقًا ويجب أن يستطيع الكتابة إلى مجلد المنزل الخاص به عبر سطر الأوامر فهذا لن يكون مناسبًا أبدًا. وبدلًا من إزالة إذن الكتابة من مجلد المنزل، فسنُنشِئ مجلد ftp لكي يكون chroot وسنُنشِئ داخله مجلد files يمكن الكتابة عليه ليحتوي على الملفات. لنُنشِئ مجلد ftp ونضبط ملكيته ونحذف إذن الكتابة منه بالأوامر الآتية: sudo mkdir /home/sammy/ftp sudo chown nobody:nogroup /home/sammy/ftp sudo chmod a-w /home/sammy/ftp لنتأكد من الأذونات: sudo ls -la /home/sammy/ftp الناتج: total 8 4 dr-xr-xr-x 2 nobody nogroup 4096 Aug 24 21:29 . 4 drwxr-xr-x 3 sammy sammy 4096 Aug 24 21:29 .. لنُنشِئ الآن المجلد الذي يحتوي على الملفات التي ستُرفَع ونضبط ملكيته إلى المستخدم: sudo mkdir /home/sammy/ftp/files sudo chown sammy:sammy /home/sammy/ftp/files لنتحقق أيضًا من أذونات المجلد files: sudo ls -la /home/sammy/ftp الناتج: total 12 dr-xr-xr-x 3 nobody nogroup 4096 Aug 26 14:01 . drwxr-xr-x 3 sammy sammy 4096 Aug 26 13:59 .. drwxr-xr-x 2 sammy sammy 4096 Aug 26 14:01 files وفي النهاية، لنضف ملفًا باسم test.txt لكي نستخدمه عند التجربة لاحقًا: echo "vsftpd test file" | sudo tee /home/sammy/ftp/files/test.txt بعد أن أصبح مجلد ftp آمنًا، وأعطينا المستخدم الأذونات اللازمة على مجلد files، فيمكننا الاهتمام الآن بموضوع الضبط. الخطوة الرابعة: ضبط وصول FTP خطتنا هي السماح للمستخدم الذي يملك وصولًا محليًا إلى سطر الأوامر بالاتصال عبر FTP، وهنالك خيارا ضبط رئيسيان مضبوطان في ملف vsftpd.conf. لنبدأ أولًا بفتح ملف الضبط للتأكد أنَّ التعليمات المذكورة فيه تُطابِق ما يلي: sudo nano /etc/vsftpd.conf محتوى الملف: . . . # Allow anonymous FTP? (Disabled by default). anonymous_enable=NO # # Uncomment this to allow local users to log in. local_enable=YES . . . علينا الآن تغيير بعض القيم في الملف، ولكي نسمح للمستخدم برفع الملفات فسنزيل رمز التعليق قبل التعليمة write_enable لكي يصبح السطر كما يلي: . . . write_enable=YES . . . سنُزيل رمز التعليق قبل التعليمة chroot_local_user لمنع المستخدم الذي يتصل عبر FTP من الوصول إلى أيّة ملفات خارج المجلد المضبوط: . . . chroot_local_user=YES . . . علينا إضافة التعليمة user_sub_token لكي نستطيع وضع اسم المستخدم في مسار local_root، وهذا لكي يعمل الضبط دون مشاكل لهذا المستخدم ولأي مستخدم آخر قد نضيفه مستقبلًا: user_sub_token=$USER local_root=/home/$USER/ftp سنُحدِّد مجال المنافذ المستخدم لاتصالات FTP غير المباشرة (passive FTP) لكي نحرص على توافر اتصالات كافية: pasv_min_port=40000 pasv_max_port=50000 تذكر أننا فتحنا هذه المنافذ سابقًا في الجدار الناري، أي لو استخدمتَ مجالًا مختلفًا عمّا سبق فاحرص على تحديث ضبط الجدار الناري بما يتوافق مع ذلك. ولأننا نخطط للسماح بوصول إلى FTP لمستخدمين معينين، فسنعدِّل في الضبط لكي نسمح بالوصول إلى قائمة معيّنة من المستخدمين: userlist_enable=YES userlist_file=/etc/vsftpd.userlist userlist_deny=NO التعليمة userlist_deny تُحدِّد ما الذي يجب فعله مع المستخدمين المذكورين في القائمة، فلو ضُبِطَت إلى YES فسيمنعون من الوصول إلى FTP، وإذا كانت NO فلن يسمح بالوصول إلى FTP إلا للمستخدمين المذكورين في القائمة. بعد أن تنتهي من إضافة الأسطر السابق فاحفظ الملف واخرج من المحرر النصي. علينا الآن إنشاء ملف القائمة وإضافة اسم المستخدم إليه، يمكننا استخدام الخيار ‎-a الخاص بالأمر tee لإسناد السطر إلى نهاية الملف: echo "sammy" | sudo tee -a /etc/vsftpd.userlist لنتأكد من محتوى الملف: cat /etc/vsftpd.userlist الناتج: sammy أعد تشغيل الخادوم لتطبيق التغييرات التي أجريناها في ملف الضبط: sudo systemctl restart vsftpd نحن جاهزون الآن للتجربة. الخطوة الخامسة: تجربة الوصول إلى FTP ضبطنا الخادوم للسماح للمستخدم sammy فقط بالوصول إلى FTP، لنتأكد من صحة ذلك. يجب ألّا يُسمَح للاتصال من المستخدمين المجهولين (anonymous users)، إذ عطلنا ذلك في الضبط، وسنجرِّب ذلك بمحاولة الاتصال بشكل مجهول، فإذا كان ضبطنا صحيحٌ فيجب ألّا يسمح لنا بالوصول إلى الخادوم: ftp -p 203.0.113.0 الناتج: Connected to 203.0.113.0. 220 (vsFTPd 3.0.3) Name (203.0.113.0:default): anonymous 530 Permission denied. ftp: Login failed. Ftp> أغلِق الاتصال: bye يجب ألّا يتمكن أيّ مستخدمٍ عدا sammy من الاتصال: وسنتحقق من ذلك عبر وضع اسم المستخدم الذي يملك امتيازات الجذر، ويجب ألّا يُسمَح له أيضًا قبل أن يُطلَب منه إدخال كلمة المرور: ftp -p 203.0.113.0 الناتج: Connected to 203.0.113.0. 220 (vsFTPd 3.0.3) Name (203.0.113.0:default): sudo_user 530 Permission denied. ftp: Login failed. Ftp> أغلِق الاتصال: bye يجب أن يتمكن المستخدم sammy من الاتصال، ومن قراءة وكتابة الملفات، لذا لنجرِّب ذلك: ftp -p 203.0.113.0 الناتج: Connected to 203.0.113.0. 220 (vsFTPd 3.0.3) Name (203.0.113.0:default): sammy 331 Please specify the password. Password: your_user's_password 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. Ftp> سندخل إلى المجلد files، ثم سنستعمل الأمر get لنقل ملف التجربة الذي أنشأناه سابقًا إلى جهازنا المحلي: cd files get test.txt الناتج: 227 Entering Passive Mode (203,0,113,0,169,12). 150 Opening BINARY mode data connection for test.txt (16 bytes). 226 Transfer complete. 16 bytes received in 0.0101 seconds (1588 bytes/s) ftp> سنحاول الآن إعادة رفع الملف باسمٍ جديد للتأكد من إمكانية الكتابة على المجلد: put test.txt upload.txt الناتج: 227 Entering Passive Mode (203,0,113,0,164,71). 150 Ok to send data. 226 Transfer complete. 16 bytes sent in 0.000894 seconds (17897 bytes/s) أغلِق الاتصال: bye بعد أن تأكدنا أنَّ الخادوم يعمل كما ضبطناه، فيمكننا إتباع إجراءات إضافية لتأمين الخادوم. الخطوة السادسة: جعل عمليات النقل آمنة لما كان بروتوكول FTP لا يشفِّر أيّة بيانات عند نقلها، بما في ذلك معلومات المستخدم، فعلينا تفعيل تشفير SSL/TLS لتأمين تلك البيانات، وأوّل خطوة هي إنشاء شهادات SSL لاستخدامها مع vsftpd. سنستخدم openssl لإنشاء شهادة جديدة، ونستخدم الخيار ‎-days لجعلها صالحةً لمدة سنة، وسنضيف –في الأمر نفسه– مفتاح ‎2048-bit RSA خاص، ثم بإسناد القيمة ذاتها إلى الخيارين ‎-keyout و ‎-out فستكون الشهادة والمفتاح الخاص في الملف نفسه. هذا هو الأمر الذي سنُطبِّقه: sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem سيُطلَب منّا توفير معلومات عن الشهادة التي سنُنشِئها، ضع المعلومات الخاصة بك عند الإجابة عن الأسئلة: Generating a 2048 bit RSA private key ............................................................................+++ ...........+++ writing new private key to '/etc/ssl/private/vsftpd.pem' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:NY Locality Name (eg, city) []:New York City Organization Name (eg, company) [Internet Widgits Pty Ltd]:Hsoub Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []: Email Address []: بعد أن أنشأنا الشهادات، فعلينا الآن تعديل ضبط vsftpd مجددًا: sudo nano /etc/vsftpd.conf ستجد قرب نهاية الملف سطرين يبدآن بالسابقة rsa_‎، أضف قبلهما رمز التعليق ليصبحا كما يلي: # rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem # rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key أضف السطرين الآتيين بعدهما، اللذان يشيران إلى الشهادة والمفتاح الخاص اللذين أنشأناهما سابقًا: rsa_cert_file=/etc/ssl/private/vsftpd.pem rsa_private_key_file=/etc/ssl/private/vsftpd.pem علينا الآن جعل استخدام SSL إجباريًا، مما يمنع العملاء غير القادرين على التعامل مع تشفير TLS من الاتصال بخادومنا، وهذا ضروري للحرص على تشفير جميع المعلومات المنقولة لكن قد يجبر المستخدم على تغيير عميل الاتصال. عدِّل قيمة التعليمة ssl_enable إلى YES: ssl_enable=YES أضف بعد ذلك الأسطر الآتية لمنع الاتصالات المجهولة عبر SSL، ولإجبار استخدام SSL لتسجيل الدخول ولنقل البيانات: allow_anon_ssl=NO force_local_data_ssl=YES force_local_logins_ssl=YES علينا ضبط الخادوم استخدام TLS بدلًا من SSL عبر إضافة الأسطر الآتية: ssl_tlsv1=YES ssl_sslv2=NO ssl_sslv3=NO علينا بعد ذلك إضافة تعليمتين إضافيتين، الأولى تسمح بعدم استخدام SSL عند إعادة استخدام الجلسة (session reuse) لأنها لا تعمل مع أغلبية عملاء FTP، وسنطلب استخدام حزم عالية التشفير، وهذا يعني أنَّ طول المفتاح أكبر أو يساوي 128 بت: require_ssl_reuse=NO ssl_ciphers=HIGH بعد أن تنتهي من التعديلات السابقة، فاحفظ الملف وأغلق المحرر. علينا الآن إعادة تشغيل الخادوم لتأخذ التعديلات مجراها: sudo systemctl restart vsftpd لم نعد نتمكن الآن من استخدام عميل FTP غير الآمن الذي يعمل من سطر الأوامر، فلو جربناه فسنشاهد الناتج الآتي: ftp -p 203.0.113.0 Connected to 203.0.113.0. 220 (vsFTPd 3.0.3) Name (203.0.113.0:default): sammy 530 Non-anonymous sessions must use encryption. ftp: Login failed. 421 Service not available, remote server has closed connection ftp> سنتحقق من الاتصال في الخطوة القادمة باستخدام عميل يدعم تشفير TLS. الخطوة السابعة: تجربة الاتصال عبر TLS باستخدام FileZilla أغلبية عملاء FTP الحديثين يدعمون تشفير TLS، وسنشرح كيفية الاتصال عبر عميل FileZilla لأنه يعمل على جميع أنظمة التشغيل؛ راجع توثيق عميلك المفضل لتعرف كيف يمكن الاتصال عبر TLS فيه. عندما تفتح برنامج FileZilla فسنجد أيقونة Site Manager تحت قائمة File مباشرةً، أي أنَّها أوّل أيقونة في الشريط العلوي. اضغط عليها: ستُفتَح نافذة جديدة، اضغط فيها على زر «New Site» في الركن السفلي الأيسر: ستجد ظهور «New site» تحت أيقونة «My Sites»، يمكنك تسمية الموقع الآن أو إعادة تسميته لاحقًا بالضغط على زر «Rename». عليك أن تملأ حقل «Host» بعنوان IP أو اسم نطاق الموقع، وعليك أن تختار «Require explicit FTP over TLS» في قائمة «Encryption» أما لخيار «Logon Type» فاختر «Ask for password»، ثم أدخِل اسم المستخدم في حقل «User»: اضغط على زر «Connect» في أسفل النافذة، وستُسأل عن كلمة مرور المستخدم: اضغط على «OK» لتتصل، يجب أن يكون اتصالك مع الخادوم مشفرًا بتشفير TLS/SSL. بعد أن تقبل الشهادة، فانقر نقرًا مزدوجًا على مجلد files واسحب الملف upload.txt وأفلته في القسم اليساري من البرنامج لكي تبدأ بتنزيله: بعد ذلك، يمكنك أن تنقر بالزر الأيمن على الملف المحلي وتعيد تسميته إلى upload-tls.txt وتسحبه مجددًا إلى الخادوم لكي ترفعه عليه. لقد تمكنا من تنزيل الملفات ورفعها بأمان مع تفعيل تشفير SSL/TLS. الخطوة الثامنة: تعديل الوصول إلى سطر الأوامر (خطوة اختيارية) إن لم تتمكن من استخدام تشفير TLS بسبب محدوديات العميل، فيمكنك تأمين الخادوم قليلًا بمنع مستخدم FTP من تسجيل الدخول إلى سطر الأوامر، إحدى الطرائق البسيطة لفعل ذلك هي إنشاء صدفة (shell) خاصة. أكرِّر أنَّ الخطوة السابقة لا توفِّر أيّ تشفير، وإنما الغرض منها هو تقليل الوصول إلى حسابات المستخدمين المسموح لهم بالاتصال عبر FTP فقط. علينا أولًا إنشاء ملف باسم ftponly في مجلد ‎/bin: sudo nano /bin/ftponly سنضيف الآن رسالةً تخبر المستخدم أنَّه ليس قادرًا على تسجيل الدخول، أضف ما يلي يلي إلى الملف: #!/bin/sh echo "This account is limited to FTP access only." عدِّل الأذونات لجعل الملف قابلًا للتنفيذ: sudo chmod a+x /bin/ftponly افتح الملف الذي يضم قائمةً بالصدفات (shells) الصالحة للاستخدام في النظام: sudo nano /etc/shells وأضف في نهاية الملف: . . . /bin/ftponly عدِّل الصدفة الافتراضية للمستخدم عبر الآمر الآتي: sudo usermod sammy -s /bin/ftponly جرِّب الآن تسجيل الدخول بحساب المستخدم sammy: ssh sammy@203.0.113.0 ستجد رسالةً شبيهةً بالرسالة الآتية: This account is limited to FTP access only. Connection to 203.0.113.0 closed. هذا يؤكد أنَّ المستخدم غير قادر على تسجيل الدخول إلى الخادوم عبر الأمر ssh، ويُسمَح له بالوصول إلى FTP فقط. الخلاصة لقد شرحنا في هذا الدرس كيفية ضبط خادوم FTP للمستخدمين الذين يملكون حسابًا محليًا على النظام، أما إذا أردتَ استخدام مصدر خارجي للاستيثاق، فيمكنك إلقاء نظرة على دعم خادوم vsftpd للمستخدمين الوهميين (virtual users). هنالك خياراتٌ واسعة لدعم استخدام PAM مما يجعلك قادرًا على إدارة المستخدمين في نظام استيثاق مختلف مثل LDAP أو Kerberos. ترجمة –وبتصرّف– للمقال How To Set Up vsftpd for a User’s Directory on Ubuntu 16.04لصاحبته Melissa Anderson
  12. هنالك الكثير من الواجهات البرمجية المبنية على JSON التي توفر وصولًا عبر دوال من جهة الخادوم فقط، فلو أردنا استخدام عميل JavaScript مع تلك الواجهات البرمجية الخارجية، فسنحتاج إلى ضبط خادومنا للوصول إلى تلك الواجهات البرمجية الخارجية ثم تخديم تلك البيانات عبر Ajax أو عبر نقطة نهاية (endpoint) خاصة بك. ولحسن الحظ، فعل ذلك سهلٌ جدًا في ووردبريس. سأريك في هذا الدرس كيفية الحصول على أجور الشحن عبر Easy Post API باستخدام نقطة نهاية في ووردبريس. لتبسيط هذا الدرس (وجعله قصيرًا) فسنرسل ستة معاملات (وهو عدد كاف لواجهة Easy Post البرمجية لإعادة أجور الشحن): عرض الطرد ارتفاع الطرد طول الطرد وزن الطرد كود Zip للمرسل كود Zip للمستقبل ضبط نقطة نهاية JSON أوّل خطوة هي ضبط المسار الذي ستُخدَّم منه بيانات JSON، وفي هذه الحالة هو: /wp-json/easy-post/v1/rates/ الشيفرة: /** * Sets up a JSON endpoint at /wp-json/easy-post/v1/rates/ */ function easy_post_api_init() { $namespace = 'easy-post/v1'; register_rest_route( $namespace, '/rates/', array( 'methods' => 'GET', 'callback' => 'easy_post_return_rates', ) ); } add_action( 'rest_api_init', 'easy_post_api_init' ); عرض البيانات تتوقع نقطة النهاية إرسال ست قيم من البيانات كطلبية، وستستخدمها للحصول على البيانات من الواجهة البرمجية الخارجية، فلو لم تكن تلك القيم موجودةً فستستعمل القيم الافتراضية، وسنحرص أن تكون تلك القيم رقميةً فقط. مثال عن رابط URL مع قيم لكل المعاملات: /wp-json/easy-post/v1/rates/?zip=78701&width=10&length=10&height=10&weight=10&shipping_zip=78751 الشيفرة: /** * عرض مخرجات Easy Post عبر النهاية الطرفية * * نستخدم القيم المبدئية في حال عدم ذكر بيانات في الطلب، إلا أن إعادة خطأ ربما تكون فكرة أفضل. * Valid URL: /wp-json/easy-post/v1/rates/?zip=78701&width=10&length=10&height=10&weight=10&shipping_zip=78751 */ function easy_post_return_rates( WP_REST_Request $request ) { // الإعدادات المبدئية للشحن $defaults = array( 'zip' => 78701, 'width' => 10, 'length' => 10, 'height' => 10, 'weight' => 16, 'shipping_zip' => 94105 ); // الحصول على المعطيات من الطلب $params = $request->get_query_params(); // التأكد من توفر جميع المعطيات $params = array_replace( $defaults, $params ); // تنظيف المفاتيح $params = array_map( "absint", $params ); // إنشاء قيم مفاتيح فريدة لتحديد قيم البيانات المؤقتة transient أو العثور عليها $key = 'easy_post_' . implode( "_", $params ); /** * نحتفظ بالإجابة في قيمة مؤقتة transient ضمن قاعدة بيانات ووردبريس * لتجنب إرسال الكثير من الطلبات في وقت قصير * * تنتهي صلاحية هذه البيانات بعد عشر دقائق */ if ( false === ( $data = get_transient( $key ) ) ) { $data = easy_post_make_request( $params ); $response = new WP_REST_Response( $data ); // التخبئة لمدة عشر دقائق set_transient( $key, $response, 60 * 10 ); } else { // إرجاع القيمة المخبّأة return get_transient( $key ); } return $response; } الحصول على البيانات الدالة easy_post_make_request()‎ هي الدالة التي تطلب البيانات من الواجهة البرمجية الخارجية، والغرض من أغلبية الشيفرات التي هنا هي تجهيز الطلبية ضمن مصفوفة يمكن لواجهة Easy Post البرمجية أن تعالجها: /** *العثور على البيانات من الواجهة البرمجية لـ Easy Post باستخدام الدالة wp_remote_post */ function easy_post_make_request( $params ) { $to_address = array( 'zip' => $params['shipping_zip'], 'country' => 'US' ); $from_address = array( 'zip' => $params['zip'], 'country' => 'US' ); $parcel = array( 'length' => $params['length'], 'width' => $params['width'], 'height' => $params['height'], 'weight' => $params['weight'] ); $request = array( 'shipment' => array( 'to_address' => $to_address, 'from_address' => $from_address, 'parcel' => $parcel ) ); $args = array( 'method' => 'POST', 'blocking' => true, 'headers' => array( 'Content-Type' => 'application/json' ), 'timeout' => 15, 'sslverify' => false, 'body' => json_encode( $request ) ); // ضع مفتاح API الخاص بك مكان EASYPOST_TEST_API_KEY $api_url = 'https://' . EASYPOST_TEST_API_KEY . ':@api.easypost.com/v2/shipments'; $response = wp_remote_post( $api_url, $args ); if ( ! is_wp_error( $response ) ) { $response = json_decode( $response['body'] ); } return $response; } استخدام البيانات عندما نحاول الوصول إلى نقطة النهاية التي أنشأناها، فإن بيانات JSON التي جلبناها من Easy Post ستظهر لنا: يمكنك الآن الحصول على أجور الشحن ديناميكيًا في موقعك باستخدام نقطة النهاية التي أنشأناها في هذا الدرس. يمكنك الاطلاع على كامل الشيفرة هنا. ترجمة –وبتصرّف– للمقال How to Set JSON Endpoints in WordPress to Access an External API لصاحبه Devin Price حقوق الصورة البارزة محفوظة لـ Freepik
  13. أعلم أنَّه ليس من السهل الاعتراف بالأخطاء التي تقوم بها، لكن الخطأ هو جزءٌ رئيسي من كل عمليات التعليم، بدءًا من التعلم كيفية المشي إلى تعلم لغة برمجة جديدة مثل بايثون. هذه قائمة بثلاثة أخطاء التي وقعتُ فيها أثناء تعلمي لبايثون، عرضتها هنا لكي يحاول مبرمجو بايثون الجدد تفاديها وعدم الوقوع فيها، وهذه الأخطاء أدت إلى حدوث مشاكل كبيرة أخذت من وقتي ساعات حتى حللتها. الخطأ الأول: استخدام أنواع البيانات القابلة للتغير كوسائط افتراضية عند تعريف الدالة لنقل أنَّ لديك دالة صغيرة التي تبحث عن روابط في الصفحة الحالية وتستطيع إضافتها إلى قائمة (list) معيّنة. def search_for_links(page, add_to=[]): new_links = page.search_for_links() add_to.extend(new_links) return add_to لا يبدو أنَّ هنالك أيّ خطأ في الدالة السابقة، وهذا صحيح، فهي تعمل لكن هنالك مشاكل فيها؛ فلو مررنا قائمةً (list) إلى المعامل add_to فستعمل كما يجب، لكن ماذا يحدث لو تركنا القيمة الافتراضية دون تعديل؟ جرِّب تنفيذ الشيفرة الآتية: def fn(var1, var2=[]): var2.append(var1) print var2 fn(3) fn(4) fn(5) ستتوقع رؤية الناتج الآتي: [3] [4] [5] لكنك ستُفاجأ بالناتج الآتي: [3] [3, 4] [3, 4, 5] لماذا؟! يمكنك أن تستنتج أن القائمة (list) نفسها ستستعمل في كل مرة، فعندما نكتب دالة مثل الدالة السابقة في بايثون فسيتم تهيئة القائمة (list) كجزءٍ من تعريف الدالة، أي أنها لن تُهيّئ كل مرة تُستدعى فيها الدالة، وهذا يعني أنَّ الدالة ستحتفظ بكائن القائمة نفسه مرارًا وتكرارًا، ما لم تُحدِّد قيمةً أخرى له: fn(3, [4]) الناتج: [4, 3] الناتج يماثل ما قد توقعناه. الطريقة الصحيحة لفعل ذلك هي: def fn(var1, var2=None): if not var2: var2 = [] var2.append(var1) لنعد كتابة الدالة السابقة: def search_for_links(page, add_to=None): if not add_to: add_to = [] new_links = page.search_for_links() add_to.extend(new_links) return add_to نقلنا عملية التهيئة من مكان تعريف الدالة إلى داخلها مما يعني أنَّ عملية التهيئة ستتم في كل مرة تُشغَّل فيها الدالة. لاحظ أنَّ ذلك ليس ضروريًا إذا كنتَ تستعمل أنواع بيانات غير قابلة للتعديل مثل tuple أو string أو int. وهذا يعني أنَّك تستطيع تعريف دالة كما في الدالة الآتية دون إمكانية حدوث أخطاء غير متوقعة: def func(message="my message"): print message الخطأ الثاني: استخدام أنواع البيانات القابلة للتعديل كمتغيرات في الأصناف هذا الخطأ شبيهٌ كثيرًا بالخطأ السابق. تمعّن في الشيفرة الآتية: class URLCatcher(object): urls = [] def add_url(self, url): self.urls.append(url) الشيفرة السابقة تبدو طبيعية جدًا، فلدينا كائن لتخزين روابط URL، وعند استدعائنا للدالة add_url فسنمرر إليها رابط URL لتخزِّنه، صحيح؟ لنجرِّبها: a = URLCatcher() a.add_url('http://www.google.') b = URLCatcher() b.add_url('http://www.bbc.co.') الناتج: b.urls ['http://www.google.com', 'http://www.bbc.co.uk'] a.urls ['http://www.google.com', 'http://www.bbc.co.uk'] ما هذا؟! لم نتوقع ذلك. إذ أنشأنا كائنين منفصلين a و b، وأسندنا رابطًا للكائن a مختلفًا عن رابط الكائن b، فكيف امتلك كلا الكائنين الرابطين نفسهما؟ اتضح أنَّ هذه المشكلة شبيهة جدًا بالمشكلة في المثال الأول، فقائمة (list) عناوين URL قد تمت تهيئتها عند تعريف الصنف (class)، وبالتالي أمست جميع الكائنات المُنشَأة من ذاك الصنف تستعمل القائمة نفسها. هنالك بعض الحالات التي نستفيد فيها من هذه الميزة، لكنها ستضرك في أغلبية الأوقات، فلو أردتَ تخزين بيانات كل كائن على حدة فيمكنك تعديل الشيفرة لتصبح كما يلي: class URLCatcher(object): def __init__(self): self.urls = [] def add_url(self, url): self.urls.append(url) أصبحت قائمة urls تُهيّئ عند إنشاء الكائن، وعندما نُنشِئ كائنين فستُهيّئ قائمتان منفصلتان. الخطأ الثالث: عملية إسناد قيم إلى نوع بيانات قابل للتعديل هذا الخطأ أربكني لفترة حتى فهمته، دعنا نستعمل نوع بيانات قابل للتعديل مثل dict: a = {'1': "one", '2': 'two'} لنفترض أننا نريد أخذ قيمة المتغير a واستعمالها في مكانٍ آخر دون تعديل القيمة الأصلية: b = a b['3'] = 'three' أليس هذا بسيطًا؟ لننظر الآن إلى القيمة المخزّنة في المتغير a التي لم نُعدِّلها قط: {'1': "one", '2': 'two', '3': 'three'} ماذا؟! كيف ستبدو قيمة المتغير b إذًا؟ {'1': "one", '2': 'two', '3': 'three'} دعنا نعود خطوةً إلى الوراء وننظر ماذا يحدث لو استعملنا أنواع البيانات غير القابلة للتعديل، مثل tuple: c = (2, 3) d = c d = (4, 5) قيمة c هي: (2, 3) بينما قيمة d هي: (4, 5) لقد جرى كل شيءٍ على ما يرام، لذا ماذا حدث في مثالنا؟ عند استخدام أنواع البيانات القابلة للتعديل فسنحصل على شيءٍ شبيهٍ بالمؤشرات (pointers) في لغة C، فعندما قلنا أنَّ b = a في الشيفرة السابقة فهذا يعني أنَّ المتغير b أصبح يُشير إلى a، وكلا المتغيرين يشير إلى نفس الكائن في ذاكرة بايثون؟ هل هذا مألوف لديك؟ ذلك لأن هذه المشكلة شبيهة بالمشاكل السابقة، وكنتُ أنوي تسمية هذا الدرس باسم «المشاكل التي تحدث مع أنواع البيانات القابلة للتعديل». هل يحدث الأمر نفسه مع القوائم (list)؟ نعم. وكيف سنلتف على المشكلة؟ حسنًا، يجب أن نكتب الشيفرة الآتية التي تنسخ القائمة: b = a[:] السطر السابق سيؤدي إلى نسخ مرجعية كل عنصر من عناصر القائمة ووضعه في قائمة جديدة، لكن لنأخذ حِذرنا فإذا كان نوع بيانات أحد الكائنات الموجودة في القائمة قابلًا للتعديل فسيؤدي ذلك إلى الحصول إلى مرجعية لتلك الكائنات بدلًا من نسخها. تخيل وجود قائمة على قطعة من الورق، ففي المثال الأصلي كان ينظر الشخص A والشخص B إلى الورقة نفسها، فلو عدّل شخصٌ ما القائمةَ فسيرى كلا الشخصين التعديلات التي أجريت على القائمة، وعندما نسخنا المرجعيات فأصبح لكل شخصٍ قائمته الخاصة به، لكن لنفترض أنَّ تلك القائمة تحتوي على أماكن يمكن البحث فيها عن طعام، فلو كانت «الثلاجة» موجودة في القائمة فحتى لو نسخها الشخص A و B فما تزال تشير إلى الثلاجة نفسها؛ فلو أتى الشخص A وعدّل محتويات الثلاثة (لنفترض أنه أكل جميع الحلويات فيها) فسيلاحظ الشخص B أن الحلويات قد اختفت من الثلاثة. ولا توجد طريقة سهلة للالتفاف على هذه المشكلة، وهذا أمرٌ مهمٌ عليك تذكره عندما تبرمج لكي تكتب شيفرتك بطريقة لا تسبِّب أيّة مشاكل. تعمل أنواع dict بنفس الطريقة، ويمكنك إنشاء نسخة كاملة باستعمال الدالة copy()‎: b = a.copy() أكرِّر أنَّ ذلك سيُنشِئ متغيرًا جديدًا من نوع dict يُشير إلى نفس العناصر الموجودة في المتغير الأصلي، وبالتالي لو كان لدينا قائمتان متماثلتين وعدّلنا كائنًا قابلًا للتعديل مُشار إليه عبر مفتاح موجود في المتغير a فيمكن معرفة تلك التعديلات من داخل المتغير b. الإشكاليات التي تواجهنا مع أنواع البيانات القابلة للتعديل تكون نتيجةً لمرونة تلك الأنواع، حيث لا تُشكِّل أيٌّ مما سبق مشكلةً حقيقة، وإنما هي أمور ضرورية يجب أخذها بالحسبان لتنجب المشاكل. وعمليات النسخ الكاملة التي ذكرناها آنفًا لن تكون ضروريةً في 99% من الحالات، أي يجب تعديل برنامجك لكي لا يحتاج إلى استخدام تلك النسخ من الأساس. ترجمة –وبتصرّف– للمقال ‎3 mistakes to avoid when learning to code in Python لصاحبه Pete Savage
  14. التدوين الصوتي هو طريقةٌ رائعةٌ لمشاركة المعلومات وبناء المجتمعات التي تتشارك بالاهتمامات، وهذا الدرس يمثِّل دليلًا لكيفية البدء بالتدوين الصوتي. السبب الرئيسي وراء قدرتي على إعطاء نصائح بالتدوين الصوتي هو أنني أدوِّن صوتيًا لما يقارب ثلاث سنوات. مدونتي الصوتية باسم Sysadministrivia تتضمن كلامًا عن إدارة الأنظمة. ما هو التدوين الصوتي؟ انتشر التدوين الصوتي انتشارًا كبيرًا في مختلف المجالات وأصبح شائعًا جدًا، إذ ينشر بعض الأشخاص تدوينات صوتية لمختلف جوانب حياتهم مثل جلسات الألعاب الإلكترونية التي يلعبونها. يعمل التدوين الصوتي بتسجيلك للصوت (أو الفيديو لأن البرمجيات قد تطورت حديثًا)، واستخدام صيغة بيانات قياسية لتنبيه المستمعين أنَّك نشرت التدوينة الصوتية podcast مباشرةً. صيغة RSS (المسؤولة عن إذاعة خبر نشر التدوينة) ومواصفة XML معينة (وهي صيغة البيانات القياسية) تجعل إنشاء هذه التنبيهات التلقائية أمرًا ممكنًا. كيف أستطيع البدء بالتدوين الصوتي؟ كل ما يلزمك هو حاسوب ونظام تشغيل. فمن البدهي أنَّك تحتاج إلى حاسوب، ولا يهم ما هو نظام تشغيلك، لكنني أنصحك باستخدام لينكس أو نظام من عائلة BSD. برمجيات تسجيل وتحرير الصوت يمكنك استخدام برمجيات متعددة المنصات (أي تعمل على أكثر من نظام تشغيل) لتسجيل الصوت مثل Audacity أو إذا كنتَ تفضِّل تحكمًا أكثر فانظر إلى Ardour. تحتوي صفحة hosts في موقع Sysadministrivia على قائمة بمواصفات العتاد التي نستعملها في التدوين (بما في ذلك الميكروفون والسماعات الرأسية والمعدات الأخرى)؛ لا أنصحك بشراء عتاد معيّن إذ هنالك مختلف أنواع الميكروفونات لتسجيل الكلام. سنحتاج إلى ميكروفون على شكل قلب (cardioid أو supercardioid) إذا كنت ستتحدث بالقرب من الميكروفون ، أو استخدام ميكروفون أحادي الاتجاه (omnidirectional) إذا أردتَ تسجيل ما يدور في غرفة مليئة بالأشخاص باستعمال ميكروفون وحيد، واحرص على أن تكون تلك الميكروفونات ذات مكثّف (condenser) لأنها أفضل لتسجيل الحديث، وسماعات الرأس ضرورية إذا كنت ستدون مع شخص آخر ليس في غرفتك نفسها. لمزيدٍ من المعلومات حول ذلك فأنصحك بقراءة قسم «Uploading» في التدوينة How to run your own podcast. استضافة الموقع ستحتاج إلى استضافة لتضع فيها الملفات الصوتية وملف XML الذي سيذيع خبر نشر التدوينات الجديدة، وموقع إلكتروني (ليس من الضروري امتلاك موقع، لكنني أنصحك بذلك بشدة). يمكنك بشكلٍ بديل أن ترفع الملفات الصوتية (أو الفيديو) إلى خدمة مثل YouTube أو SoundCloud واستخدام ميزة الاشتراك فيها لنشر خبر صدور صدور تدوينة جديدة؛ لكن دون استخدام RSS (أو XML) فهذا يعني أنَّ تدويناتك ليست تدوينات صوتية (podcast) تقنيًا، لأن هذه المواقع تطلب من مستخدميك أن يسجلوا حسابًا فيها، والتدوينات الصوتية يجب أن تسمح للمستمعين أن يبقوا مجهولين تمامًا. صيغة الملفات حسنًا، التدوينات الصوتية ليست «حرة» تمامًا، لاستخدام صيغة MPEG-1/2 Audio Layer III المعروفة باسمها المختصر MP3. هذه الصيغة محمية ببراءة اختراع ولا تتوافق مع مبادئ البرمجيات الحرة؛ لكن يمكن استخدام صيغة بديلة عنها وهي OGG لكنها ستجعل نشرك لها محدودًا، إلا أنَّ بإمكانك توفير تدوينة صوتية podcast و oggcast، وصيغة ملفات XML لهما متشابهة جدًا (لكن مع بعض الاختلافات التي يمكن تعلمها بسهولة). ملفات «التغذية» أفصل عادةً بين مختلف ملفات التغذية (feed files، التي تكون بصيغة XML)، لمختلف الخدمات مثل iTunes و Google Play والتدوينات الصوتية التقليدية (podcasts) و oggcasts. لاحظ أنَّ متصفح Firefox سيحاول تفسير (أو عرض) هذه الملفات باستخدام عميل RSS المضمّن فيه، ولعرض ملفات XML الفعلية فاستخدام الأمر curl أو wget مع الروابط السابقة، أو اعرض مصدر الصفحة في متصفحك. الطريقة السابقة تسمح لي باستخدام وسوم XML خاصة بكل خدمة، وللمزيد من التفاصيل التقنية راجع التدوينة How to run your own podcast. الموقع الإلكتروني أستخدمُ نظام إدارة محتوى باسم Textpattern مع بعض التعديلات، لكن الكثير من المدونين الصوتيين يستعملون ووردبريس مع إضافة PowerPress. كيف أوسِّع من جمهوري؟ الترويج Syndication أسهل طريقة لجلب مستمعين إلى تدويناتك الصوتية هي خدمات الترويج، فيوفر موقع DistroWatch ترويجًا لبعض تدوينات oggcast الصوتية. وأشهر الخدمات للترويج هي iTunes (لمزيدٍ من المعلومات راجع صفحة iTunes Connect Resources and Help page) و Google Play (زر صفحة Podcasts in Google Play Music page)، ويمكن أن تساعدك مواقع وخدمات الترويج الأصغر في زيادة متابعيك، لكن iTunes و Google Play هي أشهرها لسهولة الوصول إليها من مستخدمي iOS و أندرويد. وسائل التواصل الاجتماعي لا تنسَ التواصل المباشر على مواقع التواصل الاجتماعي، فيمكن أن تستعمل تويتر كطريقة أخرى لنشر تدويناتك الصوتية الحديثة، وسيسمح لك بالتواصل مباشرةً مع جمهورك. أمور متفرقة هنالك تقنيات أخرى لإشهار تدويناتك مثل بيع البضائع أو استضافة ضيوف في حلقاتك، والمشاركة في الأحداث المحلية والمنظمات الخيرية، لكن هذه التقنيات ستكون فعالة أكثر بعد أن يكون عندك جمهور. كيف أستفيد ماديًا من التدوين الصوتي؟ عليك أن تبدأ مشوارك في التدوين الصوتي لرغبتك في إنتاج ومشاركة محتوى مع فئة من الناس الذين يتشاركون الاهتمامات، فالإجابة باختصار هي: لن تتمكن من الاستفادة ماديًا (أو ربما تتمكن من ذلك إن كنتَ محظوظًا). لكن التدوين الصوتي في أغلبية الأوقات يكون نابعًا من رغبتك بمشاركة ما تعرفه مع الآخرين (كما في البرمجيات الحرة). ترجمة –وبتصرّف– للمقال A quick-start guide to podcasting لصاحبه Brent Saner
  15. سيأتي حينٌ يحس فيه كل مطوِّر وب جديد بأنَّ شيئًا ما ينقصه عندما يطلب منه أحد الخبراء أن يفتح سطر الأوامر، لكن لا بأس في ذلك، فلكنا مرّ بذلك عندما ذهب إلى منتدى أو اجتماع محلي للقاء مطوري وب الآخرين. هذا الدرس مناسب لكل شخص لا يعرف ما هو سطر الأوامر، وهو ملائمٌ أيضًا لمن له دراية بسطر الأوامر إذ سيتضمّن بعض التفاصيل والملاحظات والتي ستجدها مفيدة وستتعلم منها. لن يشرح هذا الدرس ماذا عليك أن تكتب في الطرفية (terminal، وهي نافذة البرنامج التي تصل إلى سطر الأوامر عبرها) للقيام بأمور معينة، وإنما الهدف هنا هو شرح المفاهيم الأساسية لجعل واجهة سطر الأوامر (command line interface) مألوفةً لك، وبعد أن تتمكّن من الأساسيات فستجد أن فهم أحد الأوامر سهلٌ جدًا وليس عسيرًا كما تظن. ظهرت واجهة سطر الأوامر قبل الواجهات الرسومية أوّل معلومة تساعدك في فهم سطر الأوامر هي استيعاب أنَّ سطر الأوامر قد أتى في الفترة الأولى من وجود الحواسيب، إذ إنَّ البرامج الحالية رسومية فهي تعرض عدِّة نوافذ تابعة للبرنامج للمستخدم، ويظهر أيضًا «سطح المكتب» خلف تلك النوافذ. هذه النوافذ تساعد المستخدمين في استخدام الحاسوب، لكنها مجرد واجهة بسيطة وجميلة للتعامل مع نظام التشغيل. وقبل ظهور الواجهات الرسومية، كان هنالك ما يسمى «طرفيات»، والطرفية هي الوسيلة التي نصل فيها إلى سطر الأوامر (يجدر بالذكر أنَّ الطرفيات هي أجهزة فيزيائية كانت موجودة في الأيام الأولى للحواسيب، وهي جهاز يضم شاشة سوداء وتُظهِر نصًا أبيض، وفيها لوحة مفاتيح مدمجة)، تستطيع أن تقول أنَّ سطر الأوامر هو طريقةٌ مختلفة لتشغيل البرامج كما هي البرامج الرسومية في أنظمة ويندوز أو ماك أو لينكس. إلا أنَّ الاختلاف الرئيسي بينها وبين البرامج الرسومية هي أنَّ البرامج التي تعمل من سطر الأوامر لا توفر واجهةً جميلةً لتتعامل معها، ومستخدمو الحاسوب الذين عاصروا الطرفيات لديهم خبرةٌ كبيرةٌ مع الحواسيب، وتسمعهم يقولون أنَّ الواجهات الرسومية سببت في تقليل إنتاجيتهم، وما يزال أولئك الأشخاص موجودين في هذا العصر. تستطيع أن تستخدم الفأرة وتنقر نقرًا مزدوجًا على أيقونة البرنامج لتشغيله، أما في سطر الأوامر فعليك أن تكتب اسم الأمر (والذي هو اسم البرنامج في أغلبية الحالات)، وربما تضيف بضعة خيارات لتتحكم في سلوكه، ثم تنفِّذ الأمر. لاحظ أنني ذكرتُ استخدام الفأرة بوضوح في الفقرة السابقة وذلك لأنَّها أكبر الفروقات بين الواجهات الرسومية والسطرية، إذ لا تستعمل الفأرة في بيئة سطر الأوامر فالطرفيات كانت موجودة قبل انتشار استخدام الفأرة للتعامل مع الحاسوب، لذا ستجد أنَّ طريقة التفاعل الرئيسية مع سطر الأوامر هي استخدام لوحة المفاتيح. فرقٌ رئيسيٌ آخر هو أنَّ الواجهات الرسومية تكون في وضعية «الانتظار» غالب الوقت عندما يكون البرنامج «قيد التشغيل»، ولأنَّ البرامج التي تعمل من سطر الأوامر كانت من العصر الأول للحاسوب، فلم تكن هنالك مساحة فارغة لإظهار جميع البرمجيات «قيد التشغيل»، فهي تنفَّذ بسرعة كبيرة ثم تتوقف، أي أنَّ من غير الشائع أن يطول تنفيذ أمرٍ ما في سطر الأوامر أكثر من عدِّة ثواني (على الرغم من أنَّ بعضها قد يعمل لفترات طويلة مثل المحررات النصية). لنلخِّص الفروقات بين البرامج التي تعمل من سطر الأوامر والبرامج ذات الواجهة الرسومية: البرامج السطرية هي تطبيقات بسيطة تعمل مرة واحدة. على النقيض من أغلبية التطبيقات الرسومية التي تنتظر منك التفاعل معها، فإنَّ أغلبية التطبيقات السطرية تعمل بسرعة ثم تتوقف. تكون عادة الأوامر قصيرة لأن المستخدمين يريدون أن يكتبوا أقل ما يمكن لتنفيذ ما يشاؤون. لا تُستخدَم الفأرة (عادةً) في سطر الأوامر. الاختلافات بين أنظمة التشغيل يمكننا أن نعد سطر الأوامر على أنه طريقة مباشرة للتواصل مع الحاسوب، وهذا يتيح له قدرات أكثر، مما يجعله فعّالًا، لكن في المقابل هذا يعني أنَّ عليك معروفة المزيد من المعلومات حول طريقة عمل حاسوبك. أغلبية مستخدمي الحاسوب أولي المعرفة المتوسطة يعلمون أنَّ نظام ويندوز يختلف عن ماك ويختلف عن لينكس، لكنها يعلمون أنَّ بإمكانهم تشغيل متصفح Firefox أو برنامج ليبرأوفيس على تلك الأنظمة، لكن هذا ليس صحيحًا بالنسبة إلى سطر الأوامر. هنالك نوعان رئيسيان لسطر الأوامر عليك معرفتهما، النوع الأول هو سطر الأوامر للأنظمة الشبيهة بيونكس (Unix-like)، والنوع الثاني هو سطر أوامر نظام ويندوز. يُصنَّف نظام لينكس وماك على أنهما نظامان شبيهان بيونكس، وبالتي ستتعامل مع سطر الأوامر عبر ما يسمى «صدفة» (shell) باسم Bash (سنتحدث عن ذلك لاحقًا). صحيحٌ أنَّ هنالك اختلافات في طريقة التعامل مع مختلف أنظمة يونكس، لكنها ليست مهمة لمطوري الويب المحترفين، فهذه الاختلافات صغيرة ويمكنك تجاهلها إذا كنتَ مبتدئًا (لكن الحق يقال: ستواجه هذه الاختلاف في وقتٍ ما عندما تجد نفسك مرتاحًا في استخدام سطر الأوامر، وستجد أنَّ تلك الاختلافات لها أثرها). أما نظام ويندوز فهو خارج المنافسة في مجال سطر الأوامر، وهذا هو أحد الأسباب الرئيسية التي تجعل من مطوري الويب يهاجرون من ويندوز إلى لينكس أو ماك، إذ يختلف سطر الأوامر الموجود في نظام ويندوز عن بقية الأنظمة والأوامر ليست متشابهة، وسطر الأوامر فيه قديم وتراثي أضف إلى أنَّ مستخدمي ويندوز يخافون استخدامه. سطر الأوامر في ويندوز لا يمكني الجزم بواقع سطر أوامر ويندوز أو المنافع الآتية من استخدامه في أنظمة ويندوز (ويندوز 10 وما قبله) للقيام بمهام تطوير الويب من سطر الأوامر لأنني أستخدم لينكس منذ فترةٍ طويلة، لكنني سمعتُ شكوى ممن يستعملونه وصحيحٌ أنَّ أغلبية البرمجيات تعمل «نظريًا» في سطر أوامر ويندوز، لكنني سمعتُ أنها ليست عملية. أنا لا أقول لك أن تشتري جهاز ماك أو تثبِّت لينكس على جهازك (لكنني أحثّك على تجربة لينكس على أيّ حال) لتصبح مطوِّر ويب، لكنني أحب أن أشير إلى توافر ما يسمى «Bash on Ubuntu on Windows» في ويندوز 10 وبالتالي ستحصل على سطر أوامر شبيه بيونكس داخل نظام ويندوز، لذا جرِّبه وانظر إن كان مناسبًا لك. ولأغلبية أعمال تطوير الويب، خصوصًا في عالم البرمجيات مفتوحة المصدر الذي تقطنه ووردبريس، ستجد أنَّ الخواديم تُشغِّل إحدى توزيعات لينكس، وهذا يعني أنَّ عليك الاتصال مع الخواديم عبر سطر الأوامر، وهذا سهلٌ جدًا في ويندوز (عبر برمجية PuTTY) لكن هذه البرمجية غير مضمّنة افتراضيًا في ويندوز، وليست كمثيلاتها في بقية الأنظمة. العثور على الطرفية ذكرنا سابقًا أنَّك تستطيع الوصول إلى سطر الأوامر عبر الطرفية، والتي يمكنك تشغيلها في نظام ماك وأغلبية توزيعات لينكس التي توفِّر واجهةً رسوميةً عبر البحث عن تطبيقٍ باسم Terminal وتشغيله، ثم ستجد نافذة تتيح لك التفاعل مع حاسوبك بطريقة تختلف كثيرًا عمّا اعتدت عليه. أما في ويندوز فيسمى محاكي الطرفية باسم «موجِّه الأوامر» (Command Prompt)، الذي يسمح لك بتنفيذ البرامج بكتابة أمرٍ معيّن. يجدر بالذكر أنَّ هنالك أنواع مختلفة من محاكيات الطرفيات، فهنالك طرفية غنوم وطرفية كدي (Konsole) للينكس، وطرفية iTerm لنظام ماك، وهذه الطرفيات تختلف عن بعضها لكنها تؤدي الغرض نفسه ألا وهو الوصول إلى سطر الأوامر. أنواع الصدفات ملاحظة سريعة: هنالك أنواع مختلفة من الصدفات (وهي البرمجيات التي تتواصل عبرها مع سطر الأوامر)، فأغلبية الأشخاص يستخدمون صدفة باش (bash) (وإذا لم تكن تعرف ما هي الصدفة التي تعمل عليها فمن المرجح أنها باش). الاختلافات بين الصدفات هو موضوع معقد وخارج عن نطاق هذا الدرس، لكن كل ما أردتُ تنبيهك إليه هو أنَّك تشغِّل صدفة باش في نظامك (وليس ZSH أو FISH أو غيرها). كيف تصل إلى سطر أوامر خادومك آخر موضوع أريد أن أتحدث عنه في هذا الدرس هو أنَّك تستطيع أن تصل إلى سطر أوامر الخادوم نفسه (إلا إذا كان موقعك مستضافًا على استضافة مشتركة). لا تُشغِّل الخواديم واجهةً رسوميةً (السبب الرئيسي هو الأداء والحماية)، هذا يختلف عن حاسوبك الشخصي الذي يتيح لك التفاعل مع سطر الأوامر ومع الواجهات الرسومية في الوقت نفسه. في الحالات التي ترغب بالوصول فيها إلى سطر الأوامر في خادومك، فيمكنك فعل ذلك عبر SSH (اختصار للعبارة Secure Shell)، وهذه البرمجية تسمح لك بالوصول إلى سطر الأوامر في حاسوبٍ بعيد بأمان؛ وموضوع ضبط SSH خارج عن نطاق هذه المقالة، والغرض من ذكري له هو معرفة وجود طريقة للوصول إلى سطر الأوامر لحاسوبٍ بعيد بأمان. وأذكِّر أنَّ برمجية PuTTY التي ذكرناها سابقًا هي أشهر طريقة ليتصل عبرها مستخدمو ويندوز إلى SSH. أما مستخدمو ماك أو لينكس أو غيرهما فكل ما عليهم فعله للاتصال إلى حاسوبٍ بعيد هو استخدام الأمر ssh في سطر الأوامر. الخلاصة قد يبدو سطر الأوامر شيئًا غريبًا خصوصًا لمستخدمي الحاسوب الذين بدؤوا في استعماله بعد ظهور الواجهات الرسومية التي جعلت منه شيئًا غريبًا، لكن قد نضطر أحيانًا إلى استخدام سطر الأوامر لإنجاز بعض الأمور. أرجو أن تكون قد فهمتَ من المقالة أنَّ سطر الأوامر هو طريقة أخرى للتعامل مع الحاسوب، وقد تكون هي الطريقة الوحيدة للتعامل مع الحاسوب في بعض الحالات مثل الخواديم التي لا تُثبَّت عليها واجهة رسومية للحفاظ على مواردها. تذكّر أنَّنا سنتعامل مع نظام التشغيل في النهاية سواءً استعملنا الواجهة الرسومية أو السطرية، وهذا هو السبب وراء امتلاك نظام ويندوز لسطر أوامر مختلف تمامًا عن ماك أو لينكس؛ إذ يُصنَّف ماك ولينكس على أنهما شبيهان بنظام يونكس، وهذا هو السبب وراء تشابه سطر الأوامر فيهما. سطر الأوامر معقد ومتشابك وواسع، لذا لا تقلق إذا لم تجد نفسك مرتاحًا معه في البداية، إذ تستطيع استخدام أمر ما يوميًا ثم تكتشف أشياءً جديدةً كل فترة (مثل أوامر أخرى أو خيارات للأوامر التي تستعملها أو مفاهيم جديدة في سطر الأوامر). هنالك بعض الأوامر البسيطة التي تساعدك في الاعتياد على سطر الأوامر وفهمه، لذا أنصحك بتعلمها حتى لو لم تكن تستعملها كثيرًا. أعلم أنَّ بإمكانك فعل الكثير مع ووردبريس دون الحاجة إلى استخدام سطر الأوامر، لكنني أعتقد أنَّ من الضروري تعلّم سطر الأوامر لزيادة خبرتك في إدارة مواقع ووردبريس. أرجو أن تكون هذه المقالة قد وضحت لك بعض المفاهيم الغريبة، وإذا كنتَ مهتمًا بمزيدٍ من المعلومات حول سطر الأوامر فأنصحك بقراءة كتاب «سطر أوامر لينكس». ترجمة –وبتصرّف– للمقال What is the Command Line? CLIs from First Principles لصاحبه David Hayes
  16. تملك المتصفحات الحديثة أدوات تطوير مبينة فيها للتعامل مع لغة JavaScript وتقنيات الويب الأخرى، وهذه الأدوات تتضمن سطر الأوامر (Console) الذي يشبه سطر الأوامر الخاص بأنظمة يونكس، إضافةً إلى أدواتٍ لتفحص (inspect) شجرة DOM، وأدوات للتنقيح (debugging)، وتحليل نشاط الشبكة. يمكن استخدام سطر الأوامر (Console) لإنشاء سجل من المعلومات كجزءٍ من عملية تطوير تطبيقات JavaScript، ويسمح لك بالتفاعل مع صفحة الويب بتنفيذ تعليمات JavaScript على عناصر الصفحة. وهذا يعني أنَّ سطر الأوامر يسمح لك بكتابة وإدارة ومراقبة شيفرات JavaScript عند الحاجة. سنشرح في هذا الدرس كيفية التعامل مع سطر الأوامر باستعمال JavaScript في المتصفحات، وسنعطي لمحة عن أدوات التطوير الأخرى المبنية في المتصفحات والتي يمكنك استعمالها في عملية تطوير تطبيقات الويب. العمل مع سطر الأوامر (Console) في المتصفح أغلبية متصفحات الويب الحديثة التي تدعم لغة HTML و XHTML القياسية ستوفِّر لك وصولًا إلى سطر أوامر الذي يمكنك استخدامه (عبر لغة JavaScript) بما يشبه طريقة استخدام الطرفية (terminal) في أنظمة يونكس. سنشرح الآن كيفية الوصول إلى سطر الأوامر في متصفحَي Firefox و Chrome. متصفح Firefox لفتح Web Console في متصفح Firefox، فاضغط على زر القائمة ☰ في الزاوية العليا اليمنى بجوار شريط العنوان. ثم اضغط على زر Developer الذي يقع تحت أيقونة المفك، والذي سيفتح قائمة Web Developer، ومن ثم اضغط على خيار Web Console. وهذا سيفتح لوحةً في أسفل نافذة المتصفح: يمكنك أيضًا الدخول إلى سطر الأوامر عبر اختصار لوحة المفاتيح Ctrl+Shift+K على نظامَي لينكس وويندوز، أو Command+Option+K على ماك. يمكننا التفاعل مع سطر الأوامر باستخدام JavaScript بعد أن استطعنا فتحه. متصفح Chrome لفتح JavaScript Console في متصفح Chrome فيمكنك النقر على القائمة في الزاوية العليا اليمنى من نافذة المتصفح (التي يُرمَز لها بثلاث نقط عمودية) ومن ثم اختيار More Tools ثم Developer Tools. ستُفتح لوحةٌ جديدة فيها اللسان Console في الشريط العلوي الذي عليك أن تضغط عليه للوصول إلى سطر الأوامر (هذا إن لم يكن هذا اللسان مفعّلًا من البداية): يمكنك أيضًا الوصول إلى سطر الأوامر بالضغط على اختصار لوحة المفاتيح Ctrl+Shif+J في نظامَي لينكس وويندوز، أو Command+Option+J في نظام ماك، وهذا سيؤدي إلى فتح لسان Console مباشرةً. يمكننا التفاعل مع سطر الأوامر باستخدام JavaScript بعد أن استطعنا فتحه. التعامل مع سطر الأوامر يمكنك كتابة شيفرات JavaScript داخل سطر الأوامر. لنبدأ بإظهار تحذير يحتوي على السلسلة النصية Hello, World!‎: alert("Hello, World!"); بعد أن تضغط على زر Enter بعد كتابة سطر JavaScript السابق، فيمكن أن تشاهد نافذة التحذير الآتية في متصفحك: ملاحظة: سيُظهِر سطر الأوامر نتيجة تنفيذ التعابير البرمجية، وسيُظهِر undefined إذا لم تتم إعادة (return) قيمة من التعبير المُنفَّذ. بدلًا من عرض نوافذ تحذير التي علينا الضغط على زر OK للخروج منها، يمكننا معرفة ناتج تعابير JavaScript بطباعتها إلى سطر الأوامر عبر الدالة console.log. فلو أردنا طباعة السلسلة النصية Hello, World!‎ سنكتب التعبير البرمجي الآتي في سطر الأوامر: console.log("Hello, World!"); وسيُطبَع السطر الآتي في نافذة سطر الأوامر: Hello, World!‎ يمكننا استخدام JavaScript لإجراء حسابات رياضية في سطر الأوامر: console.log(2 + 6); الناتج: 8 وسيستطيع المتصفح إجراء حسابات على أرقام أكبر: console.log(34348.2342343403285953845 * 4310.23409128534); الناتج: 148048930.17230788 لا تغفل عن إمكانية إجراء عمليات مُقسَّمة على أكثر من سطر عبر استعمال المتغيرات: let d = new Date(); console.log("Today's date is " + d); الناتج: Today's date is Wed Jun 21 2017 15:49:47 GMT-0400 (EDT) إذا أردتَ تعديل التعبير الذي كتبته في سطر الأوامر، فاضغط على زر السهم العلوي ↑ في لوحة مفاتيحك للحصول على السطر السابق، وهذا ما يسمح لك بتعديله ثم تنفيذه مجددًا. يوفر لك سطر أوامر المتصفح القدرة على تجربة شيفرات JavaScript في الوقت الحقيقي بما يشبه واجهة سطر الأوامر في أنظمة يونكس. التعامل مع ملف HTML يمكنك أيضًا إجراء عمليات على ملف HTML موجود مسبقًا أو على مستند مولّد ديناميكيًا عبر سطر الأوامر؛ وهذا يسمح لنا بتجربة كيفية تعامل شيفرات JavaScript مع عناصر HTML وقواعد CSS وسكربتات JavaScript الموجودة في صفحة الويب. أبقِ في ذهنك أنّك إذا أعدتَ تحميل الصفحة بعد تعديلها في سطر الأوامر فستعود إلى حالتها الأصلية قبل التعديل، ولذا احرص على حفظ أيّة تعديلات تريد الإبقاء عليها. لنحفظ مستند HTML الآتي باسم index.html لكي نجِّرب تعديلها عبر سطر الأوامر: <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Today's Date</title> </head> <body> </body> </html> إذا حفظتَ مستند HTML السابق في ملفٍ ما وفتحتَه باستخدام متصفحك المفضّل فيجب أن تشاهد صفحةً فارغةً عنوانها «Today’s Date». يمكنك الآن فتح سطر الأوامر لاستعمال JavaScript لتعديل الصفحة، وسنبدأ بكتابة شيفرة JavaScript لإضافة ترويسة في الصفحة: let d = new Date(); document.body.innerHTML = "<h1>Today's date is " + d + "</h1>" ستحصل على الناتج الآتي في سطر الأوامر: "<h1>Today's date is Sat Jun 24 2017 12:16:14 GMT-0400 (EDT)</h1>" يجب أن تبدو الصفحة الآن كما يلي: يمكنك أيضًا تعديل أنماط الصفحة، مثل لون الخلفية: document.body.style.backgroundColor = "lightblue"; الناتج: "lightblue" وكذلك الأمر مع لون النص في الصفحة: document.body.style.color = "white"; الناتج: "white" يجب أن تبدو الصفحة الآن كما يلي: يمكنك أيضًا إنشاء فقرة جديدة عبر العنصر <p>: let p = document.createElement("P"); بعد إنشاء العنصر، حان الوقت لإضافة عقدة نصية (text node) التي يمكننا إضافتها إلى الفقرة الجديدة: let t = document.createTextNode("Paragraph text."); سنضيفها الآن إلى الفقرة المُعرَّفة عبر المتغير p: p.appendChild(t); وأخيرًا سنضيف الفقرة المُخزَّنة في المتغير p والنص الموجود فيها إلى المستند: document.body.appendChild(p); إذا أكملتَ الخطوات السابقة، فيجب أن تبدو صفحة HTML السابقة كما يلي: يوفِّر لنا سطر الأوامر البيئة المناسبة لإجراء تجرب على صفحات HTML، لكن من المهم أن نبقي في ذهننا أنَّنا لا نعدل مستند HTML فعليًا عندما ننفذ التعليمات البرمجية في سطر الأوامر، وإنما ستذهب جميع تعديلاتنا إذا أعدنا تحديث الصفحة. لمحة عن أدوات التطوير الأخرى اعتمادًا على أدوات المطوِّر التي يوفرها متصفحك، فستقدر على استخدام أدوات أخرى لمساعدتك في عملية تطوير الويب، لنطلع على تلك الأدوات. عرض شجرة DOM في كل مرة يتم فيها تحميل صفحة الويب، فسيُنشِئ المتصفح ما يسمى شجرة DOM (اختصار للعبارة Document Object Model) للصفحة. شجرة DOM تتألف من كائنات التي تُمثِّل عناصر HTML ضمن البنية الهرمية للعناصر. وشجرة DOM متاحة ضمن لسان Inspector في متصفح Firefox أو لسان Elements في متصفح Chrome. تسمح لك هذه الأدوات بعرض وتعديل عناصر DOM وتسمح لك بمعرفة ما هي وسوم HTML المسؤولة عن عرض جزء معيّن من الصفحة. ويمكن أيضًا من هذا اللسان معرفة ما هي قيمة المعرِّف ID لصورةٍ معيّنةٍ على سبيل المثال. ستكون بنية الصفحة التي عدلناها (وقبل إعادة تحميل الصفحة) في لسان DOM كما يلي: يمكنك أيضًا رؤية ما هي قواعد CSS المطبقة في لوحة جانبية بجوار اللسان الذي يعرض بنية شجرة DOM، مما يسمح لك بمعرفة ما هي الأنماط المُطبّقة على عنصر DOM داخل مستند HTML أو عبر ملف أنماط CSS خارجي. هذه صورةٌ تظهر أنماط العنصر body في أدوات المطوِّر في Firefox: لتعديل عقدة من عقد DOM فانقر نقرًا مزدوجًا فوق العنصر المُحدَّد وأجرِ التعديلات اللازمة، فحاول مثلًا أن تحوِّل العنصر <h1> إلى <h2>. تذكَّر أنَّ الصفحة ستعود إلى حالتها الأصلية المحفوظة إذا أعدت تحميلها. لسان الشبكة يمكن في لسان الشبكة Network في أدوات المطوِّر الموجودة في متصفحك أن تراقب وتسجِّل الطلبيات الشبكية، إذ يُظهِر هذا اللسان جميع الطلبيات الشبكية التي يجريها المتصفح بما في ذلك ما طَلَبَهُ عند تحميل الصفحة، وكم استغرقت كل طلبية من الوقت، وسيوفِّر تفاصيل عن كل طلبية؛ وهذا سيساعد كثيرًا في معرفة سبل تحسين أداء الصفحة وتسريع تحميلها وتنقيح مشاكل الشبكة. يمكنك استخدام لسان الشبكة جنبًا إلى جنب مع سطر الأوامر، أي يمكنك بدء عملية تنقيح (debug) الصفحة في سطر الأوامر ثم الانتقال إلى لسان الشبكة لرؤية النشاطات الشبكية دون إعادة تحميل الصفحة. لتعلّم المزيد حول لسان الشبكة، فأنصحك بقراء working with Firefox’s Network Monitor أو getting started with analyzing Network performance with Chrome’s DevTools. التصميم المتجاوب عندما يكون موقع الويب متجاوبًا (responsive)، فهذا يعني أنَّه صُمِّمَ وطوِّرَ لكي يظهر ويعمل بشكل مناسب على مجال واسع من الأجهزة المختلفة مثل الهواتف المحمولة والحواسيب اللوحية والحواسيب المكتبة والمحمولة. قياس الشاشة وكثافة البكسلات ودعم اللمس هي عوامل مهمة يجب أخذها بالحسبان عند تطوير مواقع متجاوبة، ويجب عليك –كمطور ويب– أن تفكر في مبادئ التصميم المتجاوب عند إنشاء المواقع لإتاحتها للآخرين بغض النظر عن الجهاز الذي يصلون إلى موقعك عبره. يوفر لك متصفح Firefox و Chrome أدواتٍ للتأكد من تطبيقك لمبادئ التصميم المتجاوب أثناء إنشائك وتطويرك لمواقع وتطبيقات الويب. وستتمكن بوساطة تلك الأدوات أن تحاكي مختلف الأجهزة لكي تختبر تطبيقك وتحلّل مشاكله أثناء التطوير. اقرأ المزيد عن Responsive Design Mode في متصفح Firefox أو Device Mode في Chrome لتعلم طريقة الاستفادة من تلك الأدوات لإنشاء مواقع ويب تلبي احتياجات جميع المستخدمين. الخلاصة أخذنا في هذا الدرس لمحةً عن طريقة التعامل مع سطر الأوامر الموجود في المتصفحات الحديثة، بالإضافة إلى بعض المعلومات عن أدوات التطوير التي يمكنك الاستفادة منها في عملك. لتعلّم المزيد عن JavaScript فاقرأ كتاب تعلم JavaScript، وإذا كنتَ مهتمًا بمكتبة jQuery فأنصحك بالاطلاع على كتاب تعلم jQuery. ترجمة –وبتصرّف– للمقال How To Use the JavaScript Developer Console لصاحبته Lisa Tagliaferri
  17. Let’s Encrypt هي سلطة شهادات مفتوحة ومؤتمتة تستعمل بروتوكول ACME ‏(Automatic Certificate Management Environment) لتوفير شهادات TLS/SSL مجانية لأي عميل يحقق الشروط المطلوبة، وتلك الشهادات يمكن أن تستعمل لتشفير الاتصالات بين خادوم الويب وزوار موقعك. هنالك الكثير من العملاء المتاحة لبروتوكول ACME المكتوبة بمختلف لغات البرمجة، مع قدرة على الدمج مع أدوات الإدارة والخدمات والخواديم الشهيرة. أشهر عميل ACME باسم Certbot يُطوَّر حاليًا من Electronic Frontier Foundation. ويمكن لعميل Certbot ضبط تشفير TLS/SSL في خودايم أباتشي و Nginx إضافةً إلى التحقق من ملكية النطاق والحصول على الشهادات. سيشرح هذا الدرس سلطات الشهادات باختصار وكيف تعمل خدمة Let’s Encrypt، ثم سنتحدث عن بعض عملاء ACME. ما هي سلطة الشهادات؟ سلطات الشهادات (certificate authorities اختصارًا CAs) هي الجهات التي توقِّع شهادات TLS/SSL رقميًا لضمان وكفالة موثوقيتها. إذ تملك المتصفحات وأنظمة التشغيل قائمةً بسلطات الشهادات الموثوقة التي يمكن استعمالها للتحقق من شهادات أحد المواقع. حتى وقتٍ قريب، كانت أغلبية سلطات الشهادات خاضعة لشركات تجارية والتي تتقاضى أموالًا للحصول على خدمات توقيع الشهادات، لكن أتت خدمة Let’s Encrypt وجعلت هذه العملية مجانية للمستخدمين عبر أتمتة العملية كليًّا، وبالاعتماد على نظام الرعاية والمساهمات المالية لتمويل البنية التحتية اللازمة لتشغيل مثل هذه الخدمة. لمزيدٍ من المعلومات حول الشهادات والأنواع المختلفة من سلطات الشهادات، فاقرأ مقالة A Comparison of Let’s Encrypt, Commercial and Private Certificate Authorities, and Self-Signed SSL Certificates. كيف تعمل خدمة Let’s Encrypt بروتوكول ACME يُعرِّف كيفية تواصل العملاء مع الخواديم لطلب الشهادات والتحقق من ملكية النطاقات وتنزيل الشهادات، وهذا البروتوكول في صدد تحويله إلى معيار IETF رسمي. توفِّر خدمة Let’s Encrypt شهادات لنطاقات موثوقة، وهذا يعني أنَّها ستتحقق أنَّ الشهادة تأتي من شخصٍ يتحكم فعليًا بالنطاق، وذلك عبر إرسال العميل لرمز فريد (unique token) ثم إجراء طلبية ويب أو DNS للحصول على مفتاح مأخوذ من ذاك الرمز. على سبيل المثال، لو كنا سنجري تحقق عبر HTTP، فسيحسب العميل المفتاح من الرمز الفريد (unique token) ورمز الحساب (account token)، ثم يضع الناتج في ملف مُخدَّم من خادوم الويب، ثم يمكن لخواديم Let’s Encrypt أن تنزِّل الملف الموجود في المسار http://example.com/.well-known/acme-challenge/token فإذا كان المفتاح صحيحًا، فهذا يعني أن العميل قادرٌ على التحكم بالموارد الموجودة في النطاق example.com وبالتالي سيوقِّع الخادوم الشهادة ويتيحها للعميل. يُعرِّف بروتوكول ACME عدِّة طرائق للتحقق أنَّ العميل يملك النطاق، فاختبار HTTPS شبيه باختبار HTTP، لكن بدلًا من استخدام ملف نصي فسيوفِّر العميل شهادة موقعة ذاتيًا وفيها مفتاح التحقق. أما التحقق عبر DNS فيتم عبر وضع المفتاح في سجل DNS TXT. عميل Certbot Certbot هو أشهر عميل Let’s Encrypt، وهو متوافر في أغلبية توزيعات لينكس ويتضمن القدرة على الضبط التلقائي لخادومَي أباتشي و Nginx. يمكنك الحصول على الشهادة وتحديث ضبط أباتشي بتنفيذ الأمر الآتي بعد تثبيت عميل Certbot: sudo certbot --apache -d www.example.com سيسألك Certbot بعض الأسئلة ثم يجري عملية التحقق وينزِّل الشهادات ويُحدِّث ضبط أباتشي ويعيد تحميل الخادوم، ويمكنك بعد ذلك أن تنتقل إلى https://www.example.com في متصفح الويب الخاص بك وستشاهد القفل الأخضر مشيرًا إلى أنَّ الشهادة صحيحة والاتصال مشفّر. ولأن شهادات Let’s Encrypt صالحة لتسعين يومًا فقط، فمن المهم ضبط عملية تجديد مؤتمة. الأمر الآتي سيُجدِّد كل الشهادات الموجودة على الحاسوب: sudo certbot renew ضع الأمر السابق في جدول cron وشغِّله يوميًا، وستُجدَّد الشهادات تلقائيًا قبل ثلاثين يومًا من انتهاء صلاحيتها، وإذا أُنشِئَت الشهادة بادئ الأمر مع أحد الخيارين ‎--apache أو ‎--nginx فسيعيد Certbot تحميل الخادوم بعد نجاح عملية التجديد. إذا أردتَ معرفة المزيد من المعلومات حول جداول cron فأحيلك إلى درس كيف نستخدم المهام المجدولة باستخدامCron في أنظمة لينكس ويونكس. عملاء آخرين لأن بروتوكول ACME مفتوح وموثّق جيدًا، فقد طوِّرَ الكثير من العملاء البديلين، وهنالك قائمة بعملاء ACME في موقع Let’s Encrypt، وأغلبية العملاء لا يملكون ميزة ضبط خادوم الويب تلقائيًا التي يملكها Certbot لكن هنالك ميزات أخرى لها قد تجذبك: - هنالك عميل مكتوب بكل لغات البرمجة تقريبًا، بما في ذلك سكربتات الصدفة (shell scripts) ولغة Go و Node.js، وقد تستفيد من ذلك إن كنتَ تُنشِئ شهادات في بيئة مغلقة لا يمكن تضمين بايثون فيها ولا بقية اعتماديات Certbot. - بعض العملاء يمكن أن يعملوا دون امتيازات الجذر، فمن المستحسن تقليل كمية الشيفرات التي تعمل بامتيازات الجذر إلى أقل قدر ممكن. - الكثير من العملاء يمكنها أتمتة عملية التحقق عبر DNS عبر استخدام الواجهة البرمجية المناسبة لموفِّر خدمة DNS لإنشاء سجلات TXT تلقائيًا، والتحقق عبر DNS يسمح بتوليد شهادات لحالات الاستخدام الغريبة مثل تشفير خواديم الويب التي لا يمكن للعموم الوصول إليها. - بعض العملاء يمكن أن يندمج مع خودايم الويب أو الخواديم الوسيطة (proxy) العكسية، أو موزّعات الحِمل (load balancers) مما يسهِّل عملية الضبط والتشغيل. بعض أشهر تلك العملاء: - lego المكتوب بلغة Go، والذي يُثبَّت عبر ملفٍ ثنائيٍ وحيد، والذي يدعم عدد من مزودي خدمة DNS لتسهيل التحقق عبر DNS. - acme.sh وهو سكربت صدفة بسيط يمكن أن يعمل دون امتيازات الجذر، ويستطيع أن يتواصل مع أكثر من 30 مزودًا لخدمة DNS. - Caddy وهو خادوم ويب كامل مكتوب بلغة Go والذي يملك دعمًا مدمجًا فيه لخدمة Let’s Encrypt. يتوافر الكثير من العملاء، وأصبحت العديد من الخدمات والخواديم تؤتمت عملية إعداد TLS/SSL بدعم خدمة Let’s Encrypt فيها. الخلاصة لقد شرحنا أساسيات عمل خدمة Let’s Encrypt، وناقشنا أشهر العملاء المتوافرين، وإذا أردتَ معرفة كيفية إعداد هذه الخدمة مع بقية البرمجيات فأنصحك بالاطلاع على درس تنصيب شهادة SSL مجانية عبر خدمة Let’s encrypt على خادوم لينكس. ترجمة –وبتصرّف– للمقال An Introduction to Let’s Encrypt لصاحبه Brian Boucheron
  18. أهلًا بك في عالم العمل المستقل! سواءً كنت قد استقلتَ من عملك ذي الدوام الكامل أو كنتَ تتطلع إلى جني القليل من الأموال عبر بعض الأعمال الجانبية، فاعلم أنَّ العمل الحر في مجال ووردبريس قد يكون بدايةً ممتازةً لتأسيس مهنتك كمدير مواقع موثوق. لكن هنالك مشكلة وحيدة؛ فالكثيرون يبدؤون عملهم الحر مع ووردبريس ببناء المواقع. أنا لا أقول أنَّ ذلك خطأ، وإنما لبناء المواقع من الصفر ميزاتٌ كثيرة: ستتعلم التعامل مع ووردبريس بسرعة، بدءًا من خصائص لوحة التحكم مرورًا بالإضافات الضرورية التي عليك استعمالها. ستصبح ملمًا بشركات الاستضافة، ولوحة تحكم cPanel وما يتعلق بأمور إدارة الخادوم، وهذه المعرفة ضرورية لجميع العاملين في مجال ووردبريس. ستتعلم العمل جنبًا إلى جنب مع العملاء لبناء المواقع التي تلبي احتياجاتهم، فمهارة تطوير المواقع ذات القيمة الكبيرة عند المستخدمين هي مهارةٌ لا تقدّر بثمن. ستقع بمشكلات وسترتكب أخطاء وستتعلم منها، ولا تنسَ أنَّ الأخطاء واردة جدًا خصوصًا مع الأمور التقنية. التحديات الرئيسية ستظهر لك عندما تتوقف عن جني المال، فإذا كان عملك الحر لا يتضمن سوى بناء المواقع للآخرين فستقضي نصف وقتك في البحث عن مشاريع جديدة ولقاء العملاء المحتملين ومحاولة البقاء على قيد الحياة حتى تجد عميلك القادم. لكن لحسن الحظ، هنالك طريقٌ أفضل لبدء العمل الحر: بدلًا من بناء مواقع ووردبريس من الصفر، لِمَ لا تساعد مَن يملكون موقعًا بصيانته؟ أبزر ميزاتك! هنالك عشرات الآلاف من الشركات الصغيرة حول العالم التي تبني مواقع ووردبريس والتي تتنافس للحصول على عملائك. أضف إلى ذلك وجود «حيتان كبيرة» مثل WebDevStudios التي توفِّر حلول ووردبريس للعملاء المميزين. أفضل شيء يمكنك فعله في هذه المجال المكتظ هو جعل نفسك مميزًا، إحدى طرق فعل ذلك هي توفير الخدمات التي يحتاج لها الناس مثل الدعم التقني المستمر وأمور الحماية وتحسين السرعة والأداء وصيانة الموقع. ألا تعلم أنَّ كثيرًا من صاحبي المواقع يكرهون تحديث الإضافات لأنها قد تسبب أخطاء أو تضاربات؟ لِمَ لا تتعلم كيفية تحديث الإضافات بأمان وتطبِّقها على مواقع عملائك؟ لن تحتاج إلى تقفي آثار الزبائن! عندما يكون عملك الحر مقتصرًا على بناء مواقع ويب لمختلف العملاء، فالكثير من وقتك سيضيع بحثًا عن مشاريع جديدة (وليس بجني المال). إذا كنت توفر خدمة صيانة مواقع، فسيدفع لك العملاء شهريًا للحصول على خدماتك، وهذا يعني أنَّه طالما كان عملك متقنًا وكانت لديك خطة صيانة واضحة ومرنة وحافظتَ على عملائك فستحصل على إيراد متكرر كل شهر. وهذا يعني أنَّ دخلك سيصبح ثابتًا نسبيًا، وبالتالي تستطيع توظيف أموالك واستعمالها بشكل أكثر كفاءة. إقناع الناس بشراء خدمة الصيانة أسهل إذا كنتَ تريد إقناع عميلك بإنشاء موقع ويب جديد، فمن الصعب حثّه على دفع آلاف الدولارات قبل أن يحصل على أيّة فوائد حقيقية من الموقع؛ أضف إلى ذلك أنَّ الفترة الزمنية بين المقابلة الأوليّة (قبل بدء المشروع) إلى حين إطلاق الموقع قد تُقدَّر بالأشهر (إن لم يكن أكثر). أما تأسيس عمل متعلق بصيانة مواقع ووردبريس فهو أسهل، لأن كمية المال المدفوعة من العملاء أقل وسيدفعون شهريًا، وعملية إقناع الناس بالاشتراك بخطط شهرية أقل جهدًا ووقتًا. يمكنك التوسع بسهولة وأتمتة عملية الصيانة بناء مواقع ويب ذات جودة عالية هو أمرٌ في غاية الصعوبة، صدقني لقد جربتُ ذلك عندما بدأتُ مع ووردبريس. لكن كل زبون يحتاج إلى شيءٍ مختلف، وعليك قضاء الكثير من الوقت لنقاش أهداف شركته وتصاميم الموقع ثم تطبيق التعديلات التي طلبها العميل. وعند حلول نهاية المشروع، فلن تجد نفسك قد جنيتَ أيّة أرباح لأنك أنفقت ساعات وساعات للتعامل مع طلبات العميل وبالتالي انخفضت قيمة ساعة عملك. أجمل ما في خدمة صيانة المواقع هي القدرة على أتمتة أغلبية المهام، إذ يمكنك الاستفادة من إضافة ManageWP لإدارة عشرات ومئات وآلاف مواقع ووردبريس من لوحة تحكم واحدة. الوقت الذي عليك إنفاقه لصيانة مواقع عملائك يتضمن: إقناع العميل بخدمتك وتهيئة الخطة التي اختارها. التعامل مع التعديلات والأمور التي يخبرك بها عميلك. معالجة التنبيهات المؤتمتة التي تأتيك إذا كان هنالك تهديد أمني، أو انخفضت مستويات أداء الموقع، أو لم يكن الموقع يعمل. خلا ذلك، فكل شيءٍ مؤتمت وسيُرسَل لك تنبيه إذا حدث حادث. لن يسبب عملك في ضغط على وقتك لا أريد أن أضلِّلَك هنا، فكل عملٍ متقنٍ في هذا العالم يأخذ وقتًا وصبرًا وجهدًا كبيرًا، وصيانة مواقع ووردبريس بدلًا من تطوير مواقع جديدة من الصفر ليست أمرًا سحريًا يسمح لك بجني المال وأنت جالسٌ على أريكتك ومسترخٍ. بعد أن يكون لك نظام كفء للإدارة، فلن تأخذ عملية إدارة مواقع ووردبريس كثيرًا من وقتك، وستتمكن من التعامل مع أغلبية طلبات الدعم بسهولة مما يعني أنك تستطيع تفريغ قدر كبير من وقتك لتملأه بما تشاء. أكمل قراءة الرواية التي تركتها لعدم توافر وقت لها، واحضر مباراة كرة القدم لفريقك المفضل، واذهب إلى الحديقة وتناول قليلًا من المثلجات. أو انفق وقتك –كما فعلتُ أنا– بتطوير الأنظمة وإنشاء شركة وبتوظيف أشخاص وإدارة فريق عمل وتحويل العمل الحر إلى تجارة كاملة. الخلاصة أهم شيء عليك تذكره حول العمل الحر مع ووردبريس هو أنَّ التركيز الرئيسي للعمل يجب أن يكون النجاح في مساعدة العملاء؛ تذكر أنَّ السبب الرئيسي وراء تطور ووردبريس هو مجتمع البرمجيات مفتوحة المصدر، والذي في أساسه يعني أنَّ هدف ووردبريس هو مساعدة الآخرين. ترجمة –وبتصرّف– للمقال Kick Off Your WordPress Freelance Career With a Website Maintenance Service لصاحبه Joe Howard حقوق الصورة البارزة محفوظة لـ Freepik
  19. لغة Go (والتي يشار إليها golang أيضًا) هي لغة برمجة عصرية مفتوحة المصدر طورتها Google، وازداد انتشارها في كثير من الاستخدامات، وهي تنتهج منهج التبسيط (minimalist) في التطوير وتُسهِّل بناء برمجيات عملية ذات كفاءة عالية. سيشرح هذا الدرس كيفية تحميل وتثبيت Go 1.7، إضافةً إلى شرح تصريف (compile) وتنفيذ برنامج بسيط («!Hello World») على خادوم دبيان 8. المتطلبات المسبقة يفترض هذا الدرس أنَّ لديك وصولًا إلى خادوم دبيان 8 مضبوط فيه حساب مستخدم ليس جذرًا لكنه يمتلك امتيازات الجذر عبر الأمر sudo. الخطوة الأولى: تحميل حزمة لغة Go سنبدأ بتحميل حزمة Go على خادومنا من الموقع الرسمي. اذهب إلى صفحة تنزيل لغة Go الرسمية وابحث عن رابط URL لأرشيف النسخة الحالية من النسخة الثنائية (binary) من اللغة. احرص على أن تنسخ رابط آخر نسخة متوافرة ومتوافقة مع معمارية 64 بت. استعمل الأمر curl من مجلد المنزل لتحميل الأرشيف: curl -O https://storage.googleapis.com/golang/go1.7.4.linux-amd64.tar.gz وصحيحٌ أننا حمّلنا الملف من مصدر موثوق، إلا أنَّه من الأفضل التحقق من سلامة الملفات التي نحمّلها عبر الإنترنت، وهذا يعني أننا سنضمن أنَّ الملف لم يُعدَّل أو يتلاعب به أو يعطَب أثناء عملية التحميل. الأمر sha256sum يُظهِر رمزًا فريدًا من 256 بت: sha256sum go1.7*.tar.gz الناتج: 47fda42e46b4c3ec93fa5d4d4cc6a748aa3f9411a2a2b7e08e3a6d80d753ec8b go1.7.4.linux-amd64.tar.gz قارن الرمز الظاهر في ناتج الأمر السابق مع القيمة الموجودة في صفحة تحميل Go، إذا وجدتهما متطابقين فهذا يعني أنَّ عملية التحميل قد نجحت. لنحاول تثبيت لغة Go بعد أن تحققنا من سلامة الملف. الخطوة الثانية: تثبيت لغة Go سنستخدم الأمر tar لاستخراج محتويات الأرشيف، إذ يطلب الخيار x من الأمر tar أن يستخرج محتويات الملف، والخيار v أن يعرض مخرجات (والتي هي قائمة بالملفات التي ستُستخرَج)، أما الخيار f فيطلب من الأمر tar قراءة ملف الأرشيف المُحدَّد: tar xvf go1.7.4.linux-amd64.tar.gz يجب أن يُنشَأ مجلدٌ باسم go في مجلد العمل الحالي (وهو مجلد Home)، عليك الآن تبديل المستخدم المالك والمجموعة المالكة لمجلد go إلى الجذر، ثم نقله إلى مجلد ‎/usr/local: sudo chown -R root:root ./go sudo mv go /usr/local ملاحظة: على الرغم من أنَّ المسار ‎/usr/local/go هو المسار المنصوح به رسميًا، لكن بعض المستخدمين يفضلون استخدام مسارات مختلفة. عند هذه النقطة يجب تحديد مسار التثبيت عند استدعاء لغة Go من سطر الأوامر، ولجعل التعامل مع Go أسهل قليلًا ، سنضبط بعض المسارات. الخطوة الثالثة: ضبط مسارات Go سنضبط في هذه الخطوة بعض المسارات في البيئة (environment) عندك. لنضبط أولًا قيمة مجلد الجذر للغة Go، الذي يخبر Go أين عليها أن تبحث عن ملفاتها: sudo nano ~/.profile أضف السطرين الآتيين في نهاية الملف: export GOPATH=$HOME/work export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin إذا اخترت تثبيت Go في مجلد آخر، فأضف الأسطر الآتية بدلًا مما سبق، فلو ثبتنا Go في مجلد Home على سبيل المثال، فسنضيف: export GOROOT=$HOME/go export GOPATH=$HOME/work export PATH=$PATH:$GOROOT/bin:$GOPATH/bin بعد تعديل الملف بما هو مناسب، احفظ الملف وأغلق المحرر، ثم أعد قراءة ملف ‎.profile في جلسة bash الحالية: source ~/.profile لقد أنهينا تثبيت Go، لذا لنتأكد من ذلك بكتابة برنامج قصير. الخطوة الرابعة: تجربة Go بعد أن ثبتنا Go وضبطنا المسارات في خادومنا، يمكننا تجربتها للتأكد من أنها تعمل كما هو متوقع. أنشِئ مجلدًا جديدًا لبيئة عمل Go، وهو المكان الذي ستبني فيها Go ملفاتها: mkdir $HOME/work ثم أنشِئ هيكلة المجلدات اللازمة في ذاك المجلد لإنشاء برنامج بسيط، وسنستخدم my_project اسمًا لمشروعنا في هذا المثال: mkdir -p work/src/my_project/hello يمكنك الآن إنشاء ملف «Hello, World!‎» بلغة Go: nano ~/work/src/my_project/hello/hello.go ألصق الشيفرة الآتية داخل محررك، والذي يستخدم حزمة main في لغة go، ثم يستورد المكوِّن fmt، ثم يُنشِئ دالةً جديدةً لطباعة Hello, World!‎ عند تشغيله: package main import "fmt" func main() { fmt.Printf("Hello, World!\n") } سيطبع البرنامج السابق العبارة «Hello, World!‎» إلى الطرفية إذا عَمِلَ دون مشاكل، مما يشير إلى إمكانية تصريف تطبيقات Go بنجاح. احفظ الملف وأغلق المحرر، ثم صرِّف (compile) الملف بتنفيذ التعليمة install التابعة للغة Go: go install my_project/hello يمكنك تشغيل الملف بعد التصريف بتنفيذ الأمر: hello إذا شاهدت المخرجات الآتية فاعلم أنَّ لغة Go مثبتة بشكل صحيح: Hello, World! يمكنك معرفة مكان وجود الملف التنفيذي hello في نظامك باستخدام الأمر which: which hello الناتج: /home/user/work/bin/hello تأكدنا من أنَّ بيئة تطوير Go تعمل بسلاسة بعد تشغيلنا لبرنامج Hello World البسيط السابق. الخلاصة بعد تحميل وتثبيت آخر حزمة Go وضبط المسارات الخاصة بها، أصبح نظامك جاهزًا لتطوير تطبيقات Go. لاحظ أنَّ التطبيقات الاعتيادية تستخدم مكتبات وحزم أخرى، ولتعلم المزيد من المعلومات حول تلك المكونات، انظر إلى صفحة How to Write Go Code في الدليل الرسمي. ترجمة –وبتصرّف– للمقال How To Install Go 1.7 on Debian 8 لصاحبته Lisa Tagliaferri
  20. من المهم جدًا أن يكون الموقع سريعًا، إذ يتوقع ما نسبته 47% من الزوار أن يُحمَّل الموقع في أقل من ثانيتين، وسيترك ما نسبته 40% من الزوار موقعك إن استغرق أكثر من ثلاث ثواني ليُحمَّل. إحدى الدراسات (صحيحٌ أنَّ الدراسة قديمة، لكن الفكرة النظرية وراءها ما تزال صالحة إلى زماننا هذا) تقول أنَّ المستخدمين سيتساهلون إذا حدث تأخير بسيط، لكن درجة عدم رضاهم إذا كان التأخير متوسطًا هي نفسها إذا كان التأخير كبيرًا. فربما لا تظن أنَّ موقعك «بطيء»، لكن حتى لو كان زمن التأخير متوسطًا فقد يحسّ الزوار أنه بطيء جدًا؛ والحل الوحيد لتفادي خسارة زوار موقعك بسبب بطء الموقع هو جعله سريعًا :-) . إحدى أكبر العقبات التي ستواجهك عندما تحاول جعل موقعك سريعًا هي الصور والملفات الثابتة الأخرى مثل JS و CSS، فالصور تكون عادةً كبيرةً وتأخذ وقتًا طويلًا للتحميل (خصوصًا على الاستضافات المشتركة الرخيصة)، ولتحسين ذلك يمكنك استخدام شبكات توزيع المحتوى (CDN). ما هي شبكات توزيع المحتوى؟ شبكات توزيع المحتوى (بالإنكليزية Content Distribution Networks) هي مجموعة من الخواديم المنتشرة حول العالم والمختصة بتخديم المحتوى الثابت بسرعة. طريقة عمل تلك الشبكات تتلخص بوجود خادوم رئيسي (origin) يخزِّن ملفاتك الثابتة (مثل الصور وملفات JavaScript و CSS) وخواديم توزيع التي توصِّل المحتوى إلى المستخدمين، والخادوم الرئيسي هو الخادوم الذي يحتوي على النسخة الرئيسية من الملفات (وفي حالتنا: هو الخادوم الذي يُشغِّل ووردبريس). وعندما يتم طلب الصورة عبر شبكة توزيع المحتوى فسيُحدَّد ما هو الخادوم الأقرب لمكان المستخدم جغرافيًا وسيتحقق الخادوم إن كان يملك الصورة المطلوبة، فإن لم يكن يملكها فسينزلها من الخادوم الرئيسي، وإذا كانت موجودةً عنده فسيرسلها للمستخدم. فائدة طريقة التوزيع السابقة تتلخص في نقطتين أساسيتين: 1. تلك الخواديم مخصصة ومحسّنة لتخديم المحتوى الثابت (مثل الصور) لذا يمكنها تحميل المحتوى بشكل أسرع. 2. يتواجد أحد تلك الخواديم بالقرب من مكان المستخدم، وهذا يعني أنَّ الملف لن يحتاج إلى الانتقال لمسافات طويلة (فيزيائيًا) حتى يصل إلى المستخدم، وبالتالي سيكون زمن التأخير قليلًا. قد يبدو من الوهلة الأولى أنَّ الأمر معقدٌ جدًا، وهو كذلك، لكن لحسن الحظ لا توجد ضرورة أن تتعامل مع الأمور التقنية الخاصة بشبكات توزيع المحتوى، إذ تستطيع قطف الثمار مباشرةً، فهنالك خدماتٌ كثيرة تتولى الأمور التقنية وتُسهِّل عملية الاستفادة من تحسين الأداء عبر استعمال شبكات توزيع المحتوى في موقعك. لكن دعنا نلقي نظرةً على أفضل حلّ لاستعمال شبكات التوزيع في ووردبريس. استخدام Photon خدمة Photon هي خدمة جيدة لتوزيع المحتوى، وهي مجانية أيضًا، وهنالك أسباب تجعل خدمة Photon (التابعة لإضافة Jetpack) جيدة، ولهذا فصلناها عن بقية إضافات CDN: 1. هذه الخدمة هي جزءٌ من إضافة Jetpack، فإضافة Jetpack فيها الكثير من الميزات المفيدة ومن المرجح أنّك تستعملها في موقعك؛ كل ما عليك فعله هو تثبيت Jetpack (من إضافات – أضف جديد، ثم ابحث عن Jetpack) وفعِّل Photon وستكون خدمة CDN جاهزةً عندك، ولا حاجة إلى إجراء أيّة خطوات إضافية، وضبط هذه الخدمة بسيطٌ جدًا؛ إذ تحتاج الكثير من إضافات CDN الأخرى إلى تعديلات تقنية على ضبط خادومك، لكن هذه الإضافة لا تتطلب ذلك. 2. ستُحسِّن خدمة Photon من حجم صورك تلقائيًا، فأغلبية خدمات CDN ستُخدِّم الصور التي ترسلها لها كما هي، لكن خدمة Photon ستجعل الحجم التخزيني لتلك الصور أصغر، ولفعل ذلك ستستخدم Jetpack صيغة صور باسم webp التي طورتها Google، وتملك صيغة webp أفضل خوارزمية ضغط متوافرة حاليًا، وهي مدعومة من متصفحَي Chrome و Opera، وخدمة Photon تعرف ذلك وتُخدِّم الصور بصيغة webp لزوار موقع Chrome و Opera فقط (التي يستعملها حوالي نصف الزوار). 3. إحدى المزايا المتقدمة لخدمة Photon هي القدرة على تطبيق فلاتر إلى الصور وقصها وإعادة تحجميها، وعملية القص وإعادة التحجيم ستقوم بها خدمة Photon دون تدخل من المستخدم (باستعمال دوال add_image_size()‎ الموجودة في ووردبريس)، ويمكن للمستخدمين المتقدمين أن يضيفوا فلاتر إلى الصورة لتغيير طريقة عرضها. عملية ضبط Photon شبيهة بطريقة ضبط وحدات (modules) Jetpack الأخرى. فبعد تفعيل إضافة Jetpack فاذهب إلى صفحة الضبط الخاصة بها وابحث عن Photon ثم اضغط على «Activate». ألم أقل لك أنَّ الأمر بسيط جدًا. لمزيدٍ من المعلومات حول Photon أحيلك إلى هذه الصفحة، وإلى توثيق API. خيارات أخرى لشبكات توزيع المحتوى لماذا تريد استخدام شبكة توزيع أخرى إذا كانت خدمة Photon ممتازةً؟ هنالك ثلاثة أسباب محتملة: الخصوصية. خدمة Photon مملوكة من شركة Automattic (وهي الشركة التي تملك موقع wordpress.com) وبعض المستخدمين يشكون في أمرهم. لا تنسَ أنَّ Automattic هي شركة تجارية وتوفر خدمة مجانية ولا تتوقع أنها صدقة نابعة من طيبة قلوبهم. لن تنتهي صلاحية التخزين المؤقت. وهذا يعني أنَّك لا تستطيع حذف صورة، فلو أردتَ استبدال صورة بأخرى فعليك رفع الصورة الجديدة باسمٍ مختلف. خدمة Photon لا تدعم إلا الصور. فلو أردتَ تخديم ملفات JavaScript و CSS من شبكة توزيع محتوى، فعليك استخدام خدمة أخرى. لكن لسوء الحظ، لا توجد خدمة توزيع محتوى سهلة الإعداد كما في خدمة Photon. لكن الأسباب السابقة لا تعني بالضرورة أن تتجنب استخدام هذه الخدمة، إذ إنَّ تحميل الصورة من خدمة Photon يملك أثرًا كبيرًا على سرعة موقعك، والفائدة الآتية من تحميل الملفات الثابتة الأخرى من شبكة توزيع محتوى ستكون قليلة نسبيًا، ما لم يكن موقعك مشهورًا فعندئذٍ سيستفيد من استعمال خدمة CDN أخرى. إذا أصررتَ على إعداد شبكة CDN فسأذكر في بقية هذا الدرس أفضل الخيارات التجارية المتاحة أمامك لتختار منها ما يناسبك. أفضل الخيارات: خدمة Cloudflare خدمة Cloudflare هي خيار ممتاز، ويمكنها توفير ميزات أكثر من مجرد شبكة توزيع محتوى، بما في ذلك تحسين حماية موقعك وخلاف ذلك، لذا أنصحك بإلقاء نظرة عليها. ذكرتُ Cloudflare أولًا لأنها توفر خطةً مجانيةً رائعةً كافيةً لأغلبية المستخدمين (وإذا أردتَ المزيد من الميزات، فالخطط الاحترافية تبدأ من 20 دولارًا لكل موقع شهريًا). فإذا كنتَ مهتمًا كثيرًا بالحصول على أفضل أداء وأردتَ دمج خدمات إضافة Jetpack مع خدمة توزيع محتوى خارجية، فأنصحك باستعمال Cloudflare. الجانب السلبي الوحيد لهذه الخدمة هو أنَّ إعدادها ليس بسيطًا كما في إضافة Jetpack؛ إذ ستحتاج إلى تسجيل حساب في الخدمة واتباع التعليمات لتحديث سجلات DNS، وقد تستغرق هذه العملية بين عدِّة ساعات إلى يوم كامل، وبعد فعلك لذلك عليك تسجيل الحساب المجاني وضبطه بنفسك. يمكنك قراءة هذا الدرس لشرح طريقة فعل ذلك. الخيارات التجارية الأخرى توفِّر Incapsula خدمة شبيهة بخدمة Cloudflare، وتعطيك خدمات تحسين الأداء والأمان، والخطة المجانية التي توفرها رائعة وهي سهلة الإعداد نسبيًا (ويوفرون لك إضافة ووردبريس لتسهيل دمج الخدمة مع موقعك، لكن قد مضت فترةٌ طويلةٌ منذ آخر تحديث لهذه الإضافة). لكن من مساوئ خدمة Incapsula أنَّ الخطط المدفوعة أغلى من نظيراتها في Cloudflare، لذا إذا أردتَ الحصول على ميزات متقدمة فعليك دفع مبلغ كبير نسبيًا، إذ تبدأ الخطط المدفوعة من 59 دولارًا لكل موقع شهريًا. أما خدمة KeyCDN فهي حلٌّ رخيصٌ نسبيًا لمواقع ووردبريس، وتوفر هذه الخدمة إضافة ووردبريس مُصانة ومُحدَّثة وتستحق التجربة. يجدر بالذكر أنَّ هذه الخدمة لا توفِّر خطة مجانية لكن هنالك فترة تجريبية مجانية، والخطط المدفوعة تبدأ من 0.04 دولار لكل غيغابايت، أي لن تدفع أكثر من دولار واحد شهريًا إلا إذا كان موقعك مشهورًا جدًا. ربما أشهر الخدمات هي خدمة MaxCDN والتي تستخدم من أشهر مواقع التدوين وتُذكَر كثيرًا عند الحديث مع مطوري ووردبريس الآخرين. يمكنك إضافة دعم لخدمة MaxCDN عبر إضافات مثل W3 Total Cache (انظر التوثيق)، وتبدأ الأسعار من 9 دولارًا شهريًا. Fastly هي خدمة CDN تُستعمَل من أكبر المواقع التي تتخصص بالأخبار مثل موقع صحيفة الغارديان البريطانية، وينصحون باستخدام إضافة purgely لدمج الخدمة في موقعك. وصحيحٌ أنَّ Fastly ليست أرخص خدمة CDN لكن هنالك إمكانية تجربة الخدمة بإعطائك 50 دولارًا في حسابك، وأنصحك بتجربة هذه الخدمة إذا كنت جادًا بخصوص تحسين سرعة موقعك. خيارات أخرى إذا أردتَ المزيد من الخيارات والإعدادات فقد تضع ببالك استخدام Amazon Cloudfront أو Google’s Cloud CDN إذا توفر تلك الخدمات تحكمًا دقيقًا وتسعير أكثر مرونة، لكنها تتطلب أن تكون لديك دراية تقنية أكبر. ربما تفكر في الدفع لأحدهم لكي يضبط تلك الخدمات لك لكي تلائم احتياجاتك. الخلاصة إنَّ أفضل خيار هو استخدام خدمة Photon لتخديم الصور مع استخدام Cloudflare لبقية الملفات، وعملية إعداد تلك الخدمات سهلة ولا تأخذ وقتًا طويلًا وستحسِّن سرعة موقعك كثيرًا، مما يرضي زوار موقعك ومحركات البحث. أما إذا كان موقعك أكبر فقد تفكر في استخدام الخدمات المدفوعة التي توفر لك قدرًا كبيرًا من التحكم، وهذه الخدمات التي ناقشناها في هذا الدرس توفِّر مجالًا واسعًا من الخدمات لمختلف أنواع المواقع ولمختلف الميزانيات. الفكرة الرئيسية من استخدام شبكات توزيع المحتوى هي تخديم محتوى الموقع بشكل أسرع إلى المستخدمين، وهذه الخدمات تضبطها لمرة واحدة ثم تنساها، لذا أنصحك بأخذ وقتك لتفكِّر بالخيار الأفضل لجعل موقعك سريعًا. لا تنسَ أنَّ استخدام شبكات توزيع المحتوى هو جزءٌ بسيطٌ من الأحجية التي تجعل موقعك سريعًا، فاستخدام إضافة للتخزين الموقت واختيار قالب سريع والاستضافة في شركة جيدة هي عوامل ستساعد في تسريع موقعك. لذا أنصحك بالاطلاع على الدورة التدريبية Become a WordPress Master التي تعلِّمك المهارات اللازمة لفعل ذلك في ووردبريس. ترجمة –وبتصرّف– للمقال Using CDNs to Unlock a Big WordPress Speed Boost لصاحبه Alex Denning. حقوق الصورة البارزة محفوظة لـ Freepik
  21. تتوسع قواعد البيانات بسرعة مع مرور الزمن، وتكاد في بعض الأحيان أن تملأ المساحة التخزينية المتاحة في نظام الملفات كلها. وقد تتعرض أيضًا إلى مشاكل في الإدخال والإخراج نتيجةً لمحاولة عدِّة خدمات الكتابة على (أو القراءة من) القسم نفسه معًا. هذا الدرس سيفيدك لو كنتَ تريد إضافة المزيد من المساحة التخزينية، أو استخدام خصائص جهاز التخزين لزيادة الأداء (ربما عبر استخدام RAID)، أو تتطلّع إلى استعمال ميزات أخرى للتخزين. سيعلِّمُك هذا الدرس طريقة تغيير مجلد تخزين بيانات MySQL. المتطلبات المسبقة للمتابعة مع هذا الدرس يجب أن يكون عندك: - خادوم CentOS 7 مع حساب مستخدم ليس جذرًا لكنه يمتلك امتيازات الجذر باستعمال الأمر sudo، وفيه خادوم MariaDB مثبت مسبقًا، يمكنك معرفة المزيد من المعلومات حول ضبط CentOS 7 بقراءة درس الضبط المبدئي لخادوم CentOS 7، وإذا لم تثبت MariaDB من قبل، فسيساعدك درس تثبيت وإعداد نظامي إدارة قواعد البيانات MySQL وPostgreSQL على ذلك. سننقل البيانات من جهاز تخزينٍ موصولٍ (mounted) في نقطة الوصل ‎/mnt/volume-nyc1-01. يمكنك معرفة المزيد من المعلومات عن أجهزة التخزين والأقسام وكيفية استخدامها في درس «كيفية إجراء مهام إدارة أجهزة التخزين البسيطة في لينكس». سيعلّمك هذا الدرس طريقة نقل مجلد تخزين بيانات MySQL إلى مكانٍ جديد بغض النظر عن وسيط التخزين الذي تستخدمه (قرص صلب، أو مصفوفة RAID، أو تخزين شبكي). الخطوة الأولى: نقل مجلد بيانات MariaDB لكي نحضِّر لنقل مجلد بيانات MariaDB فلنحاول معرفة مساره الحالي عبر بدء جلسة تفاعلية بتسجيل الدخول بحساب المستخدم root: mysql -u root -p أدخِل كلمة المرور عند طلبها، ثم نفِّذ التعليمة التالية من سطر أوامر mysql: select @@datadir; الناتج: +-----------------+ | @@datadir | +-----------------+ | /var/lib/mysql/ | +-----------------+ 1 row in set (0.00 sec) الناتج السابق يُظهِر أنَّ قواعد MariaDB مضبوطة لاستخدام مجلد تخزين البيانات المبدئي ‎/var/lib/mysql/‎، وهذا هو مسار المجلد الذي علينا نقله؛ نفِّذ الأمر exit للخروج: exit لكي نضمن سلامة البيانات، علينا أولًا إغلاق خادوم MariaDB قبل تعديل مجلد البيانات: sudo systemctl stop mariadb الأمر systemctl لا يُظهِر نتيجة تنفيذ أوامر إدارة الخدمات، لذا إذا أردتَ التحقق أنَّ الخادوم قد أُغلِق بنجاح، فنفِّذ الأمر الآتي: sudo systemctl status mariadb انظر إلى آخر سطر من ناتج الأمر السابق الذي يجب أن يخبرك أنَّ الخادوم قد توقف عن العمل: . . . Dec 16 18:29:26 mysql systemd[1]: Stopped MariaDB database server. سننسخ مجلد قواعد البيانات الموجود حاليًا إلى المكان الجديد باستخدام rsync وذلك بعد إغلاق الخادوم. سنستخدم الخيار ‎-a للحفاظ على الأذونات وخصائص المجلد الأخرى، وسيزودنا الخيار ‎-v بمخرجات توضِّح سير عملية النسخ. ملاحظة: احرص على عدم وجود خط مائل (/) في نهاية مسار المجلد الذي ستُنسَخ البيانات منه، والذي قد يُضاف تلقائيًا إذا كنتَ تُكمِل المسار باستعمال زر tab، فإذا كان الخط المائل موجودًا فسينسخ الأمر rsync المجلد نفسه وليس محتوياته. sudo rsync -av /var/lib/mysql /mnt/volume-nyc1-01 بعد إكمال تنفيذ أمر rsync السابق، فأعد تسمية المجلد الحالية وأضف إليه اللاحقة ‎.bak (لتعرف أنه نسخة احتياطية وليس المجلد الأصل) وأبقِه موجودًا حتى تتأكد من نجاح عملية النقل؛ أعدنا تسميته لتفادي الخلط بين الملفات الموجودة في المكان القديم والجديد: sudo mv /var/lib/mysql /var/lib/mysql.bak سنشرع الآن بتعديل ضبط قواعد البيانات. الخطوة الثانية: الإشارة إلى مكان تخزين البيانات الجديد هنالك طرائق عدِّة لتجاوز القيم المضبوطة في MySQL، إذ تُضبَط التعليمة datadir مبدئيًا إلى ‎/var/lib/mysql في ملف ‎/etc/my.cnf، لذا لنعدِّل هذا الملف لتغيير المسار إلى المجلد الجديد: sudo vi /etc/my.cnf ابحث عن السطر الذي يبدأ بالكلمة datadir=‎ وغيّر المسار الذي يُشير إليه إلى المسار الجديد. ولوجود ملف المقبس (socket file) في مجلد البيانات القديم، فعلينا تحديثه ليشير إلى المكان الجديد أيضًا: [mysqld] . . . datadir=/mnt/volume-nyc1-01/mysql socket=/mnt/volume-nyc1-01/mysql/mysql.sock . . . بعد تحديث الأسطر السابقة الموجودة في الملف، فلنضف ضبطًا خاصًا بعميل mysql وذلك بإضافة الضبط الآتي إلى نهاية الملف (لكي لا نُقسِّم تعليمات الضبط الخاصة بخادوم MySQL إلى قسمين) لكن قبل السطر الذي يحتوي على الكلمة include: [client] port=3306 socket=/mnt/volume-nyc1-01/mysql/mysql.sock !includedir /etc/my.cnf.d بعد أن تنتهي من تعديل الملف، فاضغط على زر Escape ثم اكتب ‎:wq!‎ لحفظ الملف والخروج من المحرر. الخطوة الثالثة: إعادة تشغيل خادوم MariaDB بعد أن حدثنا الضبط ليشير إلى مسار المجلد الجديد، فيمكننا الآن تشغيل خادوم MariaDB والتأكد من عمله بشكل سليم: sudo systemctl start mariadb sudo systemctl status mariadb للتأكد أننا نستعمل المجلد الموجود في المسار الجديد لتخزين البيانات، فسنتصل عبر عميل mysql: mysql -u root -p وننظر إلى قيمة datadir مجددًا: select @@datadir; الناتج: +----------------------------+ | @@datadir | +----------------------------+ | /mnt/volume-nyc1-01/mysql/ | +----------------------------+ 1 row in set (0.01 sec) نفِّذ exit للخروج من العميل. بعد أن أعدت تشغيل خادوم MariaDB وتأكدت أنَّه يستعمل المكان الجديد، فخذ وقتك للتحقق من سلامة بياناتك وأنَّ قواعد بياناتك تعمل دون مشاكل، وبعدئذٍ تستطيع حذف المجلد الاحتياطي بالأمر sudo rm -rf /var/lib/mysql.bak. الخلاصة تعلمنا في هذا الدرس طريقة نقل مجلد بيانات MariaDB إلى مسارٍ جديد، وهذه الطريقة ستعمل مهما كانت تقنية التخزين التي يعتمدها وسيط التخزين الذي ستستعمله. ولمّا كانت قواعد بيانات MariaDB مشتقةً من MySQL، فيمكنك معرفة المزيد من المعلومات حول إدارة مجلدات البيانات في القسمين الآتيين من توثيق MySQL الرسمي: The MySQL Data Directory و Setting Up Multiple Data Directories. ترجمة –وبتصرّف– للمقال How To Change a MariaDB Data Directory to a New Location on CentOS 7 لصاحبته Melissa Anderson
  22. برمجية ووردبريس هي واحدة من أشهر أنظمة إدارة المحتوى مفتوحة المصدر في العالم، وصحيحٌ أنَّ غرضها الأساسي هو إنشاء مدونات، لكنها تطورت على مرّ السنين لتصبح منصةً مرنةً لإنشاء مواقع الويب، ولا نستطيع أن ننكر مدى ثباتها وموثوقيتها التي تطورت خلال خمسة عشر عامًا، لكن ما تزال بعض المشكلات تظهر بين الفينة والأخرى. إذا حاولت فتح موقعك الذي يعتمد على ووردبريس ورأيت رسالةً تُشير إلى خطأ في قواعد البيانات “خطأ في إنشاء اتصال بقاعدة البيانات” (Error Establishing Database Connection)، فمن المرجح أن يكون السبب بين القائمة الآتية: انهارت قاعدة البيانات، ربما بسبب نفاد الذاكرة المتاحة للخادوم معلومات الوصول إلى قاعدة البيانات الموجودة في ضبط ووردبريس غير صحيحة حدث ضرر في جداول قاعدة بيانات ووردبريس لنناقش المشاكل السابقة كلًّا على حدة لنعرف إن كان هو السبب فيما أصاب موقعك، مع ذكر طريقة حلها. المتطلبات المسبقة يفترض هذا الدرس: أنَّك تستعمل ووردبريس على خادوم يمكنك الوصول إلى سطر أوامر وتستطيع تشغيل الأوامر فيه بامتيازات الجذر عبر الأداة sudo. تعمل قاعدة البيانات على خادوم ووردبريس نفسه (وهذا شائع في مواقع ووردبريس المستضافة ذاتيًا، لكنه ليس شائعًا في مواقع ووردبريس المستضافة على استضافة مشتركة). أنَّك تعرف اسم المستخدم الذي يملك وصولًا إلى قاعدة البيانات مع كلمة مروره، واسم قاعدة البيانات الخاصة بورردبريس. يجب أن توفِّر هذه المعلومات عند ضبطك لبرمجية ووردبريس ضبطًا مبدئيًا. الخطوة الأولى: التحقق من الذاكرة المتاحة على الخادوم أوّل خطوة لمعرفة سبب المشكلة هي تسجيل الدخول إلى الخادوم لمعرفة إذا كان سليمًا وأنَّ خدمة MySQL تعمل دون مشاكل. سجِّل دخولك إلى الخادوم عبر SSH، وتذكر أن تضع اسم المستخدم واسم النطاق الخاصين بك في الأمر الآتي: ssh sammy@your_server_ip ملاحظة: إذا كنتَ متأكدًا أنَّ معلومات الاتصال الخاصة بك صحيحة لكنك تواجه مشاكل في تسجيل الدخول، فقد يكون السبب هو نفاد الذاكرة في خادومك أو أنَّه تحت حِملٍ شديد؛ وقد يكون ذلك بسبب كمية كبيرة من البيانات المُرسَلة إلى موقعك، وهذا يُفسِّر سبب الخطأ الذي حدث في ووردبريس… قد تحتاج إلى إعادة تشغيل خادومك قبل أن تتمكن من تسجيل الدخول إليه. بعد أن سجلنا دخولنا بنجاح إلى الخادوم، فيمكننا التأكد أنَّ قواعد MySQL تعمل دون مشاكل: sudo netstat -plt يعرض الأمر netstat معلوماتٍ حول الاتصالات الشبكية في نظامنا، وطلبنا من الأمر السابق أسماء البرامج ‎-p التي تستمع إلى الاتصالات ‎-l على مقابس TCP ‏‎-t؛ عليك الآن البحث عن السطر الذي تُذكر خدمة mysqld فيه: Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 localhost:mysql *:* LISTEN 1958/mysqld tcp 0 0 *:ssh *:* LISTEN 2205/sshd tcp 0 0 localhost:smtp *:* LISTEN 2361/master tcp6 0 0 [::]:http [::]:* LISTEN 16091/apache2 tcp6 0 0 [::]:ssh [::]:* LISTEN 2205/sshd tcp6 0 0 ip6-localhost:smtp [::]:* LISTEN 2361/master إذا كانت مخرجات الأمر السابق عندك مشابهةً لما سبق، فهذا يعني أنَّ خادوم MySQL يعمل ويستمع إلى الاتصالات القادمة؛ أما إذا لم ترَ خدمة MySQL مذكورةً في الناتج، فجرِّب تشغيلها يدويًا، وذلك باستعمال أمرٍ شبيهٍ بالأمر الآتي: sudo systemctl start mysql لاحظ أنَّ بعض توزيعات لينكس (وأشهرها CentOS) تستعمل mysqld بدلًا من mysql للإشارة إلى اسم الخدمة؛ لذا ضع الكلمة الملائمة لنظامك الذي تستعمله. يجب أن تبدأ خدمة MySQL الآن، وأعد تشغيل أمر netstat السابق للتأكد من ذلك، وابحث عن السطر الذي يحتوي على اسم خدمة MySQL. تحتاج قواعد بيانات MySQL وبرمجية ووردبريس إلى قدرٍ لا بأس به من الذاكرة لكي تعمل عملًا سليمًا؛ وإذا انهارت قواعد البيانات بسبب نفاد الذاكرة، فيجب أن نرى دليلًا على ذلك في سجل الأخطاء. لنلقِ نظرة: zgrep -a "allocate memory" /var/log/mysql/error.log* الأمر zgrep سيبحث في ملفات السجل، بما فيها ملفات السجل القديمة والتي ضُغِطَت لتوفير المساحة التخزينية؛ وحددنا في الأمر السابق أننا نبحث في أي سطر يحتوي على العبارة allocate memory في أي ملف error.log*‎ موجود في مجلد ‎/var/log/mysql/‎: 2017-04-11T17:38:22.604644Z 0 [ERROR] InnoDB: Cannot allocate memory for the buffer pool إذا رأيتَ سطرًا أو أكثر يشبه السطر السابق فهذا يعني أنَّ خادوم MySQL قد انهار بسبب عدم كفاية الذاكرة؛ وإذا وجدتَ سطرًا وحيدًا فقط فهذا يعني أنَّ الانهيار عَرَضي بسبب كمية مؤقتة كبيرة من البيانات، أما إذا كانت هنالك عدِّة أسطر تحوي الخطأ نفسه، فهذا يعني أنَّ الذاكرة الحالية لا تكفي خادومك. في كلا الحالتين السابقتين، الحل العملي لهذه المشكلة هو الانتقال إلى خادومٍ تتوافر فيه ذاكرة أكثر، والأمر بسيطٌ جدًا إذا كان خادومك مستضافًا على خدمةٍ سحابية، إذ تستطيع ترقية الخادوم دون انقطاع الخدمة لوقتٍ طويل. إذا لم تجد أيّة مخرجات بعد تنفيذ أمر zgrep السابق، فهذا يعني أنَّ الذاكرة تكفي خادومك، وإن بقي موقعك يُظهِر رسالة الخطأ، فانتقل إلى الخطوة التالية التي نلقي فيها نظرةً على ضبط ووردبريس ونتأكد أنَّ معلومات الدخول إلى قاعدة MySQL صحيحة. الخطوة الثانية: التحقق من معلومات الدخول إلى قاعدة البيانات إذا نقلتَ موقع ووردبريس إلى خادوم جديد أو إلى استضافة أخرى، فقد تحتاج إلى تحديث معلومات الاتصال بقاعدة البيانات، وهذه المعلومات مخزنة في ملف PHP على الخادوم باسم wp-config.php. لنعثر بدايةً على ملف wp-config.php: sudo find / -name "wp-config.php" الأمر السابق يبحث في كل النظام (بدءًا من المجلد الجذر /) عن أي ملف باسم wp-config.php، ثم سيعرض المسار الكامل للملف إن عُثِرَ عليه: /var/www/html/wp-config.php ملاحظة: إذا كنتَ تعلم مكان تثبيت برمجية ووردبريس، فيمكنك الانتقال إلى مسار تثبيتها مباشرةً وتخطي الخطوة السابقة لأنها تستهلك بعض الوقت. استعمل محرِّرك النصي المفضل لتعديل ملف الضبط، سنستعمل محرر nano في الأمر الآتي: sudo nano /var/www/html/wp-config.php ستشاهد أمامك ملفًا نصيًا مليئًا بخيارات الضبط مع بعض التعليقات التي تشرحها. لكنك ستجد قسمًا (في بداية الملف عادةً) فيه معلومات الاتصال إلى قاعدة البيانات: /** The name of the database for WordPress */ define('DB_NAME', 'database_name'); /** MySQL database username */ define('DB_USER', 'database_username'); /** MySQL database password */ define('DB_PASSWORD', 'database_password'); تأكد أن القيم الثلاث السابقة صحيحة بناءً على معلومات الاتصال المسجلة عندك؛ وإذا لم تكن صحيحةً فحدِّثها وفقًا لما تراه مناسبًا، ثم احفظ الملف واخرج من المحرر (بضغط Ctrl+o للحفظ ثم Ctrl+x للخروج، وذلك إذا كنتَ تستعمل محرر nano). حتى لو بدت لك معلومات الاتصال بقاعدة البيانات صحيحةً، فمن المفيد تجربة الاتصال إلى قاعدة البيانات من سطر الأوامر ليطمئن قلبك. انسخ المعلومات المذكورة في ملف الضبط السابق واستعملها في هذا الأمر: mysqlshow -u database_username -p عندما يُطلَب منك إدخال كلمة مرور فألصقها واضغط على زر Enter، وإن ظهر لك خطأ Access denied فهذا يعني أنَّ اسم المستخدم أو كلمة المرور خطأ، وإذا كانا صحيحين فسيعرض الأمر mysqlshow جميع قواعد البيانات التي يملك المستخدم وصولًا إليها: +--------------------+ | Databases | +--------------------+ | information_schema | | database_name | +--------------------+ تأكد أنَّ اسم إحدى قواعد البيانات يطابق تمامًا الاسم المذكور في ملف ضبط ووردبريس؛ وعندئذٍ ستعلم أنَّ ضبطك صحيح وأنَّ ووردبريس يجب أن تكون قادرةً على الاتصال بقاعدة البيانات بنجاح. ادخل إلى موقعك مجددًا لعل رسالة الخطأ تختفي، وإن بقيت موجودةً فلنحاول إصلاح قاعدة البيانات. الخطوة الثالثة: إصلاح قاعدة بيانات ووردبريس قد يحدث عطب في قاعدة بيانات ووردبريس في بعض الأحيان بسبب فشل الترقية أو انهيار قاعدة البيانات أو مشكلة في إحدى الإضافات، وقد تظهر هذه المشكلة على أنها خطأ في الاتصال بقاعدة البيانات، لذا إذا لم تكن المشكلة في خادوم MySQL ولا في ملف الضبط، فجرِّب إصلاح قاعدة البيانات. توفر ووردبريس أداةً مبنيةً داخلها لإصلاح قاعدة البيانات، وهي معطلة افتراضيًا لعدم وجود قيود مفروضة على من يستطيع الوصول إليها مما قد يسبب مشكلةً أمنيةً، لذا سنفعِّل هذه الميزة، ثم نُشغِّل أداة الإصلاح، ثم نعطلها. افتح ملف wp-config.php مرةً أخرى: sudo nano /var/www/html/wp-config.php ألصق ما يلي في سطرٍ جديد: define('WP_ALLOW_REPAIR', true); سيؤدي السطر السابق إلى تفعيل ميزة إصلاح قاعدة البيانات. احفظ الملف وأغلق المحرر النصي، وافتح العنوان الآتي في متصفحك، وتذكر أن تضع اسم النطاق الخاص بموقعك أو عنوان IP التابع له: http://www.example.com/wp-admin/maint/repair.php يجب أن تظهر صفحة الإصلاح: اضغط على زر «Repair Database» ويجب أن تنتقل إلى صفحة النتائج التي تستطع أن ترى فيها التحققات والإصلاحات التي تجريها ووردبريس في الوقت الحقيقي: بعد انتهاء هذه العملية، احرص على تعديل ملف wp-config.php وحذف السطر الذي أضفناه إليه آنفًا. هل لاحظت أيّة إصلاحات أجرتها الأداة؟ جرِّب الدخول إلى موقعك مجددًا وانظر هل اختفت رسالة الخطأ. إذا ظهرت مشاكل لا يمكن حلها فربما ستحتاج إلى استعادة قاعدة البيانات من نسخة احتياطية إذا توافرت عندك. إذا لم يُعثَر على مشاكل في قاعدة البيانات ولم تستطع أن تعرف ما أصل المشكلة، فمن المحتمل أن هنالك مشاكل أخرى لم تنتبه إليها. الخلاصة أغلبية أخطاء “خطأ في إنشاء اتصال بقاعدة البيانات” يمكن حلّها عبر اتباع الخطوات السابقة، لكن مع ذلك هنالك أخطاء أكثر تعقيدًا قد تظهر على شكل خطأ في الاتصال بقاعدة البيانات؛ لذا سأعرض لك قائمةً بالمقالات التي تساعدك في تَتَبُع وإصلاح مسبب المشكلة: أحد المسببات الشائعة للتراسل الكبير لموقع ووردبريس (وبالتالي انخفاض الأداء وحدوث أخطاء) هو هجمات brute-force ، وبالتالي يجب اتخاذ إجراءات للتخفيف من تأثيرها. يمكنك توفير بعض موارد الخادوم باستعمال التخزين المؤقت لصفحات ووردبريس؛ وهنالك عدد كبير من إضافات التخزين المؤقت البسيطة المتوافرة لها. ترجمة –وبتصرّف– للمقال How To Debug the Wordpress “Error Establishing Database Connection”‎ لصاحبه Brian Boucheron. حقوق الصورة البارزة محفوظة لـ Freepik
  23. من المهم جدًا الحفاظ على دقة وقت النظام، سواءً فعلنا ذلك للحرص على دقة ترتيب السجلات (logs) أو أنَّ تحديثات قاعدة البيانات ستُطبَّق دون مشاكل؛ فإذا كان الوقت المضبوط على النظام غير صحيح، فقد يسبب ذلك أخطاءً أو تلفًا في البيانات أو مشاكل أخرى يصعب معرفة سببها بسهولة. ميزة مزامنة الوقت مضمّنةٌ ومفعّلةٌ في أوبنتو 16.04 افتراضيًا عبر خدمة timesyncd، وسنلقي في هذا الدرس نظرةً على الأوامر الأساسية المتعلقة بالوقت، ونتأكد أنَّ خدمة timesyncd مفعّلة، ونتعلم كيفية تثبيت خدمة بديلة لمزامنة الوقت والتاريخ. المتطلبات المسبقة يجب أن تملك قبل اتباع تعليمات هذا الدرس خادومًا يعمل بنظام أوبنتو 16.04 مع مستخدم ليس جذرًا لكنه يملك امتيازات الجذر عبر الأمر sudo؛ انظر إلى درس الإعداد الابتدائي لخادوم أوبنتو 14.04» لمزيدٍ من المعلومات. تعلّم الأوامر الأساسية للتعامل مع الوقت إنَّ أبسط الأوامر لمعرفة ما هو الوقت الحالي في نظامك هو date، يمكن لأي مستخدم كتابة هذا الأمر للحصول على الوقت والتاريخ الحاليين: date مثال على الناتج: Wed Apr 26 17:44:38 UTC 2017 من المرجح أنَّ المنطقة الزمنية المستعملة في خادومك هي UTC كما هو ظاهر في المثال أعلاه، كلمة UTC هي اختصار لعبارة Coordinated Universal Time (التوقيت العالمي الموحد) وهو الوقت عند مبدأ خطوط الطول، واستعمال توقيت UTC سيسهل عليك العمل إذا كانت خواديمك تمتد لأكثر من منطقة زمنية وحيدة. إذا أردت تغيير المنطقة الزمنية لأي سببٍ من الأسباب، فيمكنك استخدام الأمر timedatectl لفعل ذلك. اعرض أولًا قائمةً بالمناطق الزمنية المتاحة: timedatectl list-timezones ستُعرَض قائمة بجميع المناطق الزمنية، يمكنك الضغط على زر Space للتمرير إلى الأسفل وزر b للتمرير إلى الأعلى؛ وبعد أن تعثر على المنطقة الزمنية الصحيحة فدوِّنها عندك ثم اضغط على q للخروج من القائمة. يمكنك الآن ضبط القائمة الزمنية باستخدام الأمر timedatectl set-timezone، احرص على وضع منطقتك الزمنية بدلًا من تلك المذكورة في الأمر الآتي؛ لاحظ أنَّك ستحتاج إلى استخدام الأمر sudo مع الأمر timedatectl لإجراء هذا التعديل: sudo timedatectl set-timezone America/New_York يمكنك التحقق من التغييرات بتشغيل الأمر date مجددًا: date الناتج: Wed Apr 26 13:55:45 EDT 2017 يجب أن يشير الاختصار المذكور في الأمر السابق إلى المنطقة الزمنية التي اخترتها. تعلمنا كيف نتحقق من الوقت الحالي وكيف نضبط المناطق الزمنية، وسنتعلم الآن كيف نتأكد من مزامنة الوقت في نظامنا. التحكم بخدمة timesyncd بواسطة timedatectl كانت أغلبية عمليات مزامنة الوقت تتم عبر خدمة بروتوكول وقت الشبكة (Network Time Protocol daemon) ntpd، أي سيتصل الخادوم إلى مجموعة من خواديم NTP التي توفر الوقت بدقة كبيرة. لكن توزيعة أوبنتو تستعمل timesyncd بدلًا من ntpd لمزامنة الوقت، إذ تتصل خدمة timesyncd إلى خواديم الوقت نفسها وتعمل العمل نفسه تقريبًا، لكنها أخف وتندمج اندماجًا أفضل مع systemd وطريقة العمل الداخلية في توزيعة أوبنتو. يمكنك الحصول على حالة خدمة timesyncd بتشغيل الأمر timedatectl دون معاملات، ولن تحتاج إلى استخدام sudo في هذا الموضع: timedatectl الناتج: Local time: Wed 2017-04-26 17:20:07 UTC Universal time: Wed 2017-04-26 17:20:07 UTC RTC time: Wed 2017-04-26 17:20:07 Time zone: Etc/UTC (UTC, +0000) Network time on: yes NTP synchronized: yes RTC in local TZ: no سيطبع الأمر السابق الوقت المحلي والوقت العالمي (والذي يساوي الوقت المحلي في حال لم تغيّر المنطقة الزمنية)، وبعض معلومات عن حالة وقت الشبكة. السطر Network time on: yes يعني أنَّ خدمة timesyncd مفعّلة، والسطر NTP synchronized: yes يشير إلى نجاح مزامنة الوقت. إذا لم تكن خدمة timesyncd مفعلةً، فشغِّلها باستعمال الأمر timedatectl: sudo timedatectl set-ntp on شغِّل الأمر timedatectl مجددًا للتأكد من حالة وقت الشبكة؛ لاحظ أنَّ عملية التزامن تحتاج إلى بعض الوقت، لكن في النهاية يجب أن تكون قيمة السطرين Network time on:‎ و NTP synchronized:‎ تساوي yes. التحويل إلى خدمة ntpd على الرغم من أنَّ خدمة timesyncd مناسبة لغالبية الاحتياجات، لكن بعض التطبيقات حساسةٌ جدًا لأدنى اضطراب في الوقت ومن المستحسن استعمال ntpd في هذه الحالات، لأنه يستعمل تقنيات معقدة لإبقاء الوقت في النظام مزامنًا دومًا. علينا إيقاف خدمة timesyncd قبل تثبيت ntpd: sudo timedatectl set-ntp no للتأكد من إيقاف خدمة timesyncd: timedatectl ابحث عن السطر Network time on: no الذي يعني أنَّ خدمة timdsyncd متوقفة؛ يمكننا الآن تثبيت حزمة ntp باستعمال الأداة apt-get: sudo apt-get install ntp يجب أن يعمل خادوم ntpd تلقائيًا بعد التثبيت، يمكنك عرض حالة خدمة ntpd للتأكد أنَّ كل شيءٍ على ما يرام: sudo ntpq -p الناتج: remote refid st t when poll reach delay offset jitter ============================================================================== 0.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000 1.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000 2.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000 3.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 0.000 0.000 ntp.ubuntu.com .POOL. 16 p - 64 0 0.000 0.000 0.000 -makaki.miuku.ne 210.23.25.77 2 u 45 64 3 248.007 -0.489 1.137 -69.10.161.7 144.111.222.81 3 u 43 64 3 90.551 4.316 0.550 +static-ip-85-25 130.149.17.21 2 u 42 64 3 80.044 -2.829 0.900 +zepto.mcl.gg 192.53.103.108 2 u 40 64 3 83.331 -0.385 0.391 ntpq هي أداة لطلب (query) معلومات حول خدمة ntpd، والخيار ‎-p يطلب معلومات حول خواديم NTP ‏(peers) التي اتصلت خدمة ntpd بها. قد يختلف الناتج عندك قليلًا، لكن يجب أن تتضمن القائمة على خواديم أوبنتو الافتراضية إضافةً إلى غيرها. أبقِ في ذهنك أنَّ خدمة ntpd تحتاج إلى بضع دقائق لتهيئة الاتصالات… الخلاصة رأينا في هذا الدرس طريقة عرض وقت النظام، وكيفية تغيير المناطق الزمنية، وطريقة التعامل مع خدمة timesyncd الموجودة افتراضيًا في أوبنتو، إضافةً إلى طريقة تثبيت ntpd. إذا كان نظامك ذو احتياجات خاصة لم نشرحها في هذا الدرس، فأنصحك بالرجوع إلى توثيق NTP الرسمي، وألقِ نظرةً على مشروع NTP Pool الذي هو مجموعةٌ من المتطوعين الذين يوفرون جزءًا كبيرًا من البنية التحتية التي يحتاج لها بروتوكول NTP في العالم. ترجمة –وبتصرّف– للمقال How To Set Up Time Synchronization on Ubuntu 16.04لصاحبه Brian Boucheron حقوق الصورة البارزة محفوظة لـ Freepik
  24. بعد إعداد أقل قدر ممكن من الضبط للخادوم الجديد الضبط المبدئي لخادوم CentOS 7، هنالك بعض الخطوات الإضافية التي يُنصَح إجراؤها في أغلبية الحالات، وسنكمل ذلك في هذا الدرس بضبط بعض الأمور الاختيارية. المتطلبات المسبقة وأهداف هذا الدرس قبل أن تبدأ بهذا الدرس، عليك أن تتبع الخطوات المذكورة في درسنا السابق الضبط المبدئي لخادوم CentOS 7، من المهم أن تعد حسابات المستخدمين، وتمنحهم امتيازات الجذر باستخدام الأمر sudo، وتحاول تأمين خدمة SSH. يمكنك المتابعة مع هذا الدرس بعد إكمال الدرس السابق، الذي سنُركِّز فيه على ضبط بعض المكونات الاختيارية والمهمة؛ مثل ضبط الجدار الناري وملف التبديل (swap file) وضبط مزامنة الوقت والتاريخ عبر بروتوكول NTP. ضبط جدار ناري بسيط توفر الجدران النارية حمايةً أساسيةً للخواديم، وهذه التطبيقات مسؤولة عن منع الوصول إلى جميع المنافذ الشبكية على خادومك باستثناء المنافذ (أو الخدمات) التي سمحتَ لها. تأتي توزيعة CentOS مع جدارٍ ناريٍ باسم firewalld، وتستعمل أداةٌ باسم firewall-cmd لضبط سياسات الجدار الناري. سنتبع منهجية لسياسات الجدار الناري ألا وهي إغلاق جميع المنافذ إلا التي نملك سببًا وجيهًا لإبقائها مفتوحةً. لخدمة firewalld القدرة على إجراء تعديلات دون قطع الاتصالات الحالية، لذا يمكننا تشغيلها قبل أن نضيف الاستثناءات التي نريدها: sudo systemctl start firewalld لاحظ أنَّ الخدمة أصبحت تعمل الآن في الخلفية، ويمكننا استعمال الأداة firewall-cmd للحصول على معلوماتٍ عن سياسات الجدار الناري أو ضبطها. لدى برمجية firewalld مفهوم هو «المناطق» (zones) لتسمية مدى ثقتك بالأجهزة الأخرى الموجودة على شبكة ما، وهذه التسمية ستمنحنا القدرة على إسناد قواعد مختلفة بناءً على مدى «ثقتنا» بالشبكة. سنُعدِّل في درسنا هذا السياسات التابعة للمنطقة الافتراضية، وعندما نُعيد تحميل خدمة الجدار الناري، فستُطبَّق سياسات هذه المنطقة على جميع البطاقات الشبكية. يمكننا البدء بإضافة استثناءات للخدمات المسموح لها بإجراء اتصالات خارجية؛ وأهمها خدمة SSH، لأننا نريد أن نبقى قادرين على الاتصال البعيد إلى الخادوم. إذا لم تُعدِّل المنفذ الذي تستمع عليه خدمة SSH، فيمكنك السماح لاتصالات SSH بكتابة الأمر الآتي: sudo firewall-cmd --permanent --add-service=ssh أما إذا غيّرتَ منفذ SSH على خادومك، فعليك التصريح عن المنفذ الجديد يدويًا، وعليك أن تُحدِّد ما هو البروتوكول الذي تستعمله تلك الخدمة. نفِّذ الأمر الآتي إذا غيرتَ المنفذ الذي تستمع عليه خدمة SSH: sudo firewall-cmd --permanent --remove-service=ssh sudo firewall-cmd --permanent --add-port=4444/tcp هذا هو الحد الأدنى من الضبط لإبقاء الوصول إلى الخادوم البعيد ممكنًا، وإذا كنتَ تخطط لتشغيل خدمات أخرى على النظام، فعليك فتح منافذ لها في الجدار الناري. فلو كنتَ تشغِّل خادوم ويب تقليدي وأردت السماح للاتصالات المتعلقة به في الجدار الناري: sudo firewall-cmd --permanent --add-service=http إذا كنتَ تخطط لتشغيل خادوم ويب مع تشفير الاتصال عبر SSL/TLS، فعليك السماح لخدمة https أيضًا: sudo firewall-cmd --permanent --add-service=https وإذا احتجتَ إلى خدمة SMTP للبريد الإلكتروني، فنفِّذ الأمر: sudo firewall-cmd --permanent --add-service=smtp لرؤية الخدمات الأخرى التي يمكن السماح لها بتحديد اسمها، فنفِّذ: sudo firewall-cmd --get-services بعد أن تنتهي من ضبط الجدار الناري، يمكنك عرض قائمة بجميع الاستثناء الموجودة في سياسة الجدار الناري عبر الأمر الآتي: sudo firewall-cmd --permanent --list-all وعندما تكون جاهزًا لتطبيق هذه التعديلات، فأعد تحميل الجدار الناري: sudo firewall-cmd --reload وبعد أن تجرب وتتأكد من عمل كل الخدمات، فيجدر بك تفعيل الجدار الناري عند الإقلاع: sudo systemctl enable firewalld تذكر أنَّ عليك فتح منفذ في الجدار الناري عند تثبيت وضبط أيّة خدمات جديدة لاحقًا. ضبط المنطقة الزمنية ومزامنة الوقت والتاريخ الخطوة التالية هي تعديل المنطقة الزمنية وضبط مزامنة الوقت عبر بروتوكول NTP (اختصار للعبارة Network Time Protocol). أوّل خطوة هي التأكد من صحة المنطقة الزمنية المضبوطة في خادومك، والخطوة الثانية هي ضبط النظام ليزامن ساعته مع شبكة من خواديم NTP للحصول على الوقت والتاريخ بدقة، وهذا سيساعد في منع بعض المشاكل التي تحدث بسبب عدم تزامن الساعة. ضبط المنطقة الزمنية أوّل خطوة هي ضبط المنطقة الزمنية للخادوم، وهذه الخطوة سهلة جدًا ويمكن إجراؤها باستعمال الأمر timedatectl. علينا أولًا أن نعرض قائمة بالمناطق الزمنية المتوافرة بتنفيذ الأمر: sudo timedatectl list-timezones سيُنتِج الأمر السابق قائمةً بالمناطق الزمنية المتوافرة لخادومك، وعندما تجد المنطقة الزمنية الصحيحة فيمكنك ضبطها بتنفيذ الأمر: sudo timedatectl set-timezone region/timezone فمثلًا لو كان خادومك موجودًا في الساحل الشرقي للولايات المتحدة الأميركية، فيمكنك تنفيذ: sudo timedatectl set-timezone America/New_York يمكنك التأكد أنَّ نظامك قد حُدِّث ليستعمل المنطقة الزمنية التي ضبطتَها بالأمر: sudo timedatectl ضبط مزامنة الوقت عبر بروتوكول NTP علينا الآن ضبط المزامنة بعد أن ضبطنا المنطقة الزمنية، وهذا يسمح للحاسوب بمزامنة الوقت والتاريخ، مما يمنع حدوث بعض المشاكل التي يتسبب بها الاختلاف في الوقت بين الخواديم. سنستخدم خدمة باسم ntp لمزامنة الوقت، والتي يمكن تثبيتها من مستودعات CentOS: sudo yum install ntp ثم عليك بدء الخدمة لهذه الجلسة، ثم تفعيل تشغيل الخدمة عند الإقلاع: sudo systemctl start ntpd sudo systemctl enable ntpd سيُصحِّح خادومك ساعته تلقائيًا لتتوافق مع الخواديم العالمية. إنشاء ملف تبديل إضافة مساحة للتبديل (swap) إلى خادوم لينكس ستُمكِّن النظام من نقل المعلومات التي لا يتم الوصول إليها كثيرًا من ذاكرة الوصول العشوائي (RAM) إلى مكانٍ ما على القرص الصلب؛ وصحيحٌ أنَّ الوصول إلى البيانات المخزنة على القرص أبطأ بكثير بقارنة بالوصول إليها من ذاكرة الوصول العشوائي مباشرةً، لكن قد تستفيد من ذاكرة التبديل في حال نفدت المساحة المتاحة في ذاكرة RAM مما يمنع انهيار الخدمات التي يشغلها خادومك، يجدر بالذكر أنَّ استعمال مساحة التبديل مفيدٌ جدًا خصوصًا إذا كان خادومك يستضيف قواعد بيانات. لا توجد قواعد لتحديد المساحة التخزينية المثلى لذاكرة التبديل، لكنها عمومًا تساوي مقدار ذاكرة RAM في نظامك أو ضعفيها… احجز المساحة التي ترغب في استخدامها لذاكرة التبديل باستخدام الأداة fallocate، فلو أردنا إنشاء ملف للتبديل بمساحة 4 غيغابايت في مجلد ‎/swapfile سنُنفِّذ الأمر: sudo fallocate -l 4G /swapfile علينا بعد إنشاء الملف أن نمنع المستخدمين أو العمليات في النظام من الوصول إلى تلك الذاكرة وقراءة محتوياتها: sudo chmod 600 /swapfile بعد ضبط الأذونات السليمة للملف، فيمكننا أن نطلب من النظام أن يُهّيئ الملف ليعمل كذاكرة تبديل بالأمر: sudo mkswap /swapfile ثم سنطلب من النظام استخدام ملف التبديل الذي أنشأناه آنفًا: sudo swapon /swapfile أصبح نظامنا يستعمل ملف التبديل لحين إعادة إقلاعه، لذا سنحتاج إلى تعديل نظام الملفات لكي يفعل النظام ذلك تلقائيًا عند الإقلاع، وذلك بإضافة سطر جديد إلى ملف ‎/etc/fstab: sudo sh -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab' يجب أن يستعمل نظامك هذا الملف كذاكرة تبديل عند كل إقلاع. الخلاصة عند هذه المرحلة يجب أن تكون قد ضبطت خادومك ضبطًا أساسيًا، ومن المرجح أن تكون عندك فكرة لما ستفعله لاحقًا، أنصحك بالاطلاع على المقالات الموجودة في قسم DevOps في أكاديمية حسوب. ترجمة –وبتصرّف– للمقال Additional Recommended Steps for New CentOS 7 Serversلصاحبه Justin Ellingwood
  25. تمهيد هنالك بعض خطوات الضبط التي عليك إجراؤها عندما تُنشِئ خادومك، إذ ستزيد من حمايته وسهولة استخدامه، وستوفر لك أساسًا تستطيع البناء عليه لإجراء عمليات أخرى. الخطوة الأولى: تسجيل الدخول بحساب الجذر لتسجيل الدخول إلى خادومك، فعليك معرفة عنوان IP العام الخاص به إضافةً إلى كلمة مرور المستخدم الجذر root؛ إذا لم تُسجِّل دخولك من قبل إلى خادومك. إذا لم تكن متصلًا بخادومك، فاستعمل الأمر الآتي الذي يُسجِّل دخولك بحساب الجذر root، لاحظ أنَّ عليك وضع عنوان IP العام لخادومك بدلًا من عبارة SERVER_IP_ADDRESS: ssh root@SERVER_IP_ADDRESS أكمل عملية تسجيل الدخول بقبولك للتحذير عن صحة وموثوقية الخادوم إن ظهر لك، ثم بتوفيرك لطريقة الاستيثاق المطلوبة لحساب الجذر (عبر كلمة مرور أو مفتاح خاص [private key]). إذا كانت هذه هي أوّل مرة تسجِّل فيها دخولك إلى الخادوم، فسيُطلَب منك تغيير كلمة مرور الجذر أيضًا. ما هو المستخدم الجذر؟ المستخدم الجذر root هو الحساب الإداري في بيئة لينكس والذي يملك صلاحيات وامتيازات واسعة جدًا؛ وبسبب امتلاك هذا الحساب لهذه الامتيازات، فمن غير المستحسن استعماله في الأحوال العادية، لأن القدرات التي يملكها حساب الجذر قادرة على إلحاق الضرر بنظامك، لو خطأً. الخطوة التالية هي إعداد حساب مستخدم له صلاحيات أقل من صلاحيات الجذر لاستعماله في إجراء المهام اليومية، ثم سنتعلم كيف نزيد من امتيازات هذا الحساب عندما نحتاج إليها. الخطوة الثانية: إنشاء حساب مستخدم جديد بعد أن نسجِّل الدخول بحساب الجذر root، فأصبحنا جاهزين لإضافة حساب مستخدم جديد الذي سنستعمله من الآن وصاعدًا لتسجيل الدخول إلى النظام. سنُنشِئ بواسطة الأمر الآتي مستخدمًا جديدًا باسم demo، لكن يمكنك استخدام أي اسم يحلو لك: adduser demo علينا بعد ذلك أن نسند كلمة مرور إلى المستخدم الجديد (تذكر أن تضع اسم المستخدم الذي اخترته بدلًا من demo): passwd demo ادخل كلمة مرور قوية، ثم كرِّر كتابتها للتأكيد. الخطوة الثالثة: الحصول على امتيازات الجذر أصبح لدينا الآن حساب مستخدم جديد يملك امتيازاتٍ عاديةً، لكننا سنحتاج في بعض الأحيان إلى إجراء عمليات إدارية. ولتنجب الحاجة إلى تسجيل الخروج من حساب المستخدم العادي ثم الدخول مجددًا بحساب الجذر، فسنحاول ضبط إمكانية الحصول على امتيازات الجذر من حساب المستخدم العادي، وهذا يسمح للمستخدم العادي بتشغيل الأوامر بصلاحيات إدارية بوضع الكلمة sudo قبل كل أمر ينفذه. لإضافة هذه الامتيازات إلى مستخدمنا الجديد، فعلينا إضافة المستخدم الجديد إلى مجموعة wheel؛ فالسلوك المبدئي لنظام CentOS 7 يسمح للمستخدمين الذين ينتمون إلى المجموعة wheel بالحصول على امتيازات الجذر باستعمال الأمر sudo. نفِّذ الأمر الآتي بعد تسجيل دخولك بحساب الجذر لإضافة المستخدم الجديد إلى مجموعة wheel (لا تنسَ أن تضع اسم المستخدم الذي أنشَأته بدلًا من demo): gpasswd -a demo wheel يمكن للمستخدم الآن أن ينفِّذ الأوامر بامتيازات الجذر؛ ولمزيدٍ من المعلومات عن هذا الموضوع، أنصحك بقراءة درس How To Edit the Sudoers File on Ubuntu and CentOS. الخطوة الرابعة: ضبط الاستيثاق عبر مفتاح عمومي (خطوة مستحسنة) الخطوة التالية في طريق زيادة حماية خادومك هي ضبط الاستيثاق عبر مفتاح عمومي (public key authentication) للمستخدم الجديد الذي أنشَأته؛ مما يزيد من حماية خادومك بطلب مفتاح SSH خاص لإتمام تسجيل الدخول. توليد زوج من المفاتيح إذا لم يكن لديك زوجٌ من مفاتيح SSH، والتي تتألف من مفتاح عمومي ومفتاح خاص، فعليك توليدها؛ أما إذا كان زوج المفاتيح متوافرًا عندك فاذهب إلى خطوة «نسخ المفتاح العمومي» مباشرةً. نفِّذ الأمر الآتي في طرفية الجهاز المحلي لتوليد زوج جديد من المفاتيح: ssh-keygen ولنفترض جدلًا أنَّ اسم المستخدم المحلي هو localuser، فستشاهد ناتجًا شبيهًا بالناتج الآتي: Generating public/private rsa key pair. Enter file in which to save the key (/Users/localuser/.ssh/id_rsa): اضغط على زر Enter لقبول اسم الملف ومساره، أو أدخِل اسمًا جديدًا له. سيُطلَب منك الآن إدخال عبارة مرور (passphrase) لتأمين المفتاح، يمكنك أن تدخِل ما تشاء في هذا الحقل أو أن تتركه فارغًا. ملاحظة: إذا تركتَ حقل عبارة المرور فارغًا فستتمكن من استخدام المفتاح الخاص للاستيثاق دون الحاجة إلى إدخال عبارة المرور؛ أما إذا أدخلت عبارة المرور، فعليك توفير المفتاح الخاص إضافةً إلى عبارة المرور عند تسجيل الدخول. وصحيحٌ أنَّ إنشاء مفاتيح محمية بعبارة مرور أكثر أمانًا، لكن هنالك مواطن استخدام لكلا الطريقتين اللتين تصنفان أنهما أكثر أمانًا من الاستيثاق التقليدي عبر كلمات المرور (passwords). سيولّد مفتاح خاص باسم id_rsa ومفتاح عام باسم id_rsa.pub في مجلد ‎.ssh الموجود في مجلد المنزل التابع للمستخدم المحلي localuser؛ تذكر أنَّ المفتاح الخاص يجب ألّا يُشارك مع أي شخص لا يحق له الوصول إلى خواديمك. نسخ المفتاح العمومي بعد توليد زوج مفاتيح SSH، عليك نسخ المفتاح العمومي إلى خادومك الجديد، وسنشرح طريقتين سهلتين لفعل ذلك. الطريقة الأولى: استخدام سكربت ssh-copy-id إذا كان السكربت ssh-copy-id مثبتًا على جهازك المحلي، فيمكنك استخدامه لتثبيت المفتاح العمومي لأي مستخدم تملك معلومات الوصول الخاصة به. شغِّل سكربت ssh-copy-id بتحديد اسم المستخدم وعنوان IP للخادوم الذي تريد تثبيت المفتاح عليه، كما في الأمر الآتي: ssh-copy-id demo@SERVER_IP_ADDRESS بعد كتابة كلمة المرور عند طلبها، فيجب أن يُضاف المفتاح العمومي الخاص بك إلى ملف ‎.ssh/authorized_keys في الخادوم البعيد؛ ويمكن الآن استخدام المفتاح الخاص لتسجيل الدخول إليه. الطريقة الثانية: تثبيت المفتاح يدويًا بفرض أنَّك ولدت زوجًا من مفاتيح SSH باستعمال الخطوة السابقة، يمكنك تنفيذ الأمر الآتي في طرفية جهازك المحلي لطباعة محتويات المفتاح العمومي (id_rsa.pub): cat ~/.ssh/id_rsa.pub يجب أن تظهر أمامك محتويات المفتاح العمومي، والذي سيبدو كما يلي: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBGTO0tsVejssuaYR5R3Y/i73SppJAhme1dH7W2c47d4gOqB4izP0+fRLfvbz/tnXFz4iOP/H6eCV05hqUhF+KYRxt9Y8tVMrpDZR2l75o6+xSbUOMu6xN+uVF0T9XzKcxmzTmnV7Na5up3QM3DoSRYX/EP3utr2+zAqpJIfKPLdA74w7g56oYWI9blpnpzxkEd3edVJOivUkpZ4JoenWManvIaSdMTJXMy3MtlQhva+j9CgguyVbUkdzK9KKEuah+pFZvaugtebsU+bllPTB0nlXGIJk98Ie9ZtxuY3nCKneB+KjKiXrAvXUPCI9mWkYS/1rggpFmu3HbXBnWSUdf localuser@machine.local حدِّد المفتاح العمومي وانسخه إلى الحافظة. يجب أن نضيف المفتاح العمومي إلى ملفٍ خاص في مجلد المنزل للمستخدم الذي أنشأناه على الخادوم البعيد، وذلك لتمكين الاستيثاق عبره في SSH. نُفِّذ الأمر الآتي بعد تسجيلك بحساب الجذر root إلى الخادوم للتبديل إلى حساب المستخدم الجديد الذي أنشأتَه (تذكر أن تضع الاسم الذي اخترتَه بدلًا من demo): su - demo ستنتقل الآن إلى مجلد المنزل الخاص بالمستخدم الجديد. أنشِئ مجلدًا جديدًا باسم ‎.ssh وامنع بقية المستخدمين من الوصول إليه، وذلك بتنفيذ الأمرين الآتيين: mkdir .ssh chmod 700 .ssh أنشِئ ملفًا جديدًا في مجلد ‎.ssh باسم authorized_keys باستعمال محررك النصي المفضل، سنستخدم هنا محرر vi لتعديل الملف : vi .ssh/authorized_keys بدِّل إلى نمط الإدخال بالضغط على i ثم ألصق المفتاح العمومي (الذي يجب أن يكون موجودًا في الحافظة)، ثم اضغط على زر ESC للخروج من نمط الإدخال. أدخِل ‎:x ثم اضغط على Enter لحفظ الملف والخروج من المحرر النصي. ثم امنع الوصول إلى ملف authorized_keys لجميع المستخدمين ما عدا المستخدم المالك باستعمال هذا الأمر: chmod 600 .ssh/authorized_keys ثم نفِّذ هذا الأمر مرةً واحدةً للعودة إلى حساب المستخدم الجذر: exit يمكنك الآن تسجيل الدخول بحساب المستخدم الجديد عبر SSH باستعمال المفتاح الخاص للاستيثاق. لمزيدٍ من المعلومات حول طريقة عمل الاستيثاق عبر المفاتيح، فأنصحك بقراءة مقالة العمل مع خواديم SSH: العملاء والمفاتيح. الخطوة الخامسة: ضبط خدمة SSH بعد تهيئتنا لحساب المستخدم الجديد، فيمكننا الآن تأمين الخادوم قليلًا بتعديل ضبط خدمة SSH (وهي الخدمة التي تسمح لنا بتسجيل الدخول عن بعد) لمنع الوصول عبر SSH إلى حساب الجذر root. ابدأ بفتح ملف الضبط بمحررك النصي المفضل باستعمال حساب الجذر root: vi /etc/ssh/sshd_config يمكننا هنا تعطيل تسجيل الدخول بحساب الجذر إلى SSH، وهذا أكثر أمانًا، وتذكر أننا نستطيع الوصول إلى خادومنا عبر حساب المستخدم العادي ثم الحصول على امتيازات الجذر عند اللزوم. لتعطيل تسجيل الدخول لحساب الجذر عن بعد، عليك العثور على سطرٍ شبيهٍ بالسطر الآتي: #PermitRootLogin yes تلميح: للبحث عن السطر السابق في محرر vi، يمكنك أن تكتب ‎/PermitRoot ثم تضغط على Enter، مما سيحرك المؤشر إلى الحرف P في السطر السابق. احذف رمز التعليق من السطر السابق بحذف محرف # (اضغط على Shift-x). ثم انقل المؤشر إلى الكلمة yes بالضغط على c. استبدل كلمة yes بالضغط على cw ثم اكتب الكلمة no ثم اضغط على زر Escape بعد أن تنتهي من التعديلات؛ ويجب أن يصبح السطر كما يلي: PermitRootLogin no أدخِل ‎:x ثم Enter لحفظ الملف والخروج من المحرر النصي. إعادة تحميل خدمة SSH بعد أن أجرينا تعديلاتنا، سنحتاج إلى إعادة تشغيل خدمة SSH لكي تستعمل الضبط المُعدَّل. اكتب السطر الآتي لإعادة تحميل SSH: systemctl reload sshd قبل أن نُسجِّل خروجنا من الخادوم، علينا أن نختبر الضبط الجديد، فلا نريد أن نقطع الاتصال قبل أن نتأكد من إمكانية إنشاء اتصالات جديدة بنجاح. افتح نافذة طرفية جديدة لإنشاء اتصال جديد إلى الخادوم، لكن هذه المرة سنستخدم حساب المستخدم الجديد للاتصال بدلًا من حساب الجذر. سنستخدم الأمر الآتي للاتصال إلى الخادوم، تذكر أن تضع المعلومات الخاصة بمستخدمك بما يناسب الأمر الآتي: ssh demo@SERVER_IP_ADDRESS ملاحظة: إذا كنتَ تستخدم برمجية PuTTY للاتصال إلى خواديمك، فاحرص على تحديث رقم المنفذ ليُطابِق إعدادات النظام الحالي. تذكر أنَّ تضع الأمر sudo قبل الأوامر التي تريد تنفيذها بامتيازات الجذر كما يلي: sudo command_to_run إذا جرى كل شيءٍ على ما يرام، فاخرج من كلا الجلستين بكتابة: exit ما هي الخطوات القادمة؟ أنشأنا في هذا الدرس أساسًا صلبًا لخادومك، ويمكنك الآن تثبيت أي برمجيات تحتاج لها عليه. لمزيدٍ من المعلومات حول الخواديم عمومًا، فتصفح قسم DevOps في أكاديمية حسوب ترجمة –وبتصرف– للمقال Initial Server Setup with CentOS 7 لصاحبه Mitchell Anicas
×
×
  • أضف...