المحتوى عن 'mysql'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • مقالات عامة
  • التجارة الإلكترونية

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML5
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • برمجة أندرويد
  • لغة R
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات عامّة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • مقالات عامّة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 23 نتائج

  1. Lighttpd هو خادوم ويب خفيف مفتوح المصدر، وهو الأمثل للبيئات عالية السرعة مع الحفاظ على استخدام أقل للموارد. وهو بديل ممتاز لخوادم الويب شائعة الاستخدام Nginx و Apache. في هذا المقال سيتم تثبيت وإعداد Lighttpd على خادوم يعمل بنظام FreeBSD 11.0. يمكنك أيضا إضافة MySQL و PHP إلى خادوم الويب Lighttpd الجديد الخاص بك حتى تتمكن من تشغيل خدمات الويب فضلا عن محتويات ثابتة. المتطلبات الأساسية لإكمال هذا البرنامج التعليمي ستحتاج إلى: - خادوم بنظام تشغيل FreeBSD 11.0. - حساب مستخدم تم إعداده لتشغيل الأوامر مع sudo . إن حساب freebsd الافتراضي الذي يأتي مع Digital Ocean FreeBSD Droplet كاف لهذا البرنامج التعليمي. لمعرفة المزيد حول إعداد FreeBSD اقرأ سلسلة المقالات حول FreeBSD. الخطوة 1 - تثبيت Lighttpd هناك عدة خيارات لتثبيت Lighttpd، ولكن في هذا الدرس سوف نستخدم حزم التثبيت. هذه الطريقة أسرع من التثبيت من المصدر أو عبر المنافذ (Ports)، والبرمجيات المثبتة مع هذه الطريقة أسهل تحديثًا. لتثبيت Lighttpd مع الحزمة الخاصة به، أولًا حدّث معلومات المستودع للتأكد من أن لديك أحدث قائمة من الحزم المتاحة: sudo pkg update بعد ذلك حمّل وثبت الحزمة lighttpd: sudo pkg install lighttpd أكّد التثبيت عن طريق كتابة y . سيتم تثبيت Lighttpd. باستخدام هذا الإعداد الافتراضي سيظهر لك هذا الخطأ عند بدء تشغيل الخادوم: (network.c.260) warning: please use server.use-ipv6 only for hostnames, not without server.bind / empty address; your config will break if the kernel default for IPV6_V6ONLY changes وذلك لأن إعدادات Lighttpd الافتراضية لم يتم تهيئتها لدعم IPv6. لتجنب المفاجآت في وقت لاحق حرر ملف إعدادات Lighttpd ثم عطل دعم IPv6، لأنك لن تحتاج إليها لإكمال هذا الدرس. يمكنك تمكينه في المستقبل إذا قررت استخدامه: sudo ee /usr/local/etc/lighttpd/lighttpd.conf ابحث عن هذا الجزء: ... ## ## Use IPv6? ## server.use-ipv6 = "enable" ... وغير enable إلى disable ... ... server.use-ipv6 = "disable" ... بعد ذلك حدد موقع هذا السطر في نهاية ملف الإعداد: ... ... $SERVER["socket"] == "0.0.0.0:80" { } ألغه بإضافة الرمز # في أوله، لأنه لا لزوم له إذ كنا لا نستخدم IPv6: #$SERVER["socket"] == "0.0.0.0:80" { } ثم احفظ الملف وأغلق المحرر. بعد هذا سوف نقوم بإعداد MySQL الخطوة 2 - تركيب وإعداد MySQL MySQL هو نظام إدارة قواعد بيانات من شأنها أن تسمح بإنشاء قواعد بيانات لتطبيقات PHP التي تخطط لاستضافتها على خادوم الويب الخاص بك Lighttpd. سوف تقوم بتثبيت MySQL عبر الحزم، تماما كما فعلت مع Lighttpd. ثم عليك إعداد كلمة مرور للمستخدم الجذر MySQL وتعطيل بعض خيارات الاختبار الأخرى. وهذا يضمن أنه سيكون لديك إعداد آمن لــ MySQL. بما أنك قمت بتحديث معلومات مستودع pkg في الخطوة 1، يمكنك الآن تحميل وتثبيت حزمة خادوم MySQL بسرعة: sudo pkg install mysql57-server أكد التثبيت عن طريق الضغط على: y. بعد اكتمال التثبيت، مكّن MySQL لكي يبدأ عند تشغيل النظام: sudo sysrc mysql_enable=yes ثم شغل خدمة mysql-server : sudo service mysql-server start بعد بدء تشغيل الخدمة أمّن تثبيت MySQL باستخدام السكريبت mysql_secure_installation . سيؤدي هذا إلى إزالة بعض الإعدادات الافتراضية الخطرة وإغلاق الوصول إلى نظام قاعدة البيانات قليلا. شغل السكريبت بالأمر: sudo mysql_secure_installation سترى الرسالة التالية: Securing the MySQL server deployment. Connecting to MySQL server using password in '/root/.mysql_secret' بعد ذلك سيتم سؤالك عما إذا كنت تريد إعداد إضافة للتحقق من صحة كلمات المرور: VALIDATE PASSWORD PLUGIN can be used to test passwords and improve security. It checks the strength of password and allows the users to set only those passwords which are secure enough. Would you like to setup VALIDATE PASSWORD plugin? تحذير: تمكين هذه الميزة لهو شيء من الحكمة. إذا تم التمكين فسيتم رفض كلمات المرور التي لا تتطابق مع المعايير المحددة من قبل MySQL مع إظهار رسالة خطأ. وهذا سوف يسبب مشاكل إذا كنت تستخدم كلمة مرور ضعيفة أو كان لك برنامج يقوم تلقائيا بإعداد بيانات اعتماد مستخدم MySQL. لذلك يعد من الآمن أن تترك التحقق معطلًا، ولكن يجب عليك دائمًا استخدام كلمات مرور قوية وفريدة من نوعها لبيانات اعتماد قاعدة البيانات. أجب بنعم أو أيّ شيء آخر للمتابعة دون تمكين. إذا اخترت تمكين هذه الميزة فسيطلب منك تحديد مستوى التحقق من صحة كلمة المرور. ضع في اعتبارك أنه إذا قمت بإدخال 2 –وهو أقوى مستوى- فسوف تتلقى أخطاء عند محاولة تعيين أي كلمة المرور لا تحتوي على أرقام وحروف كبيرة وصغيرة ورموزا خاصة أو أي كلمة المرور هي موجودة في قواميس كلمات السر الشائعة. There are three levels of password validation policy: LOW Length >= 8 MEDIUM Length >= 8, numeric, mixed case, and special characters STRONG Length >= 8, numeric, mixed case, special characters and dictionary file Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: بعد ذلك سيتم سؤالك عما إذا كنت ترغب في تغيير كلمة المرور للمستخدم الجذر: Change the password for root ? ((Press y|Y for Yes, any other key for No): اضغط على Y لتغيير كلمة المرور هذه. إذا مكنت التحقق من صحة كلمة المرور فستظهر لك قوة كلمة المرور للجذر الحالية، وستسأل إذا كنت تريد تغيير كلمة المرور هذه. New password: Re-enter new password: Estimated strength of the password: 100 Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No): اضغط Y للمتابعة مع كلمة المرور الجديدة. بالنسبة لبقية الأسئلة اضغط على Y ثم على مفتاح الإدخال في كل مرة. سيؤدي ذلك إلى إزالة بعض المستخدمين المجهولين وقاعدة بيانات الاختبار وتعطيل تسجيلات الجذر عن بعد وتحميل هذه القواعد الجديدة بحيث تجعل MySQL يعمل بالتغييرات التي أجريناها فورا. ثم قم بإعادة تشغيل خدمة mysql-server للتأكد من أن المثيل (Instance) الخاص بك نفَّذ على الفور التغييرات الأمنية: sudo service mysql-server restart بعد تثبيت وتشغيل MySQL يمكننا تثبيت وإعداد PHP. الخطوة 3 - تثبيت وإعداد PHP PHP هو المكون الذي يتكفل بعرض المحتوى الديناميكي. فإنه يمكنه أن يشغل السكريبتات، والاتصال بقواعد بيانات MySQL للحصول على المعلومات، وتسليم المحتوى إلى خادوم الويب لمعالجته ثم عرضه. مرة أخرى استخدم نظام الحزم لتثبيت PHP مع إضافة PHP المسماة mysqli لكي تضيف دعما MySQL: sudo pkg install php71 php71-mysqli Lighttpd لا يحتوي على معالجة للــ PHP مثل بعض خوادم الويب الأخرى، لذلك سوف نستخدم PHP-FPM الذي سيعمل في ” إدارة عمليات FastCGI “. سنقوم بإعداد Lighttpd لاستخدام هذه الوحدة لمعالجة طلبات PHP. قبل أن نفعل ذلك نحن بحاجة إلى إعداد PHP-FPM نفسها. ابدأ بتعديل ملف إعدادات PHP-FPM: sudo ee /usr/local/etc/php-fpm.d/www.conf سنقوم بإعداد PHP-FPM لاستخدام مقبس (socket) يونكس بدلا من منفذ شبكة للاتصال. هذا أكثر أمنا لخدمات التواصل داخل خادوم واحد. ابحث عن هذا السطر في ملف التهيئة: /usr/local/etc/php-fpm.d/www.conf listen = 127.0.0.1:9000 غيّر هذا السطر لكي يستخدم مقبس php-fpm : listen = /var/run/php-fpm.sock الآن عيّن المالك والمجموعة والأذونات للمقبس الذي سيتم إنشاؤه. ابحث عن هذا الجزء من ملف الإعداد: ... ;listen.owner = www ;listen.group = www ;listen.mode = 0660 ... قم بإلغاء علامة التعليق من أول السطر (;) بحيث يبدو كالتالي: ... listen.owner = www listen.group = www listen.mode = 0660 ... احفظ الملف وأغلقه بعد الانتهاء. بعد ذلك قم بإنشاء ملف php.ini ، هذا الملف سيقوم بإعداد السلوك العام لـ PHP. هناك نوعان من نماذج الملفات: php.ini-production و php.ini-development . سيكون php.ini-production أقرب إلى ما تريده لخادومك، لذا انسخه إلى المسار : /usr/local/etc/ وهو الموضع الذي تتوقع PHP العثور عليه في إعداداتها: sudo cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini افتح الملف php.ini الجديد باستخدام محرر النصوص: sudo ee /usr/local/etc/php.ini داخل ملف الإعداد حدّد موقع الجزء الخاص بسلوك cgi.fix_pathinfo . ستراه مَلغِيّا ومعينا إلى القيمة 1 افتراضيا: ... ;cgi.fix_pathinfo=1 ... قم بإزالة الفاصلة المنقوطة لتمكين السطر وتعيين القيمة إلى 0. هذا سيمنع PHP من محاولة تنفيذ أجزاء من المسار إذا لم يتم العثور على الملف الذي تم تمريره إلى العملية. هذا يمكن أن يستخدم من قبل المهاجم لتنفيذ الشيفرات الخبيثة. ... cgi.fix_pathinfo=0 ... احفظ الملف وأغلق المحرر. ثم مكّن خدمة php-fpm لتبدأ مع بدء تشغيل النظام: sudo sysrc php_fpm_enable=yes ثم شغّل الخدمة: sudo service php-fpm start بعد ذلك لنقم بإعداد Lighttpd لمعالجة تطبيقات PHP. الخطوة 4 - إعداد Lighttpd لخدمة تطبيقات PHP في هذه الخطوة سوف نقوم بإعداد Lighttpd لاستخدام FastCGI و PHP-FPM. هذا سيمكّن الــ PHP على Lighttpd ويقدم دعما من PHP سريعا وفعّالا. أولا مكّن وحدة FastCGI. افتح ملف إعداد وحدات Lighttpd: sudo ee /usr/local/etc/lighttpd/modules.conf حدد موقع القسم التالي: ... ## ## FastCGI (mod_fastcgi) ## #include "conf.d/fastcgi.conf" ... أزل الإلغاء عن طريق إزالة الرمز # . إذا لم تجد هذا السطر، فأضفه إلى نهاية الملف، سيصبح هكذا: ... ## ## FastCGI (mod_fastcgi) ## include "conf.d/fastcgi.conf" ... احفظ الملف وأغلق المحرر. بعد ذلك قم بتحرير ملف إعداد FastCGI: sudo ee /usr/local/etc/lighttpd/conf.d/fastcgi.conf يحتوي هذا الملف على عدة أمثلة ملغاة. أضف أسطر الإعداد التالية إلى نهاية الملف الذي سيقوم بإعداد Lighttpd لمعالجة ملفات PHP مع FastCGI و PHP-FPM: .. fastcgi.server += ( ".php" => (( "socket" => "/var/run/php-fpm.sock", "broken-scriptfilename" => "enable" )) )... بعد ذلك مكّن Lighttpd لكي يشتغل مع بداية تشغيل النظام. بهذه الطريقة سوف تبدأ Lighttpd تلقائيا كلما تم إعادة تشغيل خادوم الويب: sudo sysrc lighttpd_enable=yes ثم شغّل خدمة lighttpd : sudo service lighttpd start الآن بعد أن صار PHP على استعداد للاشتغال، دعونا نتأكد من أن كل شيء يعمل. الخطوة 5 - اختبار إعداد الخادوم لاختبار Lighttpd المعدّ حديثا أنشئ أولا المجلد /usr/local/www/data، هذا المجلد هو الذي سيبحث فيه Lighttpd عن صفحات الويب. sudo ee /usr/local/www/data/info.php ثم أنشئ info.php في المجلد /usr/local/www/data/ . سيختبر هذا الملف أن PHP يعمل ويتيح لك مراجعة المعلومات حول إعداد خادوم الويب في متصفح الويب: sudo ee /usr/local/www/data/info.php أضف هذا الكود إلى الملف: <?php phpinfo(); ?> احفظ الملف وأغلق المحرر. قم بزيارة الرابط http://your_server_ip/info.php من متصفحك سوف ترى مظهر الصفحة مثل هذا: تعرض هذه الصفحة معلومات حول نظام التشغيل وخادوم الويب وكيفية معالجة خادوم الويب لملفات PHP. كما تتحقق من أن خادوم الويب الخاص بك يمكنه أن يعالج ملفات PHP بشكل صحيح. إذا لم تشاهد هذه الصفحة ، وبدلا من ذلك شاهدت ” Error 503 Service Not Available ” فتأكد من أن خدمة php-fpm اشتغلت بشكل صحيح في الخطوة السابقة. بعد التحقق من أن الأمور تعمل قم بإزالة الصفحة info.php إذ أنها تعرض معلومات حول الخادوم الخاص بك يجب أن تبقى خاصة: sudo rm /usr/local/www/data/info.php تم الآن إعداد خادوم الويب بالكامل وهو على استعداد للعمل. ما عليك الآن سوى أن تضع ملفاتك في /usr/local/www/data لكي تتم معالجتها. الخلاصة الآن بعد أن صار خادوم الويب Lighttpd في الخدمة يمكنك استضافة صفحات الويب والمستندات والملفات الأخرى عليه. لجعل خادوم الويب أكثر أمانا من خلال إضافة إعدادات SSL وغيرها من ميزات الأمان ولمزيد من المعلومات حول Lighttpd قم بزيارة منتديات Lighttpd . ترجمة -وبتصرّف- للمقال How to Install Lighttpd with MySQL and PHP on FreeBSD 11.0 لصاحبه Brian Hogan
  2. تتوسع قواعد البيانات بسرعة مع مرور الزمن، وتكاد في بعض الأحيان أن تملأ المساحة التخزينية المتاحة في نظام الملفات كلها. وقد تتعرض أيضًا إلى مشاكل في الإدخال والإخراج نتيجةً لمحاولة عدِّة خدمات الكتابة على (أو القراءة من) القسم نفسه معًا. هذا الدرس سيفيدك لو كنتَ تريد إضافة المزيد من المساحة التخزينية، أو استخدام خصائص جهاز التخزين لزيادة الأداء (ربما عبر استخدام 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
  3. يتناول هذا المقال تثبيت بيئة تطوير Ruby on Rails على الإصدار 16.04 من أوبونتو. في أغلب الأحوال ستُنفَّذ الشفرة البرمجيّة التي تكتبها على خادوم لينكس، وأوبونتو هي إحدى توزيعات لينكس الأسهل استخداما وتوجد الكثير من الموارد عنها على الشبكة. تثبيت Ruby أول ما يجب علينا فعله هو تثبيت الاعتماديات Dependencies التي يحتاجها Ruby للعمل. نبدأ أولا بتحديث فهرس الحزم ثم تثبيت الاعتماديّات: sudo apt update sudo apt install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev nodejs الخطوة الموالية هي تثبيت Ruby. توجد طرق عدّة للتثبيت، سنستخدم rbenv وهي أداة خفيفة وسريعة لإدارة إصدارات Ruby. نبدأ بتثبيت rbenv : cd git clone https://github.com/rbenv/rbenv.git ~/.rbenv echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc echo 'eval "$(rbenv init -)"' >> ~/.bashrc exec $SHELL الأداة rbenv جاهزة الآن. سنثبّت ruby-build وهي إضافة تعمل مع الأداة rbenv وتتيح تثبيت إصدارات عدّة من Ruby في مجلّدات مختلفة على نفس النظام. git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc exec $SHELL ثم نثبّت الإصدار 2.4.0 من Ruby: TMPDIR=~/tmp/ rbenv install 2.4.0 rbenv global 2.4.0 يُثبّت الأمر الأول الإصدار المطلوب ضمن مجلّد العمل حيث نُفِّذ الأمر؛ في ما يضبط الأمر الثاني إصدار Ruby المبدئي، أي الإصدار الذي سيُستخدَم عند عدم تحديد إصدار. للتأكد من تثبيت Ruby والإصدار المثبّت ننفذ الأمر: ruby -v الذي يُظهر نتيجة تشبه التالي: ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux] الخطوة الأخيرة هي تثبيت Bundler الذي يوفّر بيئة تطوير متجانسة لـ Ruby عبر تتبّع الاعتماديات وتثبيت الإصدارات المطلوبة منها بالضبط: gem install bundler وتنفيذ الأمر لأخذ التثبيت الجديد في الحسبان: rbenv rehash تثبيت Rails يتضمّن إطار العمل Rails الكثير من الاعتماديات، لذا سنحتاج لبيئة تنفيذ JavaScript مثل NodeJS التي ستمكّننا من استخدام مكتبات تتيح إمكانيّة جمع وضغط ملفات جافاسكريبت من أجل الحصول على بيئة تطوير أسرع. نثبّت NodeJS من المستودع الرسمي على النحو التالي: curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash - sudo apt install -y nodejs ثم نثبّت Rails: gem install rails -v 5.0.1 ثم ننفذ الأمر التالي ليمكننا استخدام Rails: rbenv rehash Rails مثبّت الآن، يمكننا التأكّد من ذلك بتنفيذ الأمر التالي الذي يُظهر رقم الإصدار المثبت: rails -v إعداد قاعدة بيانات MySQL يأتي Rails مبدئيا بقاعدة بيانات sqlite3؛ إلا أن هذا النوع من قواعد البيانات لا يناسب تطبيقات كثيرة. يمكن في هذه الحالة إعداد Rails للعمل مع قاعدة بيانات MySQL (أو PostgreSQL). نثبّت خادوم وعميل MySQL من المستودعات الرسمية لأوبونتو: sudo apt install mysql-server mysql-client libmysqlclient-dev سيُطلَب منك خلال التثبيت إنشاءُ كلمة سر خاصة بالحساب الإداري root (انتبِه إلى أنّه حساب خاص بنظام MySQL لإدارة قواعد البيانات، وليس لنظام التشغيل أوبونتو). تتضمّن الحزمة libmysqlclient-dev الملفات الضرورية لتثبيت الاعتماديّات التي يحتاجها Rails للاتصال بقاعدة بيانات MySQL. ننفّذ بعد تثبيت MySQL الأمريْن التاليّيْن لتحضير قاعدة البيانات لبيئة الإنتاج (يمكنك تجاوز هذه الخطوة إن كنت تثبّت Rails على حاسوب شخصي): sudo mysql_install_db sudo mysql_secure_installation سيُطلب منك النّظام إدخال كلمة سرّ الحساب الجذر في MySQL؛ ثمّ يسألك ما إذا كنتَ تُريد تغييرها. أدخل حرف n (دلالةً على “no” أي “لا”) إن لم تكن ترغبُ في ذلك. بالنسبة لبقية الأسئلة يمكنك قبول القيم المبدئية بالنقر على زرّ Enter. أول تطبيق Rails حان الوقت الآن لتشغيل أول تطبيق Ruby on Rails. ننشئ تطبيقا باسم myapp يستخدم قاعدة البيانات MySQL: rails new myapp -d mysql انتظر اكتمال إنشاء التطبيق الذي قد يستغرق وقتا، ثم انتقل إلى مجلد التطبيق: cd myapp عدّل الملف config/database.yml بإضافة كلمة سر الحساب الإداري لقاعدة البيانات (أعددناها أثناء تثبيت MySQL، يمكنك تركها فارغة إن لم تكن أعددتَ كلمة سر لـ MySQL): default: &default adapter: mysql2 encoding: utf8 pool: 5 username: root password: socket: /var/run/mysqld/mysqld.sock اكتب كلمة السر أمام التعليمة password ضمن المقطع السابق الموجود أعلى الملف بعد التعليقات الأولى (تبدأ التعليقات بالعلامة #)؛ ثم نفّذ الأمر التالي لإنشاء قاعدة البيانات التي سيعمل عليها التطبيق: rake db:create النتيجة: Created database 'myapp_development' Created database 'myapp_test' إن واجهك خطأ Access denied for user 'root'@'localhost' (using password: NO) فهذا يعني أنك لم تكتب كلمة السر بطريقة صحيحة. نشغل خادوم التطوير: rails server يمكنك بعد تشغيل خادوم التطوير إدخال العنوان http://localhost:3000/ في المتصفح لمعاينة صفحة التطبيق المبدئي في Rails. إعداد Git هذه الخطوة اختيارية ولكنه تفيدك إن كنت تخطّط لاستعمال Git لإدارة إصدارات المشروع وربطه بحسابك على Github. أبدل YOUR NAME وYOUR@EMAIL.com في الأوامر أدناه على التوالي باسمك والبريد الذي استخدمته للتسجيل على Github. git config --global color.ui true git config --global user.name "YOUR NAME" git config --global user.email "YOUR@EMAIL.com" ssh-keygen -t rsa -b 4096 -C "YOUR@EMAIL.com" يُولّد الأمر الأخير في الأوامر أعلاه زوج مفاتيح SSH سنستخدمها في ما بعد للاتصال بحسابنا على Github. يضع الأمر ssh-keygen مبدئيا زوج المفاتيح على المسار ssh./~. نأخذ المفتاح العمومي الذي يوجد بملف المفتاح ذي الامتداد pub، ويُسمّى مبدئيا id_rsa.pub وننسخه ضمن مفاتيح SSH على حسابنا في Github الموجودة هنا. انقر على الزّر New SSH Key، أعط للمفتاح اسما تختاره ثم ألصق في الحقل الثاني محتوى الملف ssh/id_rsa.pub/~ الذي يمكن الحصول عليه بالأمر التالي، ثم انقر على زرّ Add SSH Key لاعتماد المفتاح: cat ~/.ssh/id_rsa.pub يمكنك التأكد من نجاح العملية بتنفيذ الأمر التالي: ssh -T git@github.com يجب أن تظهر لك رسالة تشبه التالي (يُذكَر فيها اسم حسابك على Github): Hi Zeine77! You've successfully authenticated, but GitHub does not provide shell access. ترجمة - بتصرّف - للمقال Setup Ruby On Rails on Ubuntu 16.04 Xenial Xerus.
  4. سنشرح في هذا الدرس كيفية إنشاء قاعدة بيانات، وجداول (مع تبيان أنواع بيانات حقولها)، وسنفصّل طريقة إجراء عمليات على البيانات على خادوم MySQL أو MariaDB. سنفترض أنَّك قد ثبّتَ الحزم اللازمة على نظامك، ونفّذتَ الأمر mysql_secure_installation لتحسين حماية خادوم قواعد البيانات. وإلا فانظر إلى درسنا عن كيفية تثبيت خادوم MySQL/MariaDB . للاختصار، سنشير إلى قواعد البيانات باسم «MariaDB» في هذا الدرس، لكن نفس الاصطلاحات والتعليمات المشروحة هنا ستنطبق تمامًا على MySQL. إنشاء قواعد البيانات والجداول والمستخدمين كما تعلم، يمكن تعريف قواعد البيانات بأبسط الكلمات على أنها مجموعة منظمة من المعلومات؛ وندعو قواعد MariaDB تحديدًا أنَّها نظام إدارة قواعد بيانات علائقية (relational database management system اختصارًا RDBMS) التي تستخدم لغة الاستعلام البنيوية (Structure Query Language أي SQL) لإجراء العمليات على قواعد البيانات. أبقِ في بالك أنَّ MariaDB تستعمل الاصطلاحين «database» (قاعدة بيانات) و «schema» (مخطط) لنفس المعنى تمامًا. نستعمل الجداول (tables) لتخزين المعلومات الدائمة في قواعد البيانات التي تُخزَّن فيها «سجلاتٌ» (rows) من البيانات. وعادةً يرتبط جدولان أو أكثر مع بعضها بطريقةٍ ما. وهذا هو جزءٌ مهمٌ من عملية التنظيم التي تُميّز قواعد البيانات العلائقية. إنشاء قاعدة بيانات جديدة علينا أن ندخل أولًا إلى مِحَث (prompt) قواعد بيانات MariaDB بإدخال الأمر الآتي، وذلك لإنشاء قاعدة بيانات جديدة (سيُطلَب منك إدخال كلمة مرور المستخدم root لقواعد البيانات): [root@TecMint ~]# mysql -u root -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 2 Server version: 10.1.14-MariaDB MariaDB Server Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> CREATE DATABASE BookstoreDB; Query OK, 1 row affected (0.00 sec) MariaDB [(none)]> بعد إنشاء قاعدة البيانات، فسنحتاج إلى إنشاء جدولين على الأقل فيها، لكن دعنا أولًا نلقي نظرةً على مفهوم أنواع البيانات في الجداول. لمحة عن أنواع البيانات في قواعد MariaDB كما ذكرنا سابقًا، الجداول هي الكائن الرئيسية في قواعد البيانات والتي ستُخزَّن فيها المعلومات الدائمة. يتألف كل جدول من حقلين أو أكثر (تُعرَف أيضًا بالأعمدة [columns]) لها نوع بيانات معيّن (أي نوع المعلومات التي ستُخزَّن فيها) التي يستطيع كل حقلٍ (أو عمودٍ) تخزينها. سأستعرض أشهر أنواع البيانات في MariaDB (يمكنك الرجوع إلى الدليل الرسمي لتحصل على قائمةٍ كاملةٍ): أنواع البيانات الرقمية BOOLEAN: قيمٌ منطقيةٌ، وتعتبَر فيها القيم المساوية للصفر (0) على أنَّها false، وبقية القيم true. TINYINT: إذا استخدمَت مع الكلمة المحجوزة SIGNED فستُمثِّل المجال من ‎-128 إلى 127، بينما مجالها إن كانت UNSIGNED فهو من 0 إلى 255. SMALLINT: إذا استخدمت مع SIGNED فهي تمثِّل المجال من ‎-32768 إلى 32767. بينما مجال UNSIGNED فهو من 0 إلى 65535. INT: إذا استخدمت مع SIGNED فهي تغطي المجال من 0 إلى 4294967295، ومن ‎‎-2147483648 إلى 2147483647 فيما عدا ذلك. ملاحظة: في أنواع البيانات TINYINT و SMAILLINT و INT، القيمة الافتراضية المرتبطة معها هي SIGNED. DOUBLE(M, D): يُمثِّل هذا النوع الأعداد العشرية ذات الفاصلة، حيث M هو العدد الكلي للأرقام و D هو عدد الأرقام بعد الفاصلة العشرية. إذا اُستعمِلَت الكلمة UNSIGND فلن يُسمَح بإدراج قيم سالبة في هذا الحقل. أنواع البيانات النصية VARCHAR(M): يُمثِّل هذا النوع السلاسل النصية ذات الطول المتغير حيث M هو عدد الأحرف المسموح الأقصى للسلسلة النصية مقدرًا بالبايت (يمكن أن يبلغ نظريًا 65535 بايت). في حال كانت السلاسل النصية المُدخَلة بالإنكليزية، فسيأخذ كل محرف بايتًا واحدًا، لكن هنالك استثناءٌ لبعض المحارف التي قد تأخذ 3 بايت لكي تُمثَّل، فمثلًا، الحرف الإسباني ñ لا يأخذ بايتًا واحدًا وإنما ثلاثة بايتات. TEXT(M): يُمثِّل هذا النوع الأعمدة ذات الطول الأقصى المقدّر 65535 محرفًا، لكن كما في نوع البيانات VARCHAR(M) سينقص طول التخزين الأقصى إذا استعملنا محارف تأخذ أكثر من بايت لتُمثَّل في الحاسوب. إذا حُدِّدَ M فسيُنشأ العمود بأصغر نوع بيانات التي يستطيع تخزين هذا العدد من المحارف. MEDIUMTEXT(M) و LONGTEXT(M) شبيهة بنوع البيانات TEXT(M) لكن الطول الأقصى المسموح هو 16777215 و 4294967295 محرفًا على التوالي وبالترتيب. الوقت والتاريخ DATE: تمثيل التاريخ بصيغة YYYY-MM-DD. TIME: تمثيل الوقت بصيغة HH:MM:SS.sss (أي الساعة والدقيقة والثانية والملي ثانية). DATETIME: جمعٌ بين DATE و TIME بالصيغة YYYY-MM-DD HH:MM:SS. TIMESTAMP: تُستعمَل بصمة الوقت لتعريف اللحظة التي أضيف أو حُدِّث فيها سجلٌ (row) ما. بعد اطلاعك على أنواع البيانات السابقة، فيمكن أن تستطيع الآن تحديد ما هو نوع البيانات الذي ستحتاج له لإسناده إلى عمودٍ معيّن في الجدول. على سبيل المثال، يمكن أن يتسع اسم المستخدم بسهولة في عمودٍ بنوع البيانات VARCHAR(50)، لكن محتوى تدوينة سيحتاج إلى نوع TEXT (اختر قيمة M بما يلبي احتياجاتك). إنشاء جداول فيها مفاتيح أساسية وأجنبية قبل أن نشرع في إنشاء جداول، فمن الضروري استيعاب مفهومين أساسيين عن قواعد البيانات العلائقية: المفتاح الأساسي (primary key) والمفتاح الأجنبي (foreign key). يحتوي المفتاح الأساسي قيمةً تُمثِّلُ مُعرِّفًا فريدًا لكل سطرٍ أو سجلٍ (row أو record) في الجدول، لكن في المقابل يستعمل المفتاح الأجنبي للربط بين البيانات في جدولين، وللتحكم في البيانات التي يمكن تخزينها في الجدول الذي يحتوي على المفتاح الأجنبي. يُعتَبَر المفتاحان الأساسي والأجنبي قيمًا رقميةً (INT) عادةً. لشرح هذا المفهوم عمليًا، فلنستخدم قاعدة بيانات BookstoreDB ونُنشِئ جدولين باسم AuthorsTBL و BooksTBL. تُشير NOT NULL إلى أنَّ الحقل المرتبط بها يتطلب قيمةً تختلف عن NULL. يمكن أيضًا استعمال AUTO_INCREMENT لزيادة قيمة عمود المفتاح الرئيسي الرقمي بمقدار 1 عند إضافة سجل جديد إلى الجدول. MariaDB [(none)]> USE BookstoreDB; Database changed MariaDB [BookstoreDB]> CREATE TABLE AuthorsTBL ( -> AuthorID INT NOT NULL AUTO_INCREMENT, -> AuthorName VARCHAR(100), -> PRIMARY KEY(AuthorID) -> ); Query OK, 0 rows affected (0.05 sec) MariaDB [BookstoreDB]> CREATE TABLE BooksTBL ( -> BookID INT NOT NULL AUTO_INCREMENT, -> BookName VARCHAR(100) NOT NULL, -> AuthorID INT NOT NULL, -> BookPrice DECIMAL(6,2) NOT NULL, -> BookLastUpdated TIMESTAMP, -> BookIsAvailable BOOLEAN, -> PRIMARY KEY(BookID), -> FOREIGN KEY (AuthorID) REFERENCES AuthorsTBL(AuthorID) -> ); Query OK, 0 rows affected (0.05 sec) MariaDB [BookstoreDB]> يمكننا الآن المتابعة وإضافة السجلات إلى جدولَي AuthorsTBL و BooksTBL. تحديد السجلات وإضافتها وتحديثها وحذفها علينا أولًا ملء الجدول AuthorsTBL، لكن لماذا؟ لأننا سنحتاج إلى وجود قيم في العمود AuthorID قبل إضافة سجلات إلى جدول BooksTBL. نفِّذ الأمر الآتي من مِحَث MariaDB: MariaDB [BookstoreDB]> INSERT INTO AuthorsTBL (AuthorName) VALUES ('Agatha Christie'), ('Stephen King'), ('Paulo Coelho'); بعدئذٍ سنُحدِّد جميع السجلات من جدول AuthorsTBL. تذكّر أننا نحتاج إلى AuthorID لكل سجل لإنشاء استعلام INSERT في جدول BooksTBL. إذا أردتَ الحصول على سجلٍ وحيدٍ فقط، فاستعمل عبارة WHERE لكتابة شرط الذي يجب أن تُحقِّقه السجلات المُعادة. على سبيل المثال: MariaDB [BookstoreDB]> SELECT * FROM AuthorsTBL WHERE AuthorName='Agatha Christie'; يمكنك عوضًا عن ذلك أن تحصل على جميع السجلات معًا: MariaDB [BookstoreDB]> SELECT * FROM AuthorsTBL; ناتج تنفيذ الطلبيتين السابقتين: MariaDB [BookstoreDB]> SELECT * FROM AuthorsTBL WHERE AuthorName='Agatha Christie'; +----------+-----------------+ | AuthorID | AuthorName | +----------+-----------------+ | 1 | Agatha Christie | +----------+-----------------+ 1 row in set (0.00 sec) MariaDB [BookstoreDB]> SELECT * FROM AuthorsTBL; +----------+-----------------+ | AuthorID | AuthorName | +----------+-----------------+ | 1 | Agatha Christie | | 2 | Stephen King | | 3 | Paulo Coelho | +----------+-----------------+ 3 rows in set (0.00 sec) MariaDB [BookstoreDB]> لنُنشِئ الآن استعلام INSERT لجدول BooksTBL، وذلك عبر استخدام حقل AuthorID المناسب لمُطابقة مؤلف كل كتاب. القيمة 1 في حقل BookIsAvaiable تعني توافر الكتاب، بينما 0 تعني عكس ذلك: MariaDB [BookstoreDB]> INSERT INTO BooksTBL (BookName, AuthorID, BookPrice, BookIsAvailable) -> VALUES ('And Then There Were None', 1, 14.95, 1), -> ('The Man in the Brown Suit', 1, 23.99, 1), -> ('The Stand', 2, 35.99, 1), -> ('Pet Sematary', 2, 17.95, 0), -> ('The Green Mile', 2, 29.99, 1), -> ('The Alchemist', 3, 25, 1), -> ('By the River Piedra I Sat Down and Wept', 3, 18.95, 0); Query OK, 7 rows affected (0.03 sec) Records: 7 Duplicates: 0 Warnings: 0 سنستخدم الآن SELECT لرؤية السجلات في جدول BooksTBL ثم سنُحدِّث عبر UPDATE سعر كتاب «The Alchemist» لمؤلفه Paulo Coelho ثم سنعرض السجلات (عبر SELECT) مرةً أخرى. لاحظ كيف يعرض الحقل BookLastUpdated قيمةً مختلفةً، وكما شرحنا سابقًا، الحقل TIMESTAMP يُخزِّن الوقت الذي أُنشِئ أو حُدِّث فيه السجل. MariaDB [BookstoreDB]> SELECT * FROM BooksTBL; +--------+-----------------------------------------+----------+-----------+---------------------+-----------------+ | BookID | BookName | AuthorID | BookPrice | BookLastUpdated | BookIsAvailable | +--------+-----------------------------------------+----------+-----------+---------------------+-----------------+ | 1 | And Then There Were None | 1 | 14.95 | 2016-10-01 23:31:41 | 1 | | 2 | The Man in the Brown Suit | 1 | 23.99 | 2016-10-01 23:31:41 | 1 | | 3 | The Stand | 2 | 35.99 | 2016-10-01 23:31:41 | 1 | | 4 | Pet Sematary | 2 | 17.95 | 2016-10-01 23:31:41 | 0 | | 5 | The Green Mile | 2 | 29.99 | 2016-10-01 23:31:41 | 1 | | 6 | The Alchemist | 3 | 25.00 | 2016-10-01 23:31:41 | 1 | | 7 | By the River Piedra I Sat Down and Wept | 3 | 18.95 | 2016-10-01 23:31:41 | 0 | +--------+-----------------------------------------+----------+-----------+---------------------+-----------------+ 7 rows in set (0.00 sec) MariaDB [BookstoreDB]> UPDATE BooksTBL SET BookPrice=22.75 WHERE BookID=6; Query OK, 1 row affected (0.04 sec) Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [BookstoreDB]> SELECT * FROM BooksTBL WHERE BookID=6; +--------+---------------+----------+-----------+---------------------+-----------------+ | BookID | BookName | AuthorID | BookPrice | BookLastUpdated | BookIsAvailable | +--------+---------------+----------+-----------+---------------------+-----------------+ | 6 | The Alchemist | 3 | 22.75 | 2016-10-01 23:35:00 | 1 | +--------+---------------+----------+-----------+---------------------+-----------------+ 1 row in set (0.00 sec) MariaDB [BookstoreDB]> لنفترض أننا نريد حذف أحد السجلات الذي لم يعد مفيدًا، فمثلًا سنحذف كتاب «The Alchemist» من جدول BooksTBL. يمكنك استخدام عبارة DELETE لفعل ذلك كما يلي: MariaDB [BookstoreDB]> DELETE FROM BooksTBL WHERE BookID=6; وكما في عبارة UPDATE، من المستحسن إجراء عملية SELECT أولًا لرؤية الحقول التي ستؤثر فيها عملية الحذف. لا تنسَ أن تُضيف عبارة WHERE وشرطًا(BookID=6) لتحديد سجل مُعيّن لحذفه. وإلا فقد تصبح جميع سجلات جدولك معرضةً للحذف. إذا أردتَ دمج حقلين (أو أكثر) معًا، فيمكنك استخدام عبارة CONCAT، فلنقل على سبيل المثال أننا نريد عرض ناتج يحتوي على عمودٍ فيه اسم الكتاب والمؤلف على الشكل الآتي «The Alchemist (Paulo Coelho)» ثم يليه عمودٌ فيه سعره. هذا سيتطلب إجراء عملية JOIN بين جدولَي AuthorsTBL و BooksTBL في الحقل المشترك بينهما (ألا وهو AuthorID): MariaDB [BookstoreDB]> SELECT CONCAT(BooksTBL.BookName, ' (', AuthorsTBL.AuthorName, ')') AS Description, BooksTBL.BookPrice FROM AuthorsTBL JOIN BooksTBL ON AuthorsTBL.AuthorID = BooksTBL.AuthorID; وكما نرى، تسمح لنا عبارة CONCAT بدمج عدِّة تعبيرات نصية المفصول بينها بفاصلة. ستلاحظ أيضًا أننا استخدمنا اسمًا بديلًا وهو Description لعرض ناتج عملية دمج الحقلين. هذا هو ناتج تنفيذ الاستعلام السابقة: MariaDB [BookstoreDB]> SELECT CONCAT(BooksTBL.BookName, ' (', AuthorsTBL.AuthorName, ')') AS Description, BooksTBL.BookPrice FROM AuthorsTBL JOIN BooksTBL ON AuthorsTBL.AuthorID = BooksTBL.AuthorID; +--------------------------------------------------------+-----------+ | Description | BookPrice | +--------------------------------------------------------+-----------+ | And Then There Were None (Agatha Christie) | 14.95 | | The Man in the Brown Suit (Agatha Christie) | 23.99 | | The Stand (Stephen King) | 35.99 | | Pet Sematary (Stephen King) | 17.95 | | The Green Mile (Stephen King) | 29.99 | | The Alchemist (Paulo Coelho) | 25.00 | | By the River Piedra I Sat Down and Wept (Paulo Coelho) | 18.95 | +--------------------------------------------------------+-----------+ 7 rows in set (0.00 sec) إنشاء مستخدم للوصول إلى قاعدة بيانات BookstoreDB لا أنصحك باستخدام المستخدم root لإجراء جميع عمليات معالجة البيانات، ولتجنب ذلك سنُنِشئ حساب مستخدم جديد (سنسميه bookstoreuser) ونُسنِد إليه جميع الامتيازات اللازمة لإدارة قاعدة البيانات BookstoreDB: MariaDB [BookstoreDB]> CREATE USER bookstoreuser@localhost IDENTIFIED BY 'tecmint'; Query OK, 0 rows affected (0.00 sec) MariaDB [BookstoreDB]> GRANT ALL PRIVILEGES ON BookstoreDB.* to bookstoreuser@localhost; Query OK, 0 rows affected (0.00 sec) MariaDB [BookstoreDB]> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) وجود حساب مستخدم منفصل ومخصص لكل قاعدة بيانات سيحمي كامل الخادوم إن حدث اختراقٌ لأحد الحسابات. نصائح إضافية في قواعد MySQL لمسح الشاشة وإظهار مِحَث MariaDB فيها فقط، فأدخِل الأمر الآتي ثم اضغط على Enter: MariaDB [BookstoreDB]> \! clear نفِّذ الأمر الآتي لرؤية بنية أحد الجداول: MariaDB [BookstoreDB]> SHOW COLUMNS IN [TABLE NAME HERE ]; لعرض الأعمدة الموجودة في جدول BooksTBL في قاعدة بياناتنا: MariaDB [BookstoreDB]> SHOW COLUMNS IN BooksTBL; +-----------------+--------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +-----------------+--------------+------+-----+-------------------+-----------------------------+ | BookID | int(11) | NO | PRI | NULL | auto_increment | | BookName | varchar(100) | NO | | NULL | | | AuthorID | int(11) | NO | MUL | NULL | | | BookPrice | decimal(6,2) | NO | | NULL | | | BookLastUpdated | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | | BookIsAvailable | tinyint(1) | YES | | NULL | | +-----------------+--------------+------+-----+-------------------+-----------------------------+ 6 rows in set (0.02 sec) تفحص سريع لبنية الجدول سيكشف أنَّ الحقل BookIsAvailable يقبل القيم NULL. ولعدم رغبتنا في ذلك، فسنُعدِّل (ALTER) الجدول كالآتي: MariaDB [BookstoreDB]> ALTER TABLE BooksTBL MODIFY BookIsAvailable BOOLEAN NOT NULL; (تستطيع الآن عرض بنية الجدول مرةً أخرى، وستجد أنَّ كلمة YES الموجودة في عمود Null أصبحت NO). أخيرًا، لعرض جميع قواعد البيانات في خادومك، تستطيع تنفيذ الأمر: MariaDB [BookstoreDB]> SHOW DATABASES; أو MariaDB [BookstoreDB]> SHOW SCHEMAS; الناتج الآتي يعرض مخرجات الأمر السابق بعد الدخول إلى مِحَث MariaDB عبر المستخدم bookstoreuser (لاحظ أنَّ هذا الحساب لا يستطيع «رؤية» أيّة قواعد بيانات ما عدا BookstoreDB و information_schema [المتوافرة لجميع المستخدمين]): [root@TecMint ~]# mysql -u bookstoreuser -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 3 Server version: 10.1.14-MariaDB MariaDB Server Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [BookstoreDB]> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | BookstoreDB | | information_schema | +--------------------+ 2 rows in set (0.00 sec) MariaDB [BookstoreDB]> SHOW SCHEMAS; +--------------------+ | Database | +--------------------+ | BookstoreDB | | information_schema | +--------------------+ 2 rows in set (0.00 sec) الخلاصة شرحنا في هذا الدرس كيفية إجراء عمليات على البيانات، إضافةً إلى إنشاء قاعدة بيانات، وجداولها، وتخصيص مستخدم لقاعدة البيانات، ثم رأينا فائدة بعض التلميحات التي تساعد في تسهيل إدارة قواعد البيانات عليك. ترجمة -وبتصرّف- للمقال Learn MySQL / MariaDB for Beginners – Part 1 لصاحبه Gabriel Cánepa.
  5. أداة mysqladmin هي أداةٌ سطريةٌ (أي تعمل من سطر الأوامر) تأتي مع خادوم MySQL ويستعملها مدراء قواعد البيانات لإجراء مهام أساسية لإدارة قواعد MySQL مثل ضبط كلمة مرور المستخدم root أو تغييرها، ومراقبة عمليات mysql وإعادة تحديث امتيازات المستخدمين والتحقق من حالة الخدمة …إلخ. سنضع في هذا الدرس بعض أوامر mysqladmin المفيدة والمُستعمَلة من مدراء النظام أو مدراء قواعد البيانات يوميًا. يجب أن يكون خادوم MySQL مثبتًا على نظامك لإجراء هذه المهام. إذا لم يكن خادوم MySQL مثبتًا على نظامك، أو كنتَ تستعمل إصدارًا قديمًا منه، فأنصحك بتثبيت أو تحديث نسختك كما ذكرنا في هذه المقالة. 1. كيفية ضبط كلمة مرور المستخدم root في MySQL؟ إذا كانت لديك نسخةٌ حديثةُ التثبيت من خادوم MySQL، فلن تحتاج إلى استخدام كلمة مرور للاتصال بها عبر المستخدم root، لكن ذلك ليس آمنًا، وأنصحك بضبط كلمة مرور له، وذلك بتنفيذ الأمر الآتي: # mysqladmin -u root password YOURNEWPASSWORD 2. كيفية تغيير كلمة مرور المستخدم root؟ إذا أردتَ تحديث أو تغيير كلمة مرور المستخدم root في قواعد بيانات MySQL، فيمكنك الاستعانة بالأمر الآتي. لنفترض مثلًا أنَّ كلمة مرورك القديمة هي 123456 وأردتَ الآن تغييرها إلى كلمةٍ أخرى ولتكن xyz123: # mysqladmin -u root -p123456 password 'xyz123' 3. كيفية التحقق إذا كان خادوم MySQL يعمل؟ استعمل الأمر الآتي لتعرف إن كان خادوم MySQL يعمل أم لا: # mysqladmin -u root -p ping Enter password: mysqld is alive 4. كيف أعرف إصدار MySQL الذي أعمل عليه؟ الأمر الآتي سيُظهِر إصدار MySQL المُثبَّت على خادومك، إضافةً إلى حالته: # mysqladmin -u root -p version Enter password: mysqladmin Ver 8.42 Distrib 5.5.28, for Linux on i686 Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Server version 5.5.28 Protocol version 10 Connection Localhost via UNIX socket UNIX socket /var/lib/mysql/mysql.sock Uptime: 7 days 14 min 45 sec Threads: 2 Questions: 36002 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 8 Queries per second avg: 0.059 5. كيف أعرف ما هي حالة خادوم MySQL الآن؟ يمكن أن يُظهِر الأمر mysqladmin حالة uptime بالإضافة إلى عدد الخيوط (threads) وإحصائيات عن الاستعلامات: # mysqladmin -u root -ptmppassword status Enter password: Uptime: 606704 Threads: 2 Questions: 36003 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 8 Queries per second avg: 0.059 6. كيفية التحقق من حالة جميع متغيرات خادوم MySQL وقيمها؟ استخدم الخيار extended-status لأمر mysqladmin لرؤية حالة جميع متغيرات خادوم MySQL والقيم المرتبطة بها. يجب أن تكون المخرجات شبيهةً بما يلي: # mysqladmin -u root -p extended-status Enter password: +------------------------------------------+-------------+ | Variable_name | Value | +------------------------------------------+-------------+ | Aborted_clients | 3 | | Aborted_connects | 3 | | Binlog_cache_disk_use | 0 | | Binlog_cache_use | 0 | | Binlog_stmt_cache_disk_use | 0 | | Binlog_stmt_cache_use | 0 | | Bytes_received | 6400357 | | Bytes_sent | 2610105 | | Com_admin_commands | 3 | | Com_assign_to_keycache | 0 | | Com_alter_db | 0 | | Com_alter_db_upgrade | 0 | | Com_alter_event | 0 | | Com_alter_function | 0 | | Com_alter_procedure | 0 | | Com_alter_server | 0 | | Com_alter_table | 0 | | Com_alter_tablespace | 0 | +------------------------------------------+-------------+ 7. كيفية معرفة قيم جميع المتغيرات المُفعّلة لخادوم MySQL؟ لرؤية جميع القيم التي تعمل حاليًا في خادوم MySQL، أدخِل الأمر الآتي: # mysqladmin -u root -p variables Enter password: +---------------------------------------------------+----------------------------------------------+ | Variable_name | Value | +---------------------------------------------------+----------------------------------------------+ | auto_increment_increment | 1 | | auto_increment_offset | 1 | | autocommit | ON | | automatic_sp_privileges | ON | | back_log | 50 | | basedir | /usr | | big_tables | OFF | | binlog_cache_size | 32768 | | binlog_direct_non_transactional_updates | OFF | | binlog_format | STATEMENT | | binlog_stmt_cache_size | 32768 | | bulk_insert_buffer_size | 8388608 | | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | | collation_connection | latin1_swedish_ci | +---------------------------------------------------+----------------------------------------------+ 8. كيفية التحقق من جميع العمليات التي يستخدمها خادوم MySQL؟ الأمر الآتي سيعرض جميع العمليات التي تستعملها استعلامات قواعد بيانات MySQL: # mysqladmin -u root -p processlist Enter password: +-------+---------+-----------------+---------+---------+------+-------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +-------+---------+-----------------+---------+---------+------+-------+------------------+ | 18001 | rsyslog | localhost:38307 | rsyslog | Sleep | 5590 | | | | 18020 | root | localhost | | Query | 0 | | show processlist | +-------+---------+-----------------+---------+---------+------+-------+------------------+ 9. كيفية إنشاء قاعدة بيانات على خادوم MySQL؟ استخدم الأمر الآتي لإنشاء قاعدة بيانات جديدة في MySQL: # mysqladmin -u root -p create databasename Enter password: للتحقق من إنشائها: # mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 18027 Server version: 5.5.28 MySQL Community Server (GPL) by Remi Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | databasename | | mysql | | test | +--------------------+ 8 rows in set (0.01 sec) mysql> 10. كيفية حذف قاعدة بيانات في خادوم MySQL؟ لحذف قاعدة بيانات في خادوم MySQL، فأدخِل الأمر الآتي. سيُطلَب منك الموافقة على ذلك بكتابة الحرف y: # mysqladmin -u root -p drop databasename Enter password: Dropping the database is potentially a very bad thing to do. Any data stored in the database will be destroyed. Do you really want to drop the 'databasename' database [y/N] y Database "databasename" dropped 11. كيفية إعادة تحميل أو إعادة تحديث الامتيازات في MySQL؟ الأمر reload سيطلب من الخادوم إعادة تحميل جداول الامتيازات، بينما الأمر refresh سيؤدي إلى إعادة قراءة جميع الجداول وإعادة فتح ملفات التسجيل (log files): # mysqladmin -u root -p reload; # mysqladmin -u root -p refresh 12. كيفية إيقاف خادوم MySQL بأمان؟ لإيقاف خادوم MySQL إيقافًا آمنًا، فاكتب الأمر الآتي: mysqladmin -u root -p shutdown Enter password: أو يمكنك استخدام الأمرين الآتيين لتشغيل أو إيقاف خادوم MySQL: # /etc/init.d/mysqld stop # /etc/init.d/mysqld start 13. بعض أوامر «التنظيف» هذه بعض أوامر التنظيف (flush) مع شرحٍ لها: flush-hosts: حذف جميع معلومات المُضيف من التخزين المؤقت. flush-tables: «تنظيف» جميع الجداول. flush-threads: تنظيف التخزين المؤقت للخيوط (threads). flush-logs: تنظيف السجلات. flush-privileges: إعادة تحميل جداول الامتيازات (مثل reload). flush-status: مسح متغيرات الحالة (status variables). # mysqladmin -u root -p flush-hosts # mysqladmin -u root -p flush-tables # mysqladmin -u root -p flush-threads # mysqladmin -u root -p flush-logs # mysqladmin -u root -p flush-privileges # mysqladmin -u root -p flush-status 14. كيفية «قتل» عمليات عملاء MySQL المتوقفة؟ يمكنك استخدام الأمر الآتي للتعرف على عمليات عملاء MySQL المتوقفة (sleeping): # mysqladmin -u root -p processlist Enter password: +----+------+-----------+----+---------+------+-------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+----+---------+------+-------+------------------+ | 5 | root | localhost | | Sleep | 14 | | | | 8 | root | localhost | | Query | 0 | | show processlist | +----+------+-----------+----+---------+------+-------+------------------+ يمكنك الآن تشغيل الأمر الآتي مع استخدام الخيار kill متبوعًا برقم العملية كما يلي: # mysqladmin -u root -p kill 5 Enter password: +----+------+-----------+----+---------+------+-------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+----+---------+------+-------+------------------+ | 12 | root | localhost | | Query | 0 | | show processlist | +----+------+-----------+----+---------+------+-------+------------------+ أما إذا أردت «قتل» (اصطلاح «قتل» [kill] في يونكس يعني إيقاف العملية قسريًا) أكثر من عملية معًا، فافصل بين أرقام العمليات بفاصلة كما في المثال الآتي: # mysqladmin -u root -p kill 5,10 15. كيفية تشغيل أكثر من أمر لأداة mysqladmin معًا؟ إذا أردت تشغيل أكثر من أمر mysqladmin معًا فيمكنك فعل ذلك بذكرها بعضها تلو بعض كالآتي: # mysqladmin -u root -p processlist status version Enter password: +----+------+-----------+----+---------+------+-------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+----+---------+------+-------+------------------+ | 8 | root | localhost | | Query | 0 | | show processlist | +----+------+-----------+----+---------+------+-------+------------------+ Uptime: 3801 Threads: 1 Questions: 15 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 8 Queries per second avg: 0.003 mysqladmin Ver 8.42 Distrib 5.5.28, for Linux on i686 Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Server version 5.5.28 Protocol version 10 Connection Localhost via UNIX socket UNIX socket /var/lib/mysql/mysql.sock Uptime: 1 hour 3 min 21 sec Threads: 1 Questions: 15 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 8 Queries per second avg: 0.003 16. كيفية الاتصال بخادوم MySQL بعيد للاتصال بخادوم MySQL بعيد فاستخدام الخيار ‎-h (أي host، ويعني المضيف) وبعده عنوان IP للخادوم البعيد: # mysqladmin -h 172.16.25.126 -u root -p 17. كيفية تنفيذ أمر على خادوم MySQL بعيد لنقل أنك تريد معرفة حالة (status) خادوم MySQL بعيد، فسيكون الأمر حينئذٍ كالآتي: # mysqladmin -h 172.16.25.126 -u root -p status 18. تشغيل وإيقاف استنساخ MySQL على خادوم ثانوي استخدم الأمرين الآتيين لتشغيل أو إيقاف استنساخ MySQL (أي MySQL replication): # mysqladmin -u root -p start-slave # mysqladmin -u root -p stop-slave 19. كيفية تخزين معلومات التنقيح في MySQL إلى السجلات معلومات التنقيح هي المعلومات التي تخبرنا ما هو استخدام الذاكرة ومعلومات متفرقة عن الاستعلامات، ويمكننا كتابتها إلى ملف سجل MySQL باستخدام الأمر الآتي: # mysqladmin -u root -p debug Enter password: 20. كيفية رؤية الخيارات المتاحة للاستخدام في mysqladmin لمعرفة المزيد من خيارات الأمر mysqladmin وطريقة استخدامه، فاطلع على المساعدة التي تظهر بكتابة الأمر الآتي، والذي سيعرض قائمة بالخيارات المتوافرة: # mysqladmin --help حاولتُ قدر المستطاع أن أُضمِّن أغلبية أوامر mysqladmin مع أمثلةٍ عنها في هذا الدرس، لكن لا مانع من محاولة استكشاف غيرها، وربما تشاركنا بها في التعليقات. ترجمة -وبتصرّف- للمقال ‎20 MySQL (Mysqladmin) Commands for Database Administration in Linux لصاحبه Ravi Saive
  6. قاعدة البيانات هي بُنيةٌ هيكليةٌ تحتوي على مجموعة من البيانات المُخزَّنة إلكترونيًا؛ وكان مفهوم قواعد البيانات معروفًا لدى أسلافنا قبل وجود الحواسيب، لكن إنشاء وصيانة تلك القواعد كان أمرًا شاقًا ومملًا. فلنقل أنَّ لدينا قاعدة بيانات فيها 100 صفحة، وأردتَ أن تبحث عن جميع الموظفين الذين يتقاضون أقل من 50 ألف دولار سنويًا، فتخيّل مدى صعوبة الأمر ومقدار الوقت الذي سيستغرقه في ذاك الحين. أما حاليًا، فأنت تصادف قواعد البيانات في كل مكان، إذ تعمل ملايين قواعد البيانات في أنحاء العالم لتخزين والحصول على أي نوع من أنواع البيانات كالبيانات العسكرية وسجلات الموظفين أو حتى مواقع الويب وتقنياتها. تُصنّف قواعد البيانات عمومًا على أنها جزءٌ من «السند الخلفي» (back-end)، وذلك لعدم ظهورها للمستخدم النهائي ولعدم تعامل المستخدم معها مباشرةً. إذ تعمل قواعد البيانات مع لغةٍ برمجيةٍ مثل PHP أو VB أو ASP.NET وتطلب تلك اللغات من قواعد البيانات إجراء عملية ما. تتوافر عدِّة خواديم قواعد بيانات وعملاءٍ لها مثل Oracle و MySQL و MySQLi و MariaDB و MongoDB …إلخ. تتشابه طريقة التعامل مع هذه البيانات، والبنية اللغوية لأوامرها شبه متماثلة، واحتراف التعامل مع إحداها يعني أنَّك ستستطيع التحكم بأريحية مع البقية، وعملية تعلم كتابة الاستعلامات (queries) هي عملية سهلة وممتعة. لنبدأ ببعض الاستعلامات البسيطة على قواعد البيانات؛ وسنستخدم قواعد MySQL التي تأتي مع أغلبية توزيعات لينُكس افتراضيًا، وتستطيع بسهولة تثبيتها من مستودعات توزيعتك إن لم تكن مثبتةً لديك. لكن ربما ينتابك فضولٌ حول معنى «استعلام» (Query)، فبأبسط الكلمات: هي شيفرةٌ بسيطةٌ (أو أمر) تُرسَل إلى قواعد البيانات للحصول على النتيجة المطلوبة. تثبيت قواعد بيانات MySQL يمكنك استخدام مديرَي الحزم yum أو apt لتثبيت قواعد بيانات MySQL: # yum install mysql mysql-client mysql-server (on Yum based Systems) # apt-get install mysql mysql-client mysql-server (on Apt based Systems) تشغيل خادوم MySQL تستطيع تشغيل خدمة MySQL كالآتي: # service mysqld start أو: # service mysql start أذكِّرك أنَّ رمز # في بداية السطر يعني أنَّ عليك تنفيذ الأمر بامتيازات الجذر. سيُطلَب منك أثناء تثبيت قاعدة بيانات MySQL إعداد كلمة مرور لحساب المدير فيها… بعدئذٍ ستتمكن من الوصول إلى مِحَث (prompt، أي المكان الذي تكتب فيه الأوامر) MySQL بتنفيذك للأمر الآتي: # mysql -u root -p ضع اسم المستخدم الذي ضبطته بدلًا من root، وأدخِل كلمة مرورك عند طلبها، فإذا كانت معلومات الدخول صحيحةً، فيمكنك أن تشاهد مِحَث MySQL مباشرةً: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 195 Server version: 5.5.31-0+wheezy1 (Debian) Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. Mysql> تستطيع الآن البدء بتنفيذ الاستعلامات وتعلم إنشاء الاستعلامات. إنشاء قاعدة بيانات سنُنشِئ الآن قاعدة بيانات باسم tecmint كالتّالي: mysql> create database tecmint ; Query OK, 1 row affected (0.02 sec) mysql> ظهر عندنا أنَّ الاستعلام السابق قد نُفِّذَ تنفيذًا سليمًا، وهذا يعني أنَّ قاعدة البيانات قد أُنشِئَت. يمكنك التحقق من وجود قاعدة البيانات الجديدة بتنفيذ الاستعلام الآتي: mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | tecmint | | test | +--------------------+ 9 rows in set (0.00 sec) mysql> لاحظ وجود قاعدة البيانات في مخرجات الاستعلام أعلاه. اختيار قاعدة البيانات علينا قبل إجراء الاستعلامات على إحدى قواعد البيانات أن نختارها، وذلك باستخدام التعليمة use كما يلي: mysql> use tecmint; Database changed mysql> إنشاء الجداول في MySQL لنقل أننا نريد إنشاء جدول باسم minttec في قاعدة البيانات وفيه ثلاثة حقول: mysql> CREATE TABLE minttec ( -> id Int(3), -> first_name Varchar (15), -> email Varchar(20) -> ); Query OK, 0 rows affected (0.08 sec) mysql> لاحظ أنَّ الاستعلام السابق قد أعاد OK مما يعني أنَّ الجدول قد أُنشِئ دون أخطاء. نفِّذ الاستعلام الآتي للتحقق من إنشاء الجدول: mysql> show tables; +-------------------+ | Tables_in_tecmint | +-------------------+ | minttec | +-------------------+ 1 row in set (0.00 sec) mysql> جيد، كل شيء يسير كما ينبغي. يمكننا أن نُطالِع الأعمدة التي أنشأتها في جدول minttec كما يلي: mysql> show columns from minttec; +------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+-------+ | id | int(3) | YES | | NULL | | | first_name | varchar(15) | YES | | NULL | | | email | varchar(20) | YES | | NULL | | +------------+-------------+------+-----+---------+-------+ 3 rows in set (0.00 sec) mysql> سأخبرك الآن عن أنواع البيانات الموجودة في الجدول السابق ومعانيها: - int: عدد صحيح. - varchar: سلسلة من المحارف التي لا يتجاوز طولها الرقم المُعرَّف. القيمة الرقمية التي تأتي بعد النوع هي «طول» الحقل الذي ستُخزَّن فيه البيانات. لنقل الآن أننا نريد إضافة عمود جديد باسم last_name بعد العمود first_name سنقوم بذلك على النّحو التّالي: mysql> ALTER TABLE minttec ADD last_name varchar (20) AFTER first_name; Query OK, 0 rows affected (0.16 sec) Records: 0 Duplicates: 0 Warnings: 0 ثم سنتحقق من أعمدة الجدول: mysql> show cسolumns from minttec; +------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+-------+ | id | int(3) | YES | | NULL | | | first_name | varchar(15) | YES | | NULL | | | last_name | varchar(20) | YES | | NULL | | | email | varchar(20) | YES | | NULL | | +------------+-------------+------+-----+---------+-------+ 4 rows in set (0.00 sec) mysql> إضافة أعمدة في MySQL سنضيف الآن عمودًا باسم country بعد العمود email كالتّالي: mysql> ALTER TABLE minttec ADD country varchar (15) AFTER email; Query OK, 0 rows affected (0.16 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> لنتحقق من إضافة العمود: mysql> show columns from minttec; +------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+-------+ | id | int(3) | YES | | NULL | | | first_name | varchar(15) | YES | | NULL | | | last_name | varchar(20) | YES | | NULL | | | email | varchar(20) | YES | | NULL | | | country | varchar(15) | YES | | NULL | | +------------+-------------+------+-----+---------+-------+ 5 rows in set (0.00 sec) mysql> إضافة قيمة إلى الحقول ماذا لو أردنا إضافة قيم إلى حقول الجدول؟ سنقوم بذلك كالتّالي: mysql> INSERT INTO minttec VALUES ('1' , 'Ravi' , 'Saive' , 'raivsaive@xyz.com' , 'India' ); Query OK, 1 row affected (0.02 sec) mysql> ماذا عن إضافة أكثر من قيمة واحدة في آنٍ واحد: mysql> INSERT INTO minttec VALUES ('2' , 'Narad' , 'Shrestha' , 'narad@xyz.com' , 'India' ), ('3' , 'user' , 'singh' , 'user@xyz.com' , 'Aus' ), ('4' , 'tecmint' , '[dot]com' , 'tecmint@gmail.com' , 'India' ); Query OK, 3 rows affected (0.05 sec) Records: 3 Duplicates: 0 Warnings: 0 سنتحقق من إدخال المعلومات السابقة في الجدول: mysql> select * from minttec; +------+------------+-----------+-------------------+---------+ | id | first_name | last_name | email | country | +------+------------+-----------+-------------------+---------+ | 1 | Ravi | Saive | raivsaive@xyz.com | India | | 2 | Narad | Shrestha | narad@xyz.com | India | | 3 | user | singh | user@xyz.com | Aus | | 4 | tecmint | [dot]com | tecmint@gmail.com | India | +------+------------+-----------+-------------------+---------+ 4 rows in set (0.00 sec) mysql> حذف قيم في حقول الجدول لنقل أنَّ المُدخَلة الثالثة في الناتج السابق لم تكن صحيحةً ونريد أن نحذفها: mysql> DELETE FROM minttec WHERE id = 3; Query OK, 1 row affected (0.02 sec) التحقق من تنفيذ الاستعلام السابق: mysql> select * from minttec; +------+------------+-----------+-------------------+---------+ | id | first_name | last_name | email | country | +------+------------+-----------+-------------------+---------+ | 1 | Ravi | Saive | raivsaive@xyz.com | India | | 2 | Narad | Shrestha | narad@xyz.com | India | | 4 | tecmint | [dot]com | tecmint@gmail.com | India | +------+------------+-----------+-------------------+---------+ 3 rows in set (0.00 sec) تحديث قيم في حقول الجدول لنفترض أننا نريد تعديل السجل ذي المُعرِّف 4 (أي id=4): mysql> UPDATE minttec SET id = 3 WHERE first_name = 'tecmint'; Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> لاحظ أنَّ الاستعلام السابق ليس مثاليًا، فستُغيّر الحقل id إلى القيمة 4 لكل سجل يكون اسمه الأول مساويًا للقيمة tecmint. من الجيد استخدام مُطابقة أكثر من عمود واحد في عبارة WHERE لتقليل نسبة حدوث خطأ، كما في الاستعلام الآتي: mysql> UPDATE minttec SET id = 6 WHERE first_name = 'tecmint'AND last_name = '[dot]com'; Query OK, 1 row affected (0.03 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> حذف أحد أعمدة الجدول لنفترض أنَّك تحتاج إلى حذف أحد أعمدة الجدول غير الضرورية، ولنقل أنَّه العمود country: mysql> ALTER TABLE minttec drop country; Query OK, 3 rows affected (0.15 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> عرض بُنية الجدول: mysql> select * from minttec; +------+------------+-----------+-------------------+ | id | first_name | last_name | email | +------+------------+-----------+-------------------+ | 1 | Ravi | Saive | raivsaive@xyz.com | | 2 | Narad | Shrestha | narad@xyz.com | | 6 | tecmint | [dot]com | tecmint@gmail.com | +------+------------+-----------+-------------------+ 3 rows in set (0.00 sec) mysql> إعادة تسمية الجداول في MySQL ربما لا تجد اسم minttec ذا معنى، وتريد تحويله مثلًا إلى tecmint_table سنقوم بتغييره كالتّالي: mysql> RENAME TABLE minttec TO tecmint_table; Query OK, 0 rows affected (0.03 sec) mysql> عرض جميع الجداول لرؤية جميع الجداول الموجودة في قاعدة البيانات الحالية: mysql> show tables; +-------------------+ | Tables_in_tecmint | +-------------------+ | tecmint_table | +-------------------+ 1 row in set (0.00 sec) mysql> لاحظ إعادة تسمية الجدول. لنأخذ الآن نسخةً احتياطيةً من قاعدة البيانات السابقة، وذلك عبر تنفيذ استعلامٍ من سطرٍ وحيد دون استخدام أيّة أدواتٍ معقدة. نفِّذ الشيفرة أدناه في سطر الأوامر وليس في مِحَث MySQL: # mysqldump -u root -p tecmint > tecmint.sql check the dumped file on your desktop which would have contents something like -- MySQL dump 10.13 Distrib 5.5.31, for debian-linux-gnu (i686) -- -- Server version 5.5.31-0+wheezy1 -- Dump completed on 2013-09-02 12:55:37 من المستحسن الإبقاء على نسخ احتياطية لقواعد بياناتك، فاستعادة قاعدة بيانات MySQL هو أمرٌ بسيطٌ ويجرى بتنفيذ أمرٍ قصيرٍ في سطر الأوامر (أكرِّر، في سطر الأوامر وليس في مِحَث MySQL). لكن ما رأيك أن نحذف قاعدة البيانات أولًا لنرى كيف ستتم عملية الاستعادة؟ حذف قاعدة بيانات mysql> drop database tecmint; Query OK, 1 row affected (0.02 sec) تحقق من وجود قاعدة بيانات باسم tecmint في خادوم قواعد البيانات عندك: mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | my_database | | mysql | | performance_schema | | phpmyadmin | | sisso | | test | +--------------------+ 7 rows in set (0.00 sec) mysql> رائع، لقد فقدنا قاعدة البيانات :-) لكن لا تقلق، فلقد أخذنا نسخةً احتياطيةً منها منذ قليل. استعادة قاعدة بيانات من نسخةٍ احتياطيةٍ منها نفِّذ الأمر الآتي لاستعادة قاعدة البيانات: # mysql -u root -p tecmint < tecmint.sql Enter password: ERROR 1049 (42000): Unknown database 'tecmint' ماذا حدث؟ لقد واجهنا رسالة خطأ، فنحن لم نُنشِئ قاعدة بيانات باسم tecmint بعد. لذا اذهب إلى مِحَث MySQL وأنشِئها: mysql> create database tecmint; Query OK, 1 row affected (0.00 sec) mysql> حان الآن الوقت لتنفيذ أمر الاستعادة في سطر الأوامر: # mysql -u root -p tecmint < tecmint.sql Enter password: لم تظهر بوجهنا أيّة رسائل خطأ مرعبة، لنتحقق الآن من وجود القاعدة في خادومنا: mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | tecmint | | test | +--------------------+ 8 rows in set (0.00 sec) ثم سنتحقق من محتويات قاعدة البيانات (أي جداولها): mysql> show tables from tecmint; +-------------------+ | Tables_in_tecmint | +-------------------+ | tecmint_table | +-------------------+ 1 row in set (0.00 sec) mysql> وليطمئن قلبنا، سنرى محتويات الجدول: mysql> select * from tecmint_table; +------+------------+-----------+-------------------+ | id | first_name | last_name | email | +------+------------+-----------+-------------------+ | 1 | Ravi | Saive | raivsaive@xyz.com | | 2 | Narad | Shrestha | narad@xyz.com | | 6 | tecmint | [dot]com | tecmint@gmail.com | +------+------------+-----------+-------------------+ 3 rows in set (0.00 sec) هذه ليست نهاية المطاف، ما زال أمامنا مناقشة بعض المفاهيم مثل primary key، و foreign key… ترجمة -وبتصرّف- للمقال MySQL Basic Database Administration Commands – Part I.
  7. يعتبر Ansible حلًا مناسبًا لأتمتة الأعمال التقنية البسيطة، فإن وجدت نفسك تقوم بتثبيت ووردبريس بشكل متكرر ومُمل، فقد يوفّر عليك Ansible الكثير من الوقت، وباستخدام بعض الأسطر بلغة YAML (وهي لغة توصيف واضحة ومباشرة) سنقوم بأتمتة عملية تثبيت ووردبريس على خادوم يعمل بنظام تشغيل Ubuntu 14.04، وفق الخطوات بصورة أوتوماتيكية. سنستخدم خادومين: أحدهما الخادوم الباني ويتم تشغيل Ansible عليه، والآخر الذي سنقوم بتثبيت ووردبريس عليه باستخدام Ansible. المتطلبات الأولية قبل المتابعة في المقال، سنحتاج للأمور التالية: خادوم يعمل بنظام تشغيل Ubuntu 14.04. سنقوم بتثبيت Ansible على هذا الخادوم (ونشير إليه في المقال بـ الخادوم الباني). سنقوم بتسجيل الدخول إلى هذا الخادوم وجميع الأوامر والملفّات المذكورة في المقال على هذا الخادوم، خادوم آخر يعمل بنظام تشغيل Ubuntu 14.04. سنقوم بتثبيت ووردبريس عليه باستخدام Ansible (وسنشير إليه في المقال بـ خادوم ووردبريس)، حساب مستخدم عادي -على كِلا الخادومين- لا يملك صلاحيات مدير نظام، لكنّه يملك صلاحية تنفيذ الأمر sudo، إضافة مفتاح SSH الخاص بالمستخدم -الذي أنشأناه على الخادوم الباني- إلى المفاتيح المصادقة authorized_keys للمستخدم الذي أنشأناه على خادوم ووردبريس، وينبغي تنفيذ هذه العملية على الخادوم الباني ورفع المفاتيح إلى خادوم ووردبريس. تنفيذ أوامر sudo بدون تأكيد باستخدام كلمة مرور إنّ من الأسرع -ولكن أقل أمانًا- تنفيذ أوامر sudo على خادوم ووردبريس بدون الحاجة لإدخال كلمة مرور تأكيد في كل مرّة. لإعطاء المستخدم على خادوم ووردبريس هذه الإمكانية، سنقوم بتعديل ملف sudoers باستخدام الأمر visudo على سطر الأوامر: $ visudo ومن ثم سنضيف السطر التالي في نهاية الملف: sammy ALL=(ALL) NOPASSWD: ALL ملاحظة: لا تنس استبدال اسم المستخدم (sammy في هذه الحالة) باسم المستخدم الموجود لديك، وتأكد من وضع السطر في نهاية الملف حتى لا يتم تجاوزه بالصلاحيات الافتراضية الموجودة في الملف. نصيحة: قم دومًا باستخدام الأمر visudo عند تعديل ملف sudoers، لأن الأمر سيقوم بالتحقق من التعديلات قبل حفظ الملف ويحميك بالتالي من ارتكاب أخطاء في الملف قد تؤدي إلى منعك من الدخول. حالما تنتهي من تنفيذ العملية السابقة سيغدو بإمكانك تنفيذ الأمر التالي على خادوم ووردبريس بدون إدخال كلمة مرور لتأكيده: $ sudo echo "Hello" وفي بقية المقال، تستطيع تنفيذ الأمر ansible-playbook بدون المُعامل K- كي تتجنب الحاجة لإدخال كلمة المرور للتأكيد بشكل يدوي: $ ansible-playbook playbook.yml -i hosts -u sammy الخطوة الأولى: تثبيت Ansible سنقوم الآن بتثبيت Ansible على الخادوم الباني، ونبدأ بتسجيل الدخول عبر SSH إلى الخادوم وتنفيذ الأمر التالي: $ sudo apt-get install ansible -y وتستطيع التأكد من تثبيت Ansible بتنفيذ الأمر: $ ansible --version حيث ينبغي أن يكون الخرج مشابهًا (وليس بالضرورة مطابقًا) لما يلي: ansible 1.5.4 الخطوة الثانية: إعداد بنية الملفات الآن وبعد أن انتهينا من تثبيت Ansible، دعونا نقوم بإعداد بنية الملفات من أجل Ansible playbook. سنقوم بإنشاء مجلّد على النحو التالي: $ cd ~ $ mkdir wordpress-ansible && cd wordpress-ansible سنقوم الآن بإنشاء ملفّين: الأول يدعى playbook.yml (حيث سنقوم بكتابة الأوامر الخاصة بتثبيت ووردبريس فيه) والثاني يدعى hosts (وهذا يُخبر Ansible عن الخواديم التي سيتم تنفيذ الأوامر عليها): $ touch playbook.yml $ touch hosts إنّ من الأفضل فصل الأوامر بحسب الأدوار، ومن الممكن اعتبار الأدوار كأجزاء من الممكن إعادة استخدامها، وسنقوم في هذا المشروع بإنشاء 4 أدوار: server php mysql wordpress سنقوم بإنشاء مجلد الأدوار في الجذر الرئيسي للمجلد الذي أنشأناه سابقًا wordpress-ansible/~ بتنفيذ الأمر التالي: $ mkdir roles && cd roles والآن سنقوم بتجهيز الأدوار باستخدام أداة من أدوات Ansible تدعى ansible-galaxy، حيث سنقوم من أجل كل دور بتنفيذ الأمر ansible-galaxy init كالتالي: $ ansible-galaxy init server $ ansible-galaxy init php $ ansible-galaxy init mysql $ ansible-galaxy init wordpress ستلاحظ بأن هذا الأمر سيقوم بإنشاء هيكل ملفات متكامل لكل دور من الأدوار، وهذه الخطوة هي إحدى الأمور التي ينصح بها في توثيق Ansible. ما يهمّنا غالبًا هو التعامل مع محتوى ملف tasks/main.yml لكل دور. عند الوصول إلى هذه المرحلة سيكون لدينا الهيكل التالي: [.] |_ playbook.yml |_ hosts |_ [roles] |_ [server] |_ ... |_ [php] |_ ... |_ [mysql] |_ ... |_ [wordpress] |_ ... الخطوة الثالثة: إنشاء الـ Playbook سنقوم الآن بكتابة الأوامر التي ستقوم بتثبيت ووردبريس على خادوم ووردبريس. ملف المخزون hosts يُخبر هذا الملف Ansible بالخواديم التي نرغب بتثبيت ووردبريس عليها، ومن الممكن تنفيذ الأوامر للخواديم أو مجموعة الخواديم المعرّفة في ملف المخزون hosts. سنقوم بتحرير ملف hosts باستخدام محرر nano أو أي محرر آخر تفضّله وكتابة التالي: [wordpress] wordpress_server_ip ملاحظة: من الممكن وضع أي عدد نرغب به من العناوين الرقمية IPs تحت مجموعة [wordpress]. سيؤدي هذا إلى تنفيذ الأوامر على جميع الخواديم المذكورة على افتراض أننا نملك صلاحية استخدام هذه الخواديم. سيمكّننا هذا من تثبيت ووردبريس على أي عدد من الخواديم دفعة واحدة. ملف Playbook يمكن اعتبار هذا الملف كتعريف لتطبيق ووردبريس الذي سنقوم بتثبيته. سيحتوي الملف على جميع الأدوار التي قمنا بإنشائها بغرض تجهيز تطبيق مفيد (ووردبريس في حالتنا). سنقوم بداية بتحرير الملف باستخدام محرر nano أو أي محرر آخر ترغب به: $ nano ~/wordpress-ansible/playbook.yml ومن ثم سنضيف المحتويات التالية إلى الملف، والتي ستُخبر Ansible أية أدوار سيتم تنفيذها على أية خواديم (سيتم تنفيذ الأدوار المذكورة في حالتنا على مجموعة العناوين الرقمية المدرجة في مجموعة wordpress المسجّلة في ملف hosts الذي أنشأناه سابقًا): - hosts: wordpress roles: - server - php - mysql - wordpress والآن لنعد إلى الجذر الرئيسي: $ cd ~/wordpress-ansible/ سنتأكد الآن من أنه من الممكن إجراء اتصال ما بين الخادوم الباني وخادوم ووردبريس من خلال تنفيذ ملف playbook الذي لن يقوم بأي شيء سوى التحقق من الاتصال: $ ansible-playbook playbook.yml -i hosts -u sammy -K ستُطالب بإدخال كلمة المرور لتأكيد الأمر، ولا تنس أن تقوم باستبدال اسم المستخدم بالموجود لديك. سيظهر لنا خرج يشبه التالي عند تنفيذ الأمر: ansible-playbook playbook.yml -i hosts -u sammy -K PLAY [wordpress] ************************************************************** GATHERING FACTS *************************************************************** ok: [188.166.68.134] PLAY RECAP ******************************************************************** 188.166.68.134 : ok=1 changed=0 unreachable=0 failed=0 والذي سيؤكد لنا بأن الاتصال قد تم بنجاح، دون أن يتم تنفيذ أي تعديلات لأننا لم نقم بتحديد أي أوامر لتنفيذها حتى الآن. إن فشل تنفيذ الأمر فتأكّد من أن باستطاعتك تسجيل الدخول إلى خادوم ووردبريس من الخادوم الباني باستخدام مفتاح SSH الذي قمت بنسخه في البداية. الخطوة الثالثة: إنشاء الأدوار دور Server سنقوم بداية بتعريف الأوامر التي سيتم تنفيذها على الخادوم ولهذا الغرض سنقوم بتحرير أوامر دور server. ستقوم الأوامر التي سنصرّح عنها بتثبيت جميع البرمجيات التي سنحتاجها على السيرفر الهدف. نبدأ بتنفيذ الأمر التالي: $ nano roles/server/tasks/main.yml قم بإضافة المحتويات التالية وتأكد من وجود سطر واحد فقط يحتوي على --- (حيث يوجد هذا السطر سلفًا بشكل افتراضي): --- - name: Update apt cache apt: update_cache=yes cache_valid_time=3600 sudo: yes - name: Install required software apt: name={{ item }} state=present sudo: yes with_items: - apache2 - mysql-server - php5-mysql - php5 - libapache2-mod-php5 - php5-mcrypt - python-mysqldb سيقوم المحتوى السابق بما يلي: تحديث خبء apt-cache (تنفيذ الأمر apt-get update)، تثبيت Apache ،MySQL ،PHP وبرمجيات أخرى مرتبطة باستخدام apt-get install. وإن كنت مهتمًّا بمعرفة تفاصيل ما نقوم بتثبيته، فيمكنك الاطلاع على هذا المقال حول تثبيت LAMP على Ubuntu 14.04 بشكل يدوي. سنقوم الآن بتنفيذ ansible-playbook مرة أخرى على النحو التالي: $ ansible-playbook playbook.yml -i hosts -u sammy -K ويفترض هذه المرة أن يكون الخرج بما يشبه التالي: ansible-playbook playbook.yml -i hosts -u sammy -K PLAY [wordpress] ************************************************************** GATHERING FACTS *************************************************************** ok: [188.166.68.134] TASK: [server | Update apt cache] ********************************************* ok: [188.166.68.134] TASK: [server | Install required software] ************************************ changed: [188.166.68.134] => (item=apache2,mysql-server,php5-mysql,php5,libapache2-mod-php5,php5-mcrypt,python-mysqldb) PLAY RECAP ******************************************************************** 188.166.68.134 : ok=3 changed=1 unreachable=0 failed=0 وبعد التنفيذ، ينبغي أن تكون قادرًا على استعراض الصفحة الافتراضية لـ Apache عبر فتح العنوان http://wordpress_server_ip في المتصفح. ملاحظة: إن توقّف تنفيذ الأمر بشكل نهائي عند سطر [TASK: [server | Update apt cache فمن المحتمل أن يكون هناك نقص في الصلاحيات المطلوبة على الخادوم الهدف، لذا تأكّد من أن الوصول باستخدام sudo تم إعداده بشكل صحيح على خادوم ووردبريس. دور PHP سنقوم الآن بتجهيز الأوامر التي تستهدف PHP، ولهذا الغرض سنقوم بتحرير الملف الخاص بهذا الدور: $ nano roles/php/tasks/main.yml ومن ثم سنضيف المحتوى التالي (تأكّد من وجود سطر واحد فقط يحتوي على --- في بداية الملف): --- - name: Install php extensions apt: name={{ item }} state=present sudo: yes with_items: - php5-gd - libssh2-php سيقوم المحتوى السابق بتثبيت الملحقات extensions الضرورية لـ PHP وهي: php5-gd و libssh2-php. دور MySQL سنقوم الآن بإعداد قاعدة بيانات MySQL لموقع ووردبريس، وذلك في دور mysql. سنحتاج من أجل القيام بذلك إلى بعض المتغيّرات، والتي من الممكن تخزينها في ملف المتغيرات الافتراضية defaults/main.yml: $ nano roles/mysql/defaults/main.yml سنضيف في الملف اسم قاعدة البيانات، اسم المستخدم الخاص بالقاعدة، كلمة المرور الخاصة بالمستخدم وبنفس الترتيب، ولا تنس أن تستخدم كلمة مرور معقّدة لأغراض أمنية: --- wp_mysql_db: wordpress wp_mysql_user: wordpress wp_mysql_password: wp_db_password والآن نستخدم nano لتحرير ملف المهام: $ nano roles/mysql/tasks/main.yml ونضيف المحتوى التالي: --- - name: Create mysql database mysql_db: name={{ wp_mysql_db }} state=present - name: Create mysql user mysql_user: name={{ wp_mysql_user }} password={{ wp_mysql_password }} priv=*.*:ALL يقوم المحتوى السابق بـ: إنشاء قاعدة بيانات MySQL، إنشاء مستخدم MySQL، إعطاء المستخدم صلاحية الوصول إلى قاعدة البيانات. وكما ترى فسيتم استخدام قيم المتغيرات بشكل تلقائي من ملف defaults/main.yml عند تنفيذ الأوامر. ملاحظة: توفّر أدوات Ansible أداة ansible-vault والتي تسمح بتخزين كلمات المرور بصورة مشفّرة حتى لا تكون قابلة للقراءة في الملف، ولكن الحديث عن هذا خارج إطار حديثنا الآن. دور WordPress والآن نأتي للحظة التي كنا ننتظرها.. تثبيت ووردبريس. نبدأ بتحرير ملف المهام كالمعتاد: $ nano roles/wordpress/tasks/main.yml وسنقوم بنسخ المحتوى التالي إليه: --- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no sudo: yes سيقوم المحتوى السابق بتحميل ووردبريس إلى مجلد tmp/ (ويمكن للحذرين أن ينتبهوا إلى أننا قمنا بتعطيل التحقق من الشهادة الأمنية، لأنه سيمنع عملية التحميل). بعد اكتمال التحميل سنقوم بفك ضغط الملف إلى var/www/، وهو المسار الذي يستخدمه Apache لتخزين محتوى الويب، وبالتالي سنضيف الجزء التالي لمحتوى الملف أيضًا: - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no sudo: yes وبعد أن يتم فك ضغط الملفات، سنقوم بتحديث مسار الجذر الافتراضي DocumentRoot في ملف إعدادات Apache كي يشير إلى موقع ووردبريس: - name: Update default Apache site sudo: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache sudo: yes لاحظ أننا استخدمنا الكتلة notify، والتي نحتاجها عند الرغبة بإعادة تشغيل خدمات بعد أن يتم تنفيذ مهمّة بنجاح، ولا يتم تنفيذ معالجات notify إلا عندما يحصل تغيير على حالة المهمّة. سنقوم بإضافة المعالج الخاص بنا لإعادة تشغيل Apache باستخدام restart apache ويتم ذلك في الملف roles/wordpress/handlers/main.yml: $ nano roles/wordpress/handlers/main.yml نضيف المحتوى التالي: --- - name: restart apache service: name=apache2 state=restarted sudo: yes ويتم تنفيذ هذه المهمّة عندما تتغير حالة المهمّة التي تحتوي على الكتلة notify: restart apache، مما يؤدي إلى إعادة تشغيل الخدمة. إعداد ووردبريس بالعودة إلى roles/wordpress/tasks/main.yml، سنقوم الآن بتجهيز إعدادات موقع ووردبريس، فنقوم أولًا بنسخ ملف الإعدادات config الافتراضي: - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php sudo: yes ومن ثم نقوم بتغيير بعض الثوابت في الملف لتتطابق مع معلومات الاتصال بقاعدة البيانات: - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} sudo: yes حيث ستقوم المهمّة بجلب معلومات الاتصال بالقاعدة من ملف المتغيّرات الافتراضية الذي قمنا بتحريره سابقًا. بعد الانتهاء من الخطوات السابقة بنجاح، سيكون قد أصبح لدينا ملفّين لدور wordpress، وفيما يلي النسخة الكاملة لمحتوى الملفّين.. ملف roles/wordpress/tasks/main.yml: --- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no sudo: yes - name: Update default Apache site sudo: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php sudo: yes - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} sudo: yes ملف roles/wordpress/handlers/main.yml: --- - name: restart apache service: name=apache2 state=restarted sudo: yes ونكون قد انتهينا. لنقم الآن بتشغيل ansible-playbook لآخر مرة لإعداد موقع ووردبريس: $ ansible-playbook playbook.yml -i hosts -u sammy -K وبعد تنفيذ الأمر ينبغي أن نكون قادرين على تصفّح الموقع عبر طلب عنوانه http://your_server_ip في المتصفح ويمكن الآن متابعة إعداد موقع ووردبريس بشكل يدوي عند هذه المرحلة. الخلاصة تهانينا! ستتمكن الآن من تثبيت مواقع ووردبريس على أي عدد من الخواديم التي تعمل بنظام تشغيل Ubuntu باستخدام أمر واحد: $ ansible-playbook playbook.yml -i hosts -u sammy -K وكل ما تحتاج للقيام به هو إضافة العنوان الرقمي IP إلى قائمة الخواديم المستهدفة في ملف hosts والتأكّد من أن الصلاحيات قد تم إعدادها مسبقًا على الخادوم الهدف. تناولنا في المقال بصورة سريعة كيفية استخدام Ansible لتثبيت مواقع ووردبريس بشكل اوتوماتيكي، وقد تكون مهتمًّا ببعض التحسينات الإضافية الممكنة: تعلّم كيفية استضافة أدوارك الخاصة في الـ Ansible Galaxy. أتمتة عملية الإعداد النهائية لموقع ووردبريس حتى لا يكون هناك حاجة للقيام بأي إعداد يدوي للموقع المطلوب إطلاقًا. ترجمة -وبتصرّف- للمقال How To Automate Installing WordPress on Ubuntu 14.04 Using Ansible لصاحبه Christo Crampton.
  8. هل أنت مهتم بتعلم PHP وبناء قوالب وملحقات خاصة بك على ووردبريس؟ أو ربما أنت مُهتمّ بتعلّم القليل الذي يُمكنك من إدخال التّعديلات التي تحتاجها على مواقعك ومدوّناتك التي تعتمد على ووردبريس. أيّا كان وضعك، هناك أمور يجب عليك أن تعرفها قبل أن تغوص في مجال تطوير ووردبريس. سنحاول في هذا المقال إعطاءك فكرة واضحة عليها. كيف يعمل ووردبريس؟ لنفهم ماذا وكيف يمكننا التطوير في ووردبريس، سنلقي أولا نظرة سريعة على آلية عمل ووردبريس. يتكون ووردبريس من ثلاثة عناصر رئيسية: النواة الأساسية والقوالب والمُلحقات. تحتوي النواة على جميع الوظائف الأساسية التي تشكل نظام إدارة المحتوى لووردبريس، وهذه الشيفرات البرمجية تتضمن كل شيء من البنية التحتية (backend) للإدارة إلى دوال جدولة المشاركات والتأكد من قوة كلمة المرور والسماح بإنشاء مستخدمين وغيرها. في حين أن النواة الأساسية (core) مسؤولة عن البنية التحتية للموقع وكيفية التعامل معها، فإن القوالب مسؤولة عن الواجهة الأمامية للموقع وكيفية ظهوره. نستخدم إدارة ووردبريس (WordPress admin) لإنشاء المشاركات والصفحات وبقية محتوى الموقع، وأما بالنسبة لكيفية ظهور هذه الأشياء للزائر فهو أمر متروك للقالب theme، لذلك فإن هذا سيعطيك قوة كبيرة للتحكم في موقعك، فقد ترغب بتثبيت وتفعيل القوالب الموجودة أو حتى تطوير قوالبك المخصصة. أبسط طريقة لوصف المُلحقات plugins هي أنها توفر وظائف إضافية للووردبريس، ولفعل ذلك، قد تعدّل المُلحق الشيفرة البرمجية للواجهة الأمامية أو البنية التحتية للموقع، وأبسط مثال لذلك هي المُلحق الذي يضيف زر لتغريدة تويتر، وقد تُنشئ أيضا صفحة إعدادات جديدة في البنية التحتية لقائمة الإدارة والتي ستمكنك من إعداد بعض الخيارات الافتراضية لتغريدة المستخدم ويمكنها إضافة نفسها إلى الواجهة الأمامية للموقع، والتي سيكون موقعها في الغالب تحت التدوينة (post). مجالات التطوير بقدر تقدمك في تطوير ووردبريس، ستتمكن من تطوير أي واحدة من المكونات الرئيسية المذكورة أعلاه بالإضافة إلى تطبيقات مستقلة بمساعدة REST API الجديدة وسنذكر المزيد عن هذا الموضوع بعد قليل. مهما كان ما تريد فعله مع ووردبريس، أنصحك باتباع منهج في دراستك، هذه القائمة ستساعدك على التعرف على الأنظمة التي تحتاج إلى معرفتها قبل بدء تعلمك المزيد حول المجال الذي اخترته: القوالب المُلحقات REST API النواة القوالب إن تعلم كيفية عمل القوالب وتطويرها سيسمح لك باحتراف إنشاء المواقع بدءا من المواقع الصفحة الواحدة إلى مواقع المحتوي الحيوي الثقيل، وستسمح لك أيضا بالحصول على المزيد من العملاء (إذا كان هذا ما يهمك) أو حتى بيع القوالب تجاريا. يوجد العديد من مطوري القوالب الناجحين في أسواق مثل Themeforest و Mojo Marketplace وغيرها. ففي وقت كتابة هذا المقال، أشهر قالب على موقع Themeforest تم بيع 1377 نسخة منه في أسبوع أي أكثر من $81,000 في أسبوع واحد فقط! يمكنك الحصول على الكثير من الأموال إذا كنت تستطيع تطوير قالب مميزة. على الرغم من أن هذا المبلغ لا يحققه جميع مطوري القوالب، وربما لن تصبح مليونيرًا بين عشيّة وضحاها من إنشاء القوالب، لكن يمكنك الحصول على مبلغ مالي جيد من القوالب إذا كنت تقوم بالأمر بالشكل الصحيح. إذا أردت رؤية بعض الأمثلة عن القوالب الشهيرة، فألق نظرة على الأسواق التي ذكرناها أعلاه، أو على قسم قوالب ووردبربس حيث جميع القوالب مجانية، فالكثير من مطوري القوالب يصدرون أعمالهم الأولى في هذا القسم. يمكنك تعلم كيفية إنشاء قوالب ووردبريس في أكاديمية حسوب من خلال سلسلة الدروس مدخل إلى تطوير قوالب ووردبريس. الملحقات plugins بطريقة ما، تعتبر المُلحقات شريان حياة ووردبريس، فهي تحوله إلى كل شيء من منتدى إلى شبكة اجتماعية أو منصة للتجارة الإلكترونية وغيرها باستخدام ضغطة زر واحدة، فالمُلحقات تعطيك تحكمًا كاملًا بجميع جوانب نظام ووردبريس، وتسمح لك بتعديل ما تشاء، وسيساعدك هذا كثيرا عند إنشاء مواقع ووردبريس للعملاء. كما هي الحال مع القوالب، فالمُلحقات تملك أيضا أسواقا وفي العادة يتم إدارتها من نفس الشركات التي تدير أسواق القوالب. يعتبر سوق CodeCanyon على سبيل المثال أكبر سوق للملحقات حيث يملك أكثر من 4000 ملحق متاحة للشراء. على الرغم من أن المبيعات ستكون أقل من القوالب إلا أنه يمكنك ربح الكثير إذا أنشأت ملحقًا جيدًا. يملك موقع ووردبريس قسمًا للملحقات المجانية ويحتوي على أكثر من 40000 ملحق، وهو بذلك مصدر كبير للأدوات والإلهام والأمثلة على الشيفرات البرمجية المميزة (والشيفرات البرمجية السيئة للأسف). يمكنك تعلم كيفية إنشاء ملحقات وإضافات ووردبريس في أكاديمية حسوب من خلال سلسلة الدروس مدخل إلى برمجة إضافات ووردبريس. REST API ستستخدم REST API لاحقا عندما تحترف تطوير القوالب والمُلحقات، ونظريا ستكون قادرا على استخدامها إذا كانت لديك خبرة في البرمجة بلغة أخرى مثل جافا أو روبي. تعتبر REST API جديدة نسبيا وتسمح لك بإنشاء تطبيقات حقيقية بالاعتماد على ووردبريس، وهذا يتضمن تطبيقات أندرويد وأيفون وغيرها. أفضل طريقة لشرح هذه الميزة هي عن طريق مقارنتها بمواقع مثل تويتر أو انستغرام، لا شك أنك قد رأيت تغذية تويتر معروضة على موقع أحدهم، ولإضافة هذه الميزة إلى موقعك لن تحتاج إلى معرفة كيفية عمل نواة شيفرة البرمجية الخاصة بتويتر، كل ما تحتاجه هو القليل من الشيفرات البرمجية التي تقول: "من فضلك استرجع آخر خمسة من تغريداتي." وسيتعامل تويتر مع الباقي وسيرجع لك بيانات آخر خمسة تغريدات التي طلبتها، وبعد ذلك يمكنك استخدام HTML و CSS لعرضها. وهذا بالضبط ما يفعله REST API لووردبريس، يمكنك الاتصال بأي موقع وطلب منه آخر خمسة مشاركات فيها، ويمكنك أيضا القيام بأكثر من ذلك: يمكنك إنشاء/حذف المستخدمين وتعديل الفئات وغيرها (بالطبع، تحتاج إلى الاستيثاق قبل استخدامها)، هذا يعني أنه يمكنك استخدام ووردبريس كمستودع للمعلومات وبناء واجهة أمامية وبنية خلفية باستخدام نظام مختلف تماما. النواة ساهم في تطوير ووردبريس مجتمع من الآلاف المتطوعين حول العالم، حيث أنه يعمل 471 شخص على الإصدار 4.4 من ووردبريس، والعديد من الأشخاص الآخرين يعملون على جوانب مختلفة من ووردبريس، من الترجمة وتطبيقات الويب إلى الإتاحة (accessibility) والدعم. في الحقيقة، يمكنك الاشتراك معهم الآن، فبينما تحتاج إلى بعض الخبرة للمشاركة في برمجة نواة ووردبريس إلا أنه يمكنك المساهمة في تحديد المشاكل والأخطاء والتأكد منها وتقديم الأفكار في أي وقت باستخدام WordPress Trac، وهو المكان الذي يمكنك من متابعة تطوير شيفرة نواة ووردبريس. إذا وجدت علة (خطأ - bug) يمكنك إرفاقها بالشيفرة المناسبة للتخلص منها، وبعد عدة مراجعات وتدقيقات سيتم استخدام شيفرتك البرمجية إذا كانت مناسبة، وهذه هي أفضل طريقة للمشاركة في تطوير النواة. تطوير ووردبريس: ماذا تحتاج أن تتعلمه يجب أن تعتاد على العمل على مجموعة محددة من الأدوات حتى تتمكن من تطوير ووردبريس. إن عملية التعلم لا تنتهي بالنسبة إلى أي مطور جيد، سوف أعرض عليك هنا حزمة للبداية كما سأريك بعض الأدوات المتقدمة التي قد تحتاج إليها لاحقا عندما تريد أن تتعلم المزيد. الحد الأدنى من المتطلبات لتطوير الووردبريس هي HTML و CSS و PHP، بالإضافة إلى هذه اللغات ستحتاج إلى جافا سكربت و MySQL في مرحلة ما، عندما تتقن هذه اللغات يمكنك الانتقال إلى أشياء أخرى مثل LESS/SASS و Coffeescript و XML و JSON وغيرها، لكن هذه الأشياء لا تعتبر ضرورية لتطوير ووردبريس، لكن إذا عرفتها سيجعل حياتك أسهل كمطور وستوسع آفاقك. HTML و CSS أول لغتين يجب عليك تعلمهما هما HTML و CSS، مهما كانت الشيفرة البرمجية التي تكتبها ومهما كانت اللغة التي تستخدمها فستحتاج حتما إلى HTML عند إرسال صفحات الويب إلى المستخدم وإلى بعض CSS لتصميم وتزيين الصفحة. إن HTML مسؤولة عن إعطاء هيكل المواقع. على المستوى الأساسي، هذا يعني أنك ستقرر ما النص الذي يجب أن يكون عنوانًا وما يجب أن يكون قائمة وما الذي يجب أن يكون في رأس أو أسفل الصفحة. أما في المستوى الأعمق، ستقرر قرارات مهمة حول SEO والتحسين (optimization). يُستخدم CSS لتطبيق أنماط لهيكل HTML، أي أنك ستُعرّف لون النص والروابط والمسافة بين الفقرات ومحاذاة الصورة وألوان الحدود وسمكها وغيرها من العناصر عن طريق استخدام شيفرة CSS. إن CSS تتميز بسهولة تعلمها وبصعوبة إتقانها. PHP تحظى PHP بشعبية كبيرة كأشهر لغة سكربتات من جانب الخادوم server-side-، ووفقا للاستطلاع الذي قام به W3Techs، تستخدم PHP في 81.6% من المواقع وهي اللغة التي كُتب بها ووردبريس (وتقريبا أغلب أنظمة إدارة المحتوى الأخرى أيضا) ولذلك فإن معرفة PHP هو أمر ضروري لتطوير ووردبريس. إن معرفتك بـ PHP وحدها، سيجعلك تحصل على أكثر من معرفة بتطوير ووردبريس فقط. إن أهم فرق بين لغات جانب الخادوم عن لغات جانب العميل - مثل HTML - هو أنه يتم معالجتها في الخادوم أولا، ففي HTML، يمكنك كتابة شيفرة برمجية لـ Good Morning وسيرسلها HTML كما هي وسيعرضها على الزوار. أما في لغات جانب الخادوم، فستكتب شيء مشابه لهذا [good [time_of_day، وقبل أن يتم إرسال ذلك الأمر إلى المستخدم، سيعالج الخادوم هذه الأمر حتى يعرف ما يضعه في مكان [time_of_day] حسب الوقت الذي دخلت فيه إلى الموقع، فيمكنك أن ترى "Good day" أو "Good evening". لاحظ أن البيانات التي يستقبلها متصفحك تبقى HTML لكن تمت معالجتها في الخادوم مسبقا، ولاحظ أيضا أن الشيفرة السابقة لم تكن شيفرة PHP بل هي مثال فقط لأعطيك فكرة عن آلية عمل هذه اللغة. كما هو الحال مع جميع لغات البرمجة، فالممارسة والتمرين هي التي تجعلك تبرمج بشكل أفضل، فيمكنك تعلم PHP في غضون بضعة أيام لكنك ستجد نفسك أنك لا تملك أية فكرة عن ما الذي تقوم به، لذلك تحتاج إلى تجربة الأشياء وتخريبها وليس الوقوف دون معرفة ما يجري، وكما يقولون الممارسة تولد الإتقان. جافا سكربت ازداد دور جافا سكربت أهمية على الإنترنت، خاصة مع ظهور أدوات مبنية على جافا سكربت مثل Node و Angular. جافاسكربت تستخدم عادة لإضافة وظائف حيوية للمواقع وللتحميل غير المتزامن. سأعطيك مثال على كل واحد منها. فمثلا لو أردت أن يتم إخفاء نموذج بشكل كامل وأن يظهر ببطء داخل lightbox عندما يضغط المستخدم على زر معين، فيمكنك فعل ذلك باستخدام جافا سكربت بما أنه يمكنه التعامل مع تحريك الرسوم (animation) وربما الوظائف الأخرى، مثل التأكد من أنه تم ملئ النموذج بشكل صحيح قبل إرساله. أما التحميل غير المتزامن فيتم عمله عبر آلية تسمى بـ AJAX، فيمكنك استخدام AJAX للحصول على معلومات من الخادوم وعرضها دون إعادة تحميل الصفحة، وأبسط مثال لذلك هو التمرير اللانهائي (endless scrolling) فعندما يتم تحميل 10 مشاركات وتصل إلى نهاية الصفحة فسيتم عرض 10 مشاركات أخرى وتستمر هكذا. الكثير من المطورين تعلموا جافا سكربت من خلال إطار jQuery، فهو يُستخدم على نطاق واسع في ووردبريس وفي ملايين المشاريع على الإنترنت، وعلى الرغم من أن هذا الأمر جيد لكن ضع في اعتبارك أن جافا سكربت هو أكثر من مجرد jQuery وإن تعلم جافا سكربت كما هو هي فكرة جيدة. MySQL إن Mysql هي لغة تُستخدم للوصول والعمل مع البيانات المخزنة في قاعدة البيانات، يستخدم ووردبريس هذه اللغة كثيرا للتعامل مع البيانات، لكن كمطور، لا تحتاج إلى معرفة الكثير لأن ووردبريس يملك مجموعة من الدوال المساعدة. لكن في بعض الحالات الخاصة، قد تحتاج إلى كتابة استعلام قاعدة البيانات بنفسك أو ربما قد ترغب بتحسين شيء في موقعك، لذلك سيفيدك تعلم أساسيات MySQL. إن العمل مع قواعد البيانات واضح للغاية، فالجدول في قاعدة البيانات يشبه كثيرا جداول بيانات Microsoft Excel، فكل عمود يملك عنوانًا وبيانات مخزنة في الأسطر، ونستخدم MySQL لإضافة وحذف وتعديل واسترجاع البيانات، ربما ترغب بكتابة استعلام MySQL يرجع لك جميع المشاركات التي تحتوي على كلمة "awesome" ولديها أكثر من 8 تعليقات، أو قد ترغب أيضا بإيجاد جميع المستخدمين الذين يملكون اسم "Daniel". مرة أخرى، إن كتابة شيفرة MySQL خام في ووردبريس هو أمر نادر، لكنه يحدث في بعض الأحيان، لذلك فإن فهم كيفية عمل اللغة سيساعدك على كتابة شيفرات أفضل بشكل عام أدوات متقدمة بمجرد أن تتعود على الأقل على استخدام ثلاثة اللغات الأساسية - HTML و CSS و PHP - يمكنك البدء باكتشاف العديد من الأدوات المساعدة، واحدة من الأشياء الأولى التي يميل الناس إلى تعلمها هي LESS و/أو SASS، كلاهما "مجموعات موسّعة" (Superset) لـ CSS، أي أن أي شيفرة CSS صحيح تعتبر صحيحة في شيفرة LESS و SASS، وتكمن أهمية إضافة هاتين اللغتين هو إمكانية استخدام متغيرات ودوال و غيرها في CSS، والذي هو غير ممكن بشكل افتراضي. إن أدوات البناء (Build tools) هو شيء سترغب في اكتشافه عند مرحلة معينة، أفضلها Gulp و Grunt فهذان يمكنهما مراقبة تعديلات الملفات وتنفيذ مختلف المهام عند استيفاء المتطلبات، فعلى سبيل المثال، في أي وقت تعدل فيه ملف SASS يمكنك ترجمته تلقائيا إلى CSS وحفظه إلى ملف معين، أو يمكنك تحسين الصور أو دمج الملفات أو تحميل الحزم الخارجية فجميع المهام الأخرى يمكنك أن تفعلها باستخدام هذه الأدوات. سطر الأوامر أو الطرفية (terminal) هو شيء يجب أن تلقي نظرة عليه. نعم إن استخدام سطر الأوامر قد يبدو مخيفا لكنه ليس كذلك، فبمجرد كتابة بضعة أوامر يمكنك حفظ الكثير من الوقت، فسكربت/أداة مثل WP-CLI يمكنه تثبيت ووردبريس في بضعة ثواني، بما في ذلك تثبيت القوالب والمُلحقات والمحتويات للتجربة والتي لو قمت بها بشكل يدوي ستتطلب الكثير من الوقت والجهد. إن أنظمة االتّحكّم في الإصدارات (Version control) هي من الأدوات المفيدة للغاية فلن تعرف حاجتك إليها إلا لو استخدمتها، فعلى الرغم من أنها وُضعت أصلا للعمل على نفس الشيفرة البرمجية في مجموعات إلا أنه يمكنك استخدامها كحل لإدارة المشاريع والمشاكل والنسخ الاحتياطي في نفس الوقت. ويعتبر كل من SVN و Git الأشهر على الإطلاق، لكن بالنسبة لي، أعتبر أن Git أفضل نظرا لأنه يعمل بشكل أفضل وبسبب Github الذي يوفر خدمة استضافة مستودعات Git على الإنترنت. ووردبريس: بوابتك إلى عالم البرمجة إن أفضل شيء بالنسبة إلى ووردبريس أنه يمكن أن يكون مدخلا لتعلم مهارات تطوير ويب ولغات أخرى. ولقد خضت هذه التجربة شخصيا، فلقد تعلمت أولا البرمجة الموجهة في PHP ثم تعلمت إطار عمل Laravel وأدوات البناء ثم LESS/SASS وأدوات سطر الأوامر وغيرها الكثير. ولقد خضت أيضا في غمار native app باستخدام #C وغيرها من اللغات. بمجرد معرفتك بكيفية عمل كل شيء، ستتعلم المزيد عند إنشاء مشاريع جديدة وكبيرة وكل شيء سيصبح أسهل، فبعد البرمجة كائنية التّوجّه في PHP لن تبذل الكثير من الجهد في تعلم #C لأن دماغك سيتعود على منطقه بطريقة مشابه لتعلم قيادة الشاحنات بعد تعلمك قيادة السيارات، فعلى الرغم من وجود الكثير من الاختلافات لكن بمجرد أن يكون لديك بعض الأساسيات سيسهل عليك التّحكمّ فيه. خاتمة ها قد عرفت الآن ما الذي تحتاجه للبدء في تطوير موقع ووردبريس، وقد تشعر بالإرباك، لكن لا تقلق، فالجميع سيشعر بذلك في هذه المرحلة. تذكّر أمرًا: من المهم أن لا تثبط عزيمتك، فجميع المبرمجين بدؤوا من مكان ما، فالكثير منهم كان سيئا للغاية عندما بدأ، يصارع لفهم المفاهيم الجديدة وشعر بالإحباط، لكنهم لم يستسلموا وكانوا دائما يدفعون أنفسهم للتّعلّم وهذا ما يُميّز المبرمج الجيد من السيئ. ترجمة -وبتصرف- للمقال: WordPress Development for Beginners: Getting Started لصاحبه Daniel Pataki. حقوق الصورة البارزة: Designed by Freepik.
  9. يُنفّذ ووردبريس استعلامًا في كل صفحة من صفحات الموقع، ليجلب البيانات من قواعد بيانات (databases) الموقع ومن ثُمّ يعرضها بالطريقة الّتي يحدّدها القالب (theme) المُستخدَم وذلك باستخدام حلقة التكرار (loop)، ويُشار إلى هذا الاستعلام بالاستعلام الرئيسي main query. سيَستخدم ووردبريس ملفّ القالب (template) المُلائم وذلك اعتمادًا على نوع الصّفحة الّتي يتمّ عرضها، بمعنى أنّ حلقة (loop) قد تتغيّر بناءً على المُحتوى، ولكنّه سيُنفّذ استعلامًا دائمًا لجلب البيانات من قاعدة البيانات. يُرغب أحيانًا في تغيير طريقة عمل الاستعلام، فعلى سبيل المثال في الصّفحة الرئيسيّة للمدوّنة قد يُرغب في استثناء منشورات من فئة (category) مُعيّنة، أو قد يُرغب في عرض قائمة بالمنشورات على حسب الصنف بدلًا من الترتيب على حسب التاريخ في صفحة الأرشيف (archive page)، كما من المُحتمل جدًا أنّ يُرغب في إضافة استعلامات إضافيّة إلى صفحات (pages) الموقع، أو إضافة قائمة بالمنشورات الأخيرة (recent posts) أو المنشورات ذات الصِلة بمنشورات أخرى، أو قد يُرغب في إنشاء ملفّ قالب (template) يستبدل الاستعلام الرئيسي (main query) باستعلام مُخصّص وجديد كليًّا. يجعل سكريبت إدارة المُحتوى ووردبريس من هذه التخصيصات أمرًا ميسّرًا للغاية، وذلك بطرقٍ عدّة، وذلك إما بالتعديل على الاستعلام الرئيسي أو بإنشاء استعلام جديد. سيتطرّق هذا الدليل إلى الأمور التّالية: متى يُستخدم الاستعلام المُخصّص، ومتى يُخصّص الاستعلام الرئيسي ومتى يتمّ إنشاء استعلام جديد. الطرق الخمس لإنشاء استعلامات مُخصّصة، بما في ذلك الطريقة الّتي لا يجب أنّ تُستخدم ولماذا. فهم الأساسيات يجب الإلمام ببعض المصطلحات قبل الدخول في التفاصيل وهي ضروريّة لمن لم يُنشئ استعلامات مُخصّصة من قَبل. الاستعلام (query) وهو طريقة يَستعين بها ووردبريس لجب البيانات من قاعدة بيانات الموقع، وتتضمّن هذه البيانات المنشورات posts، المرفقات attachments، التعليقات comments، والصّفحات pages، أو أي مُحتوى تمّت إضافته إلى الموقع. الحلقة (loop) وهي شيفرة/كود يستخدمها القالب (theme) (أو أحيانًا الإضافة plugin) لتحديد كيفيّة عرض نتائج الاستعلام على الصّفحة، فعلى سبيل المثال قد تُضمِّن الحلقة في الصّفحة الرئيسيّة عنوان كل صفحة (title)، مُلخص كل تدوينة (extract)، ربّما صورة مُميّزة/بارزة، ورابط صفحة المنشور (والّذي يُدعى permalink أو الرابط الثابت). ملفّات القالب (template files): وتُستخدم من قِبل القالب (theme) لعرض الصفحات لكل نوع من أنواع المُحتوى، مع العلم أنّ كل قالب (theme) يملك ملفّات قالب (template) تختلف عن الآخر، ولكن يجب على القالب (theme) أنّ يتضمّن ملفّ index.php رئيسي، وغالبًا على الملفّ page.php للصفحات الثابتة static pages، والملفّ single.php للمنشورات المُنفردة single posts، والملفّ archive.php لصفحات الأرشيف، وربّما الملفّ category.php للتصنيفات، والملفّ tag.php للوسوم، وغيره من الملفّات وللمزيد من التفاصيل يُمكن العودة إلى الصّفحة التّالية في التوثيق الرسمي. الوسوم/الدّوال الشرطيّة: والّتي من المُمكن أنّ تُستخدم في ملفّات القالب (template) أو من قِبل الإضافات plugins لتحديد نوع الصّفحة الّتي يتمّ عرضها، فعلى سبيل المثال الدّالّة/الوسم ()is_page تُحدّد فيما إذا كانت الصّفحة الّتي يتمّ عرضها ثابتة (static) أم لا، والدّالّة/الوسم ()is_home تُحدّد فيما إذا كانت الصّفحة هي صفحة البداية home page، ويوجد العديد من هذه الوسوم/الدّوال الشرطيّة منها ما يُحدّد فيما إذا كان المُستخدم مُسجّلًا دخوله logged in أم لا، وغيره من هذه الدوال. متى يجب استخدام الاستعلام المخصص في ووردبريس يوجد نوعان من الاستعلامات المُخصّصة: الاستعلام الرئيسي بعد تعديله. استعلامات جديدة كليًّا لجلب مُحتوى مُختلف/مُحدّد أو محتوى إضافي. التعديل على الاستعلام الرئيسي Main Query في ووردبريس يُمكن استخدام نسخة مُعدّلة من الاستعلام الرئيسي عند الرغبة في أنّ تَعرض الصّفحة نتائج الاستعلام الرئيسي لذات المحتوى ولكن مع بعض التحسين والتعديل، وفي هذا النوع من الاستعلام ليس الهدف هو إظهار محتوى مُختلف كليًّا، وليس من المُفترض إضافة حلقة تكراريّة (loop) إضافيّة. أمثلة للحالات الّتي من المُمكن بها استخدام استعلام مُعدّل: في الصّفحة الرئيسيّة للمدوّنة، عرض أنواع منشورات مُخصّصة بالإضافة إلى المنشورات. في صفحة أرشيف التصنيفات category، عرض منشورات من نوع مُحدّد فقط. في صفحة أرشيف التصنيفات، ترتيب المنشورات ترتيبًا أبجديًا بدلًا من الترتيب الافتراضي. يوجد العديد من الحالات الأُخرى، ولكن كما هو واضح فالتعديلات مقتصرة على التعديلات البسيطة للاستعلام. كتابة استعلام جديد في ووردبريس قد لا يكون التعديل على الاستعلامات كافيًا في بعض الحالات، فعندها يُمكن إنشاء استعلام جديد، ويتمّ بهذا الحصول على مرونة أكبر في بناء الاستعلام، ولكن لا يُحبّذ إنشاء استعلام جديد عندما يكون التعديل على الاستعلام الرئيسي أمرًا كافيًا، حيث يُمكن إنشاء استعلامًا جديدًا عند الحاجة إلى استخدام أكثر من حلقة loop واحدة في الصّفحة أو عند الرغبة في استبدال الاستعلام الرئيسي باستعلام جديد كليًّا. أمثلة للحالات الّتي من المُمكن بها إنشاء استعلام جديد عديدة ومُختلفة، ولكن أبرزها: عند تنفيذ حلقتين two loops في صفحة الأرشيف: إحداهما للمنشور الأوّل والأخرى للمنشورات اللاحقة، بهدف عرض مُحتوى مُختلف للمنشور الأوّل، مثلًا عندما يكون المطلوب أنّ يتضمّن المنشور الأوّل مُلخّص أو صورة مميّزة فقط بدون بقيّة المنشورات، ولكن إن كان المطلوب هو تنسيق المنشور الأوّل بشكل مُختلف فقط، فمن غير المُستحسن استخدام حلقات (loops) متعدّدة في ذلك، بل من المُفترض استخدام CSS لاستهداف المنشور الأوّل في التنسيق دون بقيّة المنشورات. في صفحة المنشور المنفردة (single post)، وذلك عند تنفيذ حلقة (loop) إضافيّة لعرض المنشورات الأخيرة (أو المنشورات المُميّزة) وذلك أسفل محتوى المنشور، بغرض تشجيع القارئ لقراءة المزيد. عند إضافة لافتة (banner) مربوطة مع منشور مُميّز منفرد single featured post (أو لجميع المنشورات المُميّزة) في أعلى كل صفحة من صفحات الموقع، كما هو الأمر عند إضافة منشور يُروّج إلى مُنتج جديد، وهذه الطريقة هي أكثر مرونة من إضافة لافتة ثابتة (static banner) بما أنّه من المُمكن تعديل المنشور المُستخدَم بسهولة. عند إنشاء قائمة من الصفحات في نفس القسم (section) من الموقع، وذلك عندما يَملك الموقع بُنية مُعتمدة على صفحات هرميّة/شجريّة، فمن المُستحسن وضعها في الشريط الجانبي sidebar. إنشاء قالب صفحة page template باستعلام مخصّص كليًّا لعرض المنشورات على حسب التصنيف (taxonomy) أو نوع المنشور (أو ربّما حسب المعيارين). في صفحة أرشيف نوع المنشور (post type archive page)، وذلك لعرض المنشورات حسب التصنيف (category) بدلًا من التاريخ. إنشاء لافتة (banner) في الشريط الجانبي sidebar للربط إلى المنشور الأخير مع صورته الرئيسيّة. إنشاء صفحة لعرض المنشورات المُرتبطة فيما بينها وبأكثر من تصنيف، مثلًا عرض المقالات البرمجيّة وللغة روبي (Ruby) مثلًا ولكاتب مُحدّد. إنشاء نوع منشور لمحتوى الشريط الجانبي واستعلام منشورات هذا النوع في الشريط الجانبي، الأمر الّذي يُساعد أصحاب الخلفيّة غير البرمجيّة في إضافة مُحتوى إلى الشريط الجانبي بمرونة أكثر فيما لو تمّ استخدام ودجت (widget). يوجد العديد من السيناريوهات الأخرى، ولكن القائمة السابقة تعطي فكرة عامّة، ولن يتمّ التفصيل في كيفيّة تنفيذ كلٍ منها بل سيتمّ تغطية بعض الأمثلة. طرق إنشاء استعلام مخصص Custom Query يتوفّر خمس طرق لإنشاء استعلامات مُخصّصة custom queries، ويُمكن أنّ تُقسّم هذه الطرق تبعًا فيما إذا كان سيتمّ التعديل على الاستعلام الرئيسي أو سيتمّ إنشاء استعلام جديد. الطرق لتعديل الاستعلام الرئيسي هي: استعمال الخطّاف الإجرائي pre_get_posts، والّذي يسمح للمطوّر في التعديل على الاستعلام الرئيسي عن طريق إضافة دالّة إلى ملفّ الدّوال الخاصّ بالقالب (theme) أو بواسطة إضافة (وليس في ملفّات القالب template) ويُمكن دمجه مع تصريح شرطي conditional statement لتأكّد من أنّه يُنفّذ فقط على الصفحات الّتي تعرض أنواع مُحدّدة من المُحتوى. استعمال ()query_posts، مع العلم أنّ وجود هذه الدّالّة ضمن القائمة لتوضيح لماذا لا يجب استخدامها، فالدّالّة ()query_posts هي دالّة غير عمليّة ولا يُمكن الاعتماد عليها في تعديل وتحسين الاستعلام الرئيسي، فبدلًا من تحسين وتعديل الاستعلام الرئيسي فهي تجلب الاستعلام الرئيسي ومن ثُمّ توقفه وتبدأ مرّة أخرى بإعادة تنفيذه مع التغيرات المُدخلة، الأمر الّذي سيؤثّر على أداء الموقع، ومن المُمكن جدًا أنّ لا تعمل كما يجب لدى استخدامها مع التّصفيح pagination. تسمح الطرق المتبقية في إنشاء استعلام جديد: باستخدام الصنف WP_Query، وهي طريقة مرنة جدًا في إنشاء استعلام جديد، ويُستخدم هذا الصنف (class) عند إنشاء حلقة (loop) ثانية في ملفّ القالب (template file) أو عند إنشاء ملفّ قالب باستعلام مُخصّص كليًّا لاستبدال الحلقة الرئيسية (main loop)، ولكن يجب الحذر في استخدامه، وتأتي الخطورة في عدم تصفير (reset) الاستعلام بعد تنفيذ الحلقة (loop)، والّذي يعني أنّ ووردبريس لن يكون قادرًا على التعرّف بشكلٍ صحيح ما نوع الصّفحة الّتي يتمّ عرضها، ولكن من المُمكن حل هذه المشكلة بسهولة. دالّة/وسم القالب ()get_posts، وتُستخدم في ملفّ القالب (template) (بما في ذلك الشريط الجانبي sidebar وذيل الصّفحة على سبيل المثال) لجلب قائمة المنشورات، ويَستخدم الصنف WP_Query لعمل ذلك، ويُمكن استخدام مُعامِلات (parameters) معه لتحديد المنشورات المطلوبة. دالّة/وسم القالب ()get_pages، والّتي تعمل بنفس طريقة عمل ()get_posts، ولكن في جلب الصفحات بدلًا من المنشورات. سيتم التطرّق إلى أهم هذه الطرق بمزيد من التفصيل بعد أنّ تمّ عرضهم بشكل سريع. الخطاف الإجرائي pregetposts إن الدّالّة pre_get_posts هي خطّاف إجرائي (action hook)، وبالتالي يُمكن ربط دالّة معها لجعل شيء ما يحدث في الوقت الذي يُنفّذ ووردبريس الإجراء pre_get_posts، وكما هو واضح، يُنفّذ ووردبريس هذا الإجراء (action) مباشرةً قبل جلب المنشورات من قاعدة البيانات، ولذلك فإن أي دالّة يتمّ ربطّها معها ستؤثّر في كيفيّة جلب ووردبريس لتلك المنشورات. إن استخدام الدّالّة pre_get_posts يتطلّب إنشاء دالّة ومن ثُمّ ربطّها مع الإجراء، كما في التّالي: <?php function my_function() { // contents of function go here } add_action( 'pre_get_posts', 'my_function'); ?> أوّلًا، تمّ إنشاء الدّالّة وبالاسم my_function وما ستفعله هذه الدّالّة سيكون داخل الحاصرتين (braces). ثانيًا، تمّ ربط تلك الدّالّة مع الخطّاف pre_get_posts باستخدام الدّالّة ()add_action، وبدون ذلك لن تعمل الدّالّة. سيتمّ الحاجة غالبًا بالإضافة إلى ما سبق، إلى تضمين وسم/دالّة شرطيّة داخل الدّالّة المنشأة، فبدونها لن يقوم ووردبريس بتنفيذ الدالة المُنشأة كل مرّة يتمّ فيها جلب المنشورات، بما في ذلك عند التعامل مع المنشورات في الصفحات الإداريّة (admin)، وعليه ستكون الدالة المُنشأة بالشكل التّالي: <?php function my_function() { if ( !is_admin() && $query_>is_main_query() ) { // contents of function go here } } add_action( 'pre_get_posts', 'my_function'); ?> تمّ في الشيفرة السابقة، التأكّد من أنّ الصّفحة ليس صفحة إداريّة (admin) وأيضًا أنّ الاستعلام الّذي يتمّ تنفيذه هو الاستعلام الرئيسي (main query)، ومن المهم التأكّد من أن ووردبريس يُنفّذ الاستعلام الرئيسي تجنبًا للمشاكل المحتملة عند تنفيذ الدّالّة من أجل استعلامات إضافية قد تم إنشاؤها، كما يُمكن إضافة وسوم/دوال شرطيّة إضافيّة هنا كما سيتمّ لاحقًا. إدراج أنواع منشورات مخصصة في صفحة المدونة الرئيسية يَعرض ووردبريس بشكلٍ افتراضي قائمة بالمنشورات فقط في صفحة البداية (homepage) فإن تمّ إنشاء نوع منشورات مخصصة، فسيفترض ووردبريس أنّ المُراد هو عرضها في مكان آخر وعدم تضمينهم هنا، ولكن أحيانًا قد يُرغب في عرض أكثر من نوع منشور واحد في صفحة البداية (home page) وفي هذه الحالة يجب استخدام الخطّاف pre_get_posts. ويتم ذلك عبر إضافة الشيفرة التّالية إلى الملفّ functions.php الخاصّ بالقالب (theme) أو الإضافة المُنشأة. <?php function my_function() { if ( is_home() && $query->is_main_query() ) { $query->set( 'post_type', array( 'post', 'custom_post_type') ); return $query; } } add_action( 'pre_get_posts', 'my_function'); ?> تتأكّد الشيفرة السابقة من أمرين اثنين، أوّلًا فيما إذا كان الاستعلام هو الاستعلام الرئيسي وثانيًا فيما إذا كانت الصّفحة هي صفحة البداية (باستخدام الدالة ()is_home) بعد ذلك يتمّ تعيين (set) الاستعلام ليتضمّن نوعين من المنشورات: هما 'post' و 'customposttype'، ليكونا نوع المنشور المُخصّص، مع مُلاحظة وجوب تضمين 'post' هنا إن كان المرغوب من صفحة البداية أن تَعرض المنشورات أيضًا بالإضافة إلى نوع المنشور المخصّص، وفي حال إضافة custom_post_type فقط، سيتمّ استبدال السلوك الافتراضي وعرض المنشورات من نوع المنشور المخصّص، وقد يكون هذا المرغوب في بعض الحالات ولكن ليس في المثال الحالي. عرض منشورات من نوع المنشور المخصص في صفحة أرشيف التصنيف يَفترض هذا المثال أنه عندما تمّ تسجيل نوع المنشورات المُخصّصة، فقد تمّ منحها دعمًا للتصنيفات (categories) وتم إسناد التصنيفات إلى منشورات نوع المنشور المُخصّص، ولتعديل أرشيفات التصنيفات لكي تَعرض منشورات نوع المنشور المُخصّص يُستخدم التّالي: <?php function my_function() { if ( is_category() && $query->is_main_query() ) { $query->set( 'post_type', 'custom_post_type' ); return $query; } } add_action( 'pre_get_posts', 'my_function'); ?> تتأكّد الشيفرة السابقة من أنّ الاستعلام المُنفّذ هو الاستعلام الرئيسي والصفحة هي أرشيف التصنيفات وذلك باستخدام الدالة ()is_category، ومن ثُمّ تمّ التعديل على الاستعلام ليجلب منشورات نوع المنشور المُخصّص، وبما أنّه لم يتمّ تضمين 'post' هنا، فإن المنشورات الاعتياديّة لن يتمّ عرضها في أيٍ من أرشيفات التصنيفات، بالإضافة إلى أنّه لن يتمّ الحاجة إلى استخدام مصفوفة بما أنّه تمّ تحديد نوع منشور واحد. إنّ كان المطلوب هو التحديد بدقة أكبر فيُمكن تحديد نوع مُعيّن من التصنيفات كما في التّالي: <?php function my_function() { if ( is_category( 'category-slug' ) && $query->is_main_query() ) { $query->set( 'post_type', 'custom_post_type' ); return $query; } } add_action( 'pre_get_posts', 'my_function'); ?> سيتمّ في الشيفرة السابقة التعديل الاستعلام الرئيسي في صفحة الأرشيف category-slug فقط، حيثُ أنّ category-slug هو الاسم اللطيف (slug) للتصنيف (category). تغيير طريقة ترتيب المنشورات لن يتعامل المثال الأخير مع ما هي البيانات الّتي يتمّ استعلامُها بل مع كيف يتمّ عرضها/خَرْجُها (output)، فمثلًا في صفحات أرشيف التصنيفات (category archive) وعند عدم الرغبة في ترتيب المنشورات بواسطة التاريخ ولكن بالترتيب الأبجدي، يُمكن استخدام pre_get_posts كما في التّالي: <?php function my_function() { if ( is_category() && $query->is_main_query() ) { $query->set( 'orderby', 'title'); $query->set( 'order', 'ASC' ); return $query; } } add_action( 'pre_get_posts', 'my_function'); ?> تمّ في الشيفرة السابقة استعمال المُعامِل orderby والمُعامِل order لتحديد بناءً على ماذا ستُرتّب المنشورات وكيف ستُرتّب وذلك عند عرضها، وللمزيد من المُعامِلات (parameters) الّتي يُمكن استخدامها مع pre_get_posts يُمكن الرجوع إلى التوثيق الرسميّ للصنف WP_Query والّذي يستخدم نفس المُعامِلات. الصنف WP_Query يُعتبر الصنف WP_Query الطريقة الأفضل لكتابة استعلام مُخصّص، ويُستخدم عند الرغبة في استبدال الاستعلام الرئيسي (main query) باستعلام جديد أو عند الرغبة في إضافة استعلام جديد بالإضافة إلى الاستعلام الرئيسي. أجزاء الصنف WP_Query: المُعطيات (arguments) للاستعلام، وذلك باستخدام المُعامِلات (parameters) بشكل مُشابه إلى الّتي قد تُستخدم مع أجل pre_get_posts. الاستعلام نفسه. الحلقة (loop). الإنهاء: وذلك بإغلاق وسوم if و while، وتصفير (reset) بيانات المنشور. ستكون الشيفرة على النحو التّالي: <?php $args = array( // arguments for your query ); // the query $query = new WP_Query( $args ); // The Loop if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post() : // contents of the Loop go here endwhile : endif; /* Restore original Post Data */ wp_reset_postdata(); ?> كما هو واضح إن الأمر أكثر تعقيدًا من استخدام pre_get_posts وهو أحد الأسباب لتجنّب استخدام الطريقة السابقة عندما يكون المطلوب هو التعديل على الاستعلام الرئيسي، ولكن السبب الرئيسي لتجنّب استخدامها هو أنها ستُجهد سكريبت ووردبريس نفسه، الأمر الّذي قد يؤثّر على أداء الموقع بالمُجمل. سيتمّ إلقاء نظرة على مثال للتوضيح أكثر، حيثُ سيتمّ إضافة حلقة (loop) ثانية بعد محتوى المنشور في ملفّ القالب (template) المُسمّى single.php، لعرض قائمة بالمنشورات المُميّزة، حيثُ تمّ تعريف هذه المنشورات المُميّزة باستخدام التصنيف "featured" (مُميّز)، ولكل واحدة من هذه المنشورات سيتمّ عرض الصورة المُميّزة والعنوان (title) مع الروابط الّتي تُحيل إلى المنشور: <?php $args = array( 'post_type' => 'post', 'posts_per_page' => '4', 'post__not_in' => array( $post->ID ) ); // the query $query = new WP_Query( $args ); // The Loop if ( $query->have_posts() ) { ?> <section class="recent-posts clear"> <?php while ( $query->have_posts() ) : $query->the_post() ; ?> <article id="post-<?php the_ID(); ?>" <?php post_class( 'left' ); ?>> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"> <?php post_thumbnail( 'thumbnail' );?> </a> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"> <?php the_title(); ?> </a> </article> <?php endwhile; ?> </section> <?php } /* Restore original Post Data */ wp_reset_postdata(); ?> تَستخدم الشيفرة السابقة ثلاثة مُعطيات (arguments) لاستعلام البيانات: 'post_type' => 'post' لجلب المنشورات فقط. 'posts_per_page' => '4' لجلب أربعة منشورات فقط. (post__not_in' => array($post->ID' للتأكيد على أنّ المنشور الّذي يُعرض حاليًا غير مُضمّن. ستُخرج (output) الشيفرة بعدها أربعة منشورات في حلقة (loop) والّتي تَعرض الصورة المُميّزة والعنوان (title) كلٍ محتوى داخل رابط يُحيل إلى صفحة المنشور، ومن المُمكن استخدام CSS للتنسيق، أو توضيعهم جنبًا إلى جنب أو في عرض شبكي (grid) أو حتّى جعل العنوان يتداخل مع الصورة. وسم/دالة القالب ()get_posts يُمكن اللجوء إلى get_posts عند عدم الحاجة إلى تلك المرونة الّتي يُقدمها الصنف WP_Query، وعليه فمن المُمكن الاستفادة منها في تطبيق المثال الأخير، مع العلم أنّ الوسم/الدالة get_posts ما هي إلا وسم قالب (template tag) يَستخدم الصنف WP_Query ويُمكن استخدامه بطريقة مُشابهة إلى WP_Query. يُمكن إنشاء قائمة بالمنشورات الأربعة الأخيرة باستخدام ()get_posts كما تمّ مع WP_Query على النحو التّالي: <?php $args = array( 'posts_per_page' => '4', 'exclude' => array( $post->ID ) ); // get posts $posts = get_posts( $args ); // check if any posts are returned if ( $posts ) { ?> <section class="recent-posts clear"> <?php foreach ($posts as $post ) { ?> <?php setup_postdata( $post ); ?> <article id="post-<?php the_ID(); ?>" <?php post_class( 'left' ); ?>> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"> <?php post_thumbnail( 'thumbnail' );?> </a> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"> <?php the_title(); ?> </a> </article> <?php } ?> </section> <?php } /* Restore original Post Data */ wp_reset_postdata(); ?> تُشبه الشيفرة السابقة إلى حدٍ كبير جدًا شيفرة مثال الصنف WP_Query السابقة، ولكن مع اختلاف طفيف: لا يجب على المُعطيات (arguments) أنّ تُضمّن نوع المنشور. تمّ استخدام المُتغيّر posts$ لتخزين خَرْج (output) المصفوفة باستخدام ()get_posts. بدلًا من التأكّد فيما إذا كان الاستعلام يملك منشورات، تمّ استخدام (if($posts في ذلك. بدلًا من استخدام حلقة (loop) معياريّة (standard)، تمّ استخدام (foreach ($posts as $post، والّتي ستُكرّر لكل صفّ (row) في المصفوفة. للوصول إلى جميع بيانات المنشور المطلوبة تمّ تضمين (setup_postdat($post. بما أنّ الدّالّة ()get_posts تستخدم الصنف WP_Query، فلا فرق يُذكر بين الاثنين عامّةً، ولذلك يميل بعض المُطوّرين إلى استخدام الصنف WP_Query بما أنّه يُقدّم مرونةً أكبر، مع ذلك يُمكن أنّ تكون الدّالّة ()get_posts أكثر نفعًا عند الرغبة من التأكّد إن كان يوجد أي منشورات مع المُعطيات (arguments)، عندها يُمكن خَرْج (output) الشيفرة اعتمادًا على وجود أية منشورات، من دون الضرورة إلى استخدام حلقة (loop). دالة/وسم القالب ()get_pages تُشبه الدّالّة ()get_pages إلى حدٍ كبيرٍ الدّالّة ()get_posts وهي تستخدم الصنف WP_Query ولكن في جلب الصفحات الثابتة (static pages) بدلًا من المنشورات، ومن الأمثلة الّتي تُستخدم بها: إن كان الموقع يملك مجموعة من الصفحات الهامّة ومن النوع top level، وكان الطلوب إضافة قائمة لها في الشريط الجانبي (sidebar) لكي يتمّ تنسيق روابطها وتشجيع الزوار إلى الذهاب إلى هذه الصفحات، فعندها وفي الملفّ sidebr.php يُمكن إضافة الشيفرة التّالية: <?php $args = array( 'parent' => 0, 'sort_order' => 'ASC', 'sort_column' => 'post_title', ); // get posts $pages = get_pages( $args ); // check if any posts are returned if ( $pages ) { ?> <ul class="sidebar-pages"> <?php foreach ( $pages as $page ) { ?> <li> <a href="<?php echo get_page_link( $page->ID ); ?>"> <?php echo $page->post_title; ?> </a> </li> <?php } ?> </ul> <?php } ?> تفاصيل الشيفرة السابقة هي كالتّالي: أوّلًا تمّ تعريف المُعطيات حيثُ أنّ parent' => 0' ستُعيد الصفحات الّتي هي بدون صفحة بداية، بينما بقيّة المُعطيات ستُحدّد كيف ستُرتّب هذه الصفحات. تمّ بعد ذلك استخدام ()get_pages وتمرير مصفوفة المُعطيات وتخزينها في المُتغيّر pages$. بعد ذلك تمّ التأكّد فيما إذا كان المُتغيّر pages$ يحتوي على أية بيانات وذلك باستخدام (if($pages. وفي حال توفّر الصفحات سيتمّ عرضها من خلال عناصر قائمة (list item). وبدلًا من استخدام ()setup_postdata كما تمّ مع ()get_pages، فقد تمّ استخدام المُتغيّر post$ مُباشرةً وبوسوم قالب (template) مُختلفة والّتي ستُخرج (output) الرابط والعنوان (title)، ومن الضروري استخدامها هنا بسبب عدم استخدام ()setup_postdata. وبسبب عدم استخدام ()setup_postdata فلا داعي لاستخدام ()wp_reset_postdata. إن طريقة الشيفرة السابقة هي طريقة أكثر عمليّة في خَرْج (output) قائمة من الصفحات من طريقة استخدام الصنف WP_Query وبكل ما يملكنه من إمكانيات. الختام إن التعديل على الاستعلام الرئيسي أو كتابة استعلامات جديدة هي مهارة ليجب الاهتمام بها وتطويرها خاصّة إن كان المطلوب هو إنشاء قوالب (themes) مُخصّصة أو إضافات (plugins) أو تطوير مواقع مُعقّدة للعُملاء. تمّ التطرّق إلى الطرق الخمس في إنشاء استعلامات مُخصّصة، ولكن أربعة منها فقط يُمكن استخدامها: pre_get_posts للتعديل على الاستعلام الرئيسي. WP_Query لإنشاء استعلامات مُخصّصة ومُعقّدة. ()get_posts و ()get_pages وذلك للاستعلامات المُخصّصة والبسيطة في جلب المنشورات والصفحات. يُمكن الخلط والمزج بين الطرق السابقة وذلك لإنشاء مواقع ووردبريس مُتقدّمة ولعرض البيانات بالكيفيّة المطلوبة. ترجمة -وبتصرّف- للمقال 5Simple Methods for Creating Custom Queries in WordPress لصاحبته Rachel McCollin.
  10. ماهو MySQL؟ MySQL هو برنامج لإدارة قواعد البيانات Database Management System, DBMS يُساعد مستخدميه في تخزين، تنظيم والعثور على البيانات. ينتشر استخدامُ MySQL في مواقع الويب نظرًا لميزاته والمرونة الّتي يُوفّرها. نهدِف في هذا الدّرس تقديم أساسيّات استخدام MySQL بطريقة مُيَسَّرة وسهلة. كيف يُثَبَّت برنامج MySQL على توزيعتيْ Ubuntu وCentOS؟ يُمكِن تنزيلُ وتثبيتُ MySQL سريعًا عبر برنامج إدارة الحزم الخاصّ بالتّوزيعة. 1- على Ubuntu: sudo apt-get install mysql-server 2- على CentOS: sudo yum install mysql-server /etc/init.d/mysqld start ملحوظة: أثناء تثبيت MySQL سيُطلب منك إدخال ثمّ تأكيد كلمة سرّ للمستخدِم الجذر Root user في MySQL (انتبه إلى أنّ المُستخدم الّذي نتحدّث عنه هنا ليس هو المستخدِم الجذر في الخادوم، بل مستخدم جذر آخر خاصّ بـMySQL). كيف يكون الاتصال بالصدفة Shell الخاصة بـ MySQL؟ يُمكن - بعد التّثبيت - الاتّصال بMySQL عن طريق صَدَفة ولوج خاصّة عبر تنفيذ الأمر التّالي: mysql -u root -p سيُطلب منك إدخال كلمة سر المُستخدم الجذر في MySQL. يُمكنك بعدها البدء في بناء قواعد بيانات في MySQL. ينبغي الانتباه للنّقطتيْن التّاليّتيْن: تنتهي كلّ أوامر MySQL بنقطة-فاصلة إنجليزيّة (;). إن لم تختِم جملةً من أوامر MySQL بنقطة-فاصلة فلن تُتنفّذ هذه الأوامر. تُكتَب أوامرُ MySQL بأحرف كبيرة Uppercase وأسماءُ كلّ من قواعد البيانات، المُستخدمين، الجداول Tables والنّصوص بأحرف صغيرة. هذه النّقطة ليست إجبارية؛ سطرُ أوامر MySQL لا يتأثّر بحالة الأحرف Case insensitive ولكن التّفريق المذكور يجعلُ من التّمييز بين الأوامر وغيرها أكثر سهولة. إنشاء وحذف قاعدة بيانات MySQL يُنظِّم MySQL معلوماتِه في قواعد بيانات تتضمّن كلّ واحدة منها جداول ببيانات مُحدَّدة. يُمكنك عرض قواعد البيانات الموجودة في MySQL عبر الأمر التّالي (يُنفَّذ في صَدَفة MySQL وليس سطر أوامر النّظام): SHOW DATABASES; يجب أن يبدو محتوى الشّاشة لديك مشابِهًا لما يلي: mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.01 sec) من اليسير إنشاءُ قاعدة بيانات عن طريق الأمر التّالي(حيثُ database name يُمثّل اسمَ قاعدة البيانات): CREATE DATABASE database name; لإنشاء قاعدة بيانات باسم events مثلًا نُنفّذ الأمر: CREATE DATABASE events; نُعيد عرضَ قواعد البيانات الموجودة في MySQL: mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | events | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec) نُلاحِظ وجود قاعدة البيانات الّتي أنشأناها للتّو. تُستخدم غالبًا عبارة DROP لحذف الكائنات Objects في MySQL. إذا أردتَ حذفَ قاعدة بيانات فالأمر المناسب هو DROP DATABASE، كما يلي (حيثُ database name اسم قاعدة البيانات المُراد حذفُها): DROP DATABASE database name; استخدام قاعدة بـيانات في MySQL نبدأ بملْء قاعدة البيانات بعدَ إنشائها عبر إضافة معلومات إليها. أولّ خطوة هيّ إنشاء جدول جديد داخل قاعدة البيانات. يتوجّب أوّلًا فتح قاعدة البيانات المُراد استخدامُها عبر الأمر التّالي: USE events; يُمكن -كما فعلنا مع قواعد البيانات- عرضُ الجداول الموجودة في قاعدة البيانات الّتي نستخدمُها الآن: SHOW tables; تظهر، عندَ تنفيذ الأمر السّابق رسالة Empty set (مجموعة خاليّة) دلالةً على عدم وجود جداول في قاعدة البيانات. هذه النّتيجة طبيعيّة جدًّا نظرًا لجِدّة قاعدة البيانات. إنشاء جدول في قاعدة بيانات MySQL نفترِض أنّنا نُخطّط لحَدَث يجمع بعضَ الأصدقاء. سنستخدم MySQL لتتبّع تفاصيل هذا الحدث. نُنشئ جدولًا في MySQL لهذا الغرض (تذكّر أننا نستخدم قاعدة بيانات باسم events أي أنّ الجدول الّذي سنُنشئه سيكون ضمن قاعدة البيانات هذه): CREATE TABLE potluck (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), food VARCHAR(30), confirmed CHAR(1), signup_date DATE); نفّذنا عبر الأمر أعلاه الإجراءات التّالية: إنشاء جدول باسم potluck ضمن قاعدة البيانات events. إنشاء خمسة أعمِدة ضمن الجدول potluck. هذه الأعمدة هيّ: id (المُعرِِّف)، name (الاسم)، food (الطّعام)، confirmed (حضور مؤكَّد) و signup date (تاريخ التّسجيل). تطبيق الأمر INT NOT NULL PRIMARY KEY AUTO_INCREMENT للعمود id من أجل إعطاء عدد صحيح (INT في الأمر) أتوماتيكيًّا لكل صف جديد. قصرُ العمود name على عدد محارِف لا يتجاوز العشرين (20)VARCHAR. نفس الشيء بالنّسبة للعمود food الّذي يُمثِّل متعلّقات الطّعام الّتي سيجلبها كل واحد من الأصدقاء. اسم الطّعام مُكوّن من محارِف لا يتجاوز عددها الثّلاثين (30)VARCHAR. تسجيل تأكيد الحضور عبر العمود confirmed المُكوّن من محرف واحد فقط (1)CHAR. عند تأكيد الحضور نكتب Y وإلّا N. حفظ تاريخ التّسجيل عبر العمود signup_date. يطلُب MySQL كتابة التّاريخ على الشّكل yyyy-mm-dd، حيثُ yyyy السّنة مكتوبة على 4 أرقام، وmm الشهر في رقمين وdd اليوم في رقميْن أيضًا. 01-01-2015 تاريخ بصيغة صحيحة. ملحوظة: كلّ من CHAR و VARCHAR يُستخدَم للدّلالة على أن العمود يحوي محارف مع تحديد طول المحتوى، ولكن طول المحتوى من نوع CHAR ثابت، أي أنّه يجب أن يكون مساويًّا للعدد بين قوسيْن؛ في حين أنّ طول المحتوى من نوع VARCHAR متغيِّر والعدد المُذكور هو الطّول الأقصى المسموح به. نُعيد عرض الجداول الموجودة في قاعدة البيانات events: mysql> SHOW TABLES; +------------------+ | Tables_in_events | +------------------+ | potluck | +------------------+ 1 row in set (0.01 sec) نُلاحِظ ظهور الجدول potluck. إن أردتَ عرض تنظيم الجدول potluck فالأمر DESCRIBE يؤدّي هذه الوظيفة: DESCRIBE potluck; انتبِه إلى أنّ أسماء الجداول وقواعد البيانات في MySQL حسّاسة لحالة الأحرف، رغم أنّ سطر الأوامر ليس كذلك. جدول باسم potluck ليس هو نفسُه جدول Potluck أو POTLUCK. mysql>DESCRIBE potluck; +-------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | food | varchar(30) | YES | | NULL | | | confirmed | char(1) | YES | | NULL | | | signup_date | date | YES | | NULL | | +-------------+-------------+------+-----+---------+----------------+ 5 rows in set (0.01 sec) إضافة معلومات إلى جدول في MySQL لدينا الآن جدول لتنظيم معلومات الحدَث، بقي ملؤه بالبيانات اللّازمة. استخدِم الأمرَ التّالي لإضافة صف بيانات جديد: INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "John", "Casserole","Y", '2012-04-11'); يُضيف هذا الأمر مُشاركًا جديدًا في الحدث اسمُه John وسيأتي بطنجرة (Casserole)؛ سجّلَ بتاريخ 2012-04-11 وأكّد حضوره (Y). المُعرّف سيُملأ أوتوماتيكيًّا لذا وضعنا NULL مكان العمود الأول. ستظهر بعد تنفيذ الأمر رسالة شبيهة بالتّاليّة: Query OK, 1 row affected (0.07 sec) نُضيف مشاركين جددًا بتفاصيل مختلفة إلى جدول المُشاركين عبر الأوامر التّاليّة: INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "Sandy", "Key Lime Tarts","N", '2012-04-14'); INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "Tom", "BBQ","Y", '2012-04-18'); INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "Tina", "Salad","Y", '2012-04-10'); لعرض جميع البيانات الموجودة في الجدول نستخدم الأمر أدناه. علامة * تعني معلومات جميع الأعمدة. mysql> SELECT * FROM potluck; +----+-------+----------------+-----------+-------------+ | id | name | food | confirmed | signup_date | +----+-------+----------------+-----------+-------------+ | 1 | John | Casserole | Y | 2012-04-11 | | 2 | Sandy | Key Lime Tarts | N | 2012-04-14 | | 3 | Tom | BBQ | Y | 2012-04-18 | | 4 | Tina | Salad | Y | 2012-04-10 | +----+-------+----------------+-----------+-------------+ 4 rows in set (0.00 sec) إن أردنا الاقتصار على المعلومات الموجودة في بعض الأعمدة وليس كلّها نذكر الأعمدة المعنيّة هنا. مثلا إن أردنا فقط الأسماء والأطعمة ننفّذ الأمر: SELECT name, food FROM potluck; تحديث بيانات موجودة في جدول MySQL يُتيح MySQL إمكانيّة تغيير بيانات موجودة في جدول. في المثال السّابق أضفنا مشارِكةً باسم Sandy. هذم المُشارِكة لم تؤكّد الحضور (قيمة العمود confirmed هي N). أبلغتْنا الآن بأنّها تأكّدت من حضورها. لتحديث عمود confirmed بالنّسبة لـsandy نُنفذ الأمر: UPDATE `potluck` SET `confirmed` = 'Y' WHERE `potluck`.`name` ='Sandy'; يُفهم الأمر أعلاه كما يلي: حدّث بيانات الجدول potluck بضبط عمود confirmed على القيمة Y إذا كانت قيمة العمود name تُساوي Sandy. كما تُلاحظ يوجد شرط للتّحديث وهو الاسم = Sandy. يُمكن أيضًا استخدامُ هذا الأمر لإضافة بيانات إلى خليّة (تقاطع عمود وصفّ) حتى ولو كانت خاويّة. إضافة أوحذف عمود من جدول في MySQL أنشأنا جدولًا ببيانات مُفيدة، ولكن تنقُصُنا معلومة مهمّة: البريد الإلكتروني للمُشترك؛ لذا سنُضيف عمودًا جديدًا نُخزّن فيه هذه المعلومة. ALTER TABLE potluck ADD email VARCHAR(40); يقول هذا الأمر "غيّر الجدول potluck عن طريق إضافة عمود جديد باسم email لا يتجاوز المُحتوى فيه 40 محرفًا". يُضاف هذا العمود افتراضًا في آخر الجدول، إذا كنتَ تُريد وضعَه في مكان مُعيّن يُمكن ذلك كما يلي: ALTER TABLE potluck ADD email VARCHAR(40) AFTER name; أي أنّ العمود الجديد سيُضاف بعد (AFTER) العمود name. بالنّسبة لحذف عمود فهو مُشابه لإضافته: ALTER TABLE potluck DROP email; حذف صفّ من جدول يُمكن إن اقتضت الحاجة حذف صفوف من الجدول عبر الأمر التّالي: DELETE from [table name] where [column name]=[field text]; حيثُ [table name] اسم الجدوَل ، [column name] اسم العمود و[field text] هيّ قيمة العمود في الصّف. نفرض مثلًا أنّنا نُريد حذف Sandy من قائمة المُشاركين: mysql> DELETE from potluck where name='Sandy'; Query OK, 1 row affected (0.00 sec) أي احذَف الصّف الّذي تُساوي فيه قيمةُ عمود الاسم Sandy. في حال وجود أكثر من شخص بهذا الاسم فسيُحذف جميع هؤلاء الأشخاص. نُعيد عرض محتوى الجدول بعد تنفيذ أمر الحذف: mysql> SELECT * FROM potluck; +----+------+-----------+-----------+-------------+ | id | name | food | confirmed | signup_date | +----+------+-----------+-----------+-------------+ | 1 | John | Casserole | Y | 2012-04-11 | | 3 | Tom | BBQ | Y | 2012-04-18 | | 4 | Tina | Salad | Y | 2012-04-10 | +----+------+-----------+-----------+-------------+ 3 rows in set (0.00 sec) لاحِظ عدم تغيّر معرّف أي واحد من المُشتركين المتبقّين. ترجمة -وبتصرّف- للمقال A Basic MySQL Tutorial لصاحبته Etel Sverdlov.
  11. تُستخدَم قواعد البيانات العلاقيّة منذ وقت طويل. لقد اكتسبت قواعد البيانات من هذا النوع شُهرة بفضل أنظمة إدارتها التي تستخدم النموذج العلاقيّ بشكل جيّد للغاية، وهو النموذج الذي أثبت نفسه كطريقة رائعة للتعامل مع البيانات وخاصة في التطبيقات ذات المهام الحرجة. سنحاول في هذا المقال شرح الفروقات الرئيسيّة في بعض أكثر أنظمة إدارة قواعد البيانات العلاقيّة (RDBMS) شُهرة واستخدامًا. سنستكشف الفروقات الرئيسيّة بينها من حيث المزايا والأداء الوظيفيّ، وكيفية عملها، ومتى تتفوق إحداها على الأخرى، وذلك من أجل مساعدة المطورين على اختيار نظام إدارة قواعد بيانات علاقية (RDBMS). أنظمة إدارة قواعد البياناتقواعد البيانات هي مساحات تخزين مرتبة منطقيًّا لكل الأنواع المختلفة من المعلومات (البيانات). لكل نوع من قواعد البيانات –باستثناء عديمة المخطط– نموذج يقدم هيكلة للبيانات التي يتم التعامل معها. أنظمة إدارة قواعد البيانات هي تطبيقات (أو مكتبات) تدير قواعد البيانات بأشكالها وأحجامها وأنواعها المختلفة. أنظمة إدارة قواعد البيانات العلاقيةتستخدم أنظمة قواعد البيانات العلاقيّة النموذج العلاقيّ للعمل على البيانات. يشكّل النموذج العلاقيّ المعلومات التي ستُخَزَّن مهما كان نوعها، وذلك بتعريفها ككيانات مترابطة ذات خصائص تتعدى الجداول (أي مخططات). تتطلب أنظمة إدارة قواعد البيانات من هذا النوع أن تكون البُنى (كالجداول مثلًا) معرّفة لتحوي بيانات وتتعامل معها. لكلّ عمود (مثل الخصائص) في الجداول نوعٌ مختلف من المعلومات (نوع البيانات). يُترجَم كلّ سجلّ في قاعدة البيانات –مُعرّف بمفتاح فريد– إلى صفّ ينتمي إلى جدول، وتكون مجموعة خصائص كل سجل معروضة كأعمدة للجدول. وتكون كلها مرتبطة ببعضها كما هو محدد في النموذج العلاقيّ. العلاقات وأنواع البياناتيمكن اعتبار العلاقات مجموعات حسابية تحوي مجموعة من الخصائص التي تشكّل معًا قاعدة البيانات والمعلومات المحفوظة فيها. تسمح هذه الطريقة في التعريف والتجميع لقواعد البيانات العلاقيّة بالعمل بالطريقة التي تعمل بها. عند تعريف جدول لإدخال سجلات، يجب أن يطابق كلّ عنصر يشكل سجلًّا (كالصفة attribute مثلًا) نوع البيانات المحدّد له (كأن يكون عددًا صحيحًا أو تاريخًا مثلًا). تستخدم أنظمة إدارة قواعد البيانات العلاقيّة أنواعًا مختلفة من البيانات ولا يمكن في العادة تبديل واحدة من هذه الأنواع مكان الأخرى. التعامل مع وعبر قيود –كالتي ذكرناها قبل قليل– شائع مع قواعد البيانات العلاقيّة. في الحقيقة، تشكّل القيودُ مركزَ العلاقات. ملاحظة: إذا كنت تحتاج للتعامل مع معلومات غير مترابطة إطلاقًا وممثلة عشوائيًّا (كالمستندات مثلًا)، فقد تكون مهتمًّا باستخدام NoSQL (قواعد البيانات عديمة المخططات schema-less). قواعد بيانات علاقية شائعة وهامةسنتعرف في هذا المقال على ثلاثة أنواع رئيسيّة وهامّة من أنظمة إدارة قواعد البيانات العلاقيّة مفتوحة المصدر التي ساهمت في تكوين عالم تطوير البرمجيات: SQLite: نظام إدارة قواعد بيانات علاقيّة مضمّن وقويّ جدًّا.MySQL: نظام إدارة قواعد البيانات العلاقيّة الأشهر والأكثر استخدامًا.PostgreSQL: نظام إدارة قواعد البيانات العلاقيّة الكيانيّ مفتوح المصدر المتوافق مع SQL الأكثر تقدّمًا.ملاحظة: تقريبًا دائمًا تتيح التطبيقات مفتوحة المصدر حريّة استخدام الطريقة التي تريدها. وفي غالب الأحيان تسمح لك أيضًا إنشاء تفرّع (fork) عن المشروع (وبالتالي استخدام نصوصه البرمجيّة) لإنشاء شيء جديد. إذا كنت مهتمًّا بأنظمة إدارة قواعد البيانات، فقد ترغب بالاطلاع على بعض المشاريع المتفرّعة المبنية على هذه المشاريع الشهيرة، مثل MariaDB. SQLite إنّ SQLite مكتبة رائعة تُضمَّن في التطبيقات التي تستخدمها. وكونها قاعدة بيانات قائمة بذاتها ومعتمدة على الملفات. تقدّم SQLite مجموعة رائعة من الأدوات للتعامل مع كل أنواع البيانات بقيود أقلّ بكثير وسهولة مقارنة بقواعد البيانات المستضافة المعتمدة على العمليات (خواديم قواعد البيانات). عندما يستخدم برنامج ما SQLite، يعمل هذا التكامل بنداءات (calls) مباشرة ومؤدية للغرض موجهة لملف يحوي البيانات (كقاعدة بيانات SQLite) بدلًا من التواصل عبر واجهة من نوع ما (كالمنافذ ports والمقابس sockets). هذا يجعل SQLite كفؤة وسريعة للغاية، وقويّة كذلك، وهذا بفضل التقنية التي بنيت عليها هذه المكتبة. أنواع البيانات التي تدعمها SQLite:NULL: قيمة فارغة NULL.INTEGER: عدد صحيح ذو إشارة (موجب أو سالب) محفوظ في بايت واحد، 2، 3، 4، 6، أو 8 بايت، وهذا يعتمد على حجم القيمة.REAL: قيمة النقطة العائمة (floating point)، مخزنة كرقم نقطة IEEE عائمة ذي 8-بايت.TEXT: سلسلة نصيّة مخزنة باستخدام ترميز قاعدة البيانات (UTF-8, UTF-16BE or UTF-16LE).BLOB: فقاعة من البيانات، تخزّن كما أدخِلَت تمامًا.ملاحظة: لمعرفة المزيد عن أنواع بيانات SQLite والعلاقات بين أنواع SQLite، ألقِ نظرة على التوثيق الرسميّ حول الموضوع. مزايا SQLite:معتمدة على الملفات: تتكون قاعدة البيانات بأكملها من ملف واحد على القرص، مما يجعلها محمولة تمامًا.مدركة للمعايير: رغم أنها قد تبدو كتطبيق قواعد بيانات "بسيط"، إلّا أن SQLite تستخدم SQL. ورغم أنّها أزالت بعض المزايا ( RIGHT OUTER JOIN أو FOR EACH STATEMENT) إلّا أنها تحوي بداخلها مزايا أخرى إضافيّة.ممتازة للتطوير، بل وحتى للاختبار: أثناء مرحلة تطوير التطبيقات، في الغالب يحتاج أغلب الناس لحلّ يمكن تطويعه للطلبات المتعدّدة. لدى SQLite قاعدة مزايا غنيّة، ويمكنها تقديم أكثر مما تحتاجه للتطوير، وبسهولة العمل مع ملف وحيد ومكتبة مرتبطة مبنية على C.عيوب SQLite:لا توفّر إدارة للمستخدمين: تأتي قواعد البيانات المتقدّمة بإدارة للمستخدمين –فمثلًا، فيها اتصالات مُدارة بصلاحيات الوصول إلى قواعد البيانات والجداول–. وبأخذ هدف وطبيعة SQLite بعين الاعتبار (عدم وجود مستوىً عالٍ من تعدّد المستخدمين في ذات الوقت)، لا وجود لهذه الميزة.عدم توفر إمكانية التلاعب بها للحصول على أداء أفضل: ونظرًا لطبيعة تصميمها أيضًا، لا يمكن التلاعب بـ SQLite للحصول على قدر كبير من الأداء. المكتبة سهلة الضبط والاستخدام. وبما أنها ليست معقّدة، فلا يمكن تقنيًّا جعلها أكثر أداءًا مما هي عليه، وبشكل يفوق أداءها الحاليّ الرائع.متى تستخدم SQLite:التطبيقات المضمّنة: كلّ التطبيقات التي تحتاج لقابليّة النقل، والتي لا تحتاج لتحجيم، كتطبيقات المستخدم المحلي والوحيد، وتطبيقات الهاتف النقّال أو الألعاب.كبديل عن الوصول إلى القرص: في العديد من الحالات، يمكن أن تستفيد التطبيقات التي تحتاج للقراءة من والكتابة إلى الملفات على القرص مباشرة من الانتقال إلى SQLite من أجل المزيد من الوظائف والسهولة اللتان تأتيان من استخدام لغة الاستعلام البنيويّة (Structured Query Language – SQL).الاختبار: من التبذير أن تستخدم نسبة كبيرة من التطبيقات عمليّة إضافيّة لاختبار منطقيّة العمل (أي الهدف الرئيسيّ للتطبيق: الوظيفيّة).متى لا تستخدم SQLite:في التطبيقات متعدّدة المستخدمين: إذا كنت تعمل على تطبيق يحتاج فيه العديد من المستخدمين الوصول إلى نفس قاعدة البيانات واستخدامها، فالغالب أنّ مدير قواعد بيانات علاقيّ كامل المزايا (مثل MySQL) خيار أفضل من SQLite.في التطبيقات التي تحتاج لقدر كبير من الكتابة: من محدوديّات SQLite عمليات الكتابة. يسمح نظام إدارة قواعد البيانات هذا عملية كتابة واحدة وحيدة أن تتم في وقت محدّد، مما يسمح بقدر محدود من الدفق.MySQL تعد MySQL أشهر خوادم قواعد البيانات الكبيرة. وهو منتج مفتوح المصدر غنيّ بالمزايا، ويشغّل الكثير من المواقع والتطبيقات على الإنترنت. من السهل البدء باستخدام MySQL، ولدى المطورين وصول إلى كمّ هائل من المعلومات المتعلقة بقواعد البيانات على الإنترنت. ملاحظة: يجب أن نذكر أنّه نتيجة لشيوع المُنتَج، فإنّ هناك الكثير من تطبيقات الشركات الأخرى وأدواتها ومكتباتها المضمّنة التي تساعد كثيرًا في الهديد من نواحي العمل مع نظام إدارة قواعد البيانات العلاقيّة هذا. ورغم عدم محاولتها تطبيق معيار SQL كامل، إلّا أنّ MySQL تقدّم الكثير من الوظائف للمستخدمين. وكخادم SQL قائم بذاته، تتصل التطبيقات بعملية مراقب MySQL (وهو تطبيق يعمل في الخلفية بعيدًا عن مرأى المستخدم، ويشار إليه أحيانًا بعبارة جنيّ أو عفريت) للوصول إلى قواعد البيانات ذاتها على خلاف SQLite. أنواع البيانات التي تدعمها MySQL:TINYINT: عدد صحيح متناهي الصغر.SMALLINT: عدد صحيح صغير.MEDIUMINT: عدد صحيح متوسّط الحجم.INT or INTEGER: عدد صحيح بحجم عاديّ.BIGINT: عدد صحيح كبير.FLOAT: عدد بفاصلة عائمة صغير أحاديّ الدقّة (single-precision floating-point). لا يمكن إلغاؤه.DOUBLE, DOUBLE PRECISION, REAL: عدد بفاصلة عائمة متوسط الحجم مزدوج الدقّة (normal-size/double-precision floating-point). لا يمكن إلغاؤه.DECIMAL, NUMERIC: عدد بفاصلة عائمة غير مُحتوىً. لا يمكن إلغاؤه.DATE: تاريخ.DATETIME: تجميعة من الوقت والتاريخTIMESTAMP: ختم زمني (وقت وتاريخ حدوث حدث ما).TIME: وقت.YEAR: سنة بهيئة منزلتين أو أربعة منازل (المبدئيّ 4 منازل).CHAR: سلسلة نصّيّة ذات طول محدّد يتم دائمًا إكمالها من ناحية اليمين بفراغات إلى الطول المحدّد عند تخزينها.VARCHAR: سلسلة نصيّة ذات طول متغيّر.TINYBLOB, TINYTEXT: عمود نصّ أو فقاعة (blob) بحدّ أقصى للطول قدره 255 (أي 2^8 – 1) محرفًا.BLOB, TEXT: عمود نصّ أو فقاعة (blob) بحدّ أقصى للطول قدره 65535 (أي 2^16 – 1) محرفًا.MEDIUMBLOB, MEDIUMTEXT: عمود نصّ أو فقاعة (blob) بحدّ أقصى للطول قدره 16777215 (أي 2^24 - 1) محرفًا.LONGBLOB, LONGTEXT: عمود نصّ أو فقاعة (blob) بحدّ أقصى للطول قدره 4294967295 (أي 2^32 - 1) محرفًا.ENUM: تِعداد.SET: مجموعة.مزايا MySQLسهلة الاستخدام: يمكن تثبيت MySQL بسهولة شديدة. أدوات الأطراف الخارجية (third-party)، بما فيها المرئيّة (أي الواجهات الرسوميّة) تجعل البدء مع قواعد البيانات سهلًا للغاية. غنيّة بالمزايا: تدعم MySQL الكثير من وظائف SQL المتوقّع وجودها في أنظمة إدارة قواعد البيانات العلاقيّة، سواء بطريقة مباشرة أو غير مباشرة. آمنة: الكثير من مزايا الأمن وبعضها متقدّم مبنيّة في MySQL. قويّة وقابلة للتحجيم: يمكن لـMySQL التعامل مع الكثير من البيانات، ويمكنها أيضًا استخدامها على نطاق واسع إذا احتاج الأمر. سريعة: التخليّ عن بعض المعايير سمح لـ MySQL بالعمل بكفاءة عالية وبطريقة سلسة، مما أكسبها سرعة عالية. عيوب MySQLالمحدوديّات المعروفة: من حيث التصميم، لا تنوي MySQL عمل كلّ شيء، وتأتي بمحدوديّات وظيفيّة قد تتطلبها بعض التطبيقات المتقدّمة جدًّا من الناحية الفنيّة. القضايا المتعلّقة بالمتانة: الطريقة التي يتم التعامل فيها مع بعض الوظائف في MySQL (كالمراجع، والتبادلات، والتدقيق، وغيرها) تجعلها أقل متانة بقليل من بعض أنظمة إدارة قواعد البيانات العلاقيّة الأخرى. بطء تطويرها: رغم أنّ MySQL ما زالت من الناحية الفنيّة منتجًا مفتوح المصدر، إلّا أنّ هناك انتقادات تتعلق بعمليّة تطويرها منذ الاستحواذ عليها. ولكن علينا التنويه إلى أنّ هناك قواعد بيانات مبنيّة على MySQL ومتكاملة معها تمامًا تضيف مزايا على تثبيت MySQL القياسيّ (مثل MariaDB). متى تستخدم MySQLالعمليّات الموزّعة: عندما تحتاج لأكثر مما تتيحه SQLite، فإنّ تضمين MySQL في قائمة التطوير لديك – كذلك بالأمر بالنسبة لتضمين أيّ خادم قواعد بيانات مستقل – يقدّم لك الكثير من الحريّة في العمل إلى جانب بعض المزايا المتقدّمة. الأمان العالي: مزايا MySQL الأمنيّة تقدّم حماية يُعتمد عليها للوصول إلى البيانات (واستخدامها) بطريقة بسيطة. المواقع وتطبيقات الوِب: يمكن للأغلبية العُظمى من المواقع (وتطبيقات الوِب) العمل ببساطة مع MySQL رغم القيود. هذه الأداة المرنة والتي يمكن تحجيمها إلى حدّ ما سهلةُ الاستخدام والإدارة؛ وهذا مفيدٌ جدًّا على المدى البعيد. الحلول الخاصّة: إذا كنت تعمل على حلول محدّدة جدًّا ومخصّصة للغاية، يمكن لـMySQL العمل ضمن احتياجاتك بسهولة، وذلك بفضل إعدادات الضبط الغنيّة فيها وأوضاع العمل. متى لا تستخدم MySQLالتوافقيّة مع SQL: بما أنّ MySQL لا تطبّق (ولا تسعى لتطبيق) معيار SQL بأكمله، فإنّ هذه الأداة ليست متوافقة بالكامل مع SQL. إذا كنت قد تحتاج التكامل مع أنظمة إدارة قواعد بيانات علاقيّة كهذه، فإنّ الانتقال من MySQL لن يكون سهلًا. التعدّدية Concurrency: رغم أنّ MySQL وبعض محرّكات الحفظ تعمل بأداء جيّد جدًّا في عمليات القراءة، إلا أنّ عمليات القراءة والكتابة متزامنتين قد تكون سيئة. نقص المزايا: مجدّدًا نقول، اعتمادًا على اختيار محرّك قواعد البيانات، يمكن أن لا تحوي MySQL على بعض المزايا، كالبحث في النصوص الكاملة. PostgreSQL إنّ PostgreSQL هي نظام إدارة قواعد البيانات العلاقيّة الكيانيّ مفتوح المصدر الأكثر تقدّمًا، والتي هدفها الرئيسيّ أن تكون موافقة للمعايير ويمكن الزيادة عليها. تسعى PostgreSQL (أو Postgres) إلى تبني معايير ANSI/ISO SQL مع مراجعاتها. تتميّز PostgreSQL عن أنظمة إدارة المحتوى الأخرى بدعمها للتوجه الكيانيّ (object-oriented) المتكامل والمطلوب بشدّة و/أو وظائف قواعد البيانات العلاقيّة، كدعمها الكامل للتبادلات (القيود transactions) التي يعتمد عليها، أي أن تكون مكونة من عناصر غير قابلة للتجزئة، وأن تكون متّسقة ومعزولة وذات قدرات تحمل عالية (Atomicity, Consistency, Isolation, Durability – ACID). وبسبب التقنية القوية التي تقف خلفها، لدى Postgres قدرات عالية جدًّا في التعامل مع العديد من المهام بكفاءة عالية. يتم الوصول إلى التعدّدية (concurrency) دون قفل قراءة، وذلك بفضل تطبيق تحكم التعدّديّة متعدد الإصدارات (Multiversion Concurrency Control – MVCC). يمكن برمجة الكثير في PostgreSQL، وبالتالي يمكن توسعتها، وذلك باستخدام إجراءات مخصّصة تُدعى "إجراءات التخزين" (store procesures). يُمكن إنشاء هذه الإجراءات لتسهيل تنفيذ عمليات قاعدة البيانات المكررة والمعقدة والتي تكثر الحاجة إليها. رغم أنّ نظام إدارة قواعد البيانات هذا لا يحظى بشعبيّة MySQL، إلّا أنّ هناك الكثير من أدوات الأطراف الأخرى ومكتباتهم مصمّمة لجعل العمل مع PostgreSQL سهلًا، رغم طبيعته القويّة. يمكن الحصول على PostgreSQL هذه الأيام كحزمة تطبيقات من خلال مدير الحزم المبدئيّ للعديد من أنظمة التشغيل بسهولة. أنواع البيانات التي تدعمها PostgreSQLbigint: عدد صحيح من 8-بايت ذو إشارة bigserial: عدد صحيح من 8-بايت يزداد تلقائيًّا [(bit [(n: سلسلة ثنائيّة ذات طول محدّد [(bit varying [(n: سلسلة ثنائيّة متغيرة الأطوال boolean: متغيّر منطقي (صواب/خطأ) box: صندوق مستطيل في سطح مستوٍ bytea: بيانات ثنائيّة ("مصفوفة بايت") [(character varying [(n: سلسلة محارف (character string) ذات طول متغير [(character [(n: سلسلة محارف ذات طول ثابت cidr: عنوان شبكة IPv4 أو IPv6 circle: دائرة في سطح مستوٍ date: تاريخ في تقويم (السنة، الشهر، اليوم) double precision: عدد فاصلة عائمة ذو دقّة مزدوجة (8 بايت) inet: عنوان مضيف IPv4 أو IPv6 integer: عدد صحيح من 4 بايت ذو إشارة [(interval [fields] [(p: مدة زمنية line: خط لا نهائيّ في مستوى lseg: جزء من خطّ مستقيم في مستوى macaddr: عنوان تحكم بالوصول إلى الوسيط (Media Access Control – MAC) money: مقدار من المال [(numeric [(p, s: دقّة رقميّة محدّدة أو يمكن اختيارها path: مسار هندسيّ على سطح point: نقطة هندسيّة على سطح polygon: شكل هندسيّ مغلق على سطح real: عدد فاصلة عائمة ذي دقّة أحاديّة (4 بايت) smallint: عدد صحيح من 2-بايت ذو إشارة serial: عدد صحيح من 4 بايت يزداد تلقائيًّا text: سلسلة محارف ذات طول متغيّر [time [(p)] [without time zone: وقت في اليوم (دون منطقة زمنية) time [(p)] with time zone: الوقت من اليوم (مع منطقة زمنية) [timestamp [(p)] [without time zone: تاريخ ووقت (دون منطقة زمنية) timestamp [(p)] with time zone: تاريخ ووقت يشمل المنطقة الزمنيّة tsquery: استعلام بحث نصّيّ tsvector: مستند بحث نصيّ txid_snapshot: لَقطَة (transaction) لهويّة التبادل على مستوى المستخدم uuid: معرّف فريد عالميًّا xml: بيانات XML مزايا PostgreSQLنظام إدارة قواعد بيانات مفتوح المصدر موافق لمعايير SQL: PostgreSQL مفتوح المصدر ومجانيّ، ولكنه نظام إدارة قواعد بيانات علاقيّة قويّ جدًّا. مجتمع قويّ: PostgreSQL مدعوم من مجتمع خبيرٍ ومخلص يمكن الوصول إليه عبر مواقع الأسئلة والإجابات والقاعدة المعرفيّة طوال الوقت ومجانًا. دعم قويّ من الأطراف الأخرى: بغض النظر عن المزايا المتقدّمة جدًّا، تُزيّن PostgreSQL العديدُ من الأدوات الجيّدة ومفتوحة المصدر من أطراف أخرى لتصميم وإدارة واستخدام نظام الإدارة هذا. إمكانية التوسعة: يمكن توسعة PostgreSQL برمجيًّا باستخدام إجراءات مخزّنة، كما يفترض أن يكون الوضع في نظام إدارة قواعد بيانات علاقيّة متقدّم. كيانيّ: ليس PostgreSQL مجرّد نظام إدارة قواعد بيانات علاقيّة، ولكنه كيانيّ (objective) أيضًا – ويدعم التضمين (nesting)، ومزايا أخرى. عيوب PostgreSQLالأداء: للعمليات البسيطة كثيفة القراءة، يمكن أن تكون PostgreSQL مبالغًا فيها، ويمكن أن تبدو أقلّ أداءً من منافساتها، مثل MySQL. الشعبيّة: نظرًا لطبيعة هذه الأداة، فإنها تقبع في الخلف فيما يتعلق بشعبيتها، رغم كثرة من استخدامها – مما قد يؤثر على سهولة الحصول على دعم. الاستضافة: نتيجة للعوامل المذكورة أعلاه، يصعب إيجاد مستضيفين أو مقدمي خدمة يعرضون خدمات PostgreSQL مُدارة. متى تستخدم PostgreSQLصحّة البيانات: عندما تكون صحّة البيانات وإمكانية التعويل عليها ضرورة حتميّة، ولا يكون هناك عذر إذا حدث خطب ما، فستكون PostgreSQL الخيار الأفضل. الإجراءات المخصّصة المعقّدة: إذا كنت تتطلّب من قاعدة بياناتك أداء إجراءات مخصّصة، فـPostgreSQL هي الخيار الأفضل، كونه يمكن توسعتها. التكامل: إذا كان يُحتمل في المستقبل أن تكون هناك حاجة لنقل نظام قاعدة البيانات بأكمله إلى حلّ مملوك (مثل أوراكل)، فستكون PostgreSQL الأكثر توافقًا والأسهل في التعامل معها عند الانتقال. التصاميم المعقّدة: مقارنة بتطبيقات أنظمة إدارة قواعد البيانات العلاقيّة المجانية ومفتوحة المصدر الأخرى، تقدّم PostgreSQL لتصاميم قواعد البيانات المعقّدة أكبر قدر من الوظائف والإمكانات دون التفريط بالأمور الأخرى. متى لا تستخدم PostgreSQLالسرعة: إذا كان كلّ ما تطلبه عمليات قراءة سريعة، فليست PostgreSQL الأداة التي عليك استخدامها. سهولة الإعداد: إذا لم تكن تحتاج لصحّة مطلقة للبيانات، أو للتوافق مع ACID أو التصاميم المعقّدة، فقد تكون PostgreSQL مبالغًا فيها للإعدادات البسيطة. التكرار: إذا لم تكن مستعدًّا لقضاء الوقت، وبذل الجهد والموارد، فالحصول على التكرار (أو تعدّد النُسَخ) في MySQL قد يكون أسهل لمن ليست لديهم خبرة في إدارة الأنظمة وقواعد البيانات. ترجمة -وبتصرّف- للمقال: SQLite vs MySQL vs PostgreSQL: A Comparison Of Relational Database Management Systems لصاحبه O.S. Tezer.
  12. منذ زمن سحيق، كانت الذاكرةُ أكثر وظيفة نحتاجها ونعتمد عليها في الحاسوب. ورغم اختلاف التقنيات وأساليب التنفيذ الكامنة وراءها، إلّا أنّ معظم الحواسيب تأتي بالعتاد الضروريّ لمعالجة المعلومات وحفظها بأمان لاستخدامها في المستقبل متى احتجنا لها. لقد صار من المستحيل في عالمنا الحديث تخيل أيّ عمل لا يستفيد من هذه القدرة في الأجهزة، سواء كانت خواديم أو حواسيب شخصية أو كفّيّة. تُعالَج البيانات وتُسجَّل وتُسترجَع مع كل عملية، وفي كل مكان من الألعاب إلى الأدوات المتعلقة بالأعمال، بما فيها المواقع. أنظمة إدارة قواعد البيانات (DataBase Management Systems – DBMS) هي برمجيات عالية المستوى تعمل مع واجهات برمجة تطبيقات (APIs) أدنى منها في المستوى، وتلك الواجهات بدورها تهتم بهذه العمليات. لقد تم تطوير العديد من أنظمة إدارة قواعد البيانات (كقواعد البيانات العلائقيّة relational databases، وnoSQL، وغيرها) لعقود من الزمن للمساعدة على حلّ المشكلات المختلفة، إضافة إلى برامج لها (مثل MySQL ,PostgreSQL ,MongoDB ,Redis، إلخ). سنقوم في هذا المقال بالمرور على أساسيّات قواعد البيانات وأنظمة إدارة قواعد البيانات. وسنتعرف من خلالها على المنطق الذي تعمل به قواعد البيانات المختلفة، وكيفية التفرقة بينها. أنظمة إدارة قواعد البياناتإن مفهوم نظام إدارة قاعدة البيانات مظلّةٌ تندرج تحتها كلّ الأدوات المختلفة أنواعها (كبرامج الحاسوب والمكتبات المضمّنة)، والتي غالبًا تعمل بطرق مختلفة وفريدة جدًّا. تتعامل هذه التطبيقات مع مجموعات من المعلومات، أو تساعد بكثرة في التعامل معها. وحيث أن المعلومات (أو البيانات) يُمكِن إن تأتي بأشكال وأحجام مختلفة، فقد تم تطوير العشرات من أنظمة قواعد البيانات، ومعها أعداد هائلة من تطبيقات قواعد البيانات منذ بداية النصف الثاني من القرن الحادي والعشرين، وذلك من أجل تلبية الاحتياجات الحوسبيّة والبرمجية المختلفة. تُبنى أنظمة إدارة قواعد البيانات على نماذج لقواعد البيانات: وهي بُنى محدّدة للتعامل مع البيانات. وكل تطبيق ونظام إدارة محتوى جديد أنشئ لتطبيق أساليبها يعمل بطريقة مختلفة فيما يتعلق بالتعريفات وعمليات التخزين والاسترجاع للمعلومات المُعطاة. ورغم أنّ هناك عددًا كبيرًا من الحلول التي تُنشئ أنظمة إدارة قواعد بيانات مختلفة، إلّا أنّ كلّ مدة زمنية تضمّنت خيارات محدودة صارت شائعة جدًّا وبقيت قيد الاستخدام لمدة أطول، والغالب أنّ أكثرها هيمنة على هذه الساحة خلال العقدين الأخيرين (وربما أكثر من ذلك) هي أنظمة إدارة قواعد البيانات العلائقيّة (Relational Database Management Systems – RDBMS). أنواع قواعد البياناتيستخدم كلُّ نظام إدارة بياناتٍ نموذجًا لقواعد البيانات لترتيب البيانات التي يديرها منطقيًّا. هذه النماذج (أو الأنواع) هي الخطوة الأولى والمحدّد الأهم لكيفية عمل تطبيق قواعد البيانات وكيفية تعامله مع المعلومات وتصرفه بها. هناك بعض الأنواع المختلفة لنماذج لقواعد البيانات التي تعرض بوضوع ودقّة معنى هيكلة البيانات، والغالب أن أكثر هذه الأنواع شهرةً قواعدُ البيانات العلائقيّة. ورغم أنّ النموذج العلائقيّ وقواعد البيانات العلائقيّة (relational databases) مرنة وقويّة للغاية –عندما يعلم المبرمج كيف يستخدمها–، إلّا أنّ هناك بعض المشكلات التي واجهات عديدين، وبعض المزايا التي لم تقدمها هذه الحلول. لقد بدأت حديثًا مجموعة من التطبيقات والأنظمة المختلفة المدعوّة بقواعد بيانات NoSQL بالاشتهار بسرعة كبيرة، والتي قدمت وعودًا لحل هذه المشكلات وتقديم بعض الوظائف المثيرة للاهتمام بشدّة. بالتخلص من البيانات المهيكلة بطريقة متصلّبة (بإبقاء النمط المعرّف في النموذج العلائقيّ (relational model))، تعمل هذه الأنظمة بتقديم طريقة حرّة أكثر في التعامل مع المعلومات، وبهذا توفّر سهولة ومرونة عاليتين جدًّا؛ رغم أنّها تأتي بمشاكل خاصة بها –والتي تكون بعضها جدّيّة– فيما يتعلق بطبيعة البيانات الهامّة والتي لا غنى عنها. النموذج العلائقيّيقدّم النظام العلائقيّ الذي ظهر في تسعينات القرن الماضي طريقة مناسبة للرياضيات في هيكلة وحفظ واستخدام البيانات. توسّع هذه الطريقة من التصاميم القديمة، كالنموذج المسطّح (flat)، والشبكيّ، وغيرها، وذلك بتقديمها مفهوم "العلاقات". تقدّم العلاقات فوائد تتعلق بتجميع البيانات كمجموعات مقيّدة، تربط فيها جداول البيانات –المحتوية على معلومات بطريقة منظمة (كاسم شخص وعنوانه مثلاً)– كل المدخلات بإعطاء قيم للصفات (كرقم هوية الشخص مثلًا). وبفضل عقود من البحث والتطوير، تعمل أنظمة قواعد البيانات التي تستخدم النموذج العلائقيّ بكفاءة وموثوقيّة عاليتين جدًّا. أضف إلى ذلك الخبرة الطويلة للمبرمجين ومديري قواعد البيانات في التعامل مع هذه الأدوات؛ لقد أدّى هذا إلى أن يصبح استخدام تطبيقات قواعد البيانات العلائقيّة الخيار الأمثل للتطبيقات ذات المهام الحرجة، والتي لا يمكنها احتمال فقدان أيّة بيانات تحت أيّ ظرف، وخاصة كنتيجة لخلل ما أو لطبيعة التطبيق نفسه الذي قد يكون أكثر عرضة للأخطاء. ورغم طبيعتها الصارمة المتعلقة بتشكيل والتعامل مع البيانات، يمكن لقواعد البيانات العلائقيّة أن تكون مرنة للغاية وأن تقدم الكثير، وذلك بتقديم قدر ضئيل من المجهود. التوجّه عديم النموذج (Model-less) أو NoSQLتعتمد طريقة NoSQL في هيكلة البيانات على التخلص من هذه القيود، حيث تحرر أساليب حفظ، واستعلام، واستخدام المعلومات. تسعى قواعد بيانات NoSQL إلى التخلص من العلائقات المعقدة، وتقدم أنواع عديدة من الطرق للحفاظ على البيانات والعمل عليها لحالات استخدام معينة بكفاءة (كتخزين مستندات كاملة النصوص)، وذلك من خلال استخدامها توجّها غير منظم (أو الهيكلة على الطريق / أثناء العمل). أنظمة إدارة قواعد بيانات شائعةهدفنا في هذا المقال هو أن نقدم لك نماذج عن بعض أشهر حلول قواعد البيانات وأكثرها استخدامًا. ورغم صعوبة الوصول إلى نتيجة بخصوص نسبة الاستخدام، يمكننا بوضوح افتراض أنّه بالنسبة لغالب الناس، تقع الاختيارات بين محرّكات قواعد البيانات العلائقيّة، أو محرك NoSQL أحدث. لكن قبل البدء بشرح الفروقات بين التطبيقات المختلفة لكل منهما، دعنا نرى ما يجري خلف الستار. أنظمة إدارة قواعد البيانات العلائقيّةلقد حصلت أنظمة إدارة قواعد البيانات العلائقيّة على اسمها من النموذج الذي تعتمد عليه، وهو النموذج العلائقيّ الذي ناقشناه أعلاه. إنّ هذه الأنظمة –الآن، وستبقى لمدة من الزمن في المستقبل– الخيار المفضّل للحفاظ على البيانات موثوقة وآمنة؛ وهي كذلك كفؤة. تتطلب أنظمة إدارة قواعد البيانات العلائقيّة مخططات معرفة ومحددة جيدًا –ولا يجب أن يختلط الأمر مع تعريف PostgreSQL الخاص بهذه الأنظمة– لقبول هذه البيانات. تشكّل هذه الهيئات التي يحددها المستخدم كيفية حفظ واستخدام البيانات. إنّ هذه المخططات شبيهة جدًّا بالجداول، وفيها أعمدة تمثّل عدد ونوع المعلومات التي تنتمي لكل سجل، والصفوف التي تمثّل المدخلات. من أنظمة إدارة قواعد البيانات الشائعة نذكر: SQLite: نظام إدارة قواعد بيانات علائقيّة مضمّن قويّ جدًّا.MySQL: نظام إدارة قواعد بيانات علائقيّة الأكثر شهرة والشائع استخدامه.PostgreSQL: أكثر نظام إدارة قواعد بيانات علائقيّة كيانيّ (objective-RDBMS) متقدم وهو متوافق مع SQL ومفتوح المصدر.ملاحظة: لمعرفة المزيد عن أنظمة إدارة قواعد بيانات NoSQL، راجع المقالة التالية عن الموضوع: A Comparison Of NoSQL Database Management Systems. أنظمة قواعد بيانات NoSQL (أو NewSQL)لا تأتي أنظمة قواعد بيانات NoSQL بنموذج كالمستخدم في (أو الذي تحتاجه) الحلول العلائقيّة المهيكلة. هناك العديد من التطبيقات، وكلّ منها تعمل بطريقة مختلفة كليًّا، وتخدم احتياجات محدّدة. هذه الحلول عديمة المخططات (schema-less) إمّا تسمح تشكيلات غير محدودة للمدخلات، أو –على العكس– بسيطة جدًّا ولكنها كفؤة للغاية كمخازن قيم معتمد على المفاتيح (key based value stores) مفيدة. على خلاف قواعد البيانات العلائقيّة التقليديّة، يمكن تجميع مجموعات من البينات معًا باستخدام قواعد بيانات NoSQL، كـ MongoDB مثلًا. تُبقي مخازن المستندات هذه كل قطعة من البيانات مع بعضها كمجموعة واحدة (أي كملف) في قاعدة البيانات. يمكن تمثيل هذه المستندات ككيانات بيانات منفردة، مثلها في ذلك كمثل JSON، ومع ذلك تبقى كراسات، وذلك يعتمد على خصائصها. ليس لقواعد بيانات NoSQL طريقة موحدة للاستعلام عن البيانات (مثل SQL لقواعد البيانات العلائقيّة) ويقدم كلّ من الحلول طريقته الخاصّة للاستعلام. ملاحظة: لمعرفة المزيد عن أنظمة إدارة قواعد البيانات العلائقيّة، ألق نظرة على هذه المقالة المتعلقة بالموضوع: A Comparison Of Relational Database Management Systems. مقارنة بين أنظمة إدارة قواعد بيانات SQL و NoSQLمن أجل الوصول إلى نتيجة بسيطة ومفهومة، لنحلّل أولًا الاختلافات بين أنظمة إدارة قواعد البيانات: هيكلية ونوع البيانات المحتفظ بها:تتطلب قواعد البيانات العلائقيّة SQL هيكلة ذات خصائص محدّدة للحفاظ على البيانات، على خلاف قواعد بيانات NoSQL التي تسمح بعمليات انسياب حُرّ (free-flow operations). الاستعلام: وبغضّ النظر عن تراخيصها، تستخدم كلّ قواعد البيانات العلائقيّة معيار SQL إلى حدّ ما، ولهذا يمكن الاستعلام فيها بلغة SQL (أي Structured Query Language). أما قواعد بيانات NoSQL فلا تستخدم طريقة محدّدة للعمل على البيانات التي تديرها. التحجيم: يمكن تحجيم كلي الحلين عموديًّا (أي بزيادة موارد النظام). لكن لكون حلول NoSQL تطبيقات أحدث (وأبسط)، فهذا يجعلها تقدّم وسائل أسهل بكثير لتحجيمها أفقيًّا (أي بإنشاء شبكة عنقودية cluster من أجهزة متعدّدة). المتانة Reliability: عندما يتعلق الأمر بالمتانة والثقة الآمنة بالقَيد المنفّذ، تبقى قواعد بيانات SQL الخيار الأفضل. الدعم: لأنظمة إدارة قواعد البيانات العلائقيّة تاريخ طويل استمر لعقود من الزمن. إنها شائعة جدًّا، ومن السهل إيجاد دعم سواء مجانيّ أو مدفوع. إذا حدثت مشكلة، فمن الأسهل حلّها عليها من قواعد بيانات NoSQL التي شاعت حديثًا، وخاصة إذا كان الحلّ موضع السؤال ذا طبيعة معقّدة (مثل MongoDB). احتياجات حفظ واستعلام البيانات المعقدة: إنّ قواعد البيانات العلائقيّة بطبيعتها الخيار الأمثل لاحتياجات حفظ البيانات والاستعلامات المعقّدة. إنها أكثر كفاءة وتتفوق في هذا المجال. ترجمة -وبتصرّف- للمقال Understanding SQL And NoSQL Databases And Different Database Models لصاحبه O.S. Tezer.
  13. حزم LAMP هيّ مجموعة من البرامج مفتوحة المصدر تُثَبَّت عادةً معًا لتمكين خادوم من استضافة مواقع ويب ديناميكيّة وتطبيقات ويب. تُشير الأحرف LAMP على التّوالي إلى نِظام تشغيل Linux، خادوم ويب Apache، قاعدة بيانات MySQL، ولغة PHP لمُعالجة المُحتوى الدّيناميكي. سنُثبِّت في هذا الدّليل حزم LAMP على خادوم Ubuntu 14.04، حيث يُمثِّل أوبنتو اللّبنة الأولى من الحزمة (نظام التّشغيل). المتطلبات يجب، من أجل مُتابعة خطوات هذا الدّرس، أن يكون لديك حساب عادي (غير الحساب الجذر Root user) بصلاحيّات sudo. يُمكنّك معرفة كيف تضبُط حسابًا بهذه المواصفات في الخطوات من 1 إلى 4 من درس الإعداد الابتدائي لخادوم أوبنتو 14.04. الخطوة الأولى: ثبت Apache خادوم ويب Apache هوّ في الوقت الحالي خادوم الويب الأكثر شعبيّة، الأمر الّذي يجعل منه خيّارًا افتراضيًّا جيّدًا لاستضافة مواقع الويب. يُمكن تثبيت خادوم ويب Apache بسهولة عن طريق مدير حزم Package manager أوبنتو، apt. نبدأ بتحديث فهرس الحزم ثمّ نُثبّت حزمة apache2 لنحصُل على خادوم ويب Apache: sudo apt-get update sudo apt-get install apache2 سيُطلب منك إدخال كلمة السّر من حين لآخر، نظرًا لاستخدام صلاحيّات الجذر (Root) عن طريق sudo. ننتقل إلى مُتصفِّح الويب بعد انتهاء تنفيذ الأمر السّابق للتّأكد من تثبيت Apache. نُدخِل عنوان IP الخادوم العمومي أو اسم نطاق الموقع Domain name في شريط عنوان المُتصفّح: http://your_server_IP_address ملحوظة: إذا كنتَ تُجرِّب هذه الخطوات على جهازك الشّخصي (أو جهاز محلّي) فعنوان خادوم الويب هو 127.0.0.1 (أو localhost). ستظهر الصّفحة الافتراضيّة لخادوم ويب Apache، حيثُ توجد بعض معلومات الإعداد. شكل الصّفحة يبدو كالتّالي: إن عُرضت الصّفحة أعلاه فتثبيتُ خادوم ويب Apache جرى كما يُرام. كيف تجد عنوان IP العمومي لخادومك ملحوظة: هذه الفقرة غير مُوَّجَّهة لمن يختبر التّثبيت على حاسوبه الشّخصي. توجد عدّة طُرُق لمعرفة عنوان IP العمومي لخادوم على شبكة الإنترنت. عنوان IP العمومي للخادوم هو في العادة نفس العنوان الّي تتّصل به عن طريق SSH. نفِّذ الأمر التّالي في سطر الأوامر: ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//' ينتُج عن هذا الأمر سطر أو اثنان (واحد عنوان كما يُكتَب في الإصدار الرّابع IPv4 من بروتوكول IP، والآخر كما يُكتَب في الإصدار السّادس IPv6). في حال كانت النّتيجة سطرين فكلاهما صحيح ولكن من الممكن ألّا يستطيعَ حاسوبك الشّخصي التّعامل إلا مع واحد منهما؛ جرّب العنوانيْن حتى تحصُل على العنوان المُناسب. توجد طريقة بديلة وهي استخدام خدمة عامّة للحصول على عنوان IP. للحصول على العنوان نتّصل بالخدمة ونطلُب منها إخبارنَا عن العنوان الّذي نتّصِل منه: curl http://icanhazip.com ملحوظة: إن استخدمتَ الأمر السّابق من جهازك الشّخصي فستحصُل على عنوان IP الّذي تظهر به للخارج؛ هذا لا يعني بالضّرورة أنّ هذا هو عنوان IP العمومي لجهازك. مهما اختلفت الطّريقة فالمهم هو الحصول على عنوان خادومك ثمّ إدخاله في شريط العناوين في المتصفّح للتّأكّد من تثبيت خادوم ويب Apache. الخطوة الثانية: ثبت MySQL يأتي الآن دورُ MySQL، بعد تثبيت MySQL. Apache هو نظام لإدارة قواعد البيانات DataBase Management System, DBMS؛ وهو برنامج مسؤول عن إدارة وتوفير الاتّصال بقاعدة البيانات الّتي تُخزَّن بها معلومات الموقع. سنستخدم - كما في الخطوة السّابقة - مُديرَ حزم Apt، ولكن هذه المرّة سنُضيف بعض الحزم المُساعدة من أجل تمكين الاتّصال بين مختلف عناصِر البيئة الّتي نحن في طور إعدادها. sudo apt-get install mysql-server php5-mysql ملحوظة: لم ننُفِّذ أمر sudo apt-get update قبل أمر التّثبيت هذه المرّة. يعود السّبب في ذلك إلى أنّنا نفّذنا هذا الإجراء للتّو وهو ما يعني أنّ فهرس الحزم لدينا مُحدَّث up-to-date. أثناء تثبيت MySQL سيطلُب منك الخادوم اختيّار كلمة سرّ للمُستخدِم root على MySQL. الحساب root هو حساب إداريّ يملك صلاحيّات واسعة على نظام قواعد البيانات؛ وهو يُشبه إلى حدٍّ مّا الحساب الجذر في خادوم أوبنتو نفسه (لكن انتبِه إلى أنّه حساب خاص بنظام MySQL لإدارة قواعد البيانات). نحتاج بعد انتهاء التّثبيت إلى تنفيذ أوامر إضافيّة من أجل تأمين MySQL. نطلُب أوّلا من MySQL إنشاءَ بُنية المجلّدات الخاصّة بقاعدة البيانات حيثُ سيُخزّن المعلومات. الأمر التّالي يُؤدّي هذه المهمّة: sudo mysql_install_db ثمّ نُنفّذ سكربت التّثبيت الآمن الّذي يحذِف بعض القيّم الافتراضيّة غير الآمنة ويمنع الوصول المُباشر لنظام إدارة قواعد البيانات: sudo mysql_secure_installation سيُطلب منك النّظام إدخال كلمة سرّ الحساب الجذر في MySQL؛ ثمّ يسألك ما إذا كنتَ تُريد تغييرها. أدخل حرف n (دلالةً على "no" أي "لا") إن لم تكن ترغبُ في ذلك. بقيّة الأسئلة تتعلّق بإزالة بعض الحسابات وقواعد البيانات المُعَدَّة للتّجربة، تعطيل الدّخول عن بُعد للحساب الجذر، ثم تحميل الإعدادات الجديدة ليبدأ MySQL العمل بها مُباشرةً؛ فقط اضغط Enter للإجابة على هذه الأسئلة. تحصُل بعدانتهاء هذه الخطوة على نظام قواعد بيانات مضبوط وجاهز للعمل. الخطوة الثالثة: ثبت PHP يتولّى PHP التّعاملَ مع البيانات لإظهار المُحتوى الدّيناميكي؛ حيث يُنفِّذ السكربتات، يتّصِل بقاعدة بيانات MySQL ويُمرّر المُحتوى - بعد معالجته - إلى خادوم الويب، الّذي يعرضه. نستعين بمُدير الحزم apt مُجدّدًا لتثبيت PHP وبعض البرامج المُساعِدة الأخرى: sudo apt-get install php5 libapache2-mod-php5 php5-mcrypt ينبغي أن يكون الأمر السّابق كفيلًا بتثبيت PHP دون أيّة مشاكل. سنختبر نجاح التّثبيت بعد قليل. يقضي الإعداد الافتراضي لخادوم ويب Apache بالبحث أوّلا عن ملفّ باسم index.html عند وصول طلب لعرض مُجلّد. سنُغيّر هذا الإعداد بحيثُ يبحث خادوم الويب أوّلًا عن ملفّ PHP باسم index.php. نفتح ملفّ dir.conf في المُحرّر بصلاحيّات المُستخدِم الجذر: sudo nano /etc/apache2/mods-enabled/dir.conf يُشبه مُحتوى الملفّ الشّكلَ التّالي: <IfModule mod_dir.c> DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm </IfModule> ما نُريده هو تقديم ملف index.php المُعلَّم بالأحمر أعلاه إلى الوضعيّة الأولى، مباشرةً بعد تعليمة DirectoryIndex هكذا: <IfModule mod_dir.c> DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm </IfModule> احفَظ الملفّ بعد الانتهاء من تحريره عن طريق الضغط على الزّرّيْن CTRL+O ثم زرّ Enter في لوحة المفاتيح وأغلِقه بالضّغط على الزّرّيْن CTRL+X. نعيد تشغيل Apache للعمَل بالإعدادات الجديدة: sudo service apache2 restart ثبت وحدات PHP Modules ،PHP توجد بعض الوِحدات Modules الاختيّاريّة الّتي نستطيع تثبيتَها من أجل تحسين وظائف PHP. ننفِّذ الأمر التّالي لعرض مكتبات Libraries ووِحدات PHP المُتاحة: apt-cache search php5- جميع ما يظهَر في النّتائج هيّ وحدات اختيّاريّة يُمكن تثبيتها إن أردت. تتضمّن كل نتيجة اسم الوحدة ووصفًا مُختَصرًا لها: php5-cgi - server-side, HTML-embedded scripting language (CGI binary) php5-cli - command-line interpreter for the php5 scripting language php5-common - Common files for packages built from the php5 source php5-curl - CURL module for php5 php5-dbg - Debug symbols for PHP5 php5-dev - Files for PHP5 module development php5-gd - GD module for php5 . . . إن أردت معلوماتٍ أكثرَ عن إحدى الوِحدَات يمكنك البحث على الشّبكة أو استخدام أمر الوصف المُطَوَّل للحزمة عبر تنفيذ الأمر (حيثُ package_name اسم الحزمة): apt-cache show package_name بالنّسبة لوحدة php5-cli على سبيل المثال: apt-cache show php5-cli ستجد أن هناك مخرجاتٍ عديدةً من بينها حقلٌ باسم Description-en يُقدّم شرحًا لوظيفة الوِحدة (بالإنجليزيّة غالبًا، إلّا إذا كان التّوثيق Documentation يتوفّر بلغة النّظام لديك). . . . SHA256: 91cfdbda65df65c9a4a5bd3478d6e7d3e92c53efcddf3436bbe9bbe27eca409d Description-en: command-line interpreter for the php5 scripting language This package provides the /usr/bin/php5 command interpreter, useful for testing PHP scripts from a shell or performing general shell scripting tasks. . The following extensions are built in: bcmath bz2 calendar Core ctype date dba dom ereg exif fileinfo filter ftp gettext hash iconv libxml mbstring mhash openssl pcntl pcre Phar posix Reflection session shmop SimpleXML soap sockets SPL standard sysvmsg sysvsem sysvshm tokenizer wddx xml xmlreader xmlwriter zip zlib. . PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. Description-md5: f8450d3b28653dcf1a4615f3b1d4e347 Homepage: http://www.php.net/ . . . إذا أردتَ تثبيت وِحدة من وِحدات PHP، بعد الحصول على المعلومات الكافيّة عن وظيفتها، فيُمكنك استخدامُ أمر apt-get install. بالعودة إلى مثال php5-cli فإنّ التّثبيت يكون كما يلي: sudo apt-get install php5-cli ُيرجى ملاحظة أنّه بالإمكان تثبيت أكثر من حزمة في نفس الوقت عبر الفصل بينها بمسافة، هكذا: sudo apt-get install package1 package2 ينبغي أن تكون حزم LAMP، بالوصول إلى هذه النّقطة من الدّليل، مُثّبَّتةً ومضبوطةً. ننتقل إلى اختبار PHP. الخطوة الرابعة: اختبر تعامل خادوم الويب مع ملفات PHP سننشئ سكربت PHP مُيَسّرًا من أجل اختبار إعدادات PHP وخادوم الويب. الهدف هوّ أن يعثُر خادوم الويب على السكربت، الّذي سنُسمّيه info.php، ثمّ يعرض محتواه بشكل صحيح. يجب أن يُحفَظ الملفّ في مجلّد خاصّ، يُسمّى جذر الويب Web root (في هذا المُجلَّد مباشرةً أو في أحد المجلّدات المتفرّعة عنه)، لكي يعثُر عليه خادوم ويب Apache . يوجد جذر الويب في أوبنتو 14.04 على المسار /var/www/html/. نُنشئ ملفَّ اختبار الإعداد داخل هذا المسار عبر الأمر: sudo nano /var/www/html/info.php سيُفتح المحرّر وبداخله ملفّ فارغ، نُضيف إليه الشيفرة البرمجيّة التّاليّة: <?php phpinfo(); ?> هذا كل ما في الأمر. احفظ الملفّ ثم أغلقه. لاختبار إعداد خادوم الويب نفتح متصفّحَ ويب ثمّ نُدخل عنوان الصّفحة في شريط العنوان. يتكوّن عنوان الصّفحة من عنوان IP العمومي لخادوم الويب (أو اسم النّطاق) متبوعًا بمسار تواجد الصّفحة بالنّسبة لجذر الويب. صفحة الاختبار الّتي أعددناها موجودة في جذر الويب وهو ما يعني أنّ عنوان الوصول إليها هوّ التّالي (حيث your_server_IP_address هو عنوان IP أو اسم نطاق الموقع): http://your_server_IP_address/info.php يجب أن تظهر في المتصفّح صفحة الويب التّاليّة: تُقدّم هذه الصّفحة معلوماتٍ عن الخادوم كما يراه PHP. بعض هذه المعلومات مهمّ لمعرفة إعدادات خادوم الويب ومُعالج PHP، كما أنّها تُساعِدك أثناء تنقيح Debugging السكربتات. إذا ظهرت الصّفحة فهذا يعني أنّ PHP يعمل كما نُريد. يُنصَح بحذف هذه الصّفحة بعد الانتهاء من الاختبار، حيث إنّها قد تُعطي معلوماتٍ عن خادومك لأشخاص لا يجدر بهم الحصول على هذه المعلومات، الأمر التّالي يؤدّي هذه المهمّة: sudo rm /var/www/html/info.php يُمكن دائمًا إنشاء صفحة الاختبار من أجل الوصول إلى المعلومات الّتي توفّرها، متى أردت ذلك. خاتمة باستكمال خطوات هذا الدّليل تكون قد وضعتَ الأساس لتثبيت، استعمال وإعداد العديد من أنواع مواقع وتطبيقات الويب. ترجمة -وبتصرف- للمقال How To Install Linux, Apache, MySQL, PHP (LAMP) stack on Ubuntu 14.04 لصاحبه Justin Ellingwood.
  14. توفر أوبنتو خادومَيّ قواعد بيانات شهيرَين هما: قواعد بيانات MySQL.قواعد بيانات PostgreSQL.حيث تتوفران في المستودع الرئيسي (main)؛ ويشرح هذا الدرس كيفية تثبيت وضبط خادومَي قواعد البيانات آنفَيّ الذكر. MySQLإن MySQL هو خادوم قواعد بيانات سريع ومتعدد الخيوط (multi-threaded) ومتعدد المستخدمين ومرن جدًا؛ مُطوَّر للأنظمة الإنتاجية المحورية والتي تتحمل حِملًا ثقيلًا، ويمكن أيضًا تضمينه في البرمجيات سريعة النشر (mass-deployed). التثبيتنفذِّ الأمر الآتي في الطرفية لتثبيت MySQL: sudo apt-get install mysql-serverسيُطلب منك إدخال كلمة مرور للمستخدم الجذر لخادوم MySQL أثناء التثبيت. بعد أن ينتهي التثبيت، فيجب أن يبدأ خادوم MySQL تلقائيًا؛ تستطيع تنفيذ الأمر الآتي في الطرفية للتحقق إذا كان خادوم MySQL يعمل أم لا: sudo netstat -tap | grep mysqlيجب أن تشاهد شيئًا شبيهًا بما يلي بعد تنفيذ الأمر السابق: tcp 0 0 localhost:mysql *:* LISTEN 2556/mysqldإذا لم يكن يعمل الخادوم، فتستطيع تشغيله بالأمر: sudo service mysql restartالضبطتستطيع تعديل الملف ‎/etc/mysql/my.cnf لضبط الإعدادات الأساسية، مثل ملف السجل، ورقم المنفذ ...إلخ. فمثلًا لضبط MySQL ليستمع إلى الاتصالات من مضيفي الشبكة، عليك تعديل قيمة التعليمة bind-address إلى عنوان IP للخادوم: bind-address = 192.168.0.5ملاحظة: عدِّل 192.168.0.5 إلى العنوان الملائم. بعد إجراء التعديلات على ملف ‎/etc/mysql/my.cnf؛ فيجب إعادة تشغيل عفريت MySQL: sudo service mysql restartأدخل الأمر الآتي في الطرفية إذا رغبت بتغيير كلمة مرور المستخدم الجذر (root) في MySQL: sudo dpkg-reconfigure mysql-server-5.5سيُوقَف عمل عفريت MySQL، وستُسأل عن كلمة المرور الجديدة. محركات قاعدة البياناتعلى الرغم من أن الضبط الافتراضي لخادوم MySQL الموفر من حزم أوبنتو يعمل عملًا صحيحًا دون مشاكل، لكن هنالك بعض الأمور التي عليك أخذها بعين الاعتبار قبل الإكمال. صُمِّمَت قواعد بيانات MySQL للسماح بتخزين البيانات بطرقٍ مختلفة؛ يُشار لهذه الطرق إما بمحركات قواعد البيانات أو محركات التخزين (Storage engine)؛ هنالك محركان رئيسيان ستكون مهتمًا بهما: InnoDB و MyISAM؛ لا تتغير طريقة التعامل مع محركات التخزين المختلفة بالنسبة للمستخدم النهائي؛ حيث تتعامل MySQL مع الأمور بطريقة مختلفة وراء الستار، أي أنه بغض النظر عن محرك التخزين الذي تستخدمه، فإنك ستتعامل مع قواعد البيانات بنفس الطريقة تمامًا. لكل محرك إيجابياته وسلبياته؛ وبينما من الممكن دمج عدِّة محركات قواعد بيانات على مستوى الجدول، لكن ذلك خطيرٌ، فربما يقلل ذلك من الفعالية والأداء لأنك تُقسِّم الموارد بين محركين بدلًا من تخصيصها لمحرك واحد فقط. المحرك MyISAM هو الأقدم بين المحركين المذكورين؛ يمكن أن يكون أسرع من InnoDB في حالات معيّنة ويفضل الأعمال التي تتطلب القراءة فقط؛ تتمحور بعض تطبيقات الويب حول MyISAM (على الرغم أنها لن تُبطَئ إذا استخدمت InnoDB)؛ يدعم MyISAM أيضًا نوع البيانات FULLTEXT؛ الذي يسمح بالبحث بسرعة كبيرة في كمياتٍ كبيرةٍ من النص؛ لكن MyISAM قادر على قفل الجدول بأكمله فقط عند الكتابة، هذا يعني أن عمليةً واحدةً فقط تستطيع تحديث الجدول في لحظة زمنية معينّة؛ قد يكون هذا إعاقةً لتوسع تطبيق يعتمد على هذا الجدول؛ ولا يحتوي MyISAM على ميزة «journaling»، وهذا يعني أنه من الصعب استرجاع البيانات بعد حدوث انهيار.المحرك InnoDB هو محرك قواعد بيانات أكثر حداثةً، صُمِّم ليكون متوافقًا مع ACID الذي يضمن إجراء العمليات على قواعد البيانات بطريقة عملية؛ قفل الكتابة يحدث على مستوى السجل (row) ضمن الجدول؛ هذا يعني أنه من الممكن إجراء عدِّة تحديثات لسجلات جدولٍ ما في نفس الوقت؛ التخزين الموقت للبيانات يحدث في الذاكرة ضمن محرك قواعد البيانات، مما يسمح بالتخزين على أساس السجل وليس على أساس كتلة الملف (file block)؛ ولكي يتوافق مع ACID، فإن كل العمليات تحدث بطريقة «journaled» مستقلةً عن الجداول الرئيسية؛ وهذا يؤدي إلى استرجاع البيانات استرجاعًا عمليًا.إن InnoDB هو المحرك الافتراضي في MySQL 5.5 ومن المستحسن بشدة استخدامه بدلًا من MyISAM ما لم تكن تريد استخدام مزايا خاصة بذاك المحرك. الضبط المتقدم: إنشاء ملف ضبط my.cnfهنالك عدد من المعاملات التي يمكن تعديلها في ملف ضبط MySQL مما يسمح لك بتحسين أداء الخادوم مع مرور الوقت؛ ربما تجد الأداة «Percona's my.cnf generating tool» مفيدةً للإعداد الابتدائي؛ ستولد هذه الأداة ملف my.cnf ليكون أكثر ملائمةً لإمكانيات ومتطلبات خادومك. لا تستبدل ملف my.cnf المولد من Percona إذا وضعت بيانات في قاعدة بيانات، بعض التغييرات في الملف لن تسبب مشاكل لأنها تُعدِّل طريقة تخزين البيانات على القرص الصلب ولن تتمكن من تشغيل MySQL؛ إذا أردت استخدامه وكانت لديك بيانات موجودة مسبقًا، فعليك أن تجري mysqldump ثم تعيد التحميل: mysqldump --all-databases --all-routines -u root -p > ~/fulldump.sqlستُسأل عن كلمة مرور المستخدم الجذر لقواعد MySQL قبل إنشاء نسخة من البيانات؛ من المستحسن أن تتأكد أنه لا يوجد مستخدمين أو عمليات تستخدم قاعدة البيانات قبل إجراء هذه الخطوة؛ ربما تأخذ عملية النسخ بعض الوقت بناءً على مقدار البيانات الموجودة في قاعدة البيانات لديك؛ لن ترى شيئًا على الشاشة أثناء تنفيذ الأمر السابق. أغلق خادوم MySQL بعد إكمال عملية التفريغ (dump): sudo service mysql stopخذ الآن نسخةً احتياطيةً من my.cnf واستبدله بالملف الجديد: sudo cp /etc/my.cnf /etc/my.cnf.backup sudo cp /path/to/new/my.cnf /etc/my.cnfالآن احذف وأعد تهيئة مجال قواعد البيانات وتأكد أن الملكية صحيحة قبل إعادة تشغيلMySQL: sudo rm -rf /var/lib/mysql/* sudo mysql_install_db sudo chown -R mysql: /var/lib/mysql sudo service start mysqlكل ما تبقى الآن هو إعادة استيراد بياناتك؛ وللحصول على فكرة عن مدى إتمام عملية الاستيراد، فربما تجد الأداة pv‏ (Pipe Viewer) مفيدةً؛ الأمر الآتي يظهر كيفية تثبيت واستخدام pv لهذه الحالة، ربما لا تريد أن تستخدمها وكل ما عليك فعله هو استبدال pv بالأمر cat؛ تجاهل أية أوقات متوقعة للانتهاء (ETA) مولدة من pv؛ لأنها مبنية على الوقت المستغرق لكي يُعالَج كل سجل من الملف، لكن سرعة إدراج البيانات قد تختلف اختلافًا كبيرًا من سجل إلى سجل: sudo apt-get install pv pv ~/fulldump.sql | mysqlملاحظة: هذا ليس ضروريًا لكل تعديلات my.cnf؛ أغلبية المتغيرات التي قد ترغب في تعديلها لتحسين الأداء يمكن أن تُغيَّر حتى وإن كان يعمل الخادوم؛ تأكد من الحصول على نسخة احتياطية من ملفات الضبط والبيانات قبل إجراء التعديلات. MySQL Tunerالأداة «MySQL Tuner» هي أداة مفيدة تستطيع الاتصال إلى خدمة MySQL التي تعمل وتوفر اقتراحات عن كيفية ضبطها بأفضل ضبط لحالتك؛ وكما كان يعمل الخادوم لوقتٍ أطول، كلما كانت «النصيحة» التي سيوفرها mysqltuner أفضل؛ خذ بعين الاعتبار الانتظار لمدة 24 ساعة في بيئة إنتاجية قبل تشغيل هذه الأداة؛ تستطيع تثبيت mysqltuner من مستودعات أوبنتو: sudo apt-get install mysqltunerثم تشغيلها بعد تثبيتها بالأمر: mysqltunerوانتظر التقرير النهائي، سيوفر القسم العلوي معلوماتٍ عن خادوم قاعدة البيانات، ويوفر القسم السفلي اقتراحاتٍ لكي تعدلها في ملف my.cnf؛ يمكن تعديل أغلبية الاقتراحات على الخادوم مباشرةً دون إعادة تشغيله، انظر إلى توثيق MySQL الرسمي للمتغيرات المناسبة لتعديلها في البيئات الإنتاجية؛ ما يلي هو جزء من تقرير من قاعدة بيانات إنتاجية الذي يُظهِر أن هنالك بعض الفائدة من زيادة مقدار ذاكرة تخزين الطلبية: -------- Recommendations ----------------------------------------------------- General recommendations: Run OPTIMIZE TABLE to defragment tables for better performance Increase table_cache gradually to avoid file descriptor limits Variables to adjust: key_buffer_size (> 1.4G) query_cache_size (> 32M) table_cache (> 64) innodb_buffer_pool_size (>= 22G)تعليق أخير عن ضبط قواعد البيانات: بينما نستطيع أن نقول أن بعض الإعدادات هي الأفضل، لكن قد يختلف الأداء من تطبيق لآخر؛ على سبيل المثال، ما يعمل عملًا ممتازًا لووردبريس (Wordpress) قد لا يكون الأفضل لدروبال (Drupal) أو جوملا (Joomla) أو التطبيقات التجارية؛ الأداء متعلقٌ بأنواع الطلبيات واستخدام الفهارس، وإذا ما كان تصميم قاعدة البيانات جيدًا، وهكذا... ربما من الجيد إنفاق بعض الوقت في البحث عن إعدادات ملائمة لقواعد البيانات بناءً على التطبيقات التي تستخدمها؛ لكن بعد أن تتجاوز التعديلات حدًا معيّنًا، فإن أيّة تغييرات تجريها لا تتسبب إلا بتحسين بسيط جدًا في أداء التطبيق، ومن الأفضل لك تحسين التطبيق نفسه، أو التفكير في توسيع خادوم MySQL إما باستخدام عتاد أفضل أو بإضافة خواديم تابعة (slave). مصادرراجع الموقع الرئيسي لقواعد MySQL لمزيدٍ من المعلومات.التوثيق الكامل متوفر بصيغ online و offline من «MySQL Developers portal».لمعلومات عامة حول SQL، انظر إلى كتاب «Using SQL Special Edition».صفحة ويكي أوبنتو «Apache MySQL PHP» فيها بعض المعلومات المفيدة.PostgreSQLPostgreSQL هي قاعدة بيانات علائقية تعتمد على الكائنات وتملك ميزات أنظمة قواعد البيانات التجارية التقليدية مع تحسينات موجودة في الجيل الجديد من أنظمة DBMS. التثبيتأدخل الأمر الآتي في الطرفية لتثبيت PostgreSQL: sudo apt-get install postgresqlبعد انتهاء التثبيت، عليك ضبط خادوم PostgreSQL بناءً على متطلباتك، على الرغم من أن الضبط الافتراضي قابل للاستخدام. الضبطالاتصال عبر TCP/IP معطَّل افتراضيًا؛ تدعم PostgreSQL عدّة طرق للاستيثاق من العميل؛ طريقة الاستيثاق IDENT تُستعمَل للمستخدمين المحليين ولمستخدم postgres ما لم يُضبَط غير ذلك؛ رجاءً راجع «PostgreSQL Administrator's Guide» إذا أردت ضبط بدائل مثل Kerberos. سنفترض في ما يلي أنك ستُفعِّل اتصالات TCP/IP وتستخدم طريقة MD5 للاستيثاق من العميل؛ تُخزَّن ملفات ضبط PostgreSQL في المجلد ‎/etc/postgresql/<version>/main؛ على سبيل المثال، إذا ثبتت خادوم PostgreSQL 9.1، فإن ملفات الضبط ستُخزَّن في المجلد ‎/etc/postgresql/9.1/main. تنويه: لضبط الاستيثاق بطريقة ident، فأضف مدخلات إلى ‎/etc/postgresql/9.1/‎ main/pg_ident.conf؛ هنالك تعليقات تفصيلية في الملف لتساعدك. لتفعيل اتصالات TCP/IP، عليك تعديل الملف ‎/etc/postgresql/9.1/main/postgresql.conf ومن ثم تحديد السطر: ‎‎#listen_addresses = 'localhost‎‎'‎ ثم تغييره إلى: listen_addresses = '*'ملاحظة: للسماح باتصالات IPv4 و IPv6، استبدل «localhost» بالرمز «::». ربما تريد تعديل بقية المعاملات، إذا كنت تعرف ماذا تفعل! للتفاصيل، ارجع إلى ملف الضبط أو إلى توثيق PostgreSQL. الآن وبعد أن استطعنا الاتصال بخادوم PostgreSQL فإن الخطوة الآتية هي ضبط كلمة مرور للمستخدم postgres؛ نفذ الأمر الآتي في الطرفية للاتصال بقاعدة بيانات PostgreSQL الافتراضية: sudo -u postgres psql template1يتصل الأمر السابق بقاعدة بيانات PostgreSQL المسماة template1 كالمستخدم postgres؛ بعد أن تتصل إلى خادوم PostgreSQL وتحصل على مِحَث لإدخال تعليمات SQL، فيمكنك إدخال أمر SQL الآتي في مِحَث psql لضبط كلمة المرور للمستخدم postgres: ALTER USER postgres with encrypted password 'your_password';بعد ضبط كلمة المرور، عدِّل الملف ‎/etc/postgresql/9.1/main/pg_hba.conf لاستخدام استيثاق MD5 مع المستخدم postgres: local all postgres md5في النهاية، يجب أن تُعيد تشغيل خدمة PostgreSQL لتهيئة الضبط الجديد، وذلك بإدخال الأمر الآتي من الطرفية: sudo service postgresql restartتحذير: الضبط السابق ليس كاملًا بأي شكل من الأشكال، رجاءً راجع «PostgreSQL Administrator's Guide» لمعاملات ضبط إضافية. يمكنك اختبار اتصالات الخادوم من الأجهزة الأخرى باستخدام عملاء PostgreSQL: sudo apt-get install postgresql-client psql -h postgres.example.com -U postgres -Wملاحظة: استبدل اسم النطاق في المثال السابق باسم نطاقك الفعلي. مصادركما ذُكِر سابقًا، فإن «PostgreSQL Administrator's Guide» هو مصدر رائع، وهو متوفر أيضًا في حزمة postgresql-doc-9.1؛ نفذ ما يلي لتثبيت تلك الحزمة:sudo apt-get install postgresql-doc-9.1أدخِل الوصلة file:///usr/share/doc/postgresql-doc-9.1/html/index.html في شريط العنوان في متصفحك لمشاهدة الدليل.راجع أيضًا صفحة ويكي أوبنتو «PostgreSQL» لمزيدٍ من المعلومات.ترجمة -وبتصرف- للمقال Ubuntu Server Guide: Databases.
  15. هذا الدّرس هو جزء من سلسلة دروس حول نشر تطبيقات PHP باستخدام Ansible على Ubuntu، تحدّثنا في أول أجزاء عن الخطوات الأساسيّة من أجل نشر تطبيق، وهي تشكل نقطة بداية من أجل الخطوات المذكورة في هذا الدّرس. سنغطّي في هذا الدّرس إعداد قاعدة البيانات (بما في ذلك كلمة السّر)، هدفنا في النهاية هو الحصول على خادوم يعمل عليه تطبيق PHP بشكل كامل مع الإعدادات المذكورة آنفًا. سنستخدم إطار عمل Laravel كمثال عن تطبيق PHP ولكن يُمكِن تعديل هذه التعليمات بسهولة لتدعم أطر عمل وتطبيقات أخرى في حال كانت متواجدة لديك. الخطوة الأولى – تثبيت حزم MySQLسنقوم في هذه الخطوة بإعداد قاعدة بيانات MySQL لكي يستخدمها تطبيقنا. إنّ الخطوة الأولى لضمان وجود MySQL مُثبّتة على خادومنا هي ببساطة إضافة الحِزَم المطلوبة إلى مهمّة تثبيت الحِزَم في أعلى الـ playbook لدينا، الحزم التي نحتاجها هي mysql-server، mysql-client، وphp5-mysql، سنحتاج أيضًا إلى python-mysqldb كي تستطيع Ansible التواصل مع MySQL. وبما أنّنا نضيف حِزَم فنحتاج إلى إعادة تشغيل nginx و php5-fpm لضمان قابلية استخدام الحِزَم الجديدة من قبل التطبيق، نحتاج في هذه الحالة أن تكون MySQL متوفرة من أجل PHP لكي تستطيع الاتصال إلى قاعدة البيانات. من الأشياء الرائعة حول Ansible هي أنّنا نستطيع تعديل أي مهمّة من المهام وإعادة تشغيل الـ playbook وسيتم حينها تطبيق التغييرات، يتضمّن هذا قوائم من الخيارات كما نملك مع مهمّة apt. نفتح الملف php.yml من أجل تحريره: nano php.yml نبحث عن المهمّة install packages ونحدّثها لتضم الحِزَم السابقة: Updated php.yml . . . - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3 - mysql-server - mysql-client - php5-mysql - python-mysqldb notify: - restart php5-fpm - restart nginx . . . نقوم بحفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass الخطوة الثانية – إعداد قاعدة بيانات MySQLسنقوم في هذه الخطوة بإنشاء قاعدة بيانات MySQL من أجل تطبيقنا. تستطيع Ansible التخاطب مباشرة مع MySQL باستخدام الوحدات المسبوقة بـ mysql_ (مثل mysql_db، mysql_user)، تزودنا الوحدة mysql_db بطريقة لضمان وجود قاعدة بيانات ذات اسم مُحدّد بحيث نستطيع استخدام مهمّة مثل هذه لإنشاء قاعدة البيانات: New Ansible task - name: Create MySQL DB mysql_db: name=laravel state=present نحتاج أيضًا إلى حساب مستخدم صحيح مع كلمة سر معروفة للسماح لتطبيقنا بالاتصال إلى قاعدة البيانات، إحدى الوسائل لتحقيق هذا هي توليد كلمة السر محليًّا وحفظها في playbook الخاصّة بـ Ansible، ولكنّ هذه الطريقة غير آمنة وتوجد وسيلة أفضل منها. سنقوم بتوليد كلمة السّر باستخدام Ansible على الخادوم ذاته واستخدامها مباشرة عند الحاجة، ولتوليد كلمة سر سنستخدم أداة الأوامر السطرية makepasswd ونطلب منها كلمة سر مكوّنة من 32 حرف، ولأنّ makepasswd لا تأتي بشكل افتراضي مع Ubuntu سنحتاج إلى إضافتها إلى قائمة الحِزَم أيضًا. سنخبر أيضًا Ansible أن تتذكر خَرْج output هذا الأمر (أي تتذكر كلمة السّر) حتى نستطيع استخدامها لاحقًا في الـ playbook الخاصّة بنا، ومع ذلك ولأنّ Ansible لا تعلم إذا ما كان قد تم تنفيذ الأمر shell فسنقوم بإنشاء ملف عند تنفيذ هذا الأمر، ستتحقّق Ansible من وجود الملف وإن وجدته فستفترض أنّه تمّ تشغيل ذلك الأمر ولن يتم تشغيله مرّة أخرى. تبدو المهمّة كما يلي: New Ansible task - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/laravel/.dbpw register: dbpwd نحتاج بعدها لإنشاء مستخدم قاعدة بيانات MySQL الفعلي مع كلمة السّر التي حدّدناها، يتم عمل ذلك باستخدام الوحدة mysql_user ونستطيع استخدام الخيار stdout على المتغيّر الذي عرّفناه خلال مهمّة توليد كلمة السّر للحصول على الخَرْج الخام لأمر الصدفة shell، مثل هذا: dbpwd.stdout. يقبل الأمر mysql_user اسم المستخدم والصلاحيّات المطلوبة، نريد في حالتنا إنشاء مستخدم يُدعى laravel وإعطاء هذا المستخدم صلاحيّات كاملة على الجدول laravel، نحتاج أيضًا إلى إخبار المهمّة أن يتم تشغيلها فقط عندما يتم تغيير المتغيّر dbpwd، والذي سيحدث فقط عند تشغيل مهمّة توليد كلمة السّر. يجب أن تبدو المهمّة كما يلي: New Ansible task - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed وبوضع كل ذلك معًا نفتح الملف php.yml من أجل تحريره كي نستطيع إضافة المهمّة السابقة: nano php.yml نبحث في البداية عن المهمّة install packages ونقوم بتحديثها لتتضمّن الحزمة makepasswd: Updated php.yml . . . - name: install packages apt: name={{ item }} update_cache=yes state=latest with_items: - git - mcrypt - nginx - php5-cli - php5-curl - php5-fpm - php5-intl - php5-json - php5-mcrypt - php5-sqlite - sqlite3 - mysql-server - mysql-client - php5-mysql - python-mysqldb - makepasswd notify: - restart php5-fpm - restart nginx . . . نضيف بعدها مهام توليد كلمة السّر، إنشاء قاعدة بيانات MySQL، وإنشاء مستخدم في نهاية الملف: Updated php.yml . . . - name: UFW limit <abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">SSH</abbr> ufw: rule=limit port=<abbr title="Secure Shell | القشرة (أو الصَدَفة) الآمنة">ssh</abbr> - name: UFW open HTTP ufw: rule=allow port=http - name: Create MySQL DB mysql_db: name=laravel state=present - name: Generate DB password shell: makepasswd --chars=32 args: creates: /var/www/laravel/.dbpw register: dbpwd - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed handlers: . . . لا تقم بتشغيل الـ playbook الآن، ربّما تكون قد لاحظت أنّه بالرغم من أنّنا أنشأنا مستخدم وقاعدة بيانات MySQL فلم نفعل أي شيء مع كلمة السّر، سنغطّي هذا الموضوع في الخطوة القادمة، عند استخدام مهام shell ضمن Ansible فمن المهم دومًا أن نتذكّر متابعة سير العمل الذي يتعلّق بخَرْج ونتائج المهمّة بأكمله قبل تشغيلها لنتجنّب الاضطرار إلى تسجيل الدخول يدويًّا وإعادة تعيين الحالة. الخطوة الثالثة – إعداد تطبيق PHP من أجل قاعدة البياناتسنقوم في هذه الخطوة بحفظ كلمة سر قاعدة بيانات MySQL في الملف .env من أجل التطبيق. سنحدّث الملف .env ليتضمن اعتمادات (credentials) قاعدة بياناتنا التي أنشأناها حديثًا، يحتوي ملف .env الخاص بـ Laravel الأسطر التالية بشكل افتراضي: Laravel .env file DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret نستطيع الإبقاء على السطر DB_HOST كما هو، ولكن سنحدّث الأسطر الثلاثة الأخرى باستخدام المهام التالية، وهي مشابهة جدًّا للمهام التي استخدمناها في الدّرس السابق من أجل تعيين APP_ENV و APP_DEBUG: New Ansible tasks - name: set DB_DATABASE lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel - name: set DB_USERNAME lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel - name: set DB_PASSWORD lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }} when: dbpwd.changed وكما فعلنا مع مهمّة إنشاء مستخدم MySQL فقد استخدمنا متغيّر كلمة السر التي تمّ توليدها (dbpwd.stdout) لنشر الملف مع كلمة السّر، وأضفنا الخيار when لضمان أن يتم تشغيلها فقط عند تغيير dbpwd. وبما أنّ الملف .env موجود مسبقًا قبل إضافة مهمّة توليد كلمة السّر، فسنحتاج إلى حفظ كلمة السّر إلى ملف آخر، تبحث مهمّة توليد كلمة السّر عن وجود الملف (والذي أعددناه مسبقًا ضمن المهمّة)، سنستخدم أيضًا الخيارات sudo وsudo_user لإخبار Ansible أن يقوم بإنشاء الملف عن طريق المستخدم www-data: New Ansible task - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed نفتح الملف php.yml من أجل تحريره: nano php.yml نضيف المهام السابقة إلى الـ playbook، يجب أن تتطابق نهاية الملف مع التالي: Updated php.yml . . . - name: Create MySQL User mysql_user: name=laravel password={{ dbpwd.stdout }} priv=laravel.*:ALL state=present when: dbpwd.changed - name: set DB_DATABASE lineinfile: dest=/var/www/laravel/.env regexp='^DB_DATABASE=' line=DB_DATABASE=laravel - name: set DB_USERNAME lineinfile: dest=/var/www/laravel/.env regexp='^DB_USERNAME=' line=DB_USERNAME=laravel - name: set DB_PASSWORD lineinfile: dest=/var/www/laravel/.env regexp='^DB_PASSWORD=' line=DB_PASSWORD={{ dbpwd.stdout }} when: dbpwd.changed - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed handlers: . . . لا تقم بتشغيل الـ playbook الآن، فقد بقيت لدينا خطوة واحدة يجب إكمالها قبل أن نتمكّن من تشغيل الـ playbook. الخطوة الرابعة – تهجير قاعدة البيانات Migrating the Databaseسنقوم في هذه الخطوة بتنفيذ تهجير قاعدة البيانات database migrations من أجل إعداد جداول قاعدة البيانات. يتم فعل هذا في Laravel عن طريق تنفيذ الأمر migrate (على سبيل المثال php artisan migrate --force) بداخل دليل Laravel، لاحظ أنّنا أضفنا العَلَم force-- لأنّ بيئة production تحتاجه. تبدو مهمّة Ansible للقيام بهذا كما يلي: New Ansible task - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: www-data when: dbpwd.changed حان الوقت الآن لتحديث playbook الخاصّة بنا، نفتح الملف php.yml لتحريره: nano php.yml نضيف المهام السابقة إلى الـ playbook، يجب أن تتطابق نهاية الملف مع التالي: Updated php.yml . . . - name: Save dbpw file lineinfile: dest=/var/www/laravel/.dbpw line="{{ dbpwd.stdout }}" create=yes state=present sudo: yes sudo_user: www-data when: dbpwd.changed - name: Run artisan migrate shell: php /var/www/laravel/artisan migrate --force sudo: yes sudo_user: www-data when: dbpwd.changed handlers: . . . بإمكاننا أخيرًا حفظ وتشغيل الـ playbook: ansible-playbook php.yml --ask-sudo-pass عند الانتهاء من تنفيذ هذا نقوم بتحديث الصفحة في متصفحنا ويجب أن نرى عندها رسالة تقول: your_server_ip/'>http://your_server_ip/ Queue: NO Cron: NO يعني هذا أنّ تم إعداد قاعدة البيانات بشكل صحيح وأنّها تعمل كما هو متوقع، ولكنّنا لم نقم حتى الآن بإعداد مهام cron أو عفريت الطابور queue daemon، والتي سنقوم بها في الدرس القادم. الخاتمةتحدّثنا في هذا الدّرس عن طريقة إعداد قاعدة بيانات MySQL وإعداد تطبيق PHP من أجلها ومن ثمّ تهجير قاعدة البيانات من أجل نشر تطبيق PHP متقدّم باستخدام Ansible. ترجمة -وبتصرّف- لـ How To Deploy an Advanced PHP Application Using Ansible on Ubuntu 14.04 لصاحبه Stephen Rees-Carter.
  16. حِزم LEMP هي مجموعة من البرامج يُمكِن استخدامُها لتقديم صفحات ويب ديناميكيّة وتطبيقات ويب. يُشير هذا الاختصار إلى بيئة تتكوَّن من نظام تشغيل Linux، وخادوم ويب Nginx؛ تُخزَّن البيانات في قاعدة بيانات MySQL ويتولّى PHP مُعالجةَ المحتوى الدّيناميكي. سنشرح في هذا الدّرس كيفيّة تثبيت حزم LEMP على خادوم Ubuntu 14.04. يُمثِّل Ubuntu اللّبنة الأولى من حزمة LEMP في هذا الدّرس؛ سنشرح كيفيّة الحصول على بقيّة المُكوِّنات وتشغيلها. المتطلباتلإجراء الخطوات المذكورة في هذا الدّليل، يجب أن يكون لديك حساب عادي (غير الحساب الجذر Root user) بصلاحيّات sudo. يُمكنك معرفة كيف تضبُط حسابًا بهذه المواصفات في الخطوات من 1 إلى 4 من درس الإعداد الابتدائي لخادوم أوبنتو 14.04. سجِّل الدّخول إلى خادومك عبر الحساب المذكور حتى تكون جاهزًا لتطبيق خطوات الشّرح. الخطوة الأولى: ثبت خادوم ويب Nginxلنكون قادرين على عرض صفحات ويب لزوّار موقعنا سنستخدم Nginx؛ وهو خادوم ويب حديث وفعّال. كلّ البرامج الّتي سنُثبِّتها موجودة في المُستودعات Repositories الرّسميّة لأوبنتو، لذا سنستعين ببرنامج apt لإدارة الحزم لإكمال عمليّة التّثبيت. نبدأ أوّلًا بتحديث فهرس الحزم، ثمّ نُثبِّت خادوم الويب: sudo apt-get update sudo apt-get install nginxفي أوبنتو 14.04 يبدأ Nginx بالعمل فور تثبيته. يُمكِن التّأكّد من ذلك عبر إدخال اسم نطاق Domain name أو عنوان IP الخادوم العموميّ في شريط العنوان الموجود في مُتصفِّح الويب. ملحوظة: إذا كنتَ تُجرِّب هذه الخطوات على جهازك الشّخصي (أو جهاز محلّي) فعنوان خادوم الويب هو 127.0.0.1 (أو localhost). يُمكنك معرفة عنوان IP خادومك العمومي إن لم تكن تعرفه، ولا تملك اسمَ نطاق يُشير إلى موقعك، عبرَ تنفيذ الأمر التّالي في الطّرفيّة: ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'مثال على نتيجة تنفيذ الأمر أعلاه: 111.111.111.111 fe80::601:17ff:fe61:9801 يُمكن أيضًا تجربة الأمر: curl http://icanhazip.comالنّتيجة: 111.111.111.111جرّب الدّخول إلى العنوان الّذي حصلتَ عليه عن طريق إدخاله في شريط عنوان المتصفِّح: http://server_domain_name_or_IPيجب أن تظهر لديك صفحة الهبوط Landing page الافتراضيّة لـNginx: إذا ظهرت لك هذه الصّفحة فمعناهُ أنّ Nginx ثُبِّت بنجاح. الخطوة الثانية: ثبت MySQL لإدارة بيانات الموقعنحتاج بعد تثبيت خادوم الويب إلى نِظامٍ لإدارة قواعد البيانات Database management system, DBMS من أجل حفظ وإدارة بيانات موقعنا. سنستخدم MySQL لهذا الغرض. لتثبيت MySQL نُنفِّذ الأمر: sudo apt-get install mysql-serverسيُطلب منك إدخال كلمة سر لحساب المُستخدم الأعلى (الجذر Root) ضمن نظام MySQL. ملحوظة: كلمة السّر هنا هيّ لحساب إداري ضمن MySQL ولا علاقةَ لها بالمستخدِم الجذر في أوبنتو. نُواصِل مع MySQL عبر استكمال إعداداتِه. أوّلًا، نُنفِّذ الأمر التّالي الّذي يطلُب من MySQL توليدَ بُنية المجلّدات الّتي يحتاجها من أجل حفظ قواعد البيانات: sudo mysql_install_dbثمّ ننتقل لإجراء بضعة إعدادات أمنيّة حيثُ سنُغيِّر قيّمًا افتراضيّة غير الآمنة، عبر تنفيذ سكربت "التثبيت الآمن": sudo mysql_secure_installation سيُطلَب منك إدخال كلمة سر حساب المُدير في MySQL (نفس كلمة السّر الّتي أدخلتها أثناء التّثبيت). بعدها ستظهر رسالة تسألك إذا ما كنتَ تُريد تغيير كلمة سر المُدير في MySQL، إن لم تكن ترغب في ذلك أدخل حرف N ثمّ اضغط زر Enter. بقيّة الأسئلة تتعلّق بإزالة بعض الحسابات وقواعد البيانات المُعَدَّة للتّجربة؛ فقط اضغط Enter للإجابة عليها وستُحذَف الإعدادات الافتراضيّة غير الآمنة. نظام إدارة قواعد البيانات MySQL جاهز الآن للعمل. الخطوة الثالثة: ثبت PHP لمعالجة البياناتثبّتنا كلًّا من Nginx لتقديم صفحات الموقع وMySQL لتخزين وإدارة البيانات؛ بقيَ ربطُ الاثنيْن من أجل توليد محتوى ديناميكي. يُؤدّي PHP هذه الوظيفة. لا يأتي خادوم ويب Nginx بمعالج PHP مُضَمَّن كما هي حال بعض خواديم الويب الأخرى، لذا سنحتاج إلى تثبيت php5-fpm (حيثُ fpm اختصار لـ fastCGI process manager، وهوّ مُكوِّن مسؤول عن تقديم المحتوى الديناميكي في PHP)، ثمّ نطلُب من Nginx تمريرَ طلبات PHP إلى هذا البرنامج لمُعالجتها. يُمكِن تثبيت هذا العُنصُر وفي نفس الوقت نُثبِّت المكوِّن الّذي يسمح ل PHP بالتّواصُل مع النّهاية الخلفيّة Backend متمثّلةً في قاعدة البيانات؛ سيُنزِّل أمرُ التّثبيت كافّةَ الملفّات الضّروريّة: sudo apt-get install php5-fpm php5-mysqlضبط مُعالج PHPينتُج عن تنفيذ الأمر السّابق تثبيتُ العناصِر الضّروريّة لعمل PHP، لكن يتوجّب ضبطُ بعض الإعدادات من أجل أمان أكثر. افتَح الملف الرّئيس لإعداد php5-fpm بصلاحيّات الجذر: sudo nano /etc/php5/fpm/php.iniنبحث عن مُعطى Parameter باسم cgi.fix_pathinfo. افتراضيًّا ستجد أنّه مسبوق بعلامة ";" (دلالةً على أن السّطر تعليق، أي أنه لا يُؤخذ في الاعتبار) بقيمة مُساويّة لـ"1". هذا الإعداد غير آمن بالمرة، فهو يطلب من PHP تخمينَ الملف الذي يبحث عنه المستخدِم وتنفيذه إن لم يجد تطابقا تامًّا مع طلبه. أي أنّ الإعداد يُتيح للمستخدمين إنشاءَ طلبات PHP بحيث تؤدّي إلى تنفيذ سكربتات لا يجوز السّماح لهم بتنفيذها. نُغيّر الإعداد عن طريق حذف علامة التّعليق (";") ثمّ تبديل قيمة المُعطى لتُصبح 0، كما يلي: cgi.fix_pathinfo=0احفظ الملف (Ctrl + O ثم زر Enter) ثم أغلقه بعد الانتهاء من تحريره (Ctrl + x). نُعيد تشغيل مُعالج PHP لأخذ التّغييرات بالاعتبار: sudo service php5-fpm restartالخطوة الرابعة: اضبط Nginx على استخدام معالج PHPجميع العناصِر مُثبَّتة الآن؛ تبقّى تعديلٌ واحدٌ وهو إعدادُ Nginx لاستخدام معالج PHP المُعدّ أعلاه للتّعامل مع المُحتوى الدّيناميكي. يُضبط هذا الإعداد على مُستوى مُربّع الخادوم Server block (مُربّعات الخادوم مُشابهة لـلمُستضيفات الافتراضيّة Virtual hosts على خادوم ويب Apache ). افتَح الملف الافتراضي لإعداد مُربّع خادوم Nginx عبر تنفيذ الأمر: sudo nano /etc/nginx/sites-available/defaultيبدو الملفّ، بعد حذف التّعليقات، كالتّالي: server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /usr/share/nginx/html; index index.html index.htm; server_name localhost; location / { try_files $uri $uri/ =404; } }سنُجري بضع تعديلات على هذا الملف. نحتاج أوّلًا إلى إضافة خيّار index.php إلى تعليمة Directive الفهرس، ممّا يسمح بتقديم ملفّات فهارس PHP عند طلَب مُجلَّد. نحتاج أيضًا إلى تعديل تعليمة server_name حتّى تُشير إلى اسم نطاق الخادوم أو عنوانه العموميّ. يحوي ملفّ الإعداد على أسطُر تُعرِّف دوّالًا للتّعامل مع الأخطاء. توجد أمام هذه الأسطُر علامة تعليق. نحذف علامة التّعليق لكي تعمَل آليّات التّعامل مع الأخطاء. نفس الشّيْء بالنّسبة لمُعالج PHP، ننزع التّعليق عن أسطُر أخرى من ملفّ الإعداد. ثمّ أخيرًا نُضيف التّعليمة try_files للتّأكّد من أنّ Nginx لا يُمرّر طلباتٍ غير صالحة لمُعالج PHP. تظهر التّغييرات في مُحتوى الملفّ أدناه باللّون الأحمر: server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /usr/share/nginx/html; index index.php index.html index.htm; server_name server_domain_name_or_IP; location / { try_files $uri $uri/ =404; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }يُمكِن حفظ الملف وغلقُه بعد إجراء التّعديلات. أعِد تشغيل Nginx لأخذ التّغييرات في الاعتبار: sudo service nginx restartالخطوة الخامسة: أنشئ ملف PHP لاختبار الإعداداتيُفترَض أن تكون حزم LEMP مُثبَّتة وجاهزة للعمل. سنتأكّد الآن أنّ خادوم ويب Nginx يتعامل مع ملفّات PHP ويُمرِّرها لمُعالج PHP. نُنشئ عبر الأمر التّالي ملفَّ اختبار PHP في مَبدَأ المستند Document root: sudo nano /usr/share/nginx/html/info.phpيُمكِن أن نُضيف الأسطُر التّالية؛ وهي شفرة برمجيّة Code صالحة في لغة PHP، ينتُج عنها عرض معلومات الخادوم على الصّفحة. <?php phpinfo(); ?>احفَظ الملفّ ثمّ أغلقه. اذهب إلى متصفِّح الويب ثم اعرض للصّفحة عبر إدخال اسم نطاق أو عنوان الموقع (server_domain_name_or_IP) متبوعًا ب info.php/ كما يلي: http://server_domain_name_or_IP/info.phpيجب أن تظهر لديك صفحة ويب تعرِض معلومات الخادوم، كما في الصّورة. يدُلّ ظهور الصّفحة على نجاح إعداد Nginx للتّعامل مع ملفّات PHP. من الأفضل حذفُ ملفّ info.php بعد انتهاء الاختبار، إذ أنّه يُمكن أن يكشف عن إعدادات موقعك، الأمر الّذي قد يُساعِد من يُحاول الحُصول على وُصول غير مُرَخَّص. يُمكِنك دائمًا إنشاء هذا الملفّ عندما تُريد إجراء اختبارات. للحذف، نفّذ الأمر التّالي: sudo rm /usr/share/nginx/html/info.phpخاتمةيُمكِّن اتّباع الخطوات السّابقة من إعداد وضبط حزمة LEMP على خادوم أوبنتو 14.04. تُعطي هذه الحزمة قاعدة جيّدة ومرنة من أجل تقديم مُحتوى ديناميكي لزوّار موقعك. ترجمة -وبتصرّف- للمقال How To Install Linux, nginx, MySQL, PHP (LEMP) stack on Ubuntu 14.04 لصاحبه Justin Ellingwood.
  17. من التحديات الشائعة التي نصادفها عند التعامل مع أنظمة قواعد البيانات النشطة active هو القيام بنسخ احتياطيّة ساخنة hot backups، وهو إنشاء نسخ احتياطيّة بدون إيقاف خدمة قاعدة البيانات أو جعلها قابلة للقراءة فقط، ينتج عادة عن نسخ ملفّات قاعدة البيانات النشطة ببساطة نسخة من قاعدة البيانات غير مستقرّة داخليًّا، أي تكون غير قابلة للاستخدام أو فاقدة لبعض المعاملات transactions التي حدثت خلال هذا النسخ، من ناحية أخرى فإنّ إيقاف قاعدة البيانات من أجل النسخ الاحتياطي المُجدوَل يجعل الأجزاء المعتمدة على قاعدة البيانات من تطبيقنا غير متوفّرة. Percona XtraBackup هو أداة مفتوحة المصدر تُستَخدم للالتفاف على هذه المشكلة وإنشاء نُسَخ احتياطيّة كاملة full backups أو تزايديّة incremental backups لقواعد بيانات قيد التشغيل من نوع MySQL، MariaDB، و Percona Server، وهي معروفة أيضًا باسم النُسَخ الاحتياطيّة الساخنة hot backups. وعلى النقيض من النُّسَخ الاحتياطيّة المنطقيّة logical backups التي تنتجها أدوات مثل mysqldump، تقوم أداة XtraBackup بإنشاء نُسَخ احتياطيّة ملموسة physical backups لملفّات قواعد البيانات، أي تقوم بعمل نسخة لملفّات البيانات، وتطبّق بعدها سجل المعاملات (transaction log (a.k.a. redo log على النُّسخ الاحتياطيّة الملموسة لتُعيد ملء أي مُعاملات نشطة لم تكتمل خلال إنشاء النُّسَخ الاحتياطيّة، مما يُؤدّي إلى نُسَخ احتياطيّة مستقرّة لقاعدة بيانات قيد التشغيل، يُمكِن بعدها النسخ الاحتياطي لنسخة قاعدة البيانات الاحتياطيّة إلى موقع بعيد remote location باستخدام rsync أو نظام نسخ احتياطي مثل Bacula. سنتعلّم في هذا الدّرس كيفيّة القيام بنسخة احتياطيّة كاملة وساخنة لقواعد بيانات MySQL أو MariaDB باستخدام Percona XtraBackup على Ubuntu، تمّت أيضًا تغطية عمليّة استعادة قاعدة البيانات من نسخة احتياطيّة. المتطلبات الأساسيةيجب أن تمتلك ما يلي من أجل متابعة هذا الدّرس: صلاحيّات مستخدم جذر Superuser على نظام Ubuntuقاعدة بيانات MySQL أو MariaDB قيد التشغيلالنفاذ إلى المستخدم المُدير (admin (root لقاعدة بياناتكومن أجل القيام بنسخة احتياطيّة ساخنة لقاعدة بياناتك يجب أيضًا أن تستخدم مُحرِّك التخزين InnoDB لأنّ XtraBackup تعتمد على سجل معاملات يُحافِظ عليه InnoDB، إن كانت قواعد بياناتك تستخدم مُحرِّك التخزين MyISAM فلا يزال بإمكانك استخدام XtraBackup ولكن سيتم قفل قاعدة البيانات لفترة قصيرة من الوقت في أواخر عمليّة النسخ الاحتياطي. 1- التحقق من محرك التخزينإن لم تكن متأكدًا من مُحرِّك التخزين الذي تستخدمه قاعدة بياناتك فتستطيع معرفته بعدّة طرق، إحدى الطرق هي استخدام وحدة التحكّم console في MySQL لاختيار قاعدة البيانات المطلوبة ومن ثمّ الحصول على حالة كل جدول فيها. ندخل في البداية إلى وحدة التحكّم console في MySQL: mysql -u root -pنقوم بإدخال كلمة سر المستخدم الجذري root في MySQL. وفي مُحث MySQL prompt نختار قاعدة البيانات التي نريد التحقّق منها، تأكد من أن تضع اسم قاعدة بياناتك هنا بدلًا من database_name: mysql> USE database_name;نطبع بعدها حالات جدولها: mysql> SHOW TABLE STATUS\G;ينبغي الإشارة للمحرك لكل صف من قاعدة البيانات: ... *************************** 11. row *************************** Name: wp_users Engine: InnoDB ...نغادر وحدة التحكّم console حالما ننتهي من هذا. mysql> exitفلنقم بتثبيت Percona XtraBackup. تثبيت Percona XtraBackupأسهل طريقة لتثبيت Percona XtraBackup هي استخدام apt-get. نضيف مفتاح مستودع Percona باستخدام هذا الأمر: sudo apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2Aنضيف بعدها مستودع Percona إلى مصادر apt لدينا: sudo sh -c "echo 'deb http://repo.percona.com/apt trusty main' > /etc/apt/sources.list.d/percona.list" sudo sh -c "echo 'deb-src http://repo.percona.com/apt trusty main' >> /etc/apt/sources.list.d/percona.list"نقوم بتنفيذ الأمر التالي لتحديث مصادر apt: sudo apt-get updateنستطيع أخيرًا تنفيذ الأمر التالي لتثبيت XtraBackup: sudo apt-get install percona-xtrabackupتتألف XtraBackup بشكل أساسي من برنامج XtraBackup و script مكتوب بلغة Perl يُدعى innobackupex سنستخدمه لإنشاء نُسَخ احتياطيّة لقواعد بياناتنا. التحضيرات لأول مرةنحتاج قبل استخدام XtraBackup لأوّل مرّة إلى تحضير النظام ومستخدم MySQL الذي سيستخدمه XtraBackup، يُغطّي هذا القسم التحضيرات الأوليّة. 1- مستخدم النظامإذا لم نكن نخطّط لاستخدام المستخدم الجذري root للنظام فيجب علينا القيام ببعض التحضيرات الأساسيّة للتأكد من أنّه يُمكن تنفيذ XtraBackup بشكل صحيح، سنفترض أنّك قمت بتسجيل الدخول باستخدام المستخدم الذي سيشغّل XtraBackup وأنّه يمتلك صلاحيّات مستخدم جذر superuser. نضيف مستخدم النظام إلى المجموعة "mysql" (ضع اسم المستخدم لديك بدلًا من username): sudo gpasswd -a username mysqlنقوم بإنشاء الدليل الذي سنستخدمه لتخزين النُّسَخ الاحتياطيّة التي يقوم XtraBackup بعملها: sudo mkdir -p /data/backups sudo chown -R username: /dataيتأكّد الأمر chown من قدرة المستخدم على الكتابة إلى دليل النُّسَخ الاحتياطيّة. 2- مستخدم MySQLيحتاج XtraBackup إلى مستخدم MySQL لكي يستخدمه لإنشاء النُّسَخ الاحتياطيّة، فلنقم بإنشاء واحد الآن. ندخل إلى وحدة التحكّم console في MySQL بهذا الأمر: mysql -u root -pنقوم بإدخال كلمة سر المستخدم الجذري root في MySQL. نُنشِئ في مُحِث MySQL prompt مستخدم MySQL جديد ونعيّن كلمة سر له، يُدعى المستخدم في هذا المثال "bkpuser" وكلمة السّر هي "bkppassword"، قم بتغييرهما إلى شيء أكثر أمانًا: mysql> CREATE USER 'bkpuser'@'localhost' IDENTIFIED BY 'bkppassword'نقوم بعدها بمنح grant مستخدم MySQL الجديد صلاحيّات إعادة التحميل reload، القفل lock، والتكرار replication لكافّة قواعد البيانات: mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost'; FLUSH PRIVILEGES; وهي الحد الأدنى من الصلاحيّات التي يحتاجها XtraBackup لإنشاء نُسَخ احتياطيّة كاملة لقواعد البيانات. عند الانتهاء نقوم بالخروج من لوحة تحكّم MySQL console: mysql> exitنحن الآن جاهزون لإنشاء نسخة احتياطيّة كاملة لقواعد بياناتنا. القيام بنسخة احتياطية ساخنة كاملةيُغطّي هذا القسم الخطوات الضرورية لإنشاء نسخة احتياطيّة ساخنة كاملة لقاعدة بيانات MySQL باستخدام XtraBackup، بعد التأكّد من أنّ أذونات permissions ملفّات قاعدة البيانات صحيحة سنستخدم XtraBackup لإنشاء create النسخة الاحتياطيّة وتحضيرها prepare. 1- تحديث أذونات Datadirيتم تخزين ملفّات قاعدة بيانات MySQL على Ubuntu في المسار var/lib/mysql/، وهو الذي يتم الإشارة إليه أحيانًا بـ datadir، يتم تقييد النفاذ إلى datadir افتراضيًّا فقط للمستخدم mysql، يتطلّب XtraBackup نفاذًا إلى هذا الدّليل لإنشاء نسخه الاحتياطيّة، لذا نقوم بتنفيذ بعض الأوامر للتأكّد من امتلاك مستخدم النظام الذي أعددناه سابقًا-كعضو في المجموعة mysql- للأذونات المناسبة: sudo chown -R mysql: /var/lib/mysql sudo find /var/lib/mysql -type d -exec chmod 770 "{}" \;تضمن هذه الأوامر أنّ كافّة الأدّلة في datadir قابلة للنفاذ من قبل المجموعة mysql، ويجب تنفيذها قبل كل نسخة احتياطيّة. 2- إنشاء نسخة احتياطيةنحن الآن على استعداد لإنشاء النسخة الاحتياطيّة، نستخدم الأداة innobackupex أثناء تشغيل قاعدة بيانات MySQL لفعل هذا، قم بتنفيذ هذا الأمر بعد وضع اسم مستخدمك وكلمة سرك لتتوافق مع معلومات تسجيل دخول مستخدم MySQL لديك: innobackupex --user=bkpuser --password=bkppassword --no-timestamp /data/backups/new_backupسيقوم هذا بإنشاء نسخة احتياطيّة لقاعدة البيانات في الموقع المُحدّد data/backups/new_backup/: innobackupex output innobackupex: Backup created in directory '/data/backups/new_backup' 150420 13:50:10 innobackupex: Connection to database server closed 150420 13:50:10 innobackupex: completed OK!وبشكل بديل تستطيع إزالة no-timestamp-- لكي يقوم XtraBackup بإنشاء دليل النسخة الاحتياطيّة بناءً على الختم الزمني timestamp الحالي كما يلي: innobackupex --user=bkpuser --password=bkppassword /data/backupsسيقوم هذا بإنشاء نسخة احتياطيّة لقاعدة البيانات في دليل فرعي مُولَّد تلقائيًّا كما يلي: innobackupex output — no timestamp innobackupex: Backup created in directory '/data/backups/2015-04-20_13-50-07' 150420 13:50:10 innobackupex: Connection to database server closed 150420 13:50:10 innobackupex: completed OK!ستعيد أي طريقة نستخدمها العبارة "innobackupex: completed OK" في السّطر الأخير من الخَرْج، ينتج عن النّسخة الاحتياطيّة الناجحة نسخة من قاعدة البيانات في المسار datadir والتي يجب تحضيرها قبل استخدامها. تحضير النسخة الاحتياطيةالخطوة الأخيرة في إنشاء نسخة احتياطيّة ساخنة باستخدام XtraBackup هي تحضيرها، ويتضمّن هذا إعادة "replaying" سجل المعاملات لتطبيق أي معاملة غير مرتبطة بالنسخة الاحتياطيّة، يجعل التحضير بيانات النسخة الاحتياطيّة مستقرة وقابلة للاستخدام من أجل الاستعادة. سنحضّر بحسب مثالنا النسخة الاحتياطيّة التي أنشأناها في المسار data/backups/new_backup/، ضع المسار الفعلي للنسخة الاحتياطيّة لديك: innobackupex --apply-log /data/backups/new_backupيجب أن نرى مرّة أخرى العبارة "innobackupex: completed OK" في السطر الأخير من الخَرْج. تمّ إنشاء النسخة الاحتياطيّة لقاعدة البيانات وهي جاهزة لاستعادتها إلى قاعدة بياناتنا، إن كنت تملك نظام نسخ احتياطي للملفّات مثل Bacula فيجب تضمين هذه النسخة الاحتياطيّة لقاعدة البيانات كجزء من اختيار النسخة الاحتياطيّة. يُغطّي القسم التالي كيفيّة استعادة قاعدة البيانات من النسخة الاحتياطيّة التي أنشأناها للتو. القيام باستعادة النسخة الاحتياطيةتتطلّب استعادة قاعدة البيانات باستخدام XtraBackup إيقاف قاعدة البيانات وأن يكون المسار datadir فارغًا. نوقف خدمة MySQL باستخدام هذا الأمر: sudo service mysql stopننقل أو نحذف محتويات datadir (وهو المسار var/lib/mysql/)، في حالتنا سننقله ببساطة إلى مكان مؤقّت: mkdir /tmp/mysql mv /var/lib/mysql/* /tmp/mysql/نستطيع الآن استعادة قاعدة البيانات من نسختنا الاحتياطيّة "new_backup": innobackupex --copy-back /data/backups/new_backupإن تم الأمر بنجاح فينبغي أن يكون السطر الأخير من الخَرْج هو العبارة "innobackupex: completed OK". تنتمي الملفّات التي تمّت استعادتها غالبًا إلى المستخدم الذي قام بتنفيذ عمليّة الاستعادة، نُعيد الملكيّة إلى mysql لكي تستطيع MySQL قراءة وكتابة الملفّات: sudo chown -R mysql: /var/lib/mysqlأصبحنا مستعدين لبدء MySQL: sudo service mysql startهذا هو كل شيء، يجب أن تكون قاعدة بيانات MySQL التي استعدناها قيد التشغيل الآن. الخاتمةبعد أن أصبحت الآن قادرًا على إنشاء نُسَخ احتياطيّة ساخنة لقاعدة بيانات MySQL باستخدام Percona XtraBackup فهنالك العديد من الأشياء التي يجب أن تنظر إلى إعدادها. يُنصَح أولًا بأتمتة العمليّة بحيث يتم إنشاء النُّسَخ الاحتياطيّة وفق جدول، يجب عليك ثانيًا القيام بنسخ بعيد remote للنسخ الاحتياطيّة في حال حدثت مشاكل في خادوم قاعدة البيانات باستخدام أدوات مثل rsync أو نظام نُسَخ احتياطيّة للملفّات على الشبكة مثل Bacula، سترغب بعدها في النظر في مداورة rotating النسخ الاحتياطيّة لديك (أي حذف النسخ الاحتياطيّة القديمة على أساس مُجدوَل) وإنشاء نُسَخ احتياطيّة تزايديّة (باستخدام XtraBackup) لتوفير مساحة القرص. ترجمة -وبتصرّف- لـ How To Create Hot Backups of MySQL Databases with Percona XtraBackup on Ubuntu 14.04 لصاحبه Mitchell Anicas.
  18. Bacula هو برنامج مفتوح المصدر للنسخ الاحتياطي في الشبكة؛ يمكّن من إنشاء نسخ احتياطية Backups من نظام التشغيل واستعادة البيانات في حال حصول مشكل. يتميز Bacula بالمرونة والمتانة، الأمر الذي يجعل منه مناسبا للنسخ الاحتياطي في حالات كثيرة؛ على الرغم من أن إعداده مرهق قليلا. يعد نظام النسخ الاحتياطي جزءا مهما في أغلب البنى التحتية للخواديم؛ نظرا لكون إعادة البيانات (إرجاعها) عنصرا أساسيا في أغلب خطط استعادة الأنظمة. سنشرح في هذا الدرس كيفية تثبيت عناصر الخادوم في Bacula على خادوم Ubuntu 14.04 وضبطها. سنعد Bacula لإنشاء شغل أسبوعي job ينشئ نسخة احتياطية محلية (أي على المضيف Host الذي يعمل عليه Bacula). لا يفرض Bacula نسخ البيانات محليَّا، إلا أننا بهذه الطريقة نوفر نقطة انطلاق جيدة لإنشاء نسخ احتياطية من خواديم أخرى يثبَّت عليها عميل Client لـ Bacula ويُضبط الاتصال بينه والخادوم. المتطلباتتتطلب خطوات المقال صلاحيات وصول المستخدم الأعلى (sudo) على خادوم Ubuntu 14.04. سيحتاج الخادوم أيضا لمساحة قرص صلب كافية لتخزين جميع النسخ الاحتياطية التي تخطط للإبقاء عليها ضمن حيز زمني محدَّد. سنعد Bacula لاستخدام اسم نطاق معرَّف بالكامل Fully Qualified Domain Name, FQDN (راجع مقال مقدّمة إلى مُصطَلحات وعناصر ومفاهيم نظام أسماء النطاقات للمزيد عن اسم النطاق المعرَّف بالكامل)، على سبيل المثال bacula.private.example.com. استخدم عناوين IP المناسبة إن لم يكن لديك نظام لإدارة النطاقات. أبدل معلومات الاتصال بالشبكة الموجودة في هذا الدرس بعناوين شبكة يمكن لخواديمك الوصول إليها (عناوين IP أو أنفاق شبكات خاصة افتراضية) نبدأ بعرض عام للعناصر المكوِّنة لـ Bacula. نظرة عامة على عناصر Baculaيتبع Bacula نموذج خادوم-عميل Server-client في النسخ الاحتياطي، ويتكون من عناصر برمجية مختلفة. سنركز في ما يلي على جزأيْ الخادوم والعميل بدلا من الحديث عن كل عنصر لوحده. إلا أنه يبقى من الأهمية بمكان أخذ معرفة سطحية بالعناصر المكونة للتطبيق. يتكون خادوم Bacula (نشير إليه في بعض الأحيان بـ”خادوم النسخ الاحتياطي”) من العناصر التالية: مدير Bacula (يُشار إليه بـDIR): وهو البرنامج الذي يتحكم في عمليات النسخ الاحتياطي والإعادة التي تنفذها خدمتا File وStorage.خدمة التخزين Storage (يُشار إليها بـSD): برنامج يقرأ من أجهزة التخزين المستخدمة للنسخ الاحتياطي ويكتب فيها.برنامج الفهرس Catalog: خدمات تحتفظ بقاعدة بيانات للملفات المنسوخة احتياطا. تُستخدم قاعدة بيانات مثل MySQL أو PostgreSQL لهذا الغرض.وحدة تحكم Bacula: واجهة بسطر أوامر يتفاعل بواسطتها مسؤول النسخ الاحتياطي مع مدير Bacula ويتحكم فيه.ملحوظة: ليس مفروضا تواجدُ جميع العناصر المكونة لخادوم Bacula على نفس الخادوم الحسي؛ إلا أنها جميعها تعمل معا لتوفير وظيفة خادوم النسخ الاحتياطي. يشغِّل عميلُ Bacula (أي الخادوم الذي نريد أخذ نسخ احتياطية منه) خدمة File (يُشار إليها بـFD). هذا العنصر عبارة عن برنامج يتيح لخادوم Bacula (مدير Bacula تحديدا) الوصول إلى البيانات التي ستُنسَخ. نسمي الخواديم التي نريد أخذ نسخ منها “عملاء النسخ الاحتياطي” أو “العملاء”. سنعدّ مثل ما أشرنا في المقدمة، خادوم النسخ الاحتياطي لإنشاء نسخة احتياطية من نظام ملفاته الخاص؛ وهو ما يعني أن خادوم النسخ الاحتياطي سيكون أيضا عميل نسخ احتياطي وبالتالي سيشغل خدمة File. نبدأ بالتثبيت. تثبيت MySQLيستخدم Bacula قاعدة بيانات SQL مثل MySQL وPostgreSQL لإدارة الفهرس. سنستخدم MySQL في هذا الدرس. نبدأ بتحديث الحزم: $ sudo apt-get updateثم نثبت خادوم MySQL: $ sudo apt-get install mysql-serverسيُطلَب منك إدخال كلمة سر خاصة بالحساب الإداري root لـMySQL. أدخل كلمة سر ثم أكدها. ستحتاج لكلمة السر هذه أثناء تثبيت Bacula. تثبيت Baculaننفذ الأمر التالي لتثبيت العناصر المكونة لخادوم Bacula وعميله: $ sudo apt-get install bacula-server bacula-clientسيُطلب منك إدخال معلومات ستُستخدم لإعداد Postfix الذي يستخدمه Bacula: النوع العام لإعداد البريد General Type of Mail Configuration: اختر Internet Site.اسم نظام البريد: أدخل اسم النطاق الكامل لخادومك أو اسم المضيف.في الخطوة الموالية تُطلب معلومات تستخدم لإعداد قاعدة بيانات Bacula: اختر Yes بالنسبة لخيار Configure database for bacula-director-mysql with dbconfig-common.أدخل كلمة سر الحساب الإداري لـMySQL ثم أكدها (خيار Password of the database's administrative user).أدخل كلمة سر جديدة وأكدها عند خيار MySQL application password for bacula-director-mysql أو اتركها فارغة لتوليد كلمة سر عشوائية.الخطوة الأخيرة في عملية التثبيت هي تحديث أذون السكربت الذي يستخدمه Bacula أثناء شغل فهرس النسخ الاحتياطي: $ sudo chmod 755 /etc/bacula/scripts/delete_catalog_backupننتقل الآن، بعد تثبيت الخادوم والعميل الخاصين بـBacula إلى إنشاء مجلدات النسخ الاحتياطي والإعادة. إنشاء مجلدات النسخ الاحتياطي والإعادةيحتاج Bacula إلى مجلد للنسخ الاحتياطي يخزِّن فيه الأرشيف، ومجلد للإعادة يضع فيه الملفات المُعادة. تأكد من إنشاء هذه المجلدات على تجزئة بمساحة كافية. ننشئ مجلدين جديدين: $ sudo mkdir -p /bacula/backup /bacula/restoreنعدّل أذون الملف لكي يقتصر إذن الوصول للمجلدات على عمليّة bacula (والمستخدم الأعلى): $ sudo chown -R bacula:bacula /bacula $ sudo chmod -R 700 /baculaبهذا نكون جاهزين لإعداد مدير Bacula. إعداد مدير Baculaيتكون Bacula من عناصر عدة يجب إعداد كل واحد منها على حدة ليعمل بطريقة صحيحة. توجد جميع ملفات الإعداد في المجلَّد etc/bacula/. نبدأ بمدير Bacula. افتح ملف إعداد المدير لتحريره: $ sudo nano /etc/bacula/bacula-dir.confإعداد الأشغال المحليةيُستخدَم شغل Bacula لـتنفيذ إجراءات النسخ الاحتياطي والإعادة. تعرِّف موارد الشغل تفاصيل ما يفعله شغلٌ مّا. تتضمن تفاصيل الشغل اسم العميل، مجموعة الملفات FileSet المُراد نسخها أو إعادتها وأمورا أخرى. سنعد هنا الأشغال التي سنستخدمها لنسخ نظام الملفات المحلي. ابحث في ملف bacula-dir.conf عن مورد الشغل ذي الاسم BackupClient1. غير قيمة Name لتصبح BackupLocalFiles: Job { Name = "BackupLocalFiles" JobDefs = "DefaultJob" }ابحث الآن عن مورد الشغل RestoreFiles. يجب أن تعدِّل قيمتين في هذا المورد: غير قيمة Name لتصبح RestoreLocalFiles وقيمة Where لتصبح bacula/restore/. يبدو الملف بعد التعديل على النحو التالي: Job { Name = "RestoreLocalFiles" Type = Restore Client=BackupServer-fd FileSet="Full Set" Storage = File Pool = Default Messages = Standard Where = /bacula/restore }تعد هذه التعليمات شغل RestoreLocalFiles لإعادة الملفات إلى المجلَّد bacula/restore/ الذي أنشأناه سابقا. إعداد مجموعة الملفاتتعيّن مجموعة ملفات Bacula - كما يشير الاسم - مجموعة ملفات أو مجلدات للتضمين أو الإبعاد من النسخ الاحتياطية. ابحث عن مجموعة ملفات FileSet باسم Full Set (توجد تحت التعليق # List of files to be backed up أي قائمة جميع الملفات المراد نسخها). سنجري ثلاثة تعديلات:(1) إضافة خيار استخدام gzip لضغط النسخ الاحتياطية، (2) تغيير الملفات المضمّنة من usr/sbin/ إلى / و(3) تغيير الملفات المبعدة وإضافة المسار bacula/. يبدو المورد بعد نزع التعليقات على النحو التالي: FileSet { Name = "Full Set" Include { Options { signature = MD5 compression = GZIP } File = / } Exclude { File = /var/lib/bacula File = /bacula File = /proc File = /tmp File = /.journal File = /.fsck } }أولا، تفعِّل التعليمات استخدام gzip لضغط الملفات أثناء إنشاء النسخ الاحتياطية؛ ثم تضيف الجذر / إلى الملفات المُراد نسخها (أي جميع ملفات التجزئة). وأخيرا تبعد المجلّد bacula/ من النسخة الاحتياطية لكي لا نعيد نسخ النسخ الاحتياطية السابقة والملفات المُعادة. ملحوظة: إن رغبت في إضافة تجزئات مركَّبة Mounted partitions في / إلى مجموعة الملفات فيجب إضافة تعليمة File لكل واحدة منها. تذكر أن النسخ الاحتياطية ستحتاج، عند استخدام مجموعات ملفات كبيرة مثل Full Set في أشغال النسخ الاحتياطي، مساحة أكبر على القرص الصلب مما لو كان اختيار ملفات النسخ أكثر تحديدا. على سبيل المثال، إن كان لديك مخطّط إعادة Recovery plan يحدد الحزم البرمجية الواجب تثبيتها والأماكن التي يجب وضع الملفات المعادة فيها؛ فإن مجموعة ملفات لا تتضمن سوى ملفات الإعداد المخصَّص وقواعد البيانات تكفي لاحتياجاتك ولا تستخدم سوى جزء يسير من القرص الصلب لتخزين أرشيف النسخ الاحتياطية. إعداد الاتصال الخاص بخدمة التخزين Storageيعرّف مورد Storage في ملف إعداد المدير خدمة التخزين التي يجب على مدير Bacula الاتصال بها. سنضبُط خدمة التخزين في ما بعد. اعثُر على مورد Storage وأبدل قيمة Address (أي localhost) باسم النطاق الكامل FQDN المحلي (أو عنوان IP المحلي) لخادوم النسخ الاحتياطي. يبدو الملف بعد التعديل كالتالي (أبدل : Storage { Name = File # Do not use "localhost" here Address = backup_server_private_FQDN # N.B. Use a fully qualified name here SDPort = 9103 Password = "ITXAsuVLi1LZaSfihQ6Q6yUCYMUssdmu_" Device = FileStorage Media Type = File } سنعد خدمة التخزين للإنصات لواجهة الشبكة المحلية حتى يتسنى للعملاء الاتصال بها، لذا من المهم إعداد المورد لاستخدام العنوان المحلي لخادوم النسخ الاحتياطي. إعداد مجمع تخزين Storage poolيعرف مورد Pool وسائط التخزين التي سيخزن عليها Bacula النسخ الاحتياطية. سنتعامل مع ملفات كما لو كانت تجزئات للتخزين ثم نحدث اللصيقة Label لتوصيف النسخ الاحتياطية المحلية. ابحث عن مورد Pool باسم File (توجد تحت التعليق # File Pool definition) وأضف سطرا لتحديد صيغة اللصيقة. يبدو المورد، بعد التعديل، على النحو التالي: # File Pool definition Pool { Name = File Pool Type = Backup Label Format = Local- Recycle = yes # Bacula can automatically recycle Volumes AutoPrune = yes # Prune expired volumes Volume Retention = 365 days # one year Maximum Volume Bytes = 50G # Limit Volume size to something reasonable Maximum Volumes = 100 # Limit number of Volumes in Pool }احفظ الملف ثم أغلقه. بهذا يكتمل إعداد مدير Bacula. التحقق من إعدادات مدير Baculaنتحقق من عدم وجود أخطاء صياغة في ملف إعداد المدير DIR: $ sudo bacula-dir -tc /etc/bacula/bacula-dir.confإن لم تظهر رسائل خطأ فملف الإعداد نظيف من أخطاء الصياغة. ننتقل لإعداد خدمة التخزين SD. إعداد خدمة التخزيننحتاج لإعداد خدمة التخزين حتى يعرف خادوم Bacula أين يخزّن النسخ الاحتياطية. افتح ملف إعداد التخزين لتحريره: $ sudo nano /etc/bacula/bacula-sd.confإعداد مورد Storageاعثر على مورد Storage في ملف الإعداد الذي فتحته للتو. يعرّف هذا المورد العنوان الذي تنصت خدمة التخزين للاتصالات القادمة منه. أضف معطى SDAddress وحدد قيمته بالنطاق الكامل (أو عنوان IP) المحلي لخادوم النسخ الاحتياطي: Storage { # definition of myself Name = BackupServer-sd SDPort = 9103 # Director's port WorkingDirectory = "/var/lib/bacula" Pid Directory = "/var/run/bacula" Maximum Concurrent Jobs = 20 SDAddress = backup_server_private_FQDN }إعداد وسيط التخزيناعثر على مورد Device باسم FileStorage وحدث قيمة Archive Device لتوافق مجلد النسخ الاحتياطي لديك: Device { Name = FileStorage Media Type = File Archive Device = /bacula/backup LabelMedia = yes; # lets Bacula label unlabeled media Random Access = Yes; AutomaticMount = yes; # when device opened, read it RemovableMedia = no; AlwaysOpen = no; }احفظ الملف ثم أغلقه. التحقق من إعداد خدمة التخزينننفذ الأمر التالي للتحقق من عدم وجود أخطاء صياغة في ملف الإعداد الخاص بخدمة التخزين: $ sudo bacula-sd -tc /etc/bacula/bacula-sd.confإن لم تظهر رسائل خطأ فملف الإعداد نظيف من أخطاء الصياغة. أكملنا إعداد Bacula وأصبحنا جاهزين لإعادة تشغيل عناصر خادوم Bacula. إعادة تشغيل مدير Bacula وخدمة التخزيننعيد تشغيل مدير Bacula وخدمة التخزين لاعتماد تعديلات الإعدادات: $ sudo service bacula-director restart $ sudo service bacula-sd restartنجرب، بعد إعادة تشغيل الخدمتين، عمل خادوم Bacula بإنشاء شغل نسخ احتياطي. اختبار شغل للنسخ الاحتياطينستخدم وحدة تحكم Bacula لتشغيل أول شغل للنسخ الاحتياطي؛ إن عمل دون مشاكل فسنتأكد أن Bacula مضبوط بطريقة صحيحة. ادخل إلى وحدة التحكم بتنفيذ الأمر التالي: $ sudo bconsoleستُنقَل إلى محثّ Prompt وحدة تحكم Bacula المُشار إليه ب*. إنشاء لصيقةابدأ بتنفيذ أمر label: * labelسيُطلب منك إدخال اسم للتجزئة: Enter new Volume name: MyVolumeثم اختر مجمع التخزين الذي تريد أن يستخدم للنسخ الاحتياطية. سنختار File الذي أعددناه سابقا بإدخال الرقم 2: Select the Pool (1-3): 2التشغيل اليدوي لشغل نسخ احتياطيأعطينا Bacula المعلومات الكافية ليعرف كيف يخزن بيانات النسخ الاحتياطية، ويمكن بالتالي تشغيل النسخ الاحتياطي لمعرفة ما إذا كان يعمل بطريقة صحيحة: * runسيطلب منك اختيار الشغل الذي تريد تشغيله. نريد تشغيل BackupLocalFiles لذا سنختار 1: Select Job resource (1-3): 1راجع التفاصيل في محث التأكيد Run Backup job ثم اختر Yes للتشغيل: * yesفحص الرسائل والحالةسيخبرك Bacula بعد تشغيل شغل للنسخ الاحتياطي أن لديك رسائل، وهي مخرجات ولّدتها الأشغال الجارية. افحص الرسائل بتنفيذ الأمر: * messagesيجب أن تظهر رسالة No prior Full backup Job record found (أي لم يُعثر على سجل لنسخة احتياطية كاملة سابقة) وأخرى تخبرك ببدء الشغل. ستظهر رسائل خطأ في حال وجود مشاكل مع تلميحات لأسبابها، لماذا لم ينفَّذ الشغل مثلا. توجد طريقة أخرى لمعرفة حالة الشغل وهي فحص حالة المدير. لاستعمال هذه الطريقة أدخل اﻷمر التالي في محث وحدة التحكم bconsole: * status directorإن كان كل شيء جرى على ما يرام فسترى أن الشغل يعمل. ستظهر مخرجات تشبه التالي: Running Jobs: Console connected at 09-Apr-15 12:16 JobId Level Name Status ====================================================================== 3 Full BackupLocalFiles.2015-04-09_12.31.41_06 is running ====ستنتقل وحدة التحكم إلى فقرة Terminated Jobs (أشغال مكتملة) من تقرير الحالة عند انتهاء تنفيذ الشغل. تظهر المخرجات بما يشبه التالي: Terminated Jobs: JobId Level Files Bytes Status Finished Name ==================================================================== 3 Full 161,124 877.5 M OK 09-Apr-15 12:34 BackupLocalFilesتشير الحالة OK إلى أن شغل النسخ الاحتياطي عمل دون مشاكل. الخطوة التالية هي اختبار شغل الإعادة. اختبار شغل الإعادةمن المهم بعد إنشاء النسخ الاحتياطية اختبار إمكانية إعادتها على نحو سليم. يمكن أمر restore من إعادة الملفات التي نسخناها احتياطا. تنفيذ الشغل Restore Allسنعيد جميع الملفات الموجودة في آخر نسخة احتياطية، لذا نستخدم الأمر: * restore allستظهر قائمة بها خيارات متعددة تستخدم لتعريف أي مجموعة نسخ احتياطية نعيد الملفات منها. بما أنه لا توجد لدينا سوى نسخة واحدة فسنحدد الخيار 5 Select the most recent backup (اختر النسخة الاحتياطية الأحدث): Select item (1-13): 5بما أنه لا يوجد سوى عميل واحد وهو خادوم Bacula فسيُختار. المحث التالي يسأل عن مجموعة الملفات التي تريد استخدامها. اختر Full Set أي الرقم 2: Select FileSet resource (1-2): 2سيُحيلك الخيار إلى شجرة افتراضية للملفات يوجد بها تخطيط كامل للمجلد الذي نسخته احتياطا. تسمح هذه الواجهة التي تشبه Shell بتحديد الملفات المرادة إعادتها أو نزع تحديدها. بما أننا نفذنا أمر restore all (إعادة الجميع) فإن كل ملف في المخطّط الشجري محدَّد لإعادته. تسبق علامة * الملفات المحدّدة. إن أردت تخصيص الاختيار فيمكن التنقل في قائمة الملفات باستخدام الأمرين ls وcd، تحديد الملفات بmark ونزع تحديدها بunmark. تحصل على قائمة بجميع الأوامر المتاحة عند تنفيذ الأمر help (مساعدة) في وحدة التحكم. لبدء عملية الإعادة، بعد الانتهاء من تحديد الملفات، نفذ الأمر: * doneأكد رغبتك في تنفيذ شغل الإعادة: OK to run? (yes/mod/no): yesفحص الرسائل والحالةندقق، مثل ما فعلنا مع شغل النسخ الاحتياطي، في رسائل مدير Bacula وحالته بعد تنفيذ شغل الإعادة. افحص الرسائل بتنفيذ: * messagesيجب أن تظهر رسالة تفيد ببدء شغل الإعادة أو أنه اكتمل مع حالة OK دلالةً على نجاح العملية. ستظهر رسائل خطأ في حال وجود مشاكل مع تلميحات لأسبابها. يمكن أيضا فحص حالة المدير: * status directorنفذ الأمر exit للخروج من وحدة تحكم Bacula بعد الانتهاء من إعادة الملفات: * exitالتحقق من إعادة الملفاتيمكن بالنظر إلى المجلد bacula/restore/ (عرّفناه ضمن شغل RestoreLocalFiles في إعداد مدير Bacula) التحقق من أن شغل الإعادة أرجع فعلا الملفات المحدَّدة: $ sudo ls -la /bacula/restoreيجب أن تظهر الملفات المُعادة في جذر نظام الملفات مع إبعاد الملفات والمجلدات الموجودة في فقرة Exclude من شغل RestoreLocalFiles. يجب أن تنسخ الملفات المعادة من النسخ الاحتياطية، عند إرجاع بيانات مفقودة، إلى أماكنها المناسبة (وضع ملفات الإعداد مثلا في المجلد المناسب حسب البرنامج أو التطبيق). حذف الملفات المعادةنفذ الأمر التالي إن أردت حذف الملفات المعادة، لإخلاء مساحة في القرص الصلب: $ sudo -u root bash -c "rm -rf /bacula/restore/*"يجب تنفيذ أمر rm بصلاحيات root إذ أن الكثير من الملفات المعادة يمتلكها المستخدم الأعلى. خاتمةيكون لديك باتباع الخطوات المشروحة في هذا المقال إعداد أساسي لـBacula يمكن من نسخ نظام الملفات المحلي وإعادته. الخطوة الموالية هي إضافة خواديم عميلة لتتمكن من إرجاع بياناتها في حال فقدان ملفات من النظام. ترجمة -وبتصرف- للمقال How To Install Bacula Server on Ubuntu 14.04 لصاحبه Mitchell Anicas.
  19. يعتبر Laravel أشهر إطار ويب بلغة PHP، ولقد شهد إصداره الخامس العديد من التغييرات وتمت إضافة الكثير من المميزات الجديدة، ولذلك لتعلم أساسيات هذا الإطار سوف نقوم بإنشاء تطبيق Todo List، وسوف نتعلم من خلال هذا التطبيق الكثير من المفاهيم والطرق البرمجية حتى نتمكن من التعامل والتوسع مع إطار Laravel 5. ملاحظة: هذا الدرس طويل للغاية لذلك سوف يتم تقسيمه إلى أجزاء أصغر، ويمكنك الحصول على الكود المصدري لكل جزء من GitHub. في هذا الدرس سوف نتحدث عن تثبيت Laravel 5 وإعداده وعن بعض التقنيات الجديد كالتهجير migration والبذر seeding. قبل أن نبدأ أهم المصطلحات التي ستصادفنا في هذه الدروس: التهجير migration: نظام لإدارة قواعد البيانات، فهو يسمح للفريق بتعديل مخطط قواعد البيانات لجميع الأعضاء. البذر seeding: يقصد بها إدخال البيانات الأولية لتجربة التطبيق، أي أنه سيقوم بإدخال بيانات لمساعدتك على التطوير واكتشاف الأخطاء. هدف المشروع سوف يتكون تطبيقنا من مشروع أو أكثر، كل واحد لديه قائمة مهام خاصة به، وسوف تتمكن من إنشاء وعرض وتعديل وحذف المهام والمشاريع. في هذا الدرس سوف نقوم بـ: إعداد وتنصيب Laravel. تركيب حزم إضافية لتسهيل عملية التطوير. استخدام التهجير migration والبذر seeds. تعلم كيفية استخدام متحكِّمات الموارد resourceful controllers. تعلم كيفية استخدام العروض views. (بما في ذلك نظام blade ومخططات المحتوى) التعامل مع علاقات النماذج. التثبيت إن عملية تثبيت Laravel سهلة للغاية بفضل Composer، لذلك سوف نستخدمه في تثبيته. استخدام Composer والآن نقوم بتشغيل مثبت Laravel (سوف تحتاج إلى عمل هذا لمرة واحدة فقط): composer global require "laravel/installer=~1.1" والآن نقوم بعمل مشروعنا: laravel new l5todo الإعداد يستخدم Laravel 5 حزمة تدعى DotEnv تقوم بتخزين المعلومات الحساسة في ملفات ذات صيغة .env والتي يتم تحميلها كمتغيرات PHP عند التشغيل. قد يبدوا لك هذا معقدا لكن بكلمات أخرى، هذا يعني أن فقط الإعدادات الحسّاسة credentials يتم تخزينها في هذه الملفات وأما بقية إعداداتك فيتم تخزينها في ملفات الإعداد العادية. قاعدة البيانات سوف نحتاج إلى قاعدة بيانات، لذلك سنقوم بعمل واحدة ثم سنقوم بنسخ .env.example إلى .env وتحديث البيانات على الشكل التالي: DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret في النهاية إذا لم تكن تستخدم MySQL فقُم بفتح config/database.php/ ثم قٌم بتغيير السطر الافتراضي: 'default' => 'mysql', تذكر أن تضيف ملفات بيئة عملك إلى .gitignore عن طريق إضافة سطر .env. خطواتنا الأولى كما ذكرنا في الأعلى، سوف يتكون تطبيق قائمة المهام على مشروع أو أكثر كل واحد مع قائمة المهام الخاصة به، ولذلك سوف نحتاج إلى مشروع، نماذج مهام، متحكِّمات، عروض views، التهجير migration، البذور seeds والطرق routes، ولقد قمنا بشرح بعض هذه المصطلحات في بداية الدرس. لنبدأ بالتعامل معهم كل واحد على حدة. التهجير migration أولا نريد أن نرى مخطط جدولنا، سوف يبدو مثل هذا: Projects +------------+------------------+------+-----+ | Field | Type | Null | Key | +------------+------------------+------+-----+ | id | int(10) unsigned | NO | PRI | | name | varchar(255) | NO | | | slug | varchar(255) | NO | | | created_at | timestamp | NO | | | updated_at | timestamp | NO | | +------------+------------------+------+-----+ Tasks +-------------+------------------+------+-----+ | Field | Type | Null | Key | +-------------+------------------+------+-----+ | id | int(10) unsigned | NO | PRI | | project_id | int(10) unsigned | NO | MUL | | name | varchar(255) | NO | | | slug | varchar(255) | NO | | | completed | tinyint(1) | NO | | | description | text | NO | | | created_at | timestamp | NO | | | updated_at | timestamp | NO | | +-------------+------------------+------+-----+ ثم سوف نقوم بعمل التهجير migration: php artisan make:migration create_projects_and_tasks_tables --create="projects" سوف نقوم بعمل كِلا الجدولين بتهجير migration واحد حتى نتمكن من حذفها بترتيب عكسي لتجنب سلامة خرق القيد integrity constraint violation، قُم بفتح: /database/migrations/createprojectsandtasks_tables.php وقُم بتحديث المعلومات حسب الآتي: <?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateProjectsAndTasksTables extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('projects', function(Blueprint $table) { $table->increments('id'); $table->string('name')->default(''); $table->string('slug')->default(''); $table->timestamps(); }); Schema::create('tasks', function(Blueprint $table) { $table->increments('id'); $table->integer('project_id')->unsigned()->default(0); $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); $table->string('name')->default(''); $table->string('slug')->default(''); $table->boolean('completed')->default(false); $table->text('description')->default(''); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('tasks'); Schema::drop('projects'); } } قم بتنفيذ الهجرة migration: php artisan migrate إذا قمت الآن بمراجعة قاعدة البيانات، يجب أن تكون الجداول مكتملة. البذور Seeds سوف نحتاج إلى بذر المشاريع/المهام ليكون لديك شيء للعمل معه عندما نصل إلى المتصفح، لذلك قم بإنشاء: /database/seeds/ProjectsTableSeeder.php و TasksTableSeeder.php كالتالي: // /database/migrations/seeds/ProjectsTableSeeder.php <?php use Illuminate\Database\Seeder; class ProjectsTableSeeder extends Seeder { public function run() { // Uncomment the below to wipe the table clean before populating DB::table('projects')->delete(); $projects = array( ['id' => 1, 'name' => 'Project 1', 'slug' => 'project-1', 'created_at' => new DateTime, 'updated_at' => new DateTime], ['id' => 2, 'name' => 'Project 2', 'slug' => 'project-2', 'created_at' => new DateTime, 'updated_at' => new DateTime], ['id' => 3, 'name' => 'Project 3', 'slug' => 'project-3', 'created_at' => new DateTime, 'updated_at' => new DateTime], ); // Uncomment the below to run the seeder DB::table('projects')->insert($projects); } } // /database/migrations/seeds/TasksTableSeeder.php <?php use Illuminate\Database\Seeder; class TasksTableSeeder extends Seeder { public function run() { // Uncomment the below to wipe the table clean before populating DB::table('tasks')->delete(); $tasks = array( ['id' => 1, 'name' => 'Task 1', 'slug' => 'task-1', 'project_id' => 1, 'completed' => false, 'description' => 'My first task', 'created_at' => new DateTime, 'updated_at' => new DateTime], ['id' => 2, 'name' => 'Task 2', 'slug' => 'task-2', 'project_id' => 1, 'completed' => false, 'description' => 'My first task', 'created_at' => new DateTime, 'updated_at' => new DateTime], ['id' => 3, 'name' => 'Task 3', 'slug' => 'task-3', 'project_id' => 1, 'completed' => false, 'description' => 'My first task', 'created_at' => new DateTime, 'updated_at' => new DateTime], ['id' => 4, 'name' => 'Task 4', 'slug' => 'task-4', 'project_id' => 1, 'completed' => true, 'description' => 'My second task', 'created_at' => new DateTime, 'updated_at' => new DateTime], ['id' => 5, 'name' => 'Task 5', 'slug' => 'task-5', 'project_id' => 1, 'completed' => true, 'description' => 'My third task', 'created_at' => new DateTime, 'updated_at' => new DateTime], ['id' => 6, 'name' => 'Task 6', 'slug' => 'task-6', 'project_id' => 2, 'completed' => true, 'description' => 'My fourth task', 'created_at' => new DateTime, 'updated_at' => new DateTime], ['id' => 7, 'name' => 'Task 7', 'slug' => 'task-7', 'project_id' => 2, 'completed' => false, 'description' => 'My fifth task', 'created_at' => new DateTime, 'updated_at' => new DateTime], ); //// Uncomment the below to run the seeder DB::table('tasks')->insert($tasks); } } ولا تنسَ إضافة أصناف البذور(seed classes) إلى database/seeds/DatabaseSeeder.php/ : use Illuminate\Database\Seeder; use Illuminate\Database\Eloquent\Model; class DatabaseSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { Model::unguard(); $this->call('ProjectsTableSeeder'); $this->call('TasksTableSeeder'); } } الآن نقوم بالبذر: composer dump-autoload ثم: php artisan db:seed # أو php artisan migrate:refresh --seed يجب الآن أن تكون قاعدة البيانات قد تم بذرها. mysql> select * from projects; +----+-----------+-----------+---------------------+---------------------+ | id | name | slug | created_at | updated_at | +----+-----------+-----------+---------------------+---------------------+ | 1 | Project 1 | project-1 | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | | 2 | Project 2 | project-2 | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | | 3 | Project 3 | project-3 | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | +----+-----------+-----------+---------------------+---------------------+ mysql> select * from tasks; +----+------------+--------+--------+-----------+----------------+---------------------+---------------+ | id | project_id | name | slug | completed | description | created_at | updated_at | +----+------------+--------+--------+-----------+----------------+---------------------+---------------+ | 1 | 1 | Task 1 | task-1 | 0 | My first task | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | 2 | 1 | Task 2 | task-2 | 0 | My first task | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | 3 | 1 | Task 3 | task-3 | 0 | My first task | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | 4 | 1 | Task 4 | task-4 | 1 | My second task | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | 5 | 1 | Task 5 | task-5 | 1 | My third task | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | 6 | 2 | Task 6 | task-6 | 1 | My fourth task | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 | 7 | 2 | Task 7 | task-7 | 0 | My fifth task | 2015-02-05 01:25:43 | 2015-02-05 01:25:43 +----+------------+--------+--------+-----------+----------------+---------------------+---------------+ النماذج Models للعمل مع جداول المشاريع والمهام نحتاج إلى نماذج مماثلة، سوف نقوم بإنشائها الآن: php artisan make:model Project php artisan make:model Task كان هذا سهلا استخدام Artisan – Tinker الآن لدينا المعلومات في قاعدة البيانات وسيكون من الرائع أن نتعلم حول واحدة من أهم ميزات artisan وهي Tinker الذي يوفر لك سطر أوامر للتعامل مع Laravel، وكمثال، لنستخدمه في معرفة عدد المشاريع في قاعدة البيانات الحالية: $ php artisan tinker > App\Project::count(); 3 > App\Task::count(); 7 وكما ترى يمكن أن يكون Tinker مفيدا للغاية، لذلك سوف نستخدمه عدة مرات في هذه السّلسلة. المُتحكِّمات Controllers الآن وصلنا إلى النقطة التي سوف نبدأ بعرض ما صنعناه على المتصفح، وسوف نحتاج إلى إنشاء بعض المتحكِّمات Controllers والطرق Routes. سنبدأ أولا بالمتحكِّمات: php artisan make:controller ProjectsController php artisan make:controller TasksController الموارد المُضمّنة نبدأ بإضافة موارد Project و Task إلى app/Http/routes.php/ : Route::get('/', 'WelcomeController@index'); //Route::get('home', 'HomeController@index'); // //Route::controllers([ // 'auth' => 'Auth\AuthController', // 'password' => 'Auth\PasswordController', //]); Route::resource('projects', 'ProjectsController');Route::resource('tasks', 'TasksController'); والآن دعونا نرى إحدى مميزات artisan والمُتمثّلة في route:list، في سطر الأوامر أكتب التالي: php artisan route:list لتكون النّتيجة +--------+----------+--------------------------+------------------+-------------------------------------------------+------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+--------------------------+------------------+-------------------------------------------------+------------+ | | GET|HEAD | / | | App\Http\Controllers\WelcomeController@index | | | | GET|HEAD | projects | projects.index | App\Http\Controllers\ProjectsController@index | | | | GET|HEAD | projects/create | projects.create | App\Http\Controllers\ProjectsController@create | | | | POST | projects | projects.store | App\Http\Controllers\ProjectsController@store | | | | GET|HEAD | projects/{projects} | projects.show | App\Http\Controllers\ProjectsController@show | | | | GET|HEAD | projects/{projects}/edit | projects.edit | App\Http\Controllers\ProjectsController@edit | | | | PUT | projects/{projects} | projects.update | App\Http\Controllers\ProjectsController@update | | | | PATCH | projects/{projects} | | App\Http\Controllers\ProjectsController@update | | | | DELETE | projects/{projects} | projects.destroy | App\Http\Controllers\ProjectsController@destroy | | | | GET|HEAD | tasks | tasks.index | App\Http\Controllers\TasksController@index | | | | GET|HEAD | tasks/create | tasks.create | App\Http\Controllers\TasksController@create | | | | POST | tasks | tasks.store | App\Http\Controllers\TasksController@store | | | | GET|HEAD | tasks/{tasks} | tasks.show | App\Http\Controllers\TasksController@show | | | | GET|HEAD | tasks/{tasks}/edit | tasks.edit | App\Http\Controllers\TasksController@edit | | | | PUT | tasks/{tasks} | tasks.update | App\Http\Controllers\TasksController@update | | | | PATCH | tasks/{tasks} | | App\Http\Controllers\TasksController@update | | | | DELETE | tasks/{tasks} | tasks.destroy | App\Http\Controllers\TasksController@destroy | | +--------+----------+--------------------------+------------------+-------------------------------------------------+------------+ ستلاحظ أن كل من projects و tasks هي روابط ذات مستوى عالي، وفي تطبيقنا، المهام تتبع المشاريع، لذلك سيكون من الأفضل للروابط أن تكون مُضمّنة مثل /projects/1/tasks/3 بدلا من /tasks/، وهذا يمكن فعله باستخدام شيء اسمه الموارد المُضمّنة nested resources، وكما هو الحال مع أغلب الأشياء في Laravel، التعديل المطلوب سريع وبسيط، فقط قٌم بفتح /app/Http/routes.php وقٌم بالتعديلات التالية: // Route::resource('tasks', 'TasksController'); Route::resource('projects.tasks', 'TasksController'); هذا كل شيء، قُم بكتابة php artisan route:list لنعلم ماذا لدينا لحد الآن: php artisan route:list +--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+ | | GET|HEAD | / | | App\Http\Controllers\WelcomeController@index | | | | GET|HEAD | projects | projects.index | App\Http\Controllers\ProjectsController@index | | | | GET|HEAD | projects/create | projects.create | App\Http\Controllers\ProjectsController@create | | | | POST | projects | projects.store | App\Http\Controllers\ProjectsController@store | | | | GET|HEAD | projects/{projects} | projects.show | App\Http\Controllers\ProjectsController@show | | | | GET|HEAD | projects/{projects}/edit | projects.edit | App\Http\Controllers\ProjectsController@edit | | | | PUT | projects/{projects} | projects.update | App\Http\Controllers\ProjectsController@update | | | | PATCH | projects/{projects} | | App\Http\Controllers\ProjectsController@update | | | | DELETE | projects/{projects} | projects.destroy | App\Http\Controllers\ProjectsController@destroy | | | | GET|HEAD | projects/{projects}/tasks | projects.tasks.index | App\Http\Controllers\TasksController@index | | | | GET|HEAD | projects/{projects}/tasks/create | projects.tasks.create | App\Http\Controllers\TasksController@create | | | | POST | projects/{projects}/tasks | projects.tasks.store | App\Http\Controllers\TasksController@store | | | | GET|HEAD | projects/{projects}/tasks/{tasks} | projects.tasks.show | App\Http\Controllers\TasksController@show | | | | GET|HEAD | projects/{projects}/tasks/{tasks}/edit | projects.tasks.edit | App\Http\Controllers\TasksController@edit | | | | PUT | projects/{projects}/tasks/{tasks} | projects.tasks.update | App\Http\Controllers\TasksController@update | | | | PATCH | projects/{projects}/tasks/{tasks} | | App\Http\Controllers\TasksController@update | | | | DELETE | projects/{projects}/tasks/{tasks} | projects.tasks.destroy | App\Http\Controllers\TasksController@destroy | | +--------+----------+----------------------------------------+------------------------+-------------------------------------------------+------------+ جعل روابط ذات اسم لطيف الطرق routes الحالية ممتازة لكنها ذات عناوين يمكن تحسينها، مثل هذا العنوان /projects/1/tasks/2، فسيكون من الرائع للزوار أن يتم تغيير المعرف الرقمي ID بالاسم اللطيف للحقول، فمثلا سوف نحصل على /projects/my-first-project/tasks/buy-milk بدلا من /projects/1/tasks/2. قم بفتح ملف /app/Http/routes.php وضع به التالي: Route::bind('tasks', function($value, $route) { return App\Task::whereSlug($value)->first(); }); Route::bind('projects', function($value, $route) { return App\Project::whereSlug($value)->first(); }); هذه الشيفرة سوف تغير السلوك الافتراضي لـ tasks و projects في artisan routes وجعل الروابط ذات إسم لطيف slug. خاتمة اليوم لقد قمنا بعمل عدة أشياء وهي: تثبيت وإعداد Laravel. إضافة موردان اثنان resources. إنشاء التهجيرات migrations. إضافة بعض بيانات البذور seeds. تكوين هيكل الروابط. بكلمات أخرى، قمنا اليوم بوضع الأساس التي سوف نعتمد عليه في الدروس القادمة من خلال إنشاء جميع العناصر اللازمة حتى تعمل الواجهة الأمامية، ولدينا الآن بعض البيانات في قاعدة البيانات بالإضافة إلى الطرق، في الدرس القادم سوف نبدأ في الواجهة الأمامية للموقع. هنالك بضعة مواقع أخرى لتحصل على المزيد من المعلومات وآخر الأخبار: The Laravel Twitter feed: أخر الأخبار حول تطورات Laravel. Taylor Otwell’s Twitter feed: حساب تويتر لمُؤسّس Laravel. Laravel.io: لمتابعة آخر الأخبار و الدورات من مختلف مواقع الويب، بالإضافة إلى بودكاست أسبوعي يتحدث عن الأفكار والاهتمامات ذات علاقة إلى المنصة. Laravel Packages Registry: مكان جيد لإيجاد أفضل حزم Laravel. Code Bright: كتاب إلكتروني مجاني من المؤلف دايلي ريس Dayle Rees. ترجمة وبتصرف للمقال: Creating a Basic ToDo Application in Laravel 5 – Part 1. حقوق الصورة البارزة: Designed by Freepik.
  20. تستغل هجمات حقن SQL البرمجة السيئة للشفرة الخاصّة بالبرمجيات. إنّها هجمات حيث يقوم المهاجمون بإرسال شفرة عبر واحدٍ من مربّعات الإدخال الموجودة على موقعك (أيّ مربّع)، عوضًا عن أن يرسل بياناتٍ عادية كنتَ تنوي استقبالها عبر مربّعات الإدخال تلك. تقوم تلك الشفرة المُدخلة بتنفيذ عمليات الاستعلام على قاعدة البيانات الخاصّة بموقعك بطريقةٍ لم تكن تتوقعها، أو تقوم بتحطيم تطبيق الويب الخاصّ بك وتقوم بتخريب خادومك السحابي. م السهل جدًا عمل هجمات حقن SQL ضدّ المواقع الغير مؤمّنة. وحراسة موقعك ضدّ هذه الهجمات قد يكون من أهمّ ما تقوم به منذ اليوم الأوّل. الخطوة الأولى: تعلم تمييز الشفرة المحتوية على ثغراتتأخذ هجمات SQL دومًا شكل سلسلة نصّية يتم إرسالها من طرف مستخدمٍ تتكون من قسمين. القسم الأول هو عبارة عن تخمين لكيفية تعطيل أمرٍ تحاول شفرتك المصدرية أن تقوم بتنفيذه بأمان; القسم الثاني هو الشفرة الخبيثة التي يريد المهاجم تنفيذها على خادومك. إليك مثالًا على سلسلة نصّية مصممة لاستغلال ثغرة ممكنة في الشفرة المصدرية لديك: x' AND user.email IS NULL; --يبدو هذا كشيء قمتَ بكتابته بنفسك، وتلك هي النقطة. يأمل المستخدم المُخترِق أن تقوم بأخذ هذا السطر، وتقوم بتنفيذه بعملية استعلام SQL تبدو كالتالي: SELECT email, passwd FROM user WHERE email = 'x' AND user.email IS NULL; --';لا يبدو أنّ هذا يقوم بالكثير حقًا، ولكن اعتمادًا على الطريقة التي سيستجيب بها تطبيقك إلى ما سبق، يمكن أن يوفّر هذا بعض المعلومات المهمّة للمُخترِق مثل اسم جدول قاعدة البيانات الذي تستعمله. بعد هذا، هناك المزيد من الهجمات التي يمكن للمهاجم أن يستخدمها لجلب المزيد من المعلومات، مثل أسماء المستخدمين وكلمات المرور. الفكرة الرئيسية التي يجب عليك فهمها هي أنّ الشفرة الخبيثة تحاول البحث عن ثغرة بعملية استعلام SQL التي يقوم بها تطبيقك لمحاولة استغلالها لجلب المعلومات أو إدراجها وتعديلها. لا تتطلب جميع هجمات حقن SQL إشارة الاقتباس المغلقة ('). إذا كانت شفرتك المصدرية تنفّذ عملية استعلامٍ متعلّقة برقم، فإنّك لن تقوم بالطبع بوضع تلك البيانات داخل إشارة اقتباس. وهذا يتركك عرضةً لهذا النوع من الهجمات: 2097 OR 1=1يأمل المهاجم أن يقوم تطبيقك بعملية استعلام مشابهة للتالي: SELECT somedata FROM yourtable WHERE userid = 2097 OR 1=1;غالبًا ما تكون شفرتك البرمجية مصممة لتقوم بعملية الاستعلام السابقة لتعيد البيانات فقط في حال تطابق الـ userid مع المستخدم الصحيح. ولكنّ حقنة الـSQL تجعل عملية الاستعلام تقوم دومًا بإرجاع البيانات. النقطة ليست في سلوكٍ معيّن لأيّ حقنة SQL. الشيء الأكثر أهمّية من هذا كلّه هو القاعدة العامّة لجميع حقن SQL: محاولة لتخمين كيفية حذف جزء معيّن من عملية استعلام، وإضافة جزءٍ آخر إليها لم تكن تتوقعه. هذا هو توقيع جميع هجمات حقن SQL. وهذه هي طريقة محاربتها. الخطوة الثانية: اعثر على مدخلاتكأفضل طريقة لتعقّب جميع نقط إدخال حقن SQL الممكنة في شفرتك البرمجية ليس عبر النظر إلى حقول إدخال HTML. بالطبع يمكنك العثور على العديد من الثغرات الممكنة هناك، ولكن هناك طرقٌ أخرى يمكن من خلالها للمستخدم أن يقوم بإدخال البيانات، مثل عنوان الويب (URL)، أو عبر واحدةٍ من واجهات AJAX الخاصّة بك. أفضل مكان للبحث فيه عن الثغرات هو الشيء الذي يريد المخترقون اختراقه بنفسه; جملة استعلام SQL بنفسها. على الأغلب، فإنّك تقوم بتنفيذ جميع عمليات الاستعلام عن طريق الأمر الأساسي نفسه، وربّما أمران آخران أو أكثر قليلًا. فقط ابحث عن هذه الأوامر في شفرتك البرمجية وستجد جميع الثغرات الممكنة بشكلٍ سريع. كمثال، إذا كانت شفرتك البرمجية مكتوبة بـPerl، فإنّ جميع عمليات استعلام SQL الخاصّة بك ستبدو هكذا: $result = mysql_query($sql)في تلك الحالة، يمكنك العثور بسرعة على جميع الثغرات الممكنة بواسطة سطر الأوامر، عبر استخدام أمر شبيه بالتالي: $ grep -R mysql_query *الخطوة الثالثة: نظف مدخلاتكهناك العديد من التقنيات التي يستخدمها الناس لمنع هجمات حقن SQL، ولكن خطّ دفاعك الأمامي يجب أن يكون تنظيف جميع مُدخلات المستخدم من أيّ شفرة خبيثة مشبوهة. يجب ألّا تعتقد بتاتًا أنّ المستخدم سيقوم بإدخال البيانات بالطريقة التي تريدها. في الواقع، يجب عليك أن تفترض العكس - أنّهم سيقومون بإدخال الشفرات الخبيثة في كلّ مكانٍ ممكن في موقعك. تنظيف المُدخلات يعني أنّه يجب اختبار جميع مُدخلات المستخدم للتأكّد من أنّها تحتوي فقط مُدخلات آمنة، مُدخلات لا يمكن استخدامها بتاتًا في شنّ هجوم. المُدخلات التي سيتم إدخالها من طرف المستخدم إلى خادوم SQL الخاصّ بك ستكون على شكلَين: كرقم، مثل 2097.كسلسلة (string)، مثل اسم المستخدم، كلمة المرور أو البريد الإلكتروني.تتوقّع شفرتك البرمجية دومًا مُدخَلًا واحدًا من هذين الشكلين. في الأمثلة التي ذكرناها ببداية هذا المقال، كان المثال الأوّل عبارة عن سلسلة نصّية، وكان المثال الثاني عبارةً عن رقم. هناك أيضًا طريقتان لتنظيف البيانات: طريقة جيدة وطريقة سيئة. الطريقة السيئة هي التحقق من وجود حقن SQL الممكنة. السبب في كونها سيئة هو لأنّ عدد حقن SQL الممكن كبير جدًا، و"إبداع" المهاجمين واسع كذلك. الطريقة الجيّدة هي تنظيف البيانات للتعرّف على ما يبدو شكل الإدخال الصحيح عليه، وتجاهل كلّ شيء لا يتوافق مع شكل ذلك الإدخال الصحيح. البيانات الرقمية هي الأسهل للتنظيف، لذا سنقوم بتغطية هذا أوّلًا. يمكن للرقم أن يحتوي على إشارة سالبة على يساره، أو أن يكون متبوعا بأرقام أخرى، وربّما يحتوي على فاصلة عشرية. هذا كلّ ما يمكن للبيانات الرقمية أن تبدو عليه، في Perl، ستبدو الشفرة التي تتحقق من البيانات الرقمية كالتالي: if($numericaluserinput !~ /^-?[0-9.]+$/) { # البيانات المُدخلة ليست رقمًا }من الصعب تخيّل أيّ حقنة خبيثة يمكنها أن تتخطى ما سبق. تنظيف المُدخلات النصّية أكثر صعوبة، لأنّه هناك العديد من الطرق لمحاولة إدخالها. يمكن للمهاجم أن يستخدم إشارات الاقتباس وغيرها بطرق "إبداعية" للقيام بالهجمات. في الواقع، محاولة إنشاء قائمة سوداء للحروف المُدخلة هو أمرٌ سيّء، لأنّه من السهل نسيان شيء مهم مثلًا. هناك طريقة أفضل، كما قمنا مع البيانات الرقمية، وهي تقييد مُدخلات المستخدم إلى قائمة بيضاء من الحروف فقط. كمثال، عناوين البريد الإلكتروني لا يجب أن تحتوي على شيء سوى الأرقام والحروف العادية وبعض الإشارات مثل @ و _ وعدا ذلك، يجب منع كلّ الحروف الأخرى. في لغة Perl، ستبدو الشفرة كالتالي: if($useremail ~= /^[0-9a-zA-Z\-_+.\@]$/) { # the user's email address is unacceptable }يمكن العثور على قوائم بيضاء للأنواع الأخرى من المُدخلات كذلك مثل اسم المستخدم وكلمة المرور.. إلخ. قد تكون القوائم البيضاء مصدر إزعاج لبعض المستخدمين. فربّما يكون هناك رموز معيّنة في بعض مربّعات الإدخال تكون غير مقبولة من طرفها مثلًا، ولكنّك بالطبع حرّ لتقوم بتعديل القوائم البيضاء حسب حاجتك، ولكن لا تنسى أن تقوم ببحث عن الرموز والمحارف التي تريد تمكينها للتأكّد من أنّه لا يمكن استخدامها في حقن SQL، فعندما تختار بين حماية الموقع وراحة المستخدم، حماية الموقع تأتي أوّلًا. تنظيف المُدخلات بواسطة القوائم البيضاء جيّد لأنّه سهل. إذا كنتَ مُدركًا بشكل صحيح للرموز والمحارف التي تقوم بتمكينها، فحينها سيكون هذا الحلّ كافيًا للتخليص من هجمات حقن SQL. الخطوة الرابعة: قبول المدخلات الخطيرةلا تنخدع بالعنوان! سنتحدّث فقط عن أهمّية عدم قبول المُدخلات الخطيرة. صحيحٌ أنّ القوائم البيضاء شديدة التقييد جيّدة من أجل الحماية في حال ما إذا كان تطبيقك يستطيع أن يتوافق مع تلك التقييدات على المستخدمين. ولكن في بعض الحالات، قد يكون من المهمّ لنموذجك الربحي الخاصّ بالتطبيق ألّا تقوم بفرض أيّ تقييدات على مُدخلات المستخدمين. في هذه الحالة، غالبًا ما تكون لغة البرمجة التي تستعملها في تطبيقك تحوي على مكتباتٍ تساعدك في تنظيف مُدخلات المستخدمين من الشفرات الخبيثة. كمثال، مكتبة Perl DBI تحوي طُرقًا متعددة لمنع مُدخلات المستخدمين من التعامل مع استعلام SQL بخارج المنطقة المخصصة لها: my $sql = "INSERT INTO user (username, email) VALUES (?, ?)"; my $handle = $dbh->prepare( $sql ); $handle->execute( $untrustedusername, $untrustedemail);في المثال السابق، تمّ استخدام إشارة ؟ كعناصر نائبة (placeholders). تقوم مكتبة Perl DBI باستبدال هذه الإشارات بالمتغيّرات الغير موثوقة والتي تمّ إدخالها من طرف المستخدم. ولكن أثناء القيام بهذا، تقوم مكتبة DBI بتقييد هذه المتغيرات وتجعلها تتعامل فقط مع الحقول المخصصة لها بجدول قاعدة البيانات. هناك مكتبات مشابهة باللغات البرمجية الأخرى، إمّا لتقييد مُدخلات المستخدم، أو لتجاهل البيانات في حال حاولت التعامل مع خارج الحقل المخصص لها. ميّزة هذه التقنية هي أنّك قادرٌ على إعطاء ثقتك بالأشخاص المطورين لتلك المكتبات، حيث أنّهم سيقومون بتطويرها، والحفاظ عليها بعيدة عن الثغرات الأمنية والمشاكل الخطيرة. ولكن عيب هذه التقنية هي أنّها أقل قابلية للقراءة البشرية، وهكذا ربّما تنسى استخدام المكتبة الصحيحة لحماية بعض من عمليات استعلام SQL الخاصّة بك. الخطوة الخامسة: خفف ضرر الهجمات الناجحةاعتمادًا على ماهيّة نموذج الأعمال الذي تقوم به بموقعك، فربّما تودّ القيام بإنشاء خطٍّ أخير للدفاع، شيء مستقل تمامًا عن مطوري تطبيقك. فبعد كلّ شيء، ربّما يستخدم واحدٌ منهم القوائم البيضاء الخاطئة في مكان ما، أو فشل باستخدام المكتبة الصحيحة لتنظيف المُدخلات. ثغرة واحدة فقط من هذا النوع قد تسبب في تحويل موقعك بأكمله إلى موقع قابل للاختراق عبر هجمات SQL. أولًا، يجب عليك أن تفترض أنّ المهاجمين نجحوا باختراق دفاعاتك ضدّ حقن SQL، وأنّهم حصلوا على الصلاحيات الكاملة لإدارة خادومك. إنهم يملكون الآلة الآن بالكامل، على الرغم من أنّك من يهتم بصيانتها وتطويرها. لتجنّب ذلك السقوط المروع، يجب على الخادوم نفسه أن يكون مضبوطًا داخل بيئة معزولة عن الشبكة، حيث يكون مستخدم الجذر على النظام غير قادر على الرؤية أو الوصول إلى أيّ أجزاء أخرى موجودة على خادومك. هذا النوع من الدفاع يدعى DMZ، وهو رائع للغاية، وهو كذلك خارج نطاق هذا الدرس. مهما كانت الطريقة التي تستخدمها لتأمين خادومك ضدّ مستخدم مهاجم نجح بالدخول بالفعل، فإنّه يجب عليك أن تقوم بإعداد نظام تنبيهات يقوم بإخطار مدراء النظام في حال حصول نشاط معيّن على الخادوم. هذه التنبيهات ستخبرك ما إذا تمّ اختراق التطبيق، وأنّه عليك عمل مراجعة سريع للشفرة البرمجية وللخادوم نفسه. دون هذه التنبيهات، سيكون المهاجم قادرًا على قضاء وقتٍ ممتع في محاولة اختراق الـDMZ الخاصّ بك دون أن تشعر، وربّما لا تشعر بتاتًا بما يفعله إلى حين أن يسرق جميع البطاقات الائتمانية التي ظننت أنّها كانت معزولة تمامًا عن الخادوم، في بيئةً كنت تظن أنّها منفصلة عن خادومك الرئيسي. الخطوة السادسة: وظف محترف حمايةإذا كنتَ تقوم بإدارة تطبيق ويب دون الاستعانة بخبير حماية، فحينها أنت تسبح بالمياه الخطيرة. وإذا كنت ولسبب ما غير قادر على توظيف خبير حماية وأمان، فإنّه يجب عليك الاستعانة بالقوائم البيضاء لتنظيف مُدخلات المستخدمين إلى حين. من السهل تضمين واستخدام القوائم البيضاء. لا بأس من تقييد تجرية المستخدمين قليلًا في سبيل حماية خادومك والبيانات الثمينة الموجودة عليه. وبمجرّد أن تقوم بتوظيف شخص يفهم في مجال الحماية والأمان، فستكون بعدها قادرًا بشكل أفضل على حماية موقعك من هجمات حقن SQL و XSS وغيرها من الهجمات الخطيرة التي قد تصيب موقعك. ترجمة -وبتصرف- للمقال: How To Secure a Cloud Server Against SQL Injection.
  21. سنقوم في هذا الدرس بإعداد خادوم بريد باستخدام Postfix، Dovecot، MySQL و SpamAssasin على توزيعة Ubuntu. بعد اتّباع هذا الدرس، ستكون قادرًا على إضافة نطاقات افتراضية (virtual domains)، المستخدمين والاختصارات إلى خادوم بريدك الإلكتروني، وليس هذا فقط، بل سيكون خادومك محميًا من هجمات السبام (Spam). المتطلّباتقبل البدء بإعداد خادوم البريد الخاصّ بك، من المهم أن يمتلك خادومك الافتراضي الخاص الأمور التالية: توجيه النطاق الرئيسي إلى عنوان الآي بي الخاصّ بخادومك.تثبيت وإعداد MySQL على الخادوم.مستخدم بصلاحيات الجذر (root privileges).إعداد وضبط اسم النطاق المؤهّل الكامل (FQDN). (إعداد FQDN).إضافي: شهادة SSL (إعداد شهادة SSL مجانية موقّعة).إضافي: تسجيل الدخول إلى المستخدم الجذر.سيكون من المفيد تثبيت الحزم باستخدام المستخدم الجذر حيث أنّك ستمتلك جميع الصلاحيات: sudo -iقم بكتابة كلمة المرور الخاصّة بالمستخدم. بمجرد نجاح العملية، سترى أنّ رمز $ قد تغيّر إلى #. الخطوة الأولى: تثبيت الحزمapt-get install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysqlعندما يتم سؤالك عن إعدادات Postfix، اختر "Internet Site": سيقوم Postfix بسؤالك عن اسم بريد النظام الإلكتروني - يمكنك استخدام FQDN أو نطاقك الرئيسي إن أردت: الخطوة الثانية: إنشاء قاعدة بيانات MySQL، نطاقات افتراضية، المستخدمين والاختصاراتبعد أن انتهى التثبيت، سنقوم الآن بإنشاء قاعدة بيانات MySQL لإعداد 3 جداول مختلفة: واحدٌ للنطاقات، واحدٌ للمستخدمين والأخير سيكون للاختصارات (aliases). سنقوم بتسمية قاعدة البيانات بـ"servermail"، ولكن يمكنك استخدام أيّ اسمٍ تريده. لإنشاء قاعدة البيانات servermail: mysqladmin -p create servermailلتسجيل الدخول كالمستخدم الجذر في MySQL: mysql -u root -pقم بإدخال كلمة مرور MySQL الخاصّة بالمستخدم الجذر; إذا نجحت العملية فسترى: mysql >يجب علينا أولًا إنشاء مستخدمٍ جديد، حيث يكون مخصصًا لعملية الاستيثاق (authentication) الخاصّة بالبريد الإلكتروني، وسنقوم بإعطائه صلاحية SELECT: mysql > GRANT SELECT ON servermail.* TO 'usermail'@'127.0.0.1' IDENTIFIED BY 'mailpassword';نحتاج بعدها إلى إعادة تحميل صلاحيات MySQL لضمان تطبيقها بشكلٍ صحيح: mysql > FLUSH PRIVILEGES;وأخيرًا، يجب علينا استخدام قاعدة البيانات الجديدة لإنشاء الجداول وحفظ بياناتنا: mysql> USE servermail;سنقوم بإنشاء جدول خاصّ بالنطاقات التي نعرفها على أنّها نطاقات موثوقة: CREATE TABLE `virtual_domains` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;سنقوم الآن بإنشاء جدول لحفظ المستخدمين فيه. ستقوم هنا بإضافة عناوين البريد الإلكتروني وكلمات المرور. من المهم جدًا أن تقوم بربط كلّ مستخدمٍ متوفّر بنطاقٍ ما: CREATE TABLE `virtual_users` ( `id` INT NOT NULL AUTO_INCREMENT, `domain_id` INT NOT NULL, `password` VARCHAR(106) NOT NULL, `email` VARCHAR(120) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;وأخيرًا، سنقوم بإنشاء جدول اختصاراتٍ افتراضي لتحديد جميع عناوين البريد الإلكتروني التي تريد توجيهها إلى عناوين بريدية أخرى: CREATE TABLE `virtual_aliases` ( `id` INT NOT NULL AUTO_INCREMENT, `domain_id` INT NOT NULL, `source` varchar(100) NOT NULL, `destination` varchar(100) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;لقد قمنا بإنشاء الجداول الثلاثة بنجاح. الآن سنقوم بإدخال البيانات. النطاقات الافتراضيةسنقوم هنا بإدخال النطاقات الخاصّة بك إلى جدول virtual_domains. يمكنك إضافة جميع النطاقات التي ترغب بها، ولكننا سنقوم في هذا الدليل بإضافة النطاق الرئيسي فقط (example.com) و اسم نطاقك المؤهّل الكامل (FQDN) والذي هو على شاكلة (hostname.example.com). INSERT INTO `servermail`.`virtual_domains` (`id` ,`name`) VALUES ('1', 'example.com'), ('2', 'hostname.example.com');عناوين البريد الإلكتروني الافتراصيةوالآن، سنقوم بإدخال عناوين البريد الإلكتروني وكلمات المرور المرتبطة بها إلى كلّ نطاقٍ على حدا. تأكّد من أنّك غيّرت جميع البيانات والمعلومات الموجودة بالشفرة أدناه لتناسب احتياجاتك قبل تطبيقها: INSERT INTO `servermail`.`virtual_users` (`id`, `domain_id`, `password` , `email`) VALUES ('1', '1', ENCRYPT('firstpassword', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'email1@example.com'), ('2', '1', ENCRYPT('secondpassword', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))), 'email2@example.com');الاختصارات الوهمية:سنُدخِل عنوان البريد الإلكتروني (المصدر) الذي سنقوم بتوجيهه إلى عنوان البريد الإلكتروني الآخر (الوجهة): INSERT INTO `servermail`.`virtual_aliases` (`id`, `domain_id`, `source`, `destination`) VALUES ('1', '1', 'alias@example.com', 'email1@example.com');للخروج من MySQL: mysql > exitالخطوة الثالثة: إعداد Postfixسنقوم بإعداد Postfix ليستلم معالجة اتصالات SMTP وإرسال الرسائل إلى كلّ مستخدمٍ موجود في قاعدة بيانات MySQL. أولًا، يجب علينا إنشاء نسخة من الملفّ الافتراضي، في حال أردنا استرجاع الإعدادات الافتراضي إذا حصلت مشكلةٌ ما: cp /etc/postfix/main.cf /etc/postfix/main.cf.origافتح ملف main.cf لتعديله: nano /etc/postfix/main.cfأولًا سنحتاج إلى القيام بوضع إشارة تعليق (#) على مُعامِلات TLS وإضافة مُعامِلات جديدة من هذا الدرس، سنقوم باستخدام شهادات SSL المجانية والمسارات التي تم اقتراحها في هذا الدليل (رابط)، ولكن يمكنك تعديل الأمور بناءً على احتياجاتك الشخصية: # TLS parameters #smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem #smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key #smtpd_use_tls=yes #smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache #smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache smtpd_tls_cert_file=/etc/ssl/certs/dovecot.pem smtpd_tls_key_file=/etc/ssl/private/dovecot.pem smtpd_use_tls=yes smtpd_tls_auth_only = yesثم سنقوم بإضافة المُعامِلات التالية إلى أسفل إعدادات TLS التي قمنا بتغييرها بالخطوة السابقة: smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destinationنحتاج الآن إلى القيام بوضع إشارة تعليق (#) قبل سطر mydestination واستبداله بـlocalhost. سيسمح هذا التغيير لخادومك الافتراضي الخاصّ باستخدام النطاق الافتراضي الموجود داخل جدول قاعدة MySQL. #mydestination = example.com, hostname.example.com, localhost.example.com, localhost mydestination = localhostتأكّد أنّ مُعامِل myhostname مضبوط على الـFQDN الخاصّ بك: myhostname = hostname.example.comقم بإضافة السطر التالي ليتم إرسال الرسائل إلى جميع النطاقات الافتراضية الموجودة داخل جدول MySQL: virtual_transport = lmtp:unix:private/dovecot-lmtpوأخيرًا، نحتاج إلى إضافة هذه المُعامِلات الثلاثة لنخبر Postfix أن يقوم بإعداد النطاقات الافتراضية، المستخدمين والاختصارات: virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cfملاحظة: قارن هذه التغييرات مع هذا الملف لتتأكد من عدم وجود أخطاء: https://www.dropbox.com/s/x9fpm9v1dr86gkw/etc-postfix-main.cf.txtسنقوم بإنشاء الملفّات الثلاثة الأخيرة التي قمنا بإدراجها في ملف main.cf لنخبر Postfix كيف يتصل بـMySQL. أولًا، نحتاج إلى إنشاء ملف mysql-virtual-mailbox-domains.cf . إنّه ضروري لتغيير قِيَم الإعدادات بناءً على احتياجاتك الخاصّة: nano /etc/postfix/mysql-virtual-mailbox-domains.cf user = usermail password = mailpassword hosts = 127.0.0.1 dbname = servermail query = SELECT 1 FROM virtual_domains WHERE name='%s'ثم نحتاج إلى إعادة تشغيل Postfix: service postfix restartيجب علينا أن نضمن قيام Postfix بإيجاد النطاق الخاصّ بك، لذا نحتاج اختباره باستخدام الأمر التالي، إذا نجح الأمر فسيتم طباعة رقم 1: postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cfوالآن، يجب علينا إنشاء ملف mysql-virtual-mailbox-maps.cf: nano /etc/postfix/mysql-virtual-mailbox-maps.cf user = usermail password = mailpassword hosts = 127.0.0.1 dbname = servermail query = SELECT 1 FROM virtual_users WHERE email='%s'ثم يجب علينا إعادة تشغيل Postfix مجددًا: service postfix restartفي هذه النقطة، سنتأكّد من أنّ Postfix سيجد عنوان البريد الإلكتروني الأول الخاصّ بك باستخدام الأمر التالي، يجب أن يتم إرجاع الرقم 1 في حال نجحت العملية: postmap -q email1@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cfوأخيرًا، سنقوم بإنشاء آخر ملفّ لإعداد الاتصال بين Postfix و MySQL: nano /etc/postfix/mysql-virtual-alias-maps.cf user = usermail password = mailpassword hosts = 127.0.0.1 dbname = servermail query = SELECT destination FROM virtual_aliases WHERE source='%s'قم بإعادة تشغيل Postfix: service postfix restartيجب أن نضمن أيضًا أنّ Postfix سيعثر على الاختصارات الخاصّة بك. قم بإدخال الأمر التالي ويجب أن يتم طباعة البريد الإلكتروني الذي يتم توجيهه إلى الاختصار: postmap -q alias@example.com mysql:/etc/postfix/mysql-virtual-alias-maps.cfإذا أردت تفعيل المنفذ 587 للاتصال بشكلٍ آمن باستخدام برامج البريد الإلكتروني (email clients)، فمن الضروري أن تقوم بتعديل ملفّ /etc/postfix/master.cf: nano /etc/postfix/master.cfنحتاج إلى إلغاء تعليق السطور التالية وإضافة سطور أخرى: submission inet n - - - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,rejectفي بعض الحالات، نحتاج إلى إعادة تشغيل Postfix لكي يتم فتح المنفذ 587: service postfix restartملاحظة: يمكنك استخدام هذه الأداة لفحص منافذ نطاقك والتأكّد من أنّ المنفذين 25 و 587 مفتوحان (http://mxtoolbox.com/SuperTool.aspx) الخطوة الرابعة: إعداد Dovecotسنقوم بنسخ الـ7 ملفّات التي سنقوم بتعديلها هنا، لكي نكون قادرين على استرجاعها في حال ما إذا حصلت مشكلة. أدخل الأوامر التالية الواحد تلو الآخر: cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.orig cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.orig cp /etc/dovecot/dovecot-sql.conf.ext /etc/dovecot/dovecot-sql.conf.ext.orig cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-master.conf.orig cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.origثمّ لتعديل ملفّ الإعدادات من Dovecot: nano /etc/dovecot/dovecot.confوتأكّد أنّ هذا الخيار ليس مُعلّقًا (لا يوجد إشارة # قبله): chown -R vmail:vmail /var/mailثمّ سنحتاج إلى تعديل ملفّ /etc/dovecot/conf.d/10-auth.conf: nano /etc/dovecot/conf.d/10-auth.confقم بإلغاء تعليق سطر استيثاق النصّ الصرف (plain text authentication) وأضف هذا السطر: disable_plaintext_auth = yesقم بتعديل مُعامِل auth_mechanisms: auth_mechanisms = plain loginوقم بتعليق هذا السطر: auth_mechanisms = plain loginالآن، قم بتفعيل استيثاق MySQL عبر إلغاء تعليق هذا السطر: !include auth-sql.conf.extملاحظة: قارن تغييراتك بهذا الملفّ: https://www.dropbox.com/s/4h472nqrj700pqk/etc.dovecot.conf.d.10-auth.conf.txtنحتاج إنشاء ملفّ /etc/dovecot/dovecot-sql.conf.ext والذي سيحتوي على معلومات الاستيثاق الخاصّة بك: nano /etc/dovecot/conf.d/auth-sql.conf.extقم بإدخال الشفرة التالية في الملفّ: passdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext } userdb { driver = static args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n }نحتاج تعديل ملفّ /etc/dovecot/dovecot-sql.conf.ext وإضافة معلومات MySQL الخاصّة بنا: nano /etc/dovecot/dovecot-sql.conf.extقم بإلغاء تعليق مُعامِل driver وقم بتعيين mysql فيه: driver = mysqlقم بإلغاء تعليق مُعامِل connect وأضف البيانات الخاصّة بإعدادات MySQL لديك: connect = host=127.0.0.1 dbname=servermail user=usermail password=mailpasswordقم بإلغاء تعليق سطر defaultpassscheme وغيّره إلى SHA-512: default_pass_scheme = SHA512-CRYPTقم بإلغاء تعليق سطر password_query وأضف هذه المعلومات: password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';ملاحظة: قارن تغييراتك مع هذا الملفّ: https://www.dropbox.com/s/48a5r0mtgdz25cz/etc.dovecot.dovecot-sql.conf.ext.txtالآن، قم بتغيير المالك ومجموعة مجلّد dovecot إلى المستخدم vmail: chown -R vmail:dovecot /etc/dovecot chmod -R o-rwx /etc/dovecotافتح وعدّل ملفّ /etc/dovecot/conf.d/10-master.conf (وكن حذرًا، لأنّه هناك أكثر من مُعامِل يجب تغييره): nano /etc/dovecot/conf.d/10-master.conf ##Uncomment inet_listener_imap and modify to port 0 service imap-login { inet_listener imap { port = 0 } #Create LMTP socket and this configurations service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { mode = 0600 user = postfix group = postfix } #inet_listener lmtp { # Avoid making LMTP visible for the entire internet #address = #port = #} }قم بتعديل مُعامِل unixlistener إلى serviceauth كالتالي: service auth { unix_listener /var/spool/postfix/private/auth { mode = 0666 user = postfix group = postfix } unix_listener auth-userdb { mode = 0600 user = vmail #group = } #unix_listener /var/spool/postfix/private/auth { # mode = 0666 #} user = dovecot }عدّل service auth-worker كالتالي: service auth-worker { # Auth worker process is run as root by default, so that it can access # /etc/shadow. If this isn't necessary, the user should be changed to # $default_internal_user. user = vmail }ملاحظة: قارن تغييراتك بهذا الملفّ: https://www.dropbox.com/s/g0vnt233obh6v2h/etc.dovecot.conf.d.10-master.conf.txtوأخيرًا، سنقوم بتعديل ملفّ إعدادات SSL من Dovecot (تخطّى هذه الخطوة في حال كنتَ تريد استخدام الإعدادات الافتراضية): nano /etc/dovecot/conf.d/10-ssl.confغيّر مُعامَل SSL إلى required: ssl = requiredعدّل المسار لـsslcert و sslkey: ssl_cert = </etc/ssl/certs/dovecot.pem ssl_key = </etc/ssl/private/dovecot.pemوقم بإعادة تشغيل Dovecot: service dovecot restartيجب أن تتأكّد أنّ المنفذ 993 يعمل ومفتوح: telnet example.com 993تهانينا!، لقد قمتَ بنجاح بإعداد خادوم بريدك الأول ويمكنك اختبار الإعدادات التالية باستخدام أحد برامج إدارة البريد الإلكتروني: - Username: email1@example.com - Password: email1's password - IMAP: example.com - SMTP: example.comملاحظة: استخدام المنفذ 993 لـIMAP المؤمّن و 587 أو 25 لـSMTP. الخطوة الخامسة: إعداد SpamAssassinنحتاج أولًا إلى تثبيت SpamAssassin: apt-get install spamassassin spamcثمّ يجب علينا إنشاء مستخدمٍ خاص بـSpamAssassin: adduser spamd --disabled-loginلإعداد SpamAssassin بنجاح، من الضروري أن تفتح وتعدّل ملفّ الإعدادات: nano /etc/default/spamassassinيجب علينا تغيير مُعامِل ENABLED لتفعيل SpamAssasin: ENABLED=1كما ونحتاج إلى تغيير مُعامِلات مجلّد المنزل والخيارات: SPAMD_HOME="/home/spamd/" OPTIONS="--create-prefs --max-children 5 --username spamd --helper-home-dir ${SPAMD_HOME} -s ${SPAMD_HOME}spamd.log"ثمّ نحتاج إلى تعديل مُعامِل PID_FILE بالشكل التالي: PIDFILE="${SPAMD_HOME}spamd.pid"وأخيرًا، نحتاج إلى تحديد أنّ قواعد SpamAssasins يجب أن يتم تحديثها تلقائيًا: CRON=1ملاحظة: قارن تغييراتك بهذا الملفّ: PIDFILE="${SPAMD_HOME}spamd.pid"نحتاج الآن إلى فتح /etc/spamassassin/local.cf لإعداد القواعد التي ستحدّ من هجمات السبام (Spam): nano /etc/spamassassin/local.cfسيقوم SpamAssasin بتسجيل كلّ بريدٍ إلكتروني ويفحص ما إذا كان هذا البريد الإلكتروني يمتلك 5 نقط أو أعلى في اختبار فحص السبام، وإن كان كذلك فسيقوم تلقائيًا باعتباره سبام. يمكنك استخدام المُعامِلات التالية لإعداد القواعد المُضادة للسبام: rewrite_header Subject ***** SPAM _SCORE_ ***** report_safe 0 required_score 5.0 use_bayes 1 use_bayes_rules 1 bayes_auto_learn 1 skip_rbl_checks 0 use_razor2 0 use_dcc 0 use_pyzor 0نحتاج إلى تغيير ملفّ /etc/postfix/master.cf لنخبره أنّه سوف يتم التحقق من كلّ بريدٍ إلكترونيٍ وارد بواسطة SpamAssasin: nano /etc/postfix/master.cfثمّ نحتاج إلى العثور على السطر التالي وإضافة مرشّح spamassasin: smtp inet n - - - - smtpd -o content_filter=spamassassinوأخيرًا نحتاج إلى إضافة المُعامِلات التالية: spamassassin unix - n n - - pipe user=spamd argv=/usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}يجب الآن إعادة تشغيل كلٍّ من Postfix و SpamAssasin لكي تأخذ التغييرات مكانها: service spamassassin start service postfix restart*تهانينا! لقد قمتَ بنجاح بإعداد خادوم بريدٍ إلكتروني باستخدام Postfix و Dovecot مع استيثاق MySQL وحماية ضدّ هجمات السبام باستخدام SpamAssasin ! حظًا موفقًا يا صاح! ترجمة -وبتصرّف- للمقال: How To Configure a Mail Server Using Postfix, Dovecot, MySQL, and SpamAssasin.
  22. هناك العديد من لغات قواعد البيانات SQL التي تعمل على أنظمة اللينكس واليونكس، ومن أشهر لغات قواعد البيانات العلائقية التي تعمل في بيئات الخوادم هما MySQL وMariaDB. ومع ذلك، مثل أغلب البرامج، هذه الأدوات يمكن أن تكون الاحتياجات الأمنية إذا تم تكوينها بشكل غير صحيح، هذا الشرح التعليمي سوف يرشدك لبعض الخطوات الأساسية التي يمكن اتخاذها لتأمين قاعدة البيانات الخاصة بك سواء MariaDB أو MySQL، والتأكد من أنها ليست بابًا مفتوحًا إلى VPS الخاص بك. من أجل البساطة والوضوح، سوف نستخدم MySQL على خادوم Ubuntu كمثال، ومع أن هذه التقنيات يمكن تطبيقها على توزيعات لينكس الأخرى، ويمكن استخدامها مع MariaDB كذلك. الإعداد الأوليMySQL يمنحك فرصة لاتخاذ الخطوة الأولى نحو تحقيق الأمن أثناء التثبيت، وسوف نطلب منكم وضع كلمة سر root (الجذر). $ sudo apt-get install mysql-server Configuring mysql-server-5.5 While not mandatory, it is highly recommended that you set a password for the MySQL administrative "root" user. If this field is left blank, the password will not be changed. New password for the MySQL "root" user:يمكنك دائما تعيين كلمة سر root في وقت لاحق، ولكن ليس هناك سبب لتخطي هذه الخطوة، لذلك يجب تأمين حساب المسؤول الخاص بك من البداية. بمجرد اكتمال التثبيت، يجب علينا تشغيل عدد قليل من النصوص المدرجة. أولاً، سوف نستخدم "mysql_install_db" وهو سكريبت نصي لإنشاء تصميم قواعد البيانات الخاصة بنا. $ sudo mysql_install_dbبعد ذلك، قم بتشغيل السكريبت الذي يسمى "mysql_secure_installation"، وسيرشدنا لبعض الإجراءات التي من شأنها إزالة بعض الافتراضات التي تشكل خطرا على استخدامها في بيئة الإنتاج. $ sudo mysql_secure_installationأولاً سوف يطلب منك إدخال كلمة السر الجذر وستقوم بإدخالها أثناء التثبيت، وبعد ذلك مباشرة ، سوف يطلب منك سلسلة من الأسئلة، بدءا من إذا كنت ترغب في تغيير كلمة سر الجذر. هذه هي فرصة أخرى لتغيير كلمة المرور الخاصة بك إلى أي شيء آمن إذا لم تكن قد فعلت ذلك بالفعل. يجب أن تكون الإجابة "Y" (نعم) لجميع الأسئلة المتبقية. سيؤدي ذلك إلى إزالة قدرة أي شخص لتسجيل الدخول إلى MySQL افتراضيا، وتعطيل تسجيل الدخول عن بعد على حساب المسؤول، وإزالة بعض قواعد بيانات الاختبار غير الآمنة، وتحديث قاعدة البيانات التي تعمل حاليا لاعتماد هذه التغيرات. اعتبارات أمنيةالقاعدة البسيطة لزيادة حماية MySQL (ومعظم الأنظمة الأخرى) هو إعطاء صلاحيات النفاذ فقط عند الضرورة. أحيانا لكي تكون بياناتك آمنة يجب أن توزان بين الراحة والأمان. في هذا الدليل، سوف نميل إلى الجانب الأمني، لذا فإن استخدامك الخاص لقاعدة البيانات يمكن أن يدفعك لإنتقاء أحد هذه الخيارات. زيادة الأمن من خلال ملف My.cnfملف الإعدادت الرئيسية في MySQL هو ملف يسمى "my.cnf" الموجود في "/etc/mysql/" هذا الامتداد على أوبونتو وامتداد "/etc/" على بعض الخواديم الأخرى. سوف نقوم بتغيير بعض الإعدادات في هذا الملف لتأمين MySQL الخاصة بنا. فتح الملف مع صلاحيات الجذر، تغيير مسار الامتداد حسب الحاجة إذا كنت تتبع هذا الشرح التعليمي على نظام مختلف: $ sudo nano /etc/mysql/my.cnfالإعداد الأولي التي يجب علينا أن نتحقق منه "وضع عنوان IP" ضمن قسم "[mysqld]". ويجب تعيين هذا الإعداد على جهاز الشبكة المحلي loopback ، وهو "127.0.0.1". $ bind-address = 127.0.0.1هذا يجعل من أن MySQL لا تقبل الاتصالات من أي مكان باستثناء الجهاز المحلي. إذا كنت بحاجة للوصول إلى قاعدة البيانات من جهاز آخر، خذ بالاعتبار الاتصال عن طريق SSH للقيام بالاستعلام وادارة قاعدة البيانات الخاصة بك محليا وإرسال النتائج من خلال قناة SSH. الفجوة التالية التي سوف نعدلها، هي وظيفة تتيح لك الوصول إلى نظام الملفات من داخل MySQL، يمكن أن يكون لها تداعيات أمنية خطيرة ويجب ايقافها إلا إذا كنت في حاجة شديدة لها. في نفس المقطع من الملف، سوف نقوم بإضافة التوجيه لتعطيل هذه القدرة على تحميل الملفات المحلية: local-infile=0إذا كان لدينا مساحة كافية ولا تعمل على قاعدة بيانات ضخمة، فإنه يمكن أن يكون مفيدا لتسجيل معلومات إضافية لمراقبة أي نشاط مثير للشبهة. تسجيل معلومات أكثر من اللازم يضعف الأداء، لذلك قم بوزن أي شيء تحتاجه بعناية. يمكنك وضع تسجيل الأحداث المتغيرة داخل القسم نفسه "[mysqld]" التي قمنا بالإضافة فيها: log=/var/log/mysql-logfileتأكد من أن سجل MySQL يعمل، سجل الأخطاء، وسجل MySQL ليس سهل القراءة: $ sudo ls -l /var/log/mysql* -rw-r----- 1 mysql adm 0 Jul 23 18:06 /var/log/mysql.err -rw-r----- 1 mysql adm 0 Jul 23 18:06 /var/log/mysql.log /var/log/mysql: total 28 -rw-rw---- 1 mysql adm 20694 Jul 23 19:17 error.logتأمين MySQL من الداخلهناك عدد من الخطوات التي يمكنك اتخاذها أثناء استخدام MySQL لتحسين الوضع الأمني. سوف نقوم بإدخال الأوامر في هذا القسم في بداخل واجهة MySQL ، لذلك نحن بحاجة إلى تسجيل الدخول. $ mysql -u root -pسيطلب منك إدخال كلمة سر الجذر التي قمت بإعدادها في وقت سابق. تأمين كلمات السر والمستخدمين المرتبطينأولاً، تأكد من وجود مستخدمين بدون كلمة مرور أو المضيف المرتبط في MySQL: SELECT User,Host,Password FROM mysql.user; +------------------+-----------+-------------------------------------------+ | user | host | password | +------------------+-----------+-------------------------------------------+ | root | localhost | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | demo-user | % | | | root | 127.0.0.1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | root | ::1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | debian-sys-maint | localhost | *ECE81E38F064E50419F3074004A8352B6A683390 | +------------------+-----------+-------------------------------------------+ 5 rows in set (0.00 sec)كما ترون في مثالنا هذا "المستخدم التجريبي " ليس لديه كلمة مرور، وهو ساري المفعول بغض النظر عن ما هو عليه في المضيف، ويعتبر هذا آمن جدا. يمكننا وضع كلمة سر للمستخدم مع هذا الأمر Change "كلمة المرور الجديدة" أدخل كلمة المرور التي ترغب بها. UPDATE mysql.user SET Password=PASSWORD('newPassWord') WHERE User=""demo-user";إذاً علينا التحقق من جدول المستخدم مرة أخرى، وسوف نرى أن المستخدم التجريبي لديه الآن كلمة سر: SELECT User,Host,Password FROM mysql.user;+------------------+-----------+-------------------------------------------+ | user | host | password | +------------------+-----------+-------------------------------------------+ | root | localhost | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | demo-user | % | *D8DECEC305209EEFEC43008E1D420E1AA06B19E0 | | root | 127.0.0.1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | root | ::1 | *DE06E242B88EFB1FE4B5083587C260BACB2A6158 | | debian-sys-maint | localhost | *ECE81E38F064E50419F3074004A8352B6A683390 | +------------------+-----------+-------------------------------------------+ 5 rows in set (0.00 sec)إذا ما نظرت هذا الحقل"host"، سترى أن لا يزال لدينا "٪"، هي عبارة عن بطاقة بديلة وهذا يعني أي مضيف. وليس هذا ما نريده، دعونا نغيرها إلى " localhost". UPDATE mysql.user SET Host='localhost' WHERE User="demo-user";إذا تحققنا مرة أخرى، يمكننا أن نرى أن جدول المستخدم لديه الآن الحقول المناسبة. SELECT User,Host,Password FROM mysql.user;إذا كان لدينا جدول يحتوي على مستخدمين فارغين (لا يجب في هذه المرحلة أن يكونوا "mysql_secure_installation", سنغطي هذه الناحية بأي حال من الأحوال لاحقا)، وينبغي علينا إزالتهم. للقيام بذلك، يمكننا استخدام الأمور التالي لحذف المستخدمين الفارغين من جدول الوصول: DELETE FROM mysql.user WHERE User="";بعد أن يتم تعديل جدول المستخدم، نحن بحاجة إلى إدخال الأمر التالي لتنفيذ صلاحيات جديدة: FLUSH PRIVILEGES;إنشاء مستخدمين محددين لتطبيقات معينة طريقة تشغيل العمليات داخل لينكس تكون معزولة لكل مستخدم على حدى، وتستخدم قاعدة بيانات MySQL نفس طريقة العزل. كل تطبيق يستخدم MySQL يجب أن يمتلك مستخدم خاص به ولديه صلاحيات محدودة ويستطيع الوصول إلى قواعد البيانات التي يحتاج لتشغيلها فقط. عندما نقوم بإعداد تطبيق جديد لاستخدام MySQL، يجب أن ننشئ قواعد البيانات التي يحتاجها هذا التطبيق: create database testDB; Query OK, 1 row affected (0.00 sec)بعد ذلك، يجب علينا إنشاء مستخدم لإدارة قاعدة البيانات، ومنحه الصلاحيات التي يحتاجها فقط، وهذه تختلف من تطبيق لآخر، وبعض الاستخدامات تحتاج لصلاحيات مفتوحة أكثر من غيرها. لإنشاء مستخدم جديد، استخدم الأمر التالي: CREATE USER 'demo-user'@'localhost' IDENTIFIED BY 'password';يمكننا منح المستخدم الجديد صلاحيات على الجدول الجديد بالأمر التالي. انظر الشرح التعليمي حول كيفية إنشاء مستخدم ومنح صلاحيات جديدة في MySQL لمعرفة المزيد عن الصلاحيات المحددة: GRANT SELECT,UPDATE,DELETE ON testDB.* TO 'demo-user'@'localhost';وكمثال على ذلك، إذا كنا بحاجة إلى وقت لاحق لإلغاء الصلاحيات من الحساب، يمكن أن نستخدم الأمر التالي: REVOKE UPDATE ON testDB.* FROM 'demo-user'@'localhost';إذا كنا بحاجة إلى كافة الصلاحيات على قاعدة بيانات معينة، يمكننا تحديد ذلك بما يلي: GRANT ALL ON testDB.* TO 'demo-user'@'localhost';لإظهار الصلاحيات الحالية للمستخدم، علينا أولا أن ننفذ الصلاحيات حددناه باستخدام أمر "flush privileges"، ثم بعد ذلك يمكننا الاستعلام عن الصلاحيات التي بحوزة المستخدم. FLUSH PRIVILEGES; show grants for 'demo-user'@'localhost'; Grants for demo-user@localhost GRANT USAGE ON *.* TO 'demo-user'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' GRANT SELECT, UPDATE, DELETE ON `testDB`.* TO 'demo-user'@'localhost' 2 rows in set (0.00 sec)دائما امسح الصلاحيات عندما تنتهي من إجراء التغييرات. تغيير المستخدم الجذرخطوة إضافية واحدة وهي، ربما تريد تغيير اسم الجذر(root login name )، فإذا كان الهاكر يحاول أن يقوم بتسجيل الدخول باسم الروت في MySQL ، فسوف يحتاج إلى تنفيذ خطوة إضافية هي العثور على اسم المستخدم. تستطيع تغيير اسم المستخدم روت باستخدام الأمر التالي: rename user 'root'@'localhost' to 'newAdminUser'@'localhost';يمكننا أن نرى التغيير باستخدام نفس الاستعلام الذي استخدمناه لقاعدة بيانات المستخدم: select user,host,password from mysql.user;مرة أخرى، يجب علينا مسح الصلاحيات التغيرات التي حدثت: FLUSH PRIVILEGES;تذكر أنه سوف تسجل دخول إلى MySQL مثل اسم مستخدم تم إنشاؤه حديثا عندما ترغب في أداء المهام الإدارية: mysql -u newAdminUser -pبأي حال من الأحوال هذه قائمة شاملة من الاجراءات الأمنية لقواعد البيانات MySQL, MariaDB، وقد أصبح لديك مقدمة جيدة لأنواع القرارات التي ستتخذها عندما تريد تأمين قواعد البيانات الخاصة بك. يمكن الاطلاع على مزيد من المعلومات حول الإعدادت والأمن في قواعد بيانات المواقع MySQL وMariaDB إضافة الى صفحات المختصين، ويمكن للتطبيقات التي اخترت استخدامها أن تقدم المشورة الأمنية. ترجمة -وبتصرّف- للمقال: How To Secure MySQL and MariaDB Databases in a Linux VPS.
  23. مقدِّمةيحتاج الكثيرُ من المستخدمين إلى نظام إدارة قواعد بيانات Database Managment System, DBMS مثل MySQL، إلّا أنّهم قد لا يكونون مرتاحين للتّفاعل مع النّظام من خلال سطر أوامر MySQL فقط. أُنشئ phpMyAdmin بحيث يتفاعل هؤلاء المستخدمون مع MySQL عن طريق واجهة ويب. سنعرض في هذا الدّرس لكيفيّة تثبيت وتأمين phpMyAdmin بحيث يُمكن استخدامُه بأمان من أجل إدارة قواعد بيانات MySQL على أوبنتو 14.04. المُتطلَّباتنفترض، قبل البدء مع خطوات هذا الدّرس، أنّك تتوفّر على المتطلَّبات التّاليّة: حساب بصلاحيّات sudo، غير حساب المستخدِم الجذر Root user كما هوّ موضَّح في الخطوات 1-4 من درس الإعداد الابتدائي لخادوم أوبنتو.حزم MySQL، Apache، Linux وPHP (المعروفة بLAMP) مُثَبَّتة ومُعدَّة. يُمكن مراجعة درس كيف تُثبِّت حِزم MySQL، Apache، Linux) LAMP وPHP) على Ubuntu 14.04 لهذا الغرض.بإكمال الخطوات أعلاه تكون مستعدا لمتابعة هذا الدّرس. الخطوة الأولى: ثبِّت phpMyAdminنبدأ بتنزيل وتثبيت phpMyAdmin من مستودعات أوبنتو عن طريق مدير الحزم apt: sudo apt-get update sudo apt-get install phpmyadminستُطرَح عليك بعضُ الأسئلة لإعداد التّثبيت بما يُناسِب: عند اختيار خادوم الويب اختَر apache2. ملحوظة: إن لم تضغط زر المسافة SPACE على لوحة المفاتيح لاختيّار Apache فلن ينقُل برنامج التّثبيت الملفّات الضّرورية أثناء التّثبيت. اختر زر SPACE على لوحة المفاتيح ثمّ زر TAB ثمّ زرّ ENTER لاختيّار Apache.اختَر نعم (YES) عند السّؤال إذا ما كنت تُريد استخدام dbconfig-common لضبط قاعدة البيانات.أدخِل كلمة سرّ مدير قاعدة البيانات عندما يُطلَب منك ذلك.سيُطلب منك أيضًا اختيّار وتأكيد كلمة سرّ تطبيق phpMyAdmin نفسِه.تُضيف عمليّة التّثبيت ملفّ إعداد phpMyAdmin إلى المُجلَّد /etc/apache2/conf-enabled/ حيثُ يقرؤه خادوم ويب Apache أوتوماتيكيًّا. كلّ ما علينا فعله يدويًّا هو تفعيل امتداد Extension يحمل الاسم php5-mcrypt (واجهة للتّعامل مع مكتبة mcrypt الّتي تضم خوارزميّات للتّعميّة Encryption) عن طريق تنفيذ الأمر: sudo php5enmod mcryptستحتاج لإعادة تشغيل Apache لكي يتعرَّف على الامتداد الجديد: sudo service apache2 restartيُمكنك بعدها الولوج إلى واجهة الويب عن طريق إدخال عنوان IP العمومي لخادومك أو اسم النّطاق في شريط العناوين بمتصفّح الويب متبوعًا ب phpmyadmin/ كما يلي: http://domain_name_or_IP/phpmyadminملحوظة: إن كنت تجرِّب التّثبيت على جهازك المحلّي فيُمكنك الوصول إلى واجهة phpmyadmin عن طريق إدخال العنوان التّالي في شريط العناوين بمتصفّح الويب http://127.0.0.1/phpmyadmin يُمكنك الآن الولوج إلى واجهة الويب عن طريق حساب المستخدم الجذر الّذي أعددته أثناء تثبيت MySQL. ستظهر عند تسجيل الدّخول واجهة المستخدِم والّتي تُشبه ما يلي: الخطوة الثّانيّة: تأمين phpMyAdminأكملنا الآن تثبيت phpMyAdmin وسجلنا الدّخول إلى واجهة المستخدِم، لكن بقي أمر آخر. يستهدِف الكثيرُ من المخترقين phpMyAdmin نظرًا لشهرته، في محاولةٍ منهم لنيل طريقة للاتّصال بقاعدة البيانات. نحتاج لتأمين التّطبيق للمساعدة في الحماية من الاستخدام غير المُصرَّح به. إحدى أسهل الطّرق لتأمين phpMyAdmin هيّ وضعُ بوّابة gateway أمام كامل التّطبيق. نستخدم الاستيثاق Authentication والتّصريح Authorization عن طريق ملفّات htaccess. المُضمَّنة في Apache. 1- إعداد Apache للسّماح بالتّجاوز Override في ملفّات htaccess.يجب علينا أوّلًا تفعيل استخدام التّجاوز في ملفّات htaccess. وذلك بالتّعديل على ملفّ إعداد خاصّ بـ phpMyAdmin في خادوم ويب Apache. يعني تفعيل التّجاوز أنه يُمكن تعريف ملفّ htaccess. لمجلَّد مُحدَّد بحيثُ تُنفَّذ تعليمات ملفّ htaccess. الموجود في المجلَّد بدلًا من ملفّ htaccess. العامّ لخادوم الويب. نُعدِّل على ملف إعداد phpMyAdmin الموجود في مجلّد Apache للإعدادات: sudo nano /etc/apache2/conf-available/phpmyadmin.confنُضيف تعليمة AllowOverride All داخل مقطع 2- أنشئ ملفّ htaccess.نبدأ الآن بعد أن فعَّلنا استخدامَ ملفّ htaccess. خاصّ بتطبيقنا، نبدأ بإنشاء هذا الملفّ من أجل إضافة إجراءات أمان إلى phpMyAdmin. يجب أن يُنشَأ ملفّ htaccess. داخل مجلَّد التّطبيق. الأمر التّالي يُنشئ ثمّ يفتح الملفّ (يتطلّب صلاحيّات المستخدم الجذر): sudo nano /usr/share/phpmyadmin/.htaccessنُضيف التّعليمات التّالية داخل هذا الملفّ: AuthType Basic AuthName "Restricted Files AuthUserFile /etc/phpmyadmin/.htpasswd Require valid-userفلنلقِ نظرة على دلالة كل واحدة من هذه التّعليمات: AuthType Basic: تُحدِّد AuthType نوع الاستيثاق الّذي سنطلُب وضعه. Basic تعني أنّنا سنستخدم الاستيثاق بكلمة سرّ عن طريق ملفّ يُسمّى ملفّ كلمة السّر.AuthName: هذه التّعليمة تُحدِّد الرّسالة الّتي تظهر في مربّع طلب كلمة السّر عند محاولة الوصول إلى التّطبيق. يجب أن تكون هذه الرّسالة عامّة بحيثُ لا تُعطي أيّ معلومات عن ما تحميه كلمة السّر.AuthUserFile: تُحدّد مكان حفظ ملفّ كلمة السّر المُستخدَمة للاستيثاق. يجب أن يُحفّظ الملفّ خارج المجلّدات الّتي يُقدّم منها خادوم الويب ملفّاتٍ للزوّار. سنُنشئ هذا الملفّ بعد قليل.Require valid-user: تُحدّد نوعيةَ المستخدمين المسموح لهم بالوصول إلى المجلَّد المحمي. هذه التّعلمية أساسيّة من أجل منع وصول المستخدمين غير المُصرَّح لهم بالدّخول إلى التّطبيق.احفَظ الملفّ (Ctrl + O) بعد التّعديل ثم أغلقه (Ctrl+ X). 3- أنشئ ملفّ htpasswd. للاستيثاقعيّنّا أثناء إنشاء ملفّ htaccess. في الفقرة السّابقة طريقة استيثاق تعتمد على ملفّ كلمة سرّ، عبرَ تعليمة AuthUserFile. نُنشئ الآن هذا الملفّ. سنحتاج إلى حزمة إضافيّة تعمل مع خادوم الويب لهذا الغرض، نُثبِّتها عبر الأمر: sudo apt-get install apache2-utilsسنحصُل بعد اكتمال التّثبيت على أداة كلمات السّر في Apache. الأمر التّالي يُنشئ ملفّ كلمة السّر في المسار الّذي عيّنّاه في ملفّ htaccess. ويُحدّد اسمَ مُستخدِم مرفقًا بهذا الملفّ: sudo htpasswd -c /etc/phpmyadmin/.htpasswd usernameسيُطلَب منك إعطاء ثمّ تأكيد كلمة سرّ المستخدِم الّذي تُنشئه (username في الأمر أعلاه).سيُنشأ بعدها ملفّ يحوي اسم المُستخدم وتلبيد Hash كلمة السّرّ (تُحفَظ كلمة السّرّ بعد تعميّتها Encryption). تُمكن إضافة مُستخدم جديد عن طريق الأمر أعلاه ولكن بدون خيار c- كما يلي: sudo htpasswd /etc/phpmyadmin/.htpasswd additionaluserعند محاولة الولوج الآن إلى phpMyAdmin فسيُطلَب منك إدخال اسم الحساب الجديد وكلمة السّر المُصاحبة له الّذيْن ضبطتهما للتّو. http://domain_name_or_IP/phpmyadmin بعدَ تخطي استيثاق Apache ستُنقَل إلى واجهة phpMyAdmin حيثُ يجب عليك إدخال اعتمادات واجهة الويب الخاصّة بـ phpMyAdmin. يُضيف هذا الإجراء طبقةً جديدة من الحماية تُساعِد في التّغلّب على أيّ نقاط ضعف قد تكون موجودة في phpMyAdmin. خاتمةيجب بعد إكمال هذه الخطوات أن تحصُل على تطبيق phpMyAdmin مضبوط وجاهز للعمل على خادوم أوبنتو 14.04. يُمكن مع phpMyAdmin إنشاء قواعد بيانات، مستخدمين، جداول… إلخ إضافةً إلى الإجراءات الاعتيّاديّة مثل حذف أو تعديل البُنيَات Structures والبيانات بكل سهولة. ترجمة - وبتصرّف - لمقال How To Install and Secure phpMyAdmin on Ubuntu 14.04.