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

kinan mawed

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

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

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

كل منشورات العضو kinan mawed

  1. يشرح هذا الدّرس كيفيّة نشر Nginx في حاوية Docker container. نقلّل باحتواء Nginx من نفقات إدارة النظام، فلن نعود في حاجة إلى إدارة Nginx عبر مُدير الحِزَم أو بنائِه من المصدر، تسمح لنا حاوية Docker ببساطة أن نستبدل كامل الحاوية عند إطلاق إصدار جديد من Nginx، نحتاج فقط إلى الحفاظ على ملفّات إعدادات Nginx ومحتوانا. يصف Nginx نفسه كما يلي: يُستَخدَم Nginx من قبل العديد من مديري النُظُم sysadmins في الممارسة العمليّة لتخديم محتوى الويب، ابتداءً من مواقع الملفّات الثابتة flat-file وحتى upstream APIs في NodeJS، سنقوم في هذا الدّرس بتخديم صفحة ويب أساسيّة حتى نستطيع التركيز على إعداد Nginx مع حاوية Docker. إنّ حاويات Docker هي شكل شائع من ممارسات عمليّة قديمة نسبيًّا وهي الاحتواء containerization. يختلف الاحتواء عن الآلات الافتراضية (virtualization) في أنّ الإيهام يقوم بعزل العتاد hardware بعيدًا، بينما يقوم الاحتواء بعزل نظام التشغيل الأساسي بعيدًا أيضًا، يعني هذا من النّاحية العمليّة أنّه يمكننا أخذ تطبيق (أو مجموعة تطبيقات) ووضعها في حاوية (أو حاويات) لجعلها من النمط التركيبي modular، محمولة portable، قابلة للتركيب composable، وخفيفة الوزن lightweight. تعني قابليّة النقل portability أنّنا نستطيع تثبيت مُحرِّك Docker Engine (تتم الإشارة له أيضًا بلُب Docker Core، أو حتى Docker فقط) على مجموعة واسعة من أنظمة التّشغيل، وأي حاوية وظيفيّة مكتوبة من قبل أي شخص ستعمل عليه. إن أردت تعلّم المزيد حول Docker بإمكانك الاطلاع على درس Docker التّمهيدي. سنقوم بتثبيت مُحرِّك Docker على Ubuntu لأغراض هذا الدّرس. سنثبّت إصدار Docker المستقر الحالي لـ Ubuntu وهو 1.8.1. هذا الدّرس مُخصَّص لمستخدمي Nginx الجديدين على Docker، إن كنت تريد الأوامر المجرّدة لإعداد حاوية Nginx لديك تستطيع تطبيق الخطوة الأولى ومن ثمّ الانتقال إلى الخطوة الخامسة. إن كنت ترغب ببناء حاويتك خطوة بخطوة والتعلّم عن تعيين المنافذ port mapping والوضع المنفصل detached mode فقم باتّباع كامل الدّرس. المتطلبات الأساسيةمن أجل احتواء Nginx يجب علينا إتمام ما يلي: إعداد خادوم Ubuntu ويُفضَّل أن يكون مع مفاتيح SSH Keys من أجل الأمان.إعداد مستخدم بصلاحيات الجذر sudo.التحقّق من إصدار النّواة Kernel لدينا.يعتمد Docker 1.8.1 إلى حدٍّ ما على بعض الميّزات الأخيرة للنواة، لذا تأكّد من أن يكون إصدار النّواة 3.10 أو أعلى، تمتلك أنظمة تشغيل لينِكس الحديثة نواة جديدة نسبيًّا، ولكن إن كنت تريد التحقّق قم بتنفيذ الأمر uname –r: uname -rلقد قمنا بتضمين الخَرْج output من نسخة Ubuntu 14.04، والتي تحتوي إصدار نواة أعلى من 3.10، لذا لا يجب أن تقلق ما لم تقم بتنفيذ هذا الأمر على نسخة أقدم: 3.13.0-57-genericالخطوة الأولى – تثبيت Dockerيستضيف Docker على موقعه script بدء للحصول على Docker وتشغيله على جهازنا، نستطيع ببساطة تنفيذ الأمر: sudo curl -sSL https://get.docker.com/ | shلا ينبغي بشكل عام تمرير scripts عشوائيّة من الإنترنت إلى الصّدفة Shell عن طريق الأنبوب (Pipe (| sh، لأنّها قد تقوم بفعل أي شيء، ألقِ نظرة على get.docker.com إن كنت تريد معرفة ما أنت مُقبِلٌ عليه. بعد أن ينتهي تنفيذ الأمر السّابق سنرى الإصدار المُثبَّت كما يلي (قد تكون الأرقام لديك أحدث ولا مشكلة في هذا) وبعض التعليمات حول التشغيل كمستخدم غير جذري non-root\بدون sudo، نقوم في هذا الدّرس بالتشغيل كمستخدم sudo لذا لا داعي للقلق حول هذا الأمر: Client: Version: 1.8.3 API version: 1.20 Go version: go1.4.2 Git commit: f4bf5c7 Built: Mon Oct 12 05:37:18 UTC 2015 OS/Arch: linux/amd64 Server: Version: 1.8.3 API version: 1.20 Go version: go1.4.2 Git commit: f4bf5c7 Built: Mon Oct 12 05:37:18 UTC 2015 OS/Arch: linux/amd64اختياري: قم بتشغيل الحاوية hello-world للتحقّق من أنّ كل شيء يعمل كما هو متوقَّع: sudo docker run hello-worldيجب أن ترى خَرْجًا مشابهًا للتالي: $ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 535020c3e8ad: Pull complete af340544ed62: Already exists library/hello-world:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security. Digest: sha256:d5fbd996e6562438f7ea5389d7da867fe58e04d581810e230df4cc073271ea52 Status: Downloaded newer image for hello-world:latest Hello from Docker. This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker Hub account: https://hub.docker.com For more examples and ideas, visit: https://docs.docker.com/userguide/نستطيع بعد الانتهاء ممّا سبق الخوض في أساسيّات Docker. الخطوة الثانية (اختيارية) – مراجعة أساسيات الحاوية: التشغيل Run، السرد List، الإزالة Removeيشرح هذا القسم كيفيّة تشغيل حاوية أساسيّة ومن ثمّ إزالتها، إن كنت تعرف مُسبقًا كيفيّة استخدام Docker بشكل عام وتريد التخطّي إلى القسم المتعلّق بـ Nginx فاذهب إلى الخطوة الخامسة. لقد ثبّتنا عميل Docker Client كجزء من تثبيت Docker لدينا، لذا نمتلك أداة سطر الأوامر التي تسمح لنا بالتفاعل مع حاوياتنا. إن قمنا بتنفيذ الأمر التالي: sudo docker ps -aينبغي أن نحصل على خَرْج مُشابِه لما يلي: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a3b149c3ddea hello-world "/hello" 3 minutes ago Exited (0) 3 minutes ago nostalgic_hopperنستطيع مشاهدة بعض المعلومات الأساسيّة حول حاويتنا. سنلاحظ أنّها تملك اسمًا لا معنى له مثل nostalgic_hopper، يتم توليد هذه الأسماء تلقائيًّا إن لم نُحدِّد اسمًا عند إنشاء الحاوية. نرى أيضًا في هذا المثال أنّه تم تشغيل الحاوية منذ 3 دقائق وتم إنشاؤها منذ 3 دقائق. إن قمنا بتشغيل الحاوية مرّة أخرى باستخدام هذا الأمر (مع وضع اسم حاويتنا بدلًا من nostalgic_hopper): sudo docker start nostalgic_hopperومن ثمّ نفّذنا الأمر التالي لعرض الحاويات: sudo docker ps -aيجب أن نشاهد أنّه تم تشغيل الحاوية مؤخّرًا: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a3b149c3ddea hello-world "/hello" 4 minutes ago Exited (0) 9 seconds ago nostalgic_hopperتقوم حاويات Docker افتراضيًّا بتنفيذ الأوامر المسندة إليها ومن ثمّ الخروج. تكون بعض الحاويات مُعدّة لتنفيذ بعض المهام ومن ثمّ الانتهاء من ذلك، بينما يبقى بعضها يعمل بدون وقت مُحدّد. الآن وقد مررنا على بعض أساسيّات Docker فلنقم بإزالة الصّورة image التي تُدعى hello-world، حيث أنّنا لن نحتاجها مرّة أخرى (تذكّر أن تضع اسم حاويتك بدلًا من nostalgic_hopper أو استخدم مُعرِّف ID الحاوية). سنبدأ بعد ذلك باستخدام Nginx. الخطوة الثالثة (اختيارية) – تعلم كيفية عرض expose المنفذ portسنقوم في هذا القسم بتنزيل صورة Nginx Docker image ونرى كيفيّة تشغيل الحاوية بحيث تكون مُتاحة للعوام كخادوم ويب. تكون الحاويات افتراضيًّا غير مُتاحة للوصول من قبل الإنترنت، لذا نحتاج إلى تعيين منفذ الحاوية الدّاخلي إلى منفذ Droplet لدينا، هذا ما سنتعلّمه في هذا القسم. سنحصل في البداية على صورة Nginx. تحتوي الخطوة الخامسة على الأوامر النهائيّة لنشر الحاوية كاملة، لذا إن لم تكن مهتمًّا بتفاصيل التنفيذ تستطيع التخطّي والانتقال إلى هناك. نقوم بتنفيذ الأمر التالي للحصول على صورة Nginx Docker: sudo docker pull nginxيقوم هذا بتنزيل جميع العناصر الضّروريّة للحاوية، يُخبِّئ Docker كل هذا في ذاكرة مؤقتة cache حتى لا نحتاج إلى تنزيل صورة الحاوية في كل مرّة نريد فيها تشغيل الحاوية. تحتفظ Docker بموقع يُدعى Dockerhub وهو مستودع عام لملفّات Docker (يتضمّن كل من الصّور الرسميّة والمُقدَّمة من قبل المستخدمين)، الصّورة التي قمنا بتنزيلها هي صورة Nginx الرسميّة، والتي توفّر علينا عناء بناء الصّورة الخاصّة بنا. فلنقم بتشغيل حاوية Nginx Docker باستخدام هذا الأمر: sudo docker run --name docker-nginx -p 80:80 nginxrun هو أمر إنشاء حاوية جديدة يُحدِّد العَلَم name-- اسم الحاوية (إن تركناه فارغًا سيتم تعيينه تلقائيًّا لنا، مثل nostalgic_hopper في الخطوة الثّانية)يُحدِّد p- المنفذ الذي نقوم بعرضه على هيئة p local-machine-port:internal-container-port-، في هذه الحالة نقوم بتعيين المنفذ 80 في الحاوية إلى المنفذ 80 على الخادومnginx هو عبارة عن اسم الصورة على dockerhub (قمنا بتنزيلها من قبل باستخدام الأمر pull، ولكن يقوم Docker بهذا تلقائيًّا إن كانت الصورة مفقودة)هذا هو كل ما نحتاجه للحصول على Nginx وتشغيله، نقوم الآن بكتابة عنوان IP لـ Droplet لدينا في متصفّح الويب وهنا يجب أن نرى صفحة "Welcome to nginx". سنلاحظ أيضًا في جلسة الصّدفة shell لدينا أنّه يتم تحديث سِجِل Nginx عندما نقوم بطلبات إلى خادومنا، لأنّنا نشغّل الحاويات لدينا بشكل تفاعلي. فلنضغط على الاختصار CTRL+C للعودة إلى جلسة الصّدفة shell لدينا. إن حاولنا الآن تحميل الصفحة سنتلقّى الصّفحة "تم رفض الاتصال" "connection refused"، وقد حدث هذا لأنّنا قمنا بإيقاف تشغيل حاويتنا، بإمكاننا التحقّق من ذلك باستخدام هذا الأمر: sudo docker ps -aيجب أن نرى شيئًا مشابهًا للخَرْج التّالي: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 05012ab02ca1 nginx "nginx -g 'daemon off" 57 seconds ago Exited (0) 47 seconds ago docker-nginxنستطيع أن نرى أنّه تمّ الخروج من حاوية Docker لدينا. لن يكون Nginx مفيدًا جدًّا إن كان يجب علينا أن نكون متصلين attached إلى صورة الحاوية من أجل أن يعمل، لذا سنشرح في الخطوة التالية كيفية فصل detach الحاوية للسماح لها بالعمل بشكل مستقل. نقوم بإزالة الحاوية docker-nginx الحالية عن طريق هذا الأمر: sudo docker rm docker-nginxسنشرح في الخطوة التالية كيفيّة تشغيلها في الوضع المنفصل detached mode. الخطوة الرابعة (اختيارية) – تعلم كيفية التشغيل في الوضع المنفصلنُنشِئ حاوية Nginx جديدة منفصلة باستخدام هذا الأمر: sudo docker run --name docker-nginx -p 80:80 -d nginxأضفنا العَلَم d- لتشغيل هذه الحاوية في الخلفيّة. يجب أن يكون الخَرْج ببساطة مُعرِّف ID الحاوية الجديدة. إن قُمنا بتشغيل أمر السّرد list: sudo docker psسنرى في الخَرْج العديد من الأشياء التي لم نشاهدها من قبل: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b91f3ce26553 nginx "nginx -g 'daemon off" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, 443/tcp docker-nginxبإمكاننا أن نرى أنّه بدلًا من Exited (0) X minutes ago نمتلك الآن Up About a minute، ونرى أيضًا تعيين المنفذ port mapping. إن ذهبنا إلى عنوان IP خادومنا باستخدام المتصفّح فسنشاهد الصفحة "!Welcome to nginx" مرّة أخرى، ولكن في هذه المرّة تعمل الحاوية في الخلفيّة لأنّنا حدّدنا العَلَم d- والذي يُخبِر Docker أن يُشغِّل هذه الحاوية في الوضع المنفصل. نمتلك الآن نسخة من Nginx تعمل في الوضع المنفصل. وبالرغم من ذلك فهي ليست مفيدة بما فيه الكفاية حتى الآن، لأنّنا لا نستطيع تحرير edit ملف الإعدادات ولا تمتلك الحاوية نفاذًا إلى أي من ملفّات مواقع الويب لدينا. نوقف الحاوية بتنفيذ الأمر التّالي: sudo docker stop docker-nginxوالآن وقد توقفت الحاوية عن العمل (نستطيع التحقّق باستخدام الأمر sudo docker ps –a إن أردنا أن نكون متأكدين من ذلك) فبإمكاننا إزالتها بتنفيذ الأمر التّالي: sudo docker rm docker-nginxسنصل الآن إلى الإصدار النّهائي لحاويتنا مع وقفة سريعة لإنشاء ملف مُخصَّص لموقع الإنترنت. الخطوة الخامسة – بناء صفحة ويب ليتم تخديمها على Nginxسنُنشِئ في هذه الخطوة صفحة فهرس index مُخصَّصة لموقعنا، يسمح لنا هذا الإعداد بأن نملك محتوى للموقع بشكل دائم تتم استضافته خارج الحاوية (العابرة transient). فلنقم بإنشاء دليل جديد من أجل محتوى موقعنا بداخل الدّليل الرئيسي home directory والانتقال إليه بتنفيذ الأوامر التالية: mkdir -p ~/docker-nginx/html cd ~/docker-nginx/htmlنُنشِئ الآن ملف HTML (طبّقنا الأوامر من أجل مُحرِّر النّصوص Vim ولكن تستطيع استخدام أي مُحرِّر نصوص آخر). vim index.htmlننتقل إلى وضع الإدخال insert mode عن طريق الضغط على i، ونلصق المحتوى التّالي بداخل الملف السّابق (أو بإمكانك إضافة محتوى HTML الخاص بك): <html> <head> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" integrity="sha256-MfvZlkHCEqatNoGiOXveE8FIwMzZg4W85qfrfIFBfYc= sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous"> <title>Docker nginx Tutorial</title> </head> <body> <div class="container"> <h1>Hello Digital Ocean</h1> <p>This nginx page is brought to you by Docker and Digital Ocean</p> </div> </body> </html>إن كنت على معرفة بـ HTML سترى أنّها صفحة ويب بسيطة، قمنا بتضمين وسم <link> يُشير إلى شبكة توزيع محتوى CDN من أجل Bootstrap (وهو إطار عمل CSS يُعطي لصفحتنا مجموعة من التنسيقات المتجاوبة responsive)، تستطيع قراءة المزيد عن Bootstrap. نحفظ هذا الملف الآن عن طريق الضغط على ESC ومن ثمّ wq: و ENTER: تُخبِر (write (w أن يقوم Vim بكتابة التغييرات إلى الملف.تُخبِر (quit (q أن يقوم Vim بالخروج.نمتلك الآن صفحة فهرس index بسيطة بدلًا من صفحة هبوط Nginx الافتراضيّة. الخطوة السادسة – ربط الحاوية إلى نظام الملفات المحليفي هذا القسم سنضع كل ما سبق معًا، سنقوم بتشغيل حاوية Nginx لدينا بحيث تكون قابلة للنفاذ على الإنترنت عبر المنفذ 80، وسنقوم بتوصيلها إلى محتوى موقع الويب لدينا على الخادوم. معلومات أساسية حول مسارات التخزين (volumes) والتي هي الرّبط إلى محتوى خادوم بشكل دائم من قبل الحاوية الخاصة بنايسمح لنا Docker بربط الأدلّة directories من نظام الملفّات المحلّي للجهاز الافتراضي Virtual Machine لدينا إلى حاوياتنا. وفي حالتنا بما أنّنا نريد تخديم صفحات ويب نحتاج إلى إعطاء حاويتنا الملفّات التي نريد تقديمها. كان باستطاعتنا نسخ الملفّات إلى الحاوية كجزء من ملفّات Docker، أو نسخها إلى الحاوية بعد إسقاطها أو توقيفها، ولكن هاتين الطريقتين تبقيان موقعنا في حالة ثابتة بداخل حاويتنا، أمّا باستخدام ميزة حجوم volumes البيانات بإمكاننا إنشاء ارتباط رمزي بين نظام ملفّات Droplet ونظام ملفّات الحاوية، يسمح لنا هذا بتحرير ملفّات صفحات الويب الموجودة حاليًّا وإضافة ملفّات جديدة إلى الدّليل وستكون الحاوية قادرة على النفاذ لها بشكل تلقائي، إن كنت ترغب بقراءة المزيد حول Docker ومسارات التخزين volumes تحقّق من وثائق حجوم البيانات data volumes. تكون حاوية Nginx مُعدَّة افتراضيًّا لتبحث عن صفحة فهرس index في المسار usr/share/nginx/html/، لذا نحتاج في حاوية Docker الجديدة الخاصّة بنا أن نقوم بإعطائها نفاذًا إلى ملفّاتنا في ذلك الموقع. إنشاء الربطلإنشاء الربط نستخدم العَلَم v- لتعيين مُجلَّد من جهازنا المحلّي (docker-nginx/html/~) إلى مسار نسبي في الحاوية (usr/share/nginx/html/). نستطيع إتمام هذا بتنفيذ الأمر التالي: sudo docker run --name docker-nginx -p 80:80 -d -v ~/docker-nginx/html:/usr/share/nginx/html nginxنرى أنّ الإضافة الجديدة إلى الأمر v ~/docker-nginx/html:/usr/share/nginx/html- هي رابط مسار تخزين volume لدينا. تُحدِّد v- أنّنا نقوم بربط مسار تخزين volume.الجزء الذي على يسار ":" هو موقع ملفّنا/دليلنا على الجهاز الافتراضي (docker-nginx/html/~).الجزء الذي على يمين ":" هو الموقع الذي نقوم بالرّبط إليه في حاويتنا (usr/share/nginx/html/).إن قمنا بعد تنفيذ هذا الأمر بالتوجّه باستخدام المتصفّح إلى عنوان IP الخاص بـ DigitalOcean Droplet مثلا (إن كنت على DigitalOcean) لدينا فيجب أن نرى الترويسة الأولى من Hello Digital Ocean (أو أي صفحة ويب أنشأتها في الخطوة الخامسة). إن كنت سعيدًا بإعدادات Nginx الافتراضيّة الأخرى فأنت الآن جاهز. تستطيع رفع المزيد من المحتوى إلى الدّليل docker-nginx/html/~ وستتم إضافته إلى موقعك بشكل مباشر. إن قمنا على سبيل المثال بتعديل ملف الفهرس لدينا وأعدنا تحميل نافذة متصفحنا، سنرى أنّ التحديث يحدث آنيًّا، نستطيع بناء موقع كامل من ملفّات HTML ثابتة بهذه الطريقة، على سبيل المثال إن أضفنا صفحة about.html فبإمكاننا النفاذ إليها على الرّابط http://your_server_ip/about.html بدون الحاجة للتعامل مع حاويتنا. الخطوة السابعة (اختيارية) – استخدام ملف إعدادات Nginx الخاص بناهذ القسم مُخصَّص للمستخدمين المتقدّمين الذين يرغبون باستخدام ملف إعدادات Nginx الخاص بهم مع حاوية Nginx لديهم، قم بتجاوز هذه الخطوة إن كنت لا تملك ملف إعدادات مُخصَّص تريد استخدامه. فلنقم بالعودة دليلًا إلى الوراء كيلا نكتب إلى دليل HTML المتاح للعوام لدينا: cd ~/docker-nginxإن كنّا نرغب بإلقاء نظرة على ملف الإعدادات الافتراضي نقوم فقط بنسخه باستخدام أمر Docker للنسخ: sudo docker cp docker-nginx:/etc/nginx/conf.d/default.conf default.confوبما أنّنا سنقوم باستخدام ملف conf. مُخصَّص من أجل Nginx سنحتاج إلى إعادة بناء الحاوية. نقوم في البداية بإيقاف الحاوية: sudo docker stop docker-nginxنزيل الحاوية باستخدام الأمر: sudo docker rm docker-nginxنستطيع الآن تحرير الملف الافتراضي محليًّا (لتخديم دليل جديد أو استخدام proxy_pass لتمرير حركة مرور البيانات traffic إلى تطبيق أو حاوية أخرى كما كنّا نفعل مع تثبيت Nginx الاعتيادي)، تستطيع القراءة حول ملف إعدادات Nginx في دليل ملف إعدادات Nginx. بعد أن نقوم بحفظ ملف إعداداتنا المُخصَّص يحين الوقت لصنع حاوية Nginx، نضيف ببساطة علم v- آخر مع المسار المناسب لإعطاء حاوية Nginx الجديدة الروابط المناسبة لتعمل من خلال ملف إعداداتنا: sudo docker run --name docker-nginx -p 80:80 -v ~/docker-nginx/html:/usr/share/nginx/html -v ~/docker-nginx/default.conf:/etc/nginx/conf.d/default.conf -d nginxلا يزال هذا الأمر يربط صفحات الموقع المُخصَّصة إلى الحاوية أيضًا. نلاحظ أنّنا سنحتاج إلى إعادة تشغيل الحاوية باستخدام الأمر docker restart بعد أي تغيير لملف الإعدادات أثناء تشغيل الحاوية، لأنّ Nginx لا يقوم بإعادة تحميل فوري إن تمّ تغيير ملف إعداداته: sudo docker restart docker-nginxالخاتمة نمتلك الآن حاوية Nginx قيد التشغيل وتُخدِّم صفحة ويب مُخصَّصة. نوصي من هذه النقطة القراءة حول ربط حاوية Docker إن كنت تريد التعلّم حول ربط الحاويات ببعضها لأغراض استخدام Nginx كوسيط عكسي reverse proxy لتخديم تطبيقات الويب الأخرى المعتمدة على الحاوية. إن كنت تريد إدارة مجموعة من الحاويات مثل حاوية تطبيق، حاوية قاعدة بيانات، وحاوية Nginx، فألقِ نظرة على تركيب Docker Compose. ترجمة -وبتصرّف- لـ How To Run Nginx in a Docker Container on Ubuntu 14.04 لصاحبه Thomas Taege.
  2. إنّ CloudFlare هي عبارة عن شركة تزوّدنا بشبكة تسليم محتوى (content delivery network (CDN وخدمات DNS مُوزَّعة من خلال العمل كوسيط عكسي reverse proxy لمواقع الإنترنت، من الممكن استخدام خدمات CloudFlare المجانيّة والمدفوعة لتحسين الأمان، السرعة، والتوفّر availability للموقع بطرق عديدة، سنشرح في هذا الدّرس كيفيّة استخدام خدمة tier المجانيّة لـ CloudFlare لحماية خادوم الويب ضدّ هجمات DDoS الجارية المعتمدة على HTTP عن طريق تمكين الوضع "أنا تحت الهجوم" "I'm Under Attack Mode"، يُخفِّف وضع الأمان هذا من هجمات DDoS من خلال تقديم صفحة وسيطة للتحقق من شرعيّة الاتصال قبل تمريره إلى خادوم الويب لدينا. المتطلبات الأساسيةيفترض هذا الدّرس أنّك تمتلك ما يلي: خادوم ويب.نطاق Domain مُسجَّل يُشير إلى خادوم الويب لدينا.نفاذ إلى لوحة التحكّم لمسجّل النطاق الذي أصدر النطاق.يجب قبل المتابعة أيضًا التسجيل Sign up من أجل حساب CloudFlare، فلنلاحظ أنّ هذا الدرس يتطلّب استخدام أسماء خواديم CloudFlare. إعداد النطاق لاستخدام CloudFlareيجب قبل أن نستخدم أي من ميّزات CloudFlare أن نقوم بإعداد النّطاق لدينا ليستخدم DNS التّابع لـ CloudFlare. إن لم نفعل هذا مُسبقًا نقوم بتسجيل الدخول إلى CloudFlare. إضافة موقع ومسح Scan تسجيلات DNS Recordsبعد تسجيل الدخول سيتم أخذنا إلى صفحة البدء Get Started with CloudFlare، وهنا يجب إضافة موقعنا إلى CloudFlare: نُدخِل اسم النّطاق الذي نريد استخدام CloudFlare معه ونضغط على زر بدء المسح Begin Scan، ينبغي أن يتم نقلنا إلى صفحة تشبه ما يلي: سيستغرق هذا حوالي دقيقة، وعندما يكتمل نضغط زر المتابعة Continue. تُظهِر الصفحة التالية نتائج مسح تسجيلات DNS، نتحقّق من أنّ تسجيلات DNS الحاليّة موجودة لأنّها التسجيلات التي ستستخدمها CloudFlare لتحليل resolve الطلبات إلى نطاقنا، استخدمنا في مثالنا cockroach.nyc كنطاق: نلاحظ أنّه من أجل تسجيلات A وCNAME التي تشير إلى خادوم الويب لدينا، يجب أن يملك عمود الحالة Status غيمة برتقاليّة مع سهم يمر من خلالها، والذي يشير إلى أنّ حركة مرور البيانات traffic ستتدفق من خلال وسيط CloudFlare العكسي قبل أن تصل إلى خادومنا أو خواديمنا. نختار بعدها خطّة CloudFlare plan، سنستخدم في هذا الدّرس خيار الخطّة المجانية Free plan، إن كنت ترغب بالدفع لأجل خطة أخرى توفّر لك ميزات CloudFlare إضافيّة تستطيع فعل ذلك: تغيير أسماء الخواديم Nameservers لديناتعرض الصفحة التالية جدولًا لأسماء الخواديم الحالية لنطاقنا والأسماء التي ينبغي تغييرها لها، يجب تغيير اثنين منهما إلى أسماء خواديم CloudFlare، أمّا بقية المُدخلات يجب إزالتها، وهذا مثال عمّا يجب أن تكون عليه الصفحة لديك إن كنت تستخدم أسماء خواديم DigitalOcean : لتغيير أسماء خواديم نطاقنا نسجّل الدخول إلى لوحة تحكّم مُسجّل النطاق domain registrar ونقوم بالتغييرات التي عرضها لنا CloudFlare، على سبيل المثال إن كُنّا قد اشترينا نطاقنا عبر مُسجِّل مثل GoDaddy أو NameCheap سنحتاج لتسجيل الدخول إلى لوحة تحكّم الملائمة لهذا المُسجِّل ونقوم بالتغييرات هناك. تتفاوت العمليّة بحسب مُسجِّل النطاق الخاص بنا، وإن لم تعرف كيفيّة القيام بها فهي مشابهة للعمليّة الموصوفة في كيف نشير إلى أسماء خواديم DigitalOcean من مُسجِّلات النطاق الشائعة عدا أنّك ستستخدم أسماء خواديم CloudFlare بدلًا من تلك الخاصة بـ DigitalOcean. يستخدم النطاق في حالة هذا المثال أسماء خواديم DigitalOcean ونحتاج إلى تحديثه لكي يستخدم DNS الخاص بـ CloudFlare، تمّ تسجيل هذا النّطاق باستخدام NameCheap لذلك هذا هو المكان الذي يجب أن نذهب إليه لتحديث أسماء الخواديم. نضغط على زر المتابعة Continue بعد الانتهاء من تغيير أسماء الخواديم لدينا، قد يستغرق حتى 24 ساعة ليتم تبديل أسماء الخواديم ولكن عادة ما يتم ذلك في غضون عدّة دقائق. انتظار أسماء الخواديم حتى يتم تحديثهاولأنّ تحديث أسماء الخواديم يستغرق وقت غير معروف فمن المحتمل أن نرى هذه الصفحة بعد ذلك: تعني الحالة قيد الانتظار Pending أنّ CloudFlare تنتظر تحديث أسماء الخواديم إلى الأسماء المطلوبة (على سبيل المثال olga.ns.cloudflare.com وrob.ns.cloudflare.com)، إن قمت بفعل ذلك فكل ما عليك الآن هو الانتظار والتحقّق لاحقًا من أجل الحالة نشيط Active، إن ضغطنا على الزر Recheck Nameservers أو انتقلنا إلى لوحة تحكّم CloudFlare فستقوم بالتحقّق من أنّ أسماء الخواديم قد تمّ تحديثها. حالة CloudFlare نشيطة Activeحالما يتم تحديث أسماء الخواديم سيستخدم النطاق DNS الخاص بـ CloudFlare وسنرى أنّه أصبح يمتلك الحالة نشيط Active، مثل ما يلي: يعني هذا أنّ CloudFlare يعمل كوسيط عكسي لموقعنا، وأنّنا نملك النفاذ للميّزات المتاحة في الخطة التي سجلّناها، إن كُنّا نستخدم الخطة المجانيّة Free كما فعلنا في هذا الدّرس فسنملك النفاذ لبعض الميّزات التي تُحسِّن أمان موقعنا وسرعته وتوفّره، لن نُغطّي هنا جميع الميّزات لأنّنا نركّز على التخفيف من هجمات DDoS، ولكنّها تتضمّن CDN، SSL، التخزين المؤقت للمحتوى الثابت static content caching، الجّدار الناري Firewall (قبل أن تصل حركة مرور البيانات إلى خادومنا)، وأدوات تحليل حركة مرور البيانات traffic analytics tools. نلاحظ أيضًا أنّ ملخّص الإعدادات Settings Summary الموجودة تحت نطاقنا يُظهِر مستوى الأمان الحالي لموقعنا (متوسّط medium افتراضيًّا) وبعض المعلومات الأخرى. للحصول على أقصى استفادة من CloudFlare قد ترغب قبل المتابعة باتّباع هذا الدّليل: الخطوات الأولى المُوصى بها لجميع مستخدمي CloudFlare، وهذا ضروري للتأكّد من أنّ CloudFlare ستسمح بالاتصالات الشرعيّة من الخدمات التي نرغب بالسّماح بها، وأنّ سجلّات خادوم الويب لدينا ستظهر عناوين IP الأصليّة للزوار (بدلًا من عناوين IP الوسيط العكسي لـ CloudFlare). بعد أن ننتهي من إعداد كل هذا سنلقي نظرة على إعدادات الوضع "أنا تحت الهجوم" "I'm Under Attack Mode" في جدار CloudFlare النّاري. الوضع "أنا تحت الهجوم" I'm Under Attack Modeيتم تعيين أمان جدار CloudFlare النّاري افتراضيًّا إلى متوسّط Medium، يوفّر هذا بعض الحماية ضدّ الزوّار المُصنّفين كتهديد معتدل عن طريق إظهار صفحة تحدّي challenge page قبل السّماح لهم بالمتابعة إلى موقعنا، ومع ذلك إن كان موقعنا هدفًا لهجمات DDoS فلن يكون هذا كافيًا لإبقاء موقعنا يعمل، وفي هذه الحالة ربّما يكون الوضع I'm Under Attack Mode مناسبًا لنا. إن قمنا بتمكين هذا الوضع سيتم عرض صفحة وسيطة لأي زائر لموقعنا تقوم بتنفيذ بعض التحقّقات من المتصفّح وتُؤخِّر الزائر لمدة 5 ثوان قبل تمريره إلى خادومنا، سيبدو هذا مشابهًا لما يلي: إن مرّت التحقّقات بنجاح سيتم السّماح للزائر بالوصول لموقعنا، ويكون عادةً مزيج المنع والتأخير للزوّار من الاتصال إلى موقعنا كافيًا لإبقائه قيد التشغيل حتى خلال هجمات DDoS. ملاحظة: يجب أن تكون JavaScript و Cookies مُمكَّنة لدى زوّار الموقع لكي يتجاوزوا الصفحة الوسيطة، وإن لم يكن هذا مقبولًا يجب النظر في استخدام إعدادات أمان الجّدار الناري العالية "High" بدلًا من ذلك. فلنبقِ في ذهننا أنّه يجب تمكين الوضع I'm Under Attack Mode فقط عندما يكون الموقع ضحيّة لهجمات DDoS، فيما عدا ذلك يجب إطفاؤه كي لا يُؤخِّر المستخدمين الطبيعيّين من النفاذ للموقع بدون سبب. كيفية تمكين الوضع I'm Under Attack Modeأبسط طريقة لتمكين هذا الوضع هي الذهاب إلى صفحة نظرة عامّة Overview في CloudFlare (وهي الصفحة الافتراضيّة) واختياره من قائمة إجراءات سريعة Quick Actions: ستتحوّل إعدادات الأمان فورًا إلى حالة I'm Under Attack، وسيتم الآن عرض صفحة CloudFlare الوسيطة لأي زائر كما تحدّثنا سابقًا. كيفية تعطيل الوضع I'm Under Attack Modeبما أنّه يجب استخدام هذا الوضع فقط في حالات الطوارئ وهجمات DDoS فينبغي علينا تعطيله عندما لا نكون تحت الهجوم، ولفعل هذا نذهب إلى صفحة نظرة عامّة Overview في CloudFlare ونضغط على الزر تعطيل Disable: نختار بعدها مستوى الأمان الذي نرغب بالتحويل إليه، الوضع الافتراضي والمُفضَّل هو متوسّط Medium: يجب أن يعود موقعنا إلى حالة نشيط Active وأن يتم تعطيل صفحة حماية DDoS. الخاتمةالآن وقد أصبح موقعنا يستخدم CloudFlare أصبحنا نملك أداة أخرى لحمايته بسهولة من هجمات DDoS المُعتمدة على HTTP، هنالك أيضًا مجموعة من الأدوات الأخرى التي توفّرها CloudFlare والتي قد نرغب بإعدادها، مثل شهادات SSL المجانيّة، ولهذا من المُفضَّل أن تقوم باستكشاف الخيارات وترى ما هو مفيد لك. حظًّا طيّبًا ! ترجمة -وبتصرّف- لـ How To Mitigate DDoS Attacks Against Your Website with CloudFlare لصاحبه Mitchell Anicas.
  3. تتّبع الأدوات المساعدة في لينِكس فلسفة Unix من ناحية تصميمها عادةً، حيث يُوصى بأن تكون الأدوات صغيرة، أن تستخدم ملفّات نص مُجرَّد plain text للدخل input والخَرْج output، وأن تعمل بالأسلوب التركيبي modular manner، ونمتلك بسبب هذا الإرث legacy وظيفة رائعة لمعالجة النّصوص مع أدوات مثل sed وawk. سنناقش في هذا الدّرس awk، والتي هي لغة برمجة ومُعالِج نصوص على حدٍّ سواء يُمكن استخدامها للتعامل مع بيانات النّصوص بطرق مفيدة جدًّا، سنناقش هذا على Ubuntu 12.04 VPS ولكن ينبغي أن يعمل بنفس الطريقة على أي نظام لينِكس حديث. الصياغة الأساسية Basic Syntaxيتم تضمين الأمر awk افتراضيًّا في جميع أنظمة لينِكس الحديثة، لذا لن نحتاج إلى تثبيته لكي نبدأ باستخدامه. يكون awk مفيدًا أكثر عند التعامل مع ملفات نصيّة مُنسَّقة بطريقة متوقعة، فعلى سبيل المثال يكون ممتازًا في تحليل parsing والتعامل مع البيانات المجدولة، فهو يعمل على الأسطر سطرًا تلو الآخر وبالتكرار عبر كامل الملف. يستخدم awk افتراضيًّا الفواصل whitespaces (المسافات spaces، tabs، إلخ) للفصل بين الحقول، ولحسن الحظ تستخدم معظم ملفّات الإعدادات على نظام لينِكس هذه الصّيغة. الصيغة الأساسيّة لأمر awk هي: awk '/search_pattern/ { action_to_take_on_matches; another_action; }' file_to_parseنستطيع إمّا إزالة قسم البحث search أو قسم الإجراء action من أي أمر awk، إنّ الإجراء الافتراضي الذي يتم اتخاذه إن لم نقم بكتابة القسم “action” هو الطباعة “print”، والذي يقوم ببساطة بطباعة كافّة الأسطر الموافقة. إن لم نقم بكتابة القسم “search” يُنفِّذ awk الإجراء المُدرَج في كل سطر. أمّا إن قمنا بكتابتهما معًا فيستخدم awk قسم البحث search ليقرّر إذا ما كان السّطر الحالي يعكس النمط pattern المطلوب، ومن ثمّ يُنفِّذ الإجراءات على الأمور المُوافِقة له. استخدامات بسيطةنستطيع استخدام awk في أبسط أشكاله مثل cat ليطبع ببساطة جميع أسطر ملف نصّي على الشّاشة. فلنطبع ملف fstab لخادومنا، والذي يعرض أنظمة الملفّات filesystems التي يعرفها: awk '{print}' /etc/fstab# /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # proc /proc proc nodev,noexec,nosuid 0 0 # / was on /dev/vda1 during installation UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd / ext4 noatime,errors=remount-ro 0 1لا يفيدنا هذا كثيرًا، فلنجرّب قدرات awk في ترشيح filtering البحث: awk '/UUID/' /etc/fstab# device; this may be used with UUID= as a more robust way to name devices UUID=b96601ba-7d51-4c5f-bfe2-63815708aabd / ext4 noatime,errors=remount-ro 0 1وكما نرى يطبع awk الآن الأسطر التي تحتوي "UUID" فقط، بإمكاننا التخلّص من سطر التعليق comment غير المهم عن طريق تحديد أنّ "UUID" يجب أن تتواجد في بداية السّطر: awk '/^UUID/' /etc/fstabUUID=b96601ba-7d51-4c5f-bfe2-63815708aabd / ext4 noatime,errors=remount-ro 0 1نستطيع بشكل مشابه استخدام قسم الإجراء action لتحديد أي قطع من المعلومات نريد طباعتها، على سبيل المثال لطباعة العمود الأول فقط نستطيع كتابة: awk '/^UUID/ {print $1;}' /etc/fstabUUID=b96601ba-7d51-4c5f-bfe2-63815708aabdيمكننا الرجوع لكل عمود (لأنّها مفصولة بفراغ بينها) عن طريق متغيرات variables مرتبطة برقم عمودها، على سبيل المثال نستطيع الرجوع للعمود الأول بواسطة المتغير 1$، والرجوع لكامل السّطر بواسطة المتغير 0$. متغيرات awk الداخلية والتنسيق الموسع Expanded Formatيستخدم awk بعض المتغيّرات الدّاخليّة internal variables لتعيين قطع معيّنة من المعلومات بينما يقوم بمعالجة الملف. إنّ المتغيّرات الدّاخليّة التي يستخدمها awk هي: FILENAME: يُرجِع ملف الدّخل input الحالي.FNR: يُرجِع عدد التسجيلات record الحاليّة نسبة لملف الدّخل الحالي، على سبيل المثال إن كُنّا نملك ملفّين للدخل فسيخبرنا هذا المتغيّر بعدد التسجيلات لكل ملف بدلًا من أن يخبرنا بالمجموع الكلّي.FS: فاصل الحقل الحالي المُستخدَم للدلالة على كل حقل في التسجيل، يتم تعيينه افتراضيًّا إلى مسافة whitespace.NF: عدد الحقول في التسجيلات الحاليّة.NR: عدد التسجيلات الحاليّة.OFS: فاصل الحقل للبيانات المُخرَجة، يتم تعيينه افتراضيًّا إلى مسافة whitespace.ORS: فاصل التّسجيلات للبيانات المُخرَجة، وهو بشكل افتراضي سطر جديد.RS: فاصل التّسجيلات المُستخدَم لتمييز التّسجيلات المنفصلة في ملف الدّخل، وهو بشكل افتراضي سطر جديد.نستطيع تغيير قيم هذه المتغيّرات بحسب رغبتنا لتوافِق احتياجات ملفّاتنا، نقوم بذلك عادةً خلال طور التهيئة لمعالجة awk. يقودنا هذا إلى مفهوم هام آخر، إنّ صياغة awk مُعقَّدة أكثر بقليل ممّا شاهدناه في البداية، حيث توجد أيضًا كُتَل blocks اختياريّة BEGIN وEND والتي يُمكن أن تحتوي على أوامر ليتم تنفيذها قبل وبعد معالجة الملف على التوالي. يجعل هذا من صيغتنا المُوسَّعة تبدو مشابهة لما يلي: awk 'BEGIN { action; } /search/ { action; } END { action; }' input_fileإنّ الكلمات المفتاحيّة BEGIN وEND هي في الواقع مجرّد مجموعات مُحدّدة من الشّروط conditions تمامًا مثل مُعامِلات parameters البحث، فهي تتوافق مع الشّروط: قبل معالجة المستند وبعد معالجته. ويعني هذا أنّه بإمكاننا تغيير بعض المتغيّرات الداخليّة في القسم BEGIN، فعلى سبيل المثال الملف etc/passwd/ مفصول بواسطة نقطتين (:) بدلًا من مسافة، وإن أردنا طباعة العمود الأول من هذا الملف نستطيع كتابة ما يلي: sudo awk 'BEGIN { FS=":"; } { print $1; }' /etc/passwdroot daemon bin sys sync games man . . .نستطيع استخدام الكُتَل BEGIN وEND لطباعة معلومات بسيطة حول الحقول التي نطبعها: sudo awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; } {print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;} END { print "---------\nFile Complete" }' /etc/passwdUser UID GID Home Shell -------------- root 0 0 /root /bin/bash daemon 1 1 /usr/sbin /bin/sh bin 2 2 /bin /bin/sh sys 3 3 /dev /bin/sh sync 4 65534 /bin /bin/sync . . . --------- File Completeبإمكاننا كما نرى تنسيق الأشياء بشكل أنيق من خلال الاستفادة من بعض ميّزات awk. جميع الأقسام المُوسّعة اختياريّة، وفي الواقع القسم action الرئيسي بذاته اختياري إن تمّ تعريف قسم آخر، نستطيع أن نفعل أشياء من هذا القبيل كما يلي: awk 'BEGIN { print "We can use awk like the echo command"; }'We can use awk like the echo commandالبحث في الحقول والتعابير المركبة في awkقُمنا في أحد الأمثلة السّابقة بطباعة السّطر الذي يبدأ بـ "UUID" من الملف etc/fstab/، وكان هذا سهلًا لأنّنا كُنّا نبحث عن بداية السّطر بأكمله. ولكن ماذا لو أردنا معرفة إذا ما كان نمط البحث قد وافق بداية الحقل field بدلًا من ذلك؟ نستطيع إنشاء الملف favorite_food.txt الذي يضم قائمة تحوي رقم العناصر والأطعمة المفضّلة لمجموعة من الأصدقاء: echo "1 carrot sandy 2 wasabi luke 3 sandwich brian 4 salad ryan 5 spaghetti jessica" > favorite_food.txtإن كُنّا نريد إيجاد جميع الأطعمة التي تبدأ بـ “sa” من هذا الملف فبإمكاننا البدء بتجربة شيء مشابه لما يلي: awk '/sa/' favorite_food.txt1 carrot sandy 2 wasabi luke 3 sandwich brian 4 salad ryanقمنا هنا بالمطابقة مع أي مثال عن “sa” في الكلمة، وهذا لا يستثني كلمات مثل " wasabi" والتي تحوي هذا النمط في منتصفها، أو "sandy" غير الموجودة في العمود الذي نريده، فنحن مهتمون فقط بالكلمات التي تبدأ بـ “sa” والموجودة في العمود الثاني. بإمكاننا إخبار awk أن يُطابِق بداية العمود الثاني باستخدام هذا الأمر: awk '$2 ~ /^sa/' favorite_food.txt3 sandwich brian 4 salad ryanيسمح لنا هذا كما نرى بالبحث فقط في بداية العمود الثاني عن مُطابِق. يُخبِر الحرف "^" بأن يُحدِّد awk بحثه في بداية الحقل، ويُحدِّد الجزء "~field_num" بأنّه يجب فقط النّظر إلى العمود الثاني. يُمكننا بسهولة البحث عن الأشياء غير المُطابِقة بتضمين الحرف "!" قبل المَدّة tilde (~). سيعيد هذا الأمر جميع الأسطر التي لا تملك طعامًا يبدأ بـ “sa”: awk '$2 !~ /^sa/' favorite_food.txt1 carrot sandy 2 wasabi luke 5 spaghetti jessicaإن قرّرنا لاحقًا أنّنا فقط مهتمّون بالأسطر التي يكون فيها ما سبق صحيحًا ورقم العنصر أقل من 5، فنستطيع استخدام تعبير مُركَّب مثل هذا: awk '$2 !~ /^sa/ && $1 < 5' favorite_food.txtيُقدِّم لنا هذا بعض الأشياء الجديدة، أوّلها هو القدرة على إضافة مُتطلّبات إضافيّة للسطر الذي نريد مُطابقته باستخدام العامل operator &&، نستطيع باستخدام هذا جمع عدد كيفي من الشّروط للسطر الذي نريد مُطابقته. نستخدم هذا العامل لإضافة التحقّق من أنّ قيمة العمود الأوّل أقل من 5. الخاتمةيجب أن يكون لدينا الآن فكرة أساسيّة حول كيفيّة قيام awk بالتعامل مع تنسيق، وطباعة الملفّات النّصيّة بانتقائيّة، رغم ذلك فإنّ awk موضوع أكبر من هذا بكثير، وهو في الواقع لغة برمجة كاملة تحتوي على إسناد للمتغيّرات، بُنى التّحكّم control structures، دوال مُضمَّنة built-in functions، والمزيد من ذلك، ويُمكن استخدامه في scripts لتنسيق النصوص بطريقة مقروءة بسهولة. ولتعلّم المزيد حول كيفيّة العمل مع awk تحقّق من الموارد الكبيرة له على الإنترنت، واقرأ عن gawk وهو إصدار GNU من awk الموجود على توزيعات لينِكس الحديثة. ترجمة -وبتصرّف- لـ How To Use the AWK language to Manipulate Text in Linux لصاحبه Justin Ellingwood.
  4. شهدت السنوات الأخيرة انتقال توزيعات لينِكس على نحو متزايد من أنظمة init الأخرى إلى systemd، تُوفِّر مجموعة أدوات systemd نموذج init مرن وسريع لإدارة الجهاز بشكل كامل من الإقلاع boot فصاعدًا. سنقوم في هذا الدرس بالمرور بشكل سريع على أهم الأوامر التي نحتاج معرفتها لإدارة خادوم يحتوي على systemd، ينبغي أن يعمل هذا على أي خادوم يُطبِّق systemd (أي إصدار نظام تشغيل يساوي أو أعلى من Ubuntu 15.04, Debian 8, CentOS 7, Fedora 15). فلنبدأ الآن. إدارة الوحدة بشكل أساسي Basic Unit Management الشيء الأساسي الذي يديره systemd ويعمل عليه هو الوحدة “unit”، يُمكن أن تكون الوحدات من عدّة أنواع، ولكن النّوع الأشيع هو الخدمة service (يتبيّن ذلك من ملف الوحدة الذي ينتهي بـ .service)، ولإدارة الخدمات على خادوم يحتوي systemd فإنّ أداتنا الرئيسيّة هي الأمر systemctl. تمتلك جميع أوامر نظام init الاعتياديّة إجراءات مُكافِئة مع الأمر systemctl، سنستخدم الوحدة nginx.service للتوضيح (يجب علينا تثبيت Nginx باستخدام مُدير الحِزَم للحصول على ملف الخدمة هذا). نستطيع على سبيل المثال تشغيل الخدمة بكتابة ما يلي: sudo systemctl start nginx.service نستطيع إيقافها مرّة أخرى بكتابة: sudo systemctl stop nginx.service ولإعادة تشغيل الخدمة نكتب: sudo systemctl restart nginx.service ولمحاولة إعادة تحميل reload الخدمة بدون مقاطعة الوظيفة الطبيعيّة نكتب ما يلي: sudo systemctl reload nginx.service تمكين أو تعطيل الوحدات لا يتم بشكل افتراضي تشغيل معظم ملفّات وحدات systemd تلقائيًّا عند الإقلاع، ولإعداد هذه الوظيفة نحتاج لتمكين “enable” الوحدة، والذي يقوم بتعليقها بخطافة hook إلى هدف “target” إقلاع مُعيَّن ممّا يُسبِّب تحفيز تشغيلها عند بدء تشغيل الهدف. لتمكين خدمة من البدء تلقائيًّا عند الإقلاع نكتب: sudo systemctl enable nginx.service إن كُنّا نرغب بتعطيل الخدمة مرّة أخرى نكتب: sudo systemctl disable nginx.service الحصول على لمحة عامة عن حالة النظام هناك قدر كبير من المعلومات التي يمكننا استخلاصها من خادوم systemd للحصول على لمحة عامّة عن حالة النّظام. على سبيل المثال للحصول على كافّة ملفّات الوحدات التي يعرضها systemd على أنّها نشطة “active” نكتب ما يلي (نستطيع فعليًّا ألّا نكتب list-units لأنّه سلوك systemctl الافتراضي): systemctl list-units ولعرض جميع الوحدات التي قام systemd بتحميلها أو حاول تحميلها إلى الذّاكرة بما في ذلك الخدمات غير النشطة حاليًّا نُضيف المحوِّل switch الذي يُدعى all--: systemctl list-units --all لعرض جميع الوحدات المُثبَّتة على النّظام بما في ذلك الوحدات التي لم يحاول systemd أن يُحمّلها إلى الذاكرة نكتب: systemctl list-unit-files عرض معلومات السجل Log الأساسية يجمع ويدير المُكوِّن في systemd الذي يُدعى journald المُدخلات اليوميّة journal entries من كافّة أجزاء النّظام. وهي بالأساس معلومات السّجلات من التطبيقات والنواة kernel. ولمشاهدة جميع مُدخلات السّجلات بدءًا من المُدخَل الأقدم نكتب: journalctl سيظهر لنا هذا افتراضيًّا المُدخلات من الإقلاعات السّابقة والحاليّة إن تمّ إعداد journald ليحفظ سجلّات records الإقلاع السّابق، تُمكِّن بعض التوزيعات هذا الأمر افتراضيًّا بينما لا تقوم توزيعات أخرى بتمكينه (ولتمكينه إمّا نُحرِّر الملف etc/systemd/journald.conf/ ونُعيِّن الخيار Storage= إلى مستمر "persistent" أو نُنشِئ الدّليل persistent بكتابة sudo mkdir -p /var/log/journal). إن كُنّا نرغب برؤية المُدخلات اليوميّة فقط من الإقلاع الحالي نُضيف العَلَم b-: journalctl -b ولمشاهدة رسائل النواة فقط، مثل تلك التي تكون ممثلة عادةً بواسطة dmesg، نستطيع استخدام العَلَم k-: journalctl -k مرةً أخرى، نستطيع تحديد الأمر السّابق ليكون فقط للإقلاع الحالي بإضافة العَلَم b-: journalctl -k -b الاستعلام عن سجلات وحالات الوحدة بينما تُمكّننا الأوامر السّابقة من الوصول إلى الحالة العامّة للنظام، فنستطيع أيضًا الحصول على معلومات حول حالة الوحدات بشكلٍ فردي. يُستخدم الخيار status مع الأمر systemctl للحصول على لمحة عامّة عن الحالة الحاليّة للوحدة، يُظهر لنا هذا الأمر إذا ما كانت الوحدة نشطة، معلومات حول العمليّة process، وآخر المُدخلات اليوميّة: systemctl status nginx.service لمشاهدة كافّة المُدخلات اليوميّة للوحدة التي نسأل عنها نضيف الخيار –u مع اسم الوحدة إلى الأمر journalctl: journalctl -u nginx.service ونستطيع كالعادة تحديد المُدخلات للإقلاع الحالي فقط بإضافة العَلَم b-: journalctl -b -u nginx.service فحص الوحدات وملفات الوحدات نعرف حتى الآن كيفيّة تعديل حالة وحدة ما بواسطة تشغيلها أو إيقافها، ونعلم كيف نشاهد معلومات اليوميّات journal والحالة لأخذ فكرة عمّا يحدث مع العمليّة، ومع ذلك لم نتعلّم كيفيّة فحص inspect جوانب أخرى للوحدات وملفّات الوحدات. يحتوي ملف الوحدة المُعامِلات parameters التي يستخدمها systemd لإدارة وتشغيل الوحدة، ولمشاهدة المحتويات الكاملة لملف الوحدة نكتب: systemctl cat nginx.service ولرؤية شجرة الاعتماديّات dependency tree لوحدة ما (والتي تحاول وحدات systemd تفعيلها عند بدء تشغيل الوحدة) نكتب: systemctl list-dependencies nginx.service يُظهر لنا هذا الأمر الوحدات المعتمدة مع توسيع expand الوحدات الهدف target بشكل تكراري recursively، ولتوسيع كافّة الوحدات المعتمدة بشكل تكراري نُمرِّر العَلَم all--: systemctl list-dependencies --all nginx.service وأخيرًا نستخدم الخيار show لمشاهدة التفاصيل ذات المستوى المُنخفض low-level لإعدادات الوحدة على النّظام: systemctl show nginx.service يُعطينا هذا الأمر قيمة كل مُعامِل تتم إدارته بواسطة systemd. تعديل ملفات الوحدة إن كُنّا نحتاج للقيام بتعديلات على ملف الوحدة فيسمح لنا systemd بالقيام بالتغييرات من خلال الأمر systemctl بنفسه بدون أن نضطر للذهاب إلى موقع الملف الفعلي على القرص. لإضافة مقطع snippet لملف الوحدة، والذي يُمكن استخدامه لإلحاق append أو تجاوز override إعدادات في ملف الوحدة الافتراضي، نستدعي ببساطة الخيار edit على الوحدة: sudo systemctl edit nginx.service وإن كُنّا نرغب بتعديل كامل محتوى ملف الوحدة بدلًا من إنشاء مقطع، نُمرَّر العَلَم --full: sudo systemctl edit --full nginx.service يجب بعد الانتهاء من تعديل ملف الوحدة إعادة تحميل العمليّة systemd نفسها لكي تلتقط تغييراتنا: sudo systemctl daemon-reload استخدام الأهداف targets (مستويات التشغيل Runlevels) ومن الوظائف الأخرى لنظام init نقل الخادوم نفسه بين حالات مختلفة، تُشير أنظمة init التقليديّة لهذا الأمر باسم مستويات التشغيل "runlevels" ممّا يسمح للنظام بأن يكون في مستوى تشغيل runlevel واحد فقط بنفس الوقت. يتم في systemd استخدام الأهداف targets بدلًا من ذلك، والتي هي بشكل أساسي نقاط تزامن يستطيع الخادوم استخدامها لنقل نفسه إلى حالة مُحدّدة، يُمكن أن يتم ربط الخدمة وملفّات الوحدة الأخرى إلى هدف، ويُمكن للأهداف المتعددة أن تكون نشطة في الوقت نفسه. ولرؤية كل الأهداف المتاحة على نظامنا نكتب: systemctl list-unit-files --type=target لمشاهدة الهدف الافتراضي الذي يحاول systemd الوصول إليه عند الإقلاع (والذي بدوره يقوم بتشغيل كافّة ملفّات الوحدة التي تُشكّل شجرة الاعتماديّات لهذا الهدف) نكتب: systemctl get-default نستطيع تغيير الهدف الافتراضي الذي سيتم استخدامه عند الإقلاع باستخدام الخيار set-default: sudo systemctl set-default multi-user.target نكتب ما يلي لكي نرى ما هي الوحدات المرتبطة بالهدف: systemctl list-dependencies multi-user.target يمكننا تعديل حالة النظام للانتقال بين الأهداف عن طريق الخيار isolate، سيقوم هذا بإيقاف تشغيل أيّة وحدات غير مرتبطة بالهدف المحدّد، ويجب أن نكون متأكدين من أنّ الهدف الذي نقوم بعزله isolate لا يوقف تشغيل أيّة خدمات أساسيّة: sudo systemctl isolate multi-user.target إيقاف تشغيل أو إعادة تشغيل الخادوم هنالك بعض الاختصارات المتاحة لبعض الحالات الرئيسيّة التي يستطيع النّظام الانتقال إليها، على سبيل المثال لإيقاف تشغيل خادومنا نكتب: sudo systemctl poweroff إن كُنّا بدلًا من ذلك نريد إعادة تشغيل النظام فبإمكاننا فعل ذلك بكتابة: sudo systemctl reboot نستطيع الإقلاع في وضع الإنقاذ rescue mode بكتابة: sudo systemctl rescue لاحظ أنّ معظم أنظمة التشغيل تقوم بتضمين كنيات aliases تقليديّة لهذه العمليّات بحيث أنّنا نستطيع ببساطة كتابة: sudo poweroff أو sudo reboot بدون systemctl، ومع ذلك ليس من المضمون أن يكون هذا مُعدًّا على كل الأنظمة. الخطوات التالية ينبغي أن نكون الآن قد تعلّمنا أساسيّات إدارة خادوم يستخدم systemd، ومع ذلك هناك المزيد لتعلمّه مع توسّع احتياجاتنا، توجد أدناه روابط دروس تحتوي معلومات أكثر تفصيلًا حول بعض المُكوّنات التي ناقشناها في هذا الدّرس: كيفيّة استخدام Systemctl لإدارة خدمات ووحدات Systemd. كيفيّة استخدام Journalctl لعرض سجلّات Systemd والتعامل معها. فهم وحدات وملفّات وحدات Systemd. نستطيع من خلال تعلّم كيفيّة الاستفادة من قوّة نظام init لدينا أن نتحكّم بحالة أجهزتنا وإدارة خدماتنا وعمليّاتنا بشكل أسهل. ترجمة -وبتصرّف- لـ Systemd Essentials: Working with Services, Units, and the Journal لصاحبه Justin Ellingwood.
  5. إنّ Mytop هي أداة سطر أوامر مفتوحة المصدر open source تُستخدَم لمراقبة أداء MySQL، وهي مستوحاة من أداة مراقبة نظام لينِكس التي تُدعى top ومُشابِهة لها في الشّكل والمظهر، تتصل Mytop إلى خادوم MySQL وتقوم بشكل دوري بتشغيل الأمرين show processlist و show global status، وتقوم بعدها بتلخيص المعلومات بشكل مفيد، نستطيع باستخدام Mytop مراقبة (بشكلٍ آني real-time) مناقشات MySQL threads، الاستعلامات queries، وزمن التشغيل uptime، بالإضافة إلى أنّها ترى أي مستخدم يقوم بتنفيذ استعلامات على أي قاعدة بيانات، وأي الاستعلامات تجري ببطء والمزيد من ذلك، نستطيع استخدام كل هذه المعلومات لتحسين أداء خادوم MySQL. سنناقش في هذا الدّرس كيفيّة تثبيت، إعداد، واستخدام mytop. المتطلبات الأساسيةقبل البدء في هذا الدرس ينبغي أن نمتلك ما يلي لدينا: CentOS 7 64-bit Droplet (تعمل أيضًا مع CentOS 6).مستخدم غير جذري non-root مع صلاحيّات sudo سيتم تنفيذ جميع الأوامر عن طريق هذا المستخدم.خادوم MySQL يعمل على الـ Droplet.الخطوة الأولى – تثبيت Mytopفلنقم بتثبيت الحِزَم المطلوبة من أجل mytop. نحتاج في البداية إلى تثبيت مستودع yum الذي يُدعى (EPEL (Extra Packages for Enterprise Linux على الخادوم، إنّ EPEL هي مجموعة ذات اهتمامات مشتركة بتوزيعة Fedora تقوم بإنشاء، إدارة، والحفاظ على مجموعة حِزَم برمجيّة إضافيّة add-on مفتوحة المصدر عالية الجّودة من أجل Enterprise Linux، نقوم بتنفيذ الأمر التالي لتثبيت وتمكين مستودع EPEL على خادومنا: على CentOS 7: sudo rpm -ivh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpmعلى CentOS 6: sudo rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpmوقبل المتابعة نتحقّق أنّه تم تمكين المستودع EPEL باستخدام: sudo yum repolistإن تمّ تمكينه سنشاهد في الخَرْج ما يلي: epel/x86_64 Extra Packages for Enterprise Linux 7 - x86_64فلنقم بعد ذلك بحماية الحِزَم الأساسيّة من EPEL باستخدام إضافة yum plugin التي تُدعى protectbase: sudo yum install yum-plugin-protectbase.noarch -yالغرض من الإضافة protectbase هو حماية بعض مستودعات yum من تحديثات المستودعات الأخرى، فلن يتم تحديث أو تجاوز override الحِزَم الموجودة في المستودعات المحميّة بواسطة الحِزَم في المستودعات غير المحميّة حتى ولو كان المستودع غير المحمي يملك إصدارًا أحدث. نحن الآن مستعدون لتثبيت حِزمة mytop، فلنقم بتنفيذ الأمر التالي لتثبيتها: sudo yum install mytop -yسيقوم هذا الأمر بتثبيت حِزمة mytop بالإضافة إلى جميع اعتمادياتها dependencies والتي هي في معظمها وحدات perl modules. الخطوة الثانية – ضبط إعدادات Mytopنقوم قبل استخدام mytop بإنشاء ملف إعدادات مُخصَّص من أجل mytop يُدعى mytop.، وذلك بكتابة الأمر التالي: sudo nano /root/.mytopنضيف المحتوى التالي إلى الملف ونقوم بحفظه وإغلاقه: root/.mytop/ host=localhost db=mysql delay=5 port=3306 socket= batchmode=0 color=1 idle=1سيتم استخدام ملف الإعدادات عندما نقوم بتشغيل mytop بشكل مباشر كمستخدم جذري root وعندما نقوم بتشغيلها باستخدام الأمر sudo كمستخدم غير جذري يملك صلاحيّات sudo. نستطيع القيام بتغييرات إلى ملف الإعدادات اعتمادًا على احتياجاتنا، على سبيل المثال يُحدِّد الخيار delay الفترة الزمنيّة مقدرةً بالثانية بين تحديثات العرض display، فإن كُنّا نرغب بتحديث عرض mytop كل 3 ثوان بإمكاننا تحرير الملف root/.mytop/ باستخدام: sudo nano /root/.mytopومن ثمّ تغيير ما يلي: root/.mytop/ delay=3يُحدِّد المُعامِل idle إذا ما كان سيسمح للمناقشات threads الخاملة idle (النائمة) بالظهور في قائمة شاشة عرض mytop، الوضع الافتراضي هو إظهار المناقشات الخاملة، إن تمّ حذف المناقشات الخاملة سينعكس ترتيب الفرز sorting الافتراضي بحيث تظهر أطول الاستعلامات قيد التشغيل في أعلى القائمة، إن كُنّا نرغب في فعل هذا نُحرّر الملف root/.mytop/ ونغيّر ما يلي: root/.mytop/ idle=0نستطيع الرجوع إلى صفحات mytop اليدويّة للمزيد من المعلومات عن جميع المُعامِلات في ملف الإعدادات والتي تحتوي على وصف لكل مُعامِل، للوصول إلى الصفحات اليدويّة نستخدم الأمر: man mytopنستطيع كتابة q للخروج من الدّليل. الخطوة الثالثة – الاتصال إلى Mytopسنناقش في هذا القسم كيفيّة الاتصال إلى mytop واستخدامها لعرض استعلامات MySQL. تتطلّب Mytop اعتمادات credentials للنفاذ إلى قاعدة البيانات، والتي يمكن تزويدها عبر مُحِث prompt في سطر الأوامر أو عبر تخزينها في ملف الإعدادات، سنستخدم من أجل أمان أفضل الخيار prompt-- والذي يسأل كل مرّة عن كلمة السّر. فلنتصل إلى mytop باستخدام: sudo mytop --promptونُدخِل كلمة سر المستخدم root في MySQL في المُحِث، بإمكاننا أيضًا استخدام العديد من مُعطيات arguments سطر الأوامر مع الأمر mytop، نرجو الرجوع إلى الصفحات اليدويّة من أجل الحصول على قائمة كاملة بها، على سبيل المثال إن كُنّا نرغب باستخدام مستخدم mysql مُختلف مثل sammy للاتصال إلى mytop نقوم باستخدام الأمر التالي: sudo mytop -u sammy --promptوللاتصال ومراقبة قاعدة بيانات مُحدّدة فقط نستخدم الأمر التالي: sudo mytop -d databasename --promptللخروج من mytop والعودة إلى مُحث الصّدفة shell prompt نكتب q. الخطوة الرابعة – عرض وتفسير شاشة عرض Mytopسنرى في هذا القسم كيفيّة تفسير شاشة عرض mytop والميزات المختلفة التي تُقدّمها هذه الأداة. حالما نتصل إلى mytop باستخدام mytop --prompt سيتم أخذنا إلى طريقة عرض المناقشات thread view، والتي ستظهر خَرْج مشابه لما يلي: Output of mytop MySQL on localhost (5.5.41-MariaDB) up 0+00:05:52 [01:33:15] Queries: 148 qps: 0 Slow: 0.0 Se/In/Up/De(%): 09/00/00/00 qps now: 2 Slow qps: 0.0 Threads: 6 ( 5/ 0) 67/00/00/00 Key Efficiency: 2.0% Bps in/out: 14.7/320.7k Now in/out: 192.5/731.8k Id User Host/IP DB Time Cmd Query or State -- ---- ------- -- ---- --- ---------- 2 root localhost mysql 0 Query show full processlist 16 root localhost 0 Sleep 17 root localhost testdb 0 Query SELECT * FROM dept_emp 18 root localhost testdb 0 Query SELECT * FROM dept_emp 19 root localhost testdb 0 Query SELECT * FROM dept_emp 20 root localhost testdb 0 Query SELECT * FROM dept_empنستطيع العودة إلى طريقة العرض هذه إن كُنّا في طريقة عرض أخرى بكتابة t. تُقسم شاشة العرض السّابقة إلى قسمين، تُؤلّف الأسطر الأربعة الأولى الترويسة header والتي يُمكن تشغيلها وإيقافها بضغط SHIFT-H، تحتوي الترويسة على معلومات موجزة حول خادوم MySQL لدينا. يُحدِّد السطر الأول اسم المضيف hostname للخادوم وإصدار MySQL الموجود، يُظهر القسم الأيمن منه زمن التشغيل uptime لعمليّة خادوم MySQL بصيغة الأيام+السّاعات:الدّقائق:الثواني (days+hours:minutes:seconds) بالإضافة للوقت الحالي.يعرض السطر الثاني العدد الكلّي للاستعلامات التي قام الخادوم بمعالجتها (148 في حالتنا)، متوسط عدد الاستعلامات في الثانية، عدد الاستعلامات البطيئة، والنسبة المئوية للاستعلامات اختيار Select، إدخال Insert، تحديث Update، وحذف Delete.يُظهِر السطر الثالث قيم آنيّة real-time منذ التحديث refresh الأخير لـ mytop، إنّ زمن التّحديث (التأخير) الطبيعي في mytop هو 5 ثوان، لذا إن تمّ إجراء 100 استعلام خلال آخر 5 ثوان منذ التحديث سيكون عدد qps now هو 20، الحقل الأول هو عدد الاستعلامات في الثانية (qps now: 2). القيمة الثانية هي عدد الاستعلامات البطيئة في الثانية، يُشير القسم Threads: 6 ( 5/ 0) إلى وجود 6 مناقشات threads مُتّصلة، 5 منها نشطة (واحدة منها نائمة) وعدم وجود أي مناقشات (الرقم 0) في الذّاكرة المؤقّتة cache للمناقشات، يُظهر الحقل الأخير في السّطر الثالث النّسبة المئويّة للاستعلام، كما هو الحال في السّطر السابق، ولكن منذ التحديث الأخير لـ mytop.يعرض السّطر الرّابع فعاليّة key buffer (وهو عدد المرات التي فيها قراءة المفاتيح keys من الـ buffer بدلًا من القرص) وعدد البايتات التي أرسلتها واستقبلتها MySQL، كلاهما بالمجمل ومنذ آخر تحديث لـ mytop. تُظهِر Key Efficiency: 2.0% أنّه يتم قراءة 2% من المفاتيح من الـ buffer وليس من القرص، تُظهِر Bps in/out: 14.7/320.7k أنّه منذ بدء التشغيل تلقّت MySQL ما يُعادِل 14.7kbps من حركة البيانات traffic الواردة و 320.7kbps من حركة البيانات الصادرة، يُظهِر Now in/out حركة البيانات أيضًا ولكن منذ آخر تحديث لـ mytop.يعرض القسم الثاني من شاشة العرض مناقشات MySQL الحاليّة مع فرزها بحسب زمن خمولها (الأقل خمولًا أولًا)، نستطيع عكس ترتيب الفرز بضغط O عند الحاجة لذلك، يتم هنا أيضًا عرض مُعرِّف المناقشة thread id، اسم المستخدم، المُضيف الذي يتصل منه المستخدم، قاعدة البيانات التي يتصل إليها المستخدم، زمن الخمول مُقدّرًا بالثانية، الأمر الذي تقوم المناقشة بتنفيذه (أو حالة المناقشة)، والقسم الأول من معلومات الاستعلام، إن كانت المناقشة في حالة استعلام Query (أي يعرض العمود Cmd القيمة Query) فسيعرض العمود التالي الذي يُدعى Query or State القسم الأول من الاستعلام الذي يتم تنفيذه، أمّا إن كانت حالة الأمر هي نائم Sleep أو خامل Idle فسيكون العمود Query or State فارغًا عادةً، في مثال الخَرْج السّابق لدينا فإنّ المناقشة ذات المُعرِّف id 2 هي فعليًّا mytop والتي تقوم بتشغيل الاستعلام show processlist لجمع المعلومات، والمناقشة ذات المُعرِّف 16 نائمة (أي لا تقوم بمعالجة استعلام ولكنّها تبقى متصلة)، والمناقشة ذات المُعرِّف 17 تقوم بتشغيل استعلام SELECT على قاعدة البيانات testdb. الآن وقد فهمنا أساسيّات شاشة عرض mytop، سنرى كيفيّة استخدامها لجمع المزيد من المعلومات حول مناقشات واستعلامات MySQL، فلنلقِ نظرة على شاشة عرض mytop التّالية: [secondary_output Output of mytop] MySQL on localhost (5.5.41-MariaDB) up 0+00:13:10 [23:54:45] Queries: 2.8k qps: 4 Slow: 51.0 Se/In/Up/De(%): 45/00/00/00 qps now: 17 Slow qps: 0.0 Threads: 52 ( 51/ 0) 96/00/00/00 Key Efficiency: 100.0% Bps in/out: 215.4/ 7.6M Now in/out: 2.0k/16.2M Id User Host/IP DB Time Cmd Query or State -- ---- ------- -- ---- --- ---------- 34 root localhost testdb 0 Query show full processlist 1241 root localhost 1 Sleep 1242 root localhost testdb 1 Query SELECT * FROM dept_emp 1243 root localhost testdb 1 Query SELECT * FROM dept_emp 1244 root localhost testdb 1 Query SELECT * FROM dept_emp 1245 root localhost testdb 1 Query SELECT * FROM dept_emp 1246 root localhost testdb 1 Query SELECT * FROM dept_emp 1247 root localhost testdb 1 Query SELECT * FROM dept_empتكون الاستعلامات مبتورة في طريقة عرض المناقشات thread view (طريقة العرض الافتراضيّة)، ولمشاهدة كامل الاستعلام بإمكاننا أن نضغط F وسيتم سؤالنا كما يلي: Full query for which thread id:نُدخِل مُعرِّف المناقشة thread id التي نريد عرض استعلامها، على سبيل المثال نكتب 1244 وسنشاهد ما يلي: Thread 1244 was executing following query: SELECT * FROM dept_emp WHERE ... -- paused. press any key to resume or (e) to explain --نستطيع كتابة e لشرح explain الاستعلام، والذي يقوم بشرح الاستعلام الذي يتم تنفيذه حتى نعرف إذا ما كان هذا هو الاستعلام الأمثل، إنّ EXPLAIN هي واحدة من أقوى الأدوات لفهم وتحسين استعلامات MySQL الصعبة، على سبيل المثال: EXPLAIN SELECT * FROM dept_emp: *** row 1 *** table: dept_emp type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 332289 Extra: NULL -- paused. press any key to resume --بإمكاننا أن نضغط على أي مفتاح للخروج من هذا الوضع أو نكتب t للعودة إلى طريقة عرض المناقشات الافتراضيّة. ومن طرق العرض المفيدة الأخرى المتاحة في mytop هي طريقة عرض الأوامر command view، وللوصول إليها نكتب c، ستبدو مشابهة لما يلي: Command Total Pct | Last Pct ------- ----- --- | ---- --- select 1782 55% | 100 8% show status 723 22% | 533 45% show processlist 708 22% | 532 45% change db 2 0% | 0 0% show variables 1 0% | 0 0% Compression 0 0% | 0 0%يُظهِر العمود Command نوع الأمر أو الاستعلام الذي يتم تنفيذه، يرمز العمود Total إلى العدد الإجمالي لهذا النوع من الأوامر التي تم تنفيذها منذ بدء تشغيل الخادوم، ويُظهِر العمود Pct نفس ما سبق ولكن بالنسبة المئوية. وعلى الناحية الأخرى من الخط العمودي نجد العمود Last والذي يُخبرنا بعدد هذا النوع من الأوامر التي تم تشغيلها منذ آخر تحديث لـ mytop، تُعطينا هذه المعلومات فكرة عمّا يقوم به خادوم MySQL على المدى القريب والبعيد. ناقشنا في هذا الدّرس بعضًا من ميّزات mytop الهامّة والمفيدة، هناك العديد من الميّزات الأخرى المتاحة، ولعرض قائمة كاملة من الخيارات نستطيع أن نضغط المفتاح أثناء تشغيل mytop. الخاتمةيجب أن يكون لدينا الآن معرفة جيّدة حول كيفيّة استخدام mytop لمراقبة خادوم MySQL لدينا، وهي أيضًا نقطة انطلاق لإيجاد مشاكل استعلامات SQL وتحسينها، وبالتالي زيادة الأداء الإجمالي للخادوم. ترجمة -وبتصرّف- لـ How To Use Mytop to Monitor MySQL Performance لصاحبته Veena K John.
  6. عند إعداد خادوم ويب توجد غالبًا أقسام من الموقع نرغب بتقييد الوصول إليها، تُوفِّر تطبيقات الويب عادةً طرق التصريح authorization والاستيثاق authentication الخاصّة بها، ولكن يُمكِن استخدام خادوم الويب بذاته لتقييد الوصول إن كانت هذه الطّرق غير كافية أو غير متوفّرة. سنشرح في هذا الدّرس كيف نحمي الممتلكات assets باستخدام كلمة سر على خادوم ويب Apache يعمل على Ubuntu. المتطلبات الأساسيةنحتاج للوصول إلى بيئة خادوم Ubuntu لكي نبدأ، نحتاج أيضًا لمستخدم غير جذري non-root مع صلاحيّات sudo من أجل تنفيذ مهام إداريّة administrative، لكي تتعلّم كيفيّة إعداد مستخدم بامتيازات sudo اتبع دليلنا للإعداد الأولي لخادوم Ubuntu 14.04. تثبيت حزمة أدوات Apache المساعدةسنستخدم أداة مُساعِدة utility تُدعى htpasswd من أجل إنشاء الملف الذي يقوم بتخزين كلمات السّر التي نحتاجها للوصول إلى المحتوى المُقيَّد لدينا، تُوجَد هذه الأداة في الحِزمة apache2-utils داخل المستودعات repositories في Ubuntu. نُحدِّث الذاكرة المؤقتة cache للحِزَم المحليّة ونُثبِّت الحِزمَة بكتابة هذا الأمر، سننتهز الفرصة أيضًا لتثبيت خادوم Apache2 في حال لم يكن مُثبّتًا لديك: sudo apt-get update sudo apt-get install apache2 apache2-utilsإنشاء ملف كلمات السرنستطيع الآن الوصول للأمر htpasswd واستخدامه لإنشاء ملف كلمات السّر والذي يستعمله خادوم Apache لاستيثاق authenticate المستخدمين، سنقوم بإنشاء ملف مخفي لهذا الغرض يُدعى htpasswd. بداخل دليل الإعدادات etc/apache2/. عند استخدام هذه الأداة لأوّل مرّة نحتاج لإضافة الخيار c- لإنشاء الملف المُحدَّد، نقوم بتحديد اسم مستخدم (في هذا المثال sammy) في نهاية الأمر لإنشاء مُدخَل جديد بداخل الملف: sudo htpasswd -c /etc/apache2/.htpasswd sammyسيتم سؤالنا عن تزويد كلمة سر وتأكيدها للمستخدم. نترك الوسيط c- لأي مستخدمين آخرين نرغب في إضافتهم: sudo htpasswd /etc/apache2/.htpasswd another_userإن قمنا بمشاهدة محتويات الملف نستطيع رؤية اسم المستخدم وكلمة السّر المُشفّرة لكل تسجيل record: cat /etc/apache2/.htpasswdsammy:$apr1$lzxsIfXG$tmCvCfb49vpPFwKGVsuYz. another_user:$apr1$p1E9MeAf$kiAhneUwr.MhAE2kKGYHK.إعداد استيثاق كلمة السر لخادوم Apacheالآن وبعد أن أصبحنا نمتلك ملف لأسماء المستخدمين وكلمات السّر في صيغة يستطيع خادوم Apache قراءتها، نحتاج لإعداد Apache لكي يتفحّص هذا الملف قبل تخديم محتوانا المحمي، بإمكاننا فعل هذا بطريقتين مختلفتين. الخيار الأول هو تحرير edit إعدادات Apache وإضافة حماية كلمة السّر إلى ملف المضيف الافتراضي virtual host file. يُعطينا هذا الخيار أداء أفضل بشكل عام لأنّه يتجنّب تكلفة قراءة ملفات إعدادات مُوزَّعة، إن كنت تملك هذا الخيار فإنّنا ننصح بهذا الأسلوب. إن لم تكن لدينا القدرة على تعديل ملف المضيف الافتراضي (أو كنّنا نستخدم مُسبقًا ملفات htaccess. لأغراض أخرى) نستطيع تقييد النفاذ باستخدام ملف htaccess.، يستخدم Apache ملفّات htaccess. من أجل السّماح لتعيين بعض عناصر الإعدادات داخل ملف في دليل المحتوى. العيب في هذا هو أنّه يجب على Apache إعادة قراءة هذه الملفّات عند كل طلب يتضمّن هذا الدّليل ممّا قد يؤثر على الأداء. اختر الخيار الذي يُناسِب احتياجاتك أدناه. إعداد التحكم بالنفاذ Access Control داخل تعريف المضيف الافتراضينبدأ بفتح ملف المضيف الافتراضي الذي نرغب بإضافة تقييد له، سنستخدم في مثالنا الملف 000-default.conf الذي يحمل المضيف الظاهري الافتراضي والمُثبَّت عبر حزمة apache في Ubuntu: sudo nano /etc/apache2/sites-enabled/000-default.confينبغي أن يبدو المحتوى داخل الملف مُشابِهًا لما يلي بعد إزالة التّعليقات: etc/apache2/sites-enabled/000-default.conf/ <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>يتم الاستيثاق على أساس كل دليل، سنحتاج لإعداد الاستيثاق إلى استهداف الدّليل الذي نرغب بتقييد الوصول إليه بواسطة كتلة <Directory ___>، في مثالنا سنقيّد الوصول إلى كامل جذر المستند document root ولكن نستطيع تعديل القائمة لاستهداف دليل مُحدَّد داخل مساحة الويب: etc/apache2/sites-enabled/000-default.conf/ <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory "/var/www/html"> </Directory> </VirtualHost>نُحدِّد داخل كتلة الدّليل أنّنا نرغب بإعداد استيثاق أساسي Basic، نختار من أجل AuthName اسم حقل يتم عرضه عند السؤال عن الاعتمادات credentials، نستخدم الأمر التوجيهي AuthUserFile ليشير إلى Apache عن ملف كلمات السّر الذي أنشأناه، سنحتاج أخيرًا إلى valid-user للوصول إلى هذا المورد، وهذا يعني أنّه سيتم السماح بالدخول لكل من يثبت صحّة هويته بكلمة سر: etc/apache2/sites-enabled/000-default.conf/ <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory "/var/www/html"> AuthType Basic AuthName "Restricted Content" AuthUserFile /etc/apache2/.htpasswd Require valid-user </Directory> </VirtualHost>عند الانتهاء نحفظ ونغلق الملف، نعيد تشغيل Apache لتنفيذ سياسة policy كلمات السّر: sudo service apache2 restartيجب الآن أن يكون الملف الذي حدّدناه محميًّا بكلمة سر. إعداد التحكم بالنفاذ Access Control باستخدام ملفات htaccess.إن كُنّا نرغب بإعداد حماية كلمة السّر باستخدام ملفّات htaccess. بدلًا من الطريقة السّابقة فينبغي أن نبدأ بتحرير ملف إعدادات Apache الرئيسي للسماح بملفّات htaccess.: sudo nano /etc/apache2/apache2.confنبحث عن الكتلة <Directory> من أجل الدّليل var/www/ الذي يحتوي جذر المستند، نقوم بتشغيل معالجة htaccess. بتغيير الأمر التّوجيهي AllowOverride داخل تلك الكتلة من “None” إلى “All”: etc/apache2/apache2.conf/ . . . <Directory /var/www/> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> . . .عند الانتهاء نحفظ ونغلق الملف. نحتاج بعد ذلك لإضافة ملف htaccess. إلى الدّليل الذي نرغب بتقييد الوصول إليه، في هذا المثال سنقيّد الوصول إلى كامل جذر المستند (كامل الموقع) والذي يتواجد في المسار var/www/html/، ولكن يُمكننا وضع هذا الملف في أي دليل نرغب بتقييد الوصول إليه: sudo nano /var/www/html/.htaccessنُحدِّد بداخل هذا الملف أنّنا نرغب بإعداد استيثاق أساسي Basic، نختار من أجل AuthName اسم حقل يتم عرضه عند السؤال عن الاعتمادات credentials، نستخدم الأمر التوجيهي AuthUserFile ليشير إلى Apache عن ملف كلمات السّر الذي أنشأناه، سنحتاج أخيرًا إلى valid-user للوصول إلى هذا المورد، وهذا يعني أنّه سيتم السماح بالدخول لكل من يثبت صحّة هويته بكلمة سر: var/www/html/.htaccess/ AuthType Basic AuthName "Restricted Content" AuthUserFile /etc/apache2/.htpasswd Require valid-userنحفظ ونغلق الملف، نعيد تشغيل خادوم الويب لنحمي بكلمة سر كل المحتوى الموجود في الدّليل بواسطة الملف htaccess.: sudo service apache2 restartتأكيد استيثاق كلمة السرللتأكّد من أنّ المحتوى محمي لدينا نُجرِّب النفاذ إلى المحتوى المُقيَّد من متصفّح إنترنت، يجب أن يتم عرض مُحث prompt لاسم المستخدم وكلمة السّر يُشبه ما يلي: إن أدخلنا الاعتمادات الصحيحة سيتم السماح لنا بالنفاذ إلى المحتوى، وإن أدخلنا الاعتمادات الخاطئة أو ضغطنا على إلغاء Cancel سنشاهد صفحة الخطأ "Authorization Required": الخاتمة يجب أن يكون لدينا الآن كل ما نحتاجه لإعداد استيثاق أساسي لموقعنا، فلنضع في اعتبارنا أنّ حماية كلمة السّر يجب أن تكون جنبًا إلى جنب مع تشفير SSL كي لا يتم إرسال اعتماداتنا إلى الخادوم في شكل نص مُجرَّد plain text، يمكنك الإطلاع أيضا على كيفيّة إنشاء شهادة SSL موقّعة ذاتيًّا لاستخدامها مع Apache. ترجمة -وبتصرّف- لـ How To Set Up Password Authentication with Apache on Ubuntu 14.04 لصاحبه Justin Ellingwood. حقوق الصورة البارزة: Designed by Freepik.
  7. عند إعداد خادوم ويب توجد غالبًا أقسام من الموقع نرغب بتقييد الوصول إليها، تُوفِّر تطبيقات الويب عادةً طرق التصريح authorization والاستيثاق authentication الخاصّة بها، ولكن يُمكِن استخدام خادوم الويب بذاته لتقييد الوصول إن كانت هذه الطّرق غير كافية أو غير متوفّرة. سنشرح في هذا الدّرس كيف نحمي الممتلكات assets باستخدام كلمة سر على خادوم ويب Nginx يعمل على Ubuntu. المتطلبات الأساسيةنحتاج للوصول إلى بيئة خادوم Ubuntu لكي نبدأ، نحتاج أيضًا لمستخدم غير جذري non-root مع صلاحيّات sudo من أجل تنفيذ مهام إداريّة administrative، لكي تتعلّم كيفيّة إعداد مستخدم بامتيازات sudo اتبع دليلنا للإعداد الأولي لخادوم Ubuntu 14.04. إن لم نقم مُسبقًا بتثبيت Nginx نستطيع تثبيته على جهازنا بكتابة ما يلي: sudo apt-get update sudo apt-get install nginxإنشاء ملف كلمات السرللبدء نحتاج لإنشاء الملف الذي سيحمل تركيبات أسماء المستخدمين وكلمات السّر، نستطيع فعل ذلك باستخدام أدوات OpenSSL المساعدة التي ربّما تكون متوفّرة مُسبقًا على خادومنا، وبشكلٍ بديل نستطيع استخدام الأداة المساعدة htpasswd المُصمّمة لهذا الغرض والمُضمّنة في الحِزمة apache2-utils (تستخدم ملفّات كلمات سر Nginx نفس الصّيغة التي تستخدمها Apache)، بإمكانك اختيار الطّريقة التي تفضّلها. إنشاء ملف كلمات السر باستخدام أدوات OpenSSL المساعدةإن كُنّا نملك OpenSSL مُثبتًا على خادومنا فبإمكاننا إنشاء ملف كلمات سر بدون أي حِزَم إضافيّة. سنقوم بإنشاء ملف مخفي يُدعى htpasswd. في دليل الإعدادات etc/nginx/ لتخزين تركيبات أسماء المستخدمين وكلمات السّر. نستطيع إضافة اسم مستخدم إلى هذا الملف باستخدام هذا الأمر، سنختار الاسم sammy ليكون اسم مستخدم لدينا، ولكن تستطيع استخدام أي اسم ترغب به: sudo sh -c "echo -n 'sammy:' >> /etc/nginx/.htpasswd"سنقوم بعد ذلك بإضافة كلمة سر مُشفّرة encrypted لاسم المستخدم بكتابة ما يلي: sudo sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd"نستطيع إعادة هذه العمليّة من أجل أسماء مستخدمين آخرين، وبإمكاننا أن نرى كيف يتم تخزين أسماء المستخدمين وكلمات السّر المُشفّرة داخل الملف بكتابة ما يلي: cat /etc/nginx/.htpasswd sammy:$apr1$wI1/T0nB$jEKuTJHkTOOWkopnXqC1d1إنشاء ملف كلمات السر باستخدام الأدوات المساعدة لـ Apacheفي حين أنّ OpenSSL تستطيع تشفير كلمات السّر من أجل استيثاق Nginx، يجد معظم المستخدمين أنّه من الأسهل استخدام أداة مُساعِدة مبنيّة لهذا الغرض، تقوم الأداة المُساعِدة htpasswd الموجودة في الحزمة apache2-utils بتخديم هذا الأمر بشكل جيّد. نُثبِّت الحِزمة apache2-utils على خادومنا بكتابة ما يلي: sudo apt-get update sudo apt-get install apache2-utilsوالآن بعد أن أصبح بإمكاننا الوصول للأمر htpasswd نستطيع استخدامه لإنشاء ملف كلمات السّر الذي يستخدمه خادوم Nginx من أجل استيثاق المستخدمين، سنقوم بإنشاء ملف مخفي لهذا الغرض يُدعى htpasswd. بداخل دليل الإعدادات etc/nginx/. عند استخدام هذه الأداة لأوّل مرّة نحتاج لإضافة الخيار c- لإنشاء الملف المُحدَّد، نقوم بتحديد اسم مستخدم (في هذا المثال sammy) في نهاية الأمر لإنشاء مُدخَل جديد بداخل الملف: sudo htpasswd -c /etc/nginx/.htpasswd sammyسيتم سؤالنا عن تزويد كلمة سر وتأكيدها للمستخدم. نترك الوسيط c- لأي مستخدمين آخرين نرغب في إضافتهم: sudo htpasswd /etc/nginx/.htpasswd another_userإن قمنا بمشاهدة محتويات الملف نستطيع رؤية اسم المستخدم وكلمة السّر المُشفّرة لكل تسجيل record: cat /etc/nginx/.htpasswdsammy:$apr1$lzxsIfXG$tmCvCfb49vpPFwKGVsuYz. another_user:$apr1$p1E9MeAf$kiAhneUwr.MhAE2kKGYHK.إعداد استيثاق كلمة السر لخادوم Nginxالآن وبعد أن أصبحنا نمتلك ملف لأسماء المستخدمين وكلمات السّر في صيغة يستطيع خادوم Nginx قراءتها، نحتاج لإعداد Nginx لكي يتفحّص هذا الملف قبل تخديم محتوانا المحمي. نبدأ بفتح ملف إعدادات الحجب للخادوم والذي نرغب في إضافة تقييد restriction له، سنستخدم في مثالنا هذا ملف الخادوم الافتراضي default للحجب والمُثبَّت عبر حزمة Nginx في Ubuntu: sudo nano /etc/nginx/sites-enabled/defaultينبغي أن يبدو المحتوى داخل الملف مُشابِهًا لما يلي بعد إزالة التّعليقات: /etc/nginx/sites-enabled/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; } }نحتاج لإعداد الاستيثاق أن نقرّر السياق context الذي نريد تقييده، يسمح لنا Nginx من بين الخيارات الأخرى بتعيين التقييد على مستوى الخادوم أو بداخل موقع مُحدَّد، سنقوم في مثالنا بتقييد كامل المستند root بحجب على المكان، ولكن بإمكانك تعديل هذه القائمة لكي تستهدف فقط دليل مُحدَّد ضمن مجال الويب. نستخدم ضمن هذا الحجب على المكان الأمر التوجيهي auth_basic لتشغيل الاستيثاق واختيار اسم نطاق ليتم عرضه للمستخدم عند المطالبة بالاعتمادات credentials، سنستخدم الأمر التوجيهي auth_basic_user_file لكي يشير لخادوم Nginx إلى ملف كلمات السّر الذي أنشأناه: /etc/nginx/sites-enabled/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; auth_basic "Restricted Content"; auth_basic_user_file /etc/nginx/.htpasswd; } }بعد أن ننتهي نحفظ ونغلق الملف، نعيد تشغيل خادوم Nginx لتنفيذ سياسة policy كلمات السّر لدينا: sudo service nginx restartيجب أن يكون الدليل الذي حددناه محميًّا الآن بكلمة سر. تأكيد استيثاق كلمة السرللتأكّد من أنّ المحتوى محمي لدينا نُجرِّب النفاذ إلى المحتوى المُقيَّد من متصفّح إنترنت، يجب أن يتم عرض مُحث prompt لاسم المستخدم وكلمة السّر يُشبه ما يلي: إن أدخلنا الاعتمادات الصحيحة سيتم السماح لنا بالنفاذ إلى المحتوى، وإن أدخلنا الاعتمادات الخاطئة أو ضغطنا على إلغاء Cancel سنشاهد صفحة الخطأ "Authorization Required": الخاتمةيجب أن يكون لدينا الآن كل ما نحتاجه لإعداد استيثاق أساسي لموقعنا، فلنضع في اعتبارنا أنّ حماية كلمة السّر يجب أن تكون جنبًا إلى جنب مع تشفير SSL كي لا يتم إرسال اعتماداتنا إلى الخادوم في شكل نص مُجرَّد plain text، يمكنك الإطلاع أيضا على كيفيّة إنشاء شهادة SSL موقّعة ذاتيًّا لاستخدامها مع Nginx. ترجمة -وبتصرّف- للمقال: How To Set Up Password Authentication with Nginx on Ubuntu 14.04 لصاحبه Justin Ellingwood. حقوق الصورة البارزة: Designed by Freepik.
  8. من المهم عند العمل على خادوم ويب تنفيذ تدابير أمنيّة لحماية موقعنا ومستخدمينا، إنّ حماية مواقع الإنترنت والتّطبيقات لدينا باستخدام سياسات الجّدار النّاري firewall policies وتقييد الوصول إلى بعض المناطق باستخدام استيثاق كلمة السّر password authentication هو نقطة بدء رائعة لتأمين النظام لدينا، ومع ذلك من المُرجَّح أن يجذب أي طلب لكلمة السّر مُتاح للعوام محاولات القوة القاسية brute force من قبل المستخدمين والروبوتات bots الخبيثين. يتمكّن إعداد fail2ban من المساعدة في الحد من هذه المشكلة، فعندما يفشل المستخدمون بالاستيثاق إلى خدمة ما بشكلٍ متكرّر (أو الانخراط في أي نشاط مشبوه آخر) تستطيع fail2ban أن تصدر حظرًا مؤقّتًا على عنوان IP المُهاجِم عن طريق التّعديل بشكل ديناميكي على سياسة الجّدار النّاري التي تعمل حاليًّا. تعمل كل "jail" تابعة لـ fail2ban عن طريق تفحّص السّجلّات المكتوبة من قبل خدمة ما بحثًا عن أنماط patterns تُشير إلى محاولات فاشلة بالاستيثاق. من السّهل إعداد fail2ban لكي تراقب سجلّات Apache باستخدام مُرشِّحات filters الإعداد المُضمَّنة. سنشرح في هذا الدّرس كيفيّة تثبيت fail2ban وإعدادها لمراقبة سجلّات Apache بحثًا عن محاولات التّسلّل، سنستخدم خادوم Ubuntu من أجل هذا. المتطلبات الأساسيةينبغي قبل أن نبدأ أن نمتلك خادوم Ubuntu مع إعداد حساب غير جذري non-root، ويجب أن يكون هذا الحساب مُعدًّا بامتيازات sudo من أجل إصدار أوامر إداريّة administrative commands. لكي تتعلّم كيفيّة إعداد مستخدم بامتيازات sudo اتبع دليلنا للإعداد الأولي لخادوم Ubuntu 14.04. تثبيت Apache وإعداد استيثاق كلمة السرإن كنتَ مهتمًّا بحماية خادوم Apache باستخدام fail2ban فمن الغالب أنك تملك مسبقًا خادومًا مُعدًّا وقيد التشغيل، وإن لم تكن كذلك تستطيع تثبيت Apache من خلال مستودعات Ubuntu الافتراضيّة باستخدام apt. فلنقم بتحديث دليل الحِزَم المحلّي وتثبيت Apache بكتابة ما يلي: sudo apt-get update sudo apt-get install apache2إنّ خدمة fail2ban مفيدة من أجل حماية نقاط تسجيل الدخول، ومن أجل أن يكون هذا مفيدًا لتثبيت Apache يجب تنفيذ استيثاق كلمة السّر على الأقل لمجموعة فرعيّة من المحتوى على الخادوم، تستطيع اتباع هذا الدّليل لإعداد حماية كلمة السّر من أجل خادوم Apache لديك. تثبيت Fail2Banبعد أن أصبح خادوم Apache لدينا قيد التّشغيل وتمّ تمكين استيثاق كلمة السّر عليه نستطيع المضي قدمًا وتثبيت fail2ban (نقوم هنا بإدراج إعادة جلب للمستودع مرّة أخرى في حال قمتَ بالفعل بتثبيت Apache في الخطوات السّابقة): sudo apt-get update sudo apt-get install fail2banسيقوم هذا بتثبيت برمجيّة fail2ban، والتي هي مُعدَّة افتراضيًّا لكي تحظر فقط محاولات تسجيل دخول SSH الفاشلة، نحتاج إلى تمكين بعض القواعد التي تقوم بإعدادها لكي تتفحّص سجلّات Apache لدينا بحثًا عن أنماط تشير إلى نشاط خبيث. ضبط الإعدادات العامة داخل Fail2Banنحتاج لكي نبدأ إلى ضبط ملف الإعدادات الذي تستخدمه fail2ban لتحديد سجلّات التطبيقات التي يجب أن تراقبها والإجراءات التي يجب أن يتمّ اتخاذها عند إيجاد مُدخلات مُخالِفة، ومن الموارد الرئيسيّة التي يتم تزويدنا بها لهذا الأمر نجد الملف etc/fail2ban/jail.conf/. ولإجراء التعديلات نحتاج إلى نسخ هذا الملف إلى etc/fail2ban/jail.local/، وهذا يمنع الكتابة فوق التغييرات التي أجريناها إن قام تحديث الحِزمة package بتزويدنا بملف جديد افتراضي: sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localنقوم بفتح الملف الجديد المنسوخ حتى نستطيع إعداد مراقبة سجلّات Apache لدينا: sudo nano /etc/fail2ban/jail.local تغيير الإعدادات الافتراضيةينبغي أن نبدأ بتقييم المجموعة الافتراضيّة داخل الملف لنرى إن كانت تُلائِم احتياجاتنا، نستطيع إيجاد هذه المجموعة تحت قسم [DEFAULT] داخل الملف. تقوم هذه العناصر بتعيين السّياسة policy العامّة وبإمكاننا تجاوز أي منها في jails مُحدّدة. ومن أوائل العناصر التي يجب أن ننظر إليها هي قائمة العُمَلاء Clients التي لا تخضع لسياسات fail2ban، ويتم تعيينها باستخدام الأمر التّوجيهي ignoreip، من الجّيد أحيانًا إضافة عنوان IP الخاص بنا أو بشبكتنا إلى قائمة الاستثناءات لتجنّب حظر أنفسنا، على الرّغم من أنّ هذا أقل من أن يكون مشكلة مع تسجيلات الدّخول إلى خادوم الويب إن كان بإمكاننا المحافظة على النفاذ للـ Shell، حيث أنّنا دائمًا نستطيع إلغاء الحظر يدويًّا. نستطيع إضافة عناوين IP أو شبكات إضافيّة بفصلها بمسافة Space إلى القائمة الحاليّة: etc/fail2ban/jail.local/ [DEFAULT] . . . ignoreip = 127.0.0.1/8 your_home_IPومن العناصر الأخرى التي قد نرغب بضبطها نجد bantime والذي يتحكّم بعدد الثّواني التي سيتم خلالها حظر العضو المُخالِف، من المثالي تعيينه إلى مدّة طويلة كافية لتكون مُدمِّرة لجهود المستخدم الخبيث، وفي نفس الوقت قصيرة بما فيه الكفاية لتسمح للمستخدمين الشرعيّين لتصحيح أخطائهم، يتم تعيين هذه القيمة افتراضيًّا إلى 600 ثانية (10 دقائق)، قم بزيادتها أو إنقاصها على النحو الذي تراه مناسبًا: etc/fail2ban/jail.local/ [DEFAULT] . . . bantime = 3600يُحدّد العنصران التّاليان نطاق أسطر السّجلّات المستخدمة لتحديد العميل المُخالِف، يُحدِّد findtime المدّة الزمنية مُقدّرةً بالثواني ويُشير الأمر التّوجيهي maxretry إلى عدد المحاولات التي يتم التسامح معها خلال تلك المدّة، فإن قام العميل بعدد محاولات أكثر من maxretry خلال المدّة الزمنيّة المُحدّدة بواسطة findtime فسيتمّ حظره: etc/fail2ban/jail.local/ [DEFAULT] . . . findtime = 3600 # These lines combine to ban clients that fail maxretry = 6 # to authenticate 6 times within a half hour.إعداد تنبيهات البريد الإلكتروني (اختياري)نستطيع تمكين تنبيهات البريد الإلكتروني إن كُنّا نرغب باستقبال بريد كلّما حدث حظر، ويتوجب علينا أولًا لفعل هذا أن نقوم بإعداد MTA على خادومنا بحيث يستطيع إرسال بريد إلكتروني، لتتعلّم كيفيّة استخدام Postfix من أجل هذه المهمّة اتبع هذا الدّليل. ويتوجّب علينا بعد الانتهاء من إعداد MTA أن نقوم بضبط بعض الإعدادات الإضافيّة داخل القسم [DEFAULT] من الملف etc/fail2ban/jail.local/. نبدأ بإعداد الأمر التّوجيهي mta، فإن قمنا بإعداد Postfix -كما هو واضح في الدّرس التعليمي المذكور بالأعلى- نُغيّر هذه القيمة إلى “mail”: etc/fail2ban/jail.local/ [DEFAULT] . . . mta = mailيجب أن نختار عنوان البريد الإلكتروني الذي سيتم إرسال التنبيهات إليه ونكتبه داخل الأمر التّوجيهي destemail، بإمكاننا استخدام الأمر التّوجيهي sendername لتعديل حقل المُرسِل Sender في تنبيهات البريد الإلكتروني: etc/fail2ban/jail.local/ [DEFAULT] . . . destemail = youraccount@email.com sendername = Fail2BanAlertsإنّ الإجراء action -بحسب تعبير fail2ban- هو العمليّة التي تتلو فشل العميل بالاستيثاق مرات كثيرة، الإجراء الافتراضي (يُدعى _action) هو ببساطة حظر عنوان الـ IP من المنفذ port قيد الطلب، ويوجد على أيّة حال إجراءان آخران مُعدّان مُسبقًا يُمكن استخدامهما إن كنّا نملك إعداد بريد إلكتروني. نستطيع استخدام الإجراء action_mw لحظر العميل وإرسال تنبيه بريد إلكتروني إلى الحساب المضبوط لدينا مع تقرير “whois” حول عنوان المُخالِف، بإمكاننا أيضًا استخدام الإجراء action_mwl والذي يقوم بنفس العمل ولكن يقوم بتضمين سطور سجلّات المُخالِف والتي قامت بإطلاق عمليّة الحظر: etc/fail2ban/jail.local/ [DEFAULT] . . . action = %(action_mwl)sإعداد Fail2Ban لمراقبة سجلات Apacheبعد أن قمنا بضبط بعض إعدادات fail2ban العامّة في مكانها الصحيح نستطيع التركيز على تمكين بعض jails المرتبطة بـ Apache والتي ستراقب سجلّات خادوم الويب لدينا بحثًا عن أنماط سلوك مُعيّن. تتميّز كل jails داخل ملف الإعدادات بترويسة header تحتوي اسم الـ jail بين قوسين مربّعين (كل قسم يشير إلى إعدادات jail مُحدّدة ما عدا القسم [DEFAULT])، وافتراضيًّا نجد ssh] jail] هي الوحيدة المُمكّنة. لتمكين مراقبة السّجلّات بحثًا عن محاولات تسجيل دخول Apache سنقوم بتمكين [jail [apache، نُعدّل الأمر التّوجيهي enabled داخل هذا القسم بحيث يصبح true: etc/fail2ban/jail.local/ [apache] enabled = true port = http,https filter = apache-auth logpath = /var/log/apache*/*error.log maxretry = 6 . . .إن كان خادوم Apache يقوم بالكتابة إلى موقع السّجلّات الافتراضي (var/log/apache/error.log/) تكون jail مُعدّة مُسبقًا للبحث في المكان المناسب، وإن كُنّا نقوم بوضع السّجلّات في مكان آخر نُعدِّل مسار السّجل logpath حسب الحاجة، لا تتردد في ضبط الأمر التّوجيهي maxretry أو إضافة قيمة findtime لهذه الـ jail إن كنت ترغب في وضع قيود أخرى لهذه الـ jail تحديدًا: etc/fail2ban/jail.local/ [apache] enabled = true port = http,https filter = apache-auth logpath = /var/log/apache/custom_log_location.log maxretry = 3 findtime = 600 . . .تهتم jail السابقة بأمر حظر فشل الاستيثاق الأساسي، توجد أيضًا بعض jails التي تستحق تمكينها (إنّ jail التي تُدعى [apache-multiport] هي jail تراثيّة legacy لا نحتاج إليها). تُستَخدم jail التي تُدعى [apache-noscript] لحظر العُملاء الذين يبحثون عن تنفيذ واستغلال scripts على الموقع، إن لم نكن نستخدم PHP أو أيّة لغة برمجة أخرى بالتزامن مع خادوم الويب لدينا فبإمكاننا تمكين هذه الـ jail لحظر هؤلاء العملاء الذين يطلبون هذا النوع من الموارد: etc/fail2ban/jail.local/ [apache-noscript] enabled = true . . .تُستخدَم jail التي تُدعى [apache-overflows] لحظر العملاء الذين يحاولون طلب روابط URLs طويلة غير معتادة ومثيرة للشك، والتي تكون عادةً إشارة لمحاولات استغلال Apache عن طريق محاولة تحريض حدوث buffer overflow. بإمكاننا تمكين هذه الـ jail إن أردنا منع هذا النوع من الهجمات: etc/fail2ban/jail.local/ [apache-overflows] enabled = true . . .نستطيع القيام بفحوصات إضافيّة للتحقّق عن طريق نسخ ولصق المدخلة entry التي تُدعى [apache-overflows] وتعديلها قليلًا، فعلى سبيل المثال بإمكاننا نسخ ولصق هذا القسم وتعديل اسم الـ jail والمُرشِّح filter إلى apache-badbots لإيقاف بعض نماذج طلبات الروبوتات bots الخبيثة المعروفة: etc/fail2ban/jail.local/ [apache-overflows] enabled = true port = http,https filter = apache-overflows logpath = /var/log/apache*/*error.log maxretry = 2 [apache-badbots] enabled = true port = http,https filter = apache-badbots logpath = /var/log/apache*/*error.log maxretry = 2إن لم نكن نستخدم Apache لتزويدنا بالنفاذ إلى محتوى الويب داخل دليل المستخدمين الرئيسي فبإمكاننا نسخ ولصق ما سبق مرةً أخرى وتغيير أسماء الـ jail والمُرشِّح إلى apache-nohome: etc/fail2ban/jail.local/ [apache-overflows] enabled = true port = http,https filter = apache-overflows logpath = /var/log/apache*/*error.log maxretry = 2 [apache-badbots] enabled = true port = http,https filter = apache-badbots logpath = /var/log/apache*/*error.log maxretry = 2 [apache-nohome] enabled = true port = http,https filter = apache-nohome logpath = /var/log/apache*/*error.log maxretry = 2وأخيرًا إن كُنّا نستخدم Apache مع PHP فقد نرغب بتمكين jail التي تُدعى [php-url-fopen] والتي تقوم بحجب محاولات استخدام سلوك PHP مُحدَّد لأغراض خبيثة، من المحتمل أن يتوجّب علينا تغيير الأمر التّوجيهي logpath لكي يشير إلى مسار السّجلّات الصحيح (المسار الافتراضي على Ubuntu هو var/log/apache2/access.log/)، نستطيع استخدام نموذج مشابه للنموذج الذي يوافق سجل الأخطاء في jails الأخرى: etc/fail2ban/jail.local/ [php-url-fopen] enabled = true port = http,https filter = php-url-fopen logpath = /var/www/apache*/*access.logعندما ننتهي من التّعديلات التي نحتاجها نقوم بحفظ وإغلاق الملف. تنفيذ Apache Jails لدينالكي يتم تنفيذ تغييراتنا على الإعدادات نحتاج إلى إعادة تشغيل خدمة fail2ban، نستطيع فعل ذلك بكتابة ما يلي: sudo service fail2ban restartينبغي أن يتم إعادة تشغيل الخدمة وتنفيذ سياسات الحظر المختلفة التي قمنا بإعدادها. الحصول على معلومات حول Jails التي تم تمكينهانستطيع رؤية جميع jails التي تمّ تمكينها لدينا باستخدام الأمر fail2ban-client: sudo fail2ban-client statusينبغي أن نشاهد قائمة بكامل jails التي قمنا بتمكينها: Status |- Number of jail: 7 `- Jail list: php-url-fopen, apache-overflows, apache-noscript, ssh, apache-badbots, apache-nohome, apacheنستطيع أن نرى قيام fail2ban بتعديل قواعد الجّدار النّاري لدينا لإنشاء إطار عمل لمنع العملاء، وحتى بدون قواعد الجّدار النّاري السابقة سيكون لدينا الآن إطار عمل مُمكّن يسمح لـ fail2ban بحظر العملاء انتقائيًّا عن طريق إضافتهم إلى سلاسل chains مبنيّة لهذا الغرض: sudo iptables -S-P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT -N fail2ban-apache -N fail2ban-apache-badbots -N fail2ban-apache-nohome -N fail2ban-apache-noscript -N fail2ban-apache-overflows -N fail2ban-php-url-fopen -N fail2ban-ssh -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-apache-nohome -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-apache-badbots -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-php-url-fopen -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-apache-overflows -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-apache-noscript -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-apache -A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh -A fail2ban-apache -j RETURN -A fail2ban-apache-badbots -j RETURN -A fail2ban-apache-nohome -j RETURN -A fail2ban-apache-noscript -j RETURN -A fail2ban-apache-overflows -j RETURN -A fail2ban-php-url-fopen -j RETURN -A fail2ban-ssh -j RETURNوإن أردنا رؤية تفاصيل حظر مُطبَّق من قبل أي jail فمن الأسهل ربّما استخدام الأمر fail2ban-client مرة أخرى: sudo fail2ban-client status apacheStatus for the jail: apache |- filter | |- File list: /var/log/apache2/error.log | |- Currently failed: 0 | `- Total failed: 0 `- action |- Currently banned: 0 | `- IP list: `- Total banned: 0اختبار سياسات Fail2Banمن الهام اختبار سياسات fail2ban لكي نتأكّد من أنها تقوم بحظر نقل البيانات كما هو متوقّع، على سبيل المثال نستطيع إعطاء بيانات خاطئة في مُحث prompt استيثاق Apache عدّة مرات، وبعد أن نتجاوز الحدّ ينبغي أن يتم حظرنا وألا نكون قادرين على الوصول للموقع، وإن قمنا بإعداد تنبيهات البريد الإلكتروني فيجب أن نرى رسائل حول الحظر في البريد الإلكتروني الذي قمنا باختياره لاستقبال التّنبيهات. عندما ننظر إلى الحالة باستخدام الأمر fail2ban-client سنشاهد أنّ عنوان IP الخاص بنا يتم حظره من الموقع: sudo fail2ban-client status apacheStatus for the jail: apache |- filter | |- File list: /var/log/apache2/error.log | |- Currently failed: 0 | `- Total failed: 12 `- action |- Currently banned: 1 | `- IP list: 111.111.111.111 `- Total banned: 1وعندما نكون مقتنعين بأنّ قواعدنا تعمل بشكل صحيح نستطيع فك الحظر يدويًّا عن عنوان IP الخاص بنا عن طريق الأمر fail2ban-client بكتابة ما يلي: sudo fail2ban-client set apache unbanip 111.111.111.111ينبغي أن نكون الآن قادرين على محاولة الاستيثاق مرة أخرى. الخاتمةإنّ إعداد fail2ban لحماية خادوم Apache لدينا هو عمليّة سهلة إلى حدٍّ ما في أبسط الحالات، توفّر fail2ban على أيّة حال قدرًا كبيرًا من المرونة لبناء سياسات تُلائِم احتياجاتنا الأمنيّة، وبإلقاء نظرة على المتغيّرات والأنماط داخل الملف etc/fail2ban/jail.local/ والملفات التي يعتمد عليها داخل الدّليل etc/fail2ban/filter.d/ والدّليل etc/fail2ban/action.d/ نجد العديد من الأجزاء التي يمكننا تطويعها tweak وتغييرها لكي تلبّي احتياجاتنا، إنّ تعلّم أساسيّات كيفيّة حماية خادومنا باستخدام fail2ban يزوّدنا بقدرٍ كبير من الأمان وبأقل جهد. إن كنت ترغب في تعلّم المزيد حول fail2ban قم بزيارة الروابط التالية: كيف تعمل Fail2Ban لحماية الخدمات على خادوم لينِكسكيفيّة حماية SSH باستخدام Fail2Ban على Ubuntu 14.04كيفيّة حماية خادوم Nginx باستخدام Fail2Banعلى Ubuntu 14.04ترجمة -وبتصرّف- للمقال How To Protect an Apache Server with Fail2Ban on Ubuntu 14.04 لصاحبه Justin Ellingwood.
  9. إنّ Redis هي عبارة عن ذاكرة مؤقتة cache بنمط مفتاح-قيمة key-value ومَخزَن في الذاكرة (أي قاعدة بيانات) والتي يمكن نقلها وحفظها بشكل دائم على القرص، سنشرح في هذا الدّرس كيفيّة النّسخ الاحتياطي لقاعدة بيانات Redis على خادوم Ubuntu. يتم حفظ بيانات Redis بشكل افتراضي إلى القرص في ملف rdb.، والذي هو لقطة snapshot لنقطة في الوقت المناسب لمجموعة بيانات Redis لدينا، يتم عمل اللقطة في فواصل مُحدّدة، ويكون هذا رائعًا من أجل النسخ الاحتياطيّة لدينا. المتطلبات الأساسيةسنحتاج لإكمال الخطوات في هذا الدّرس إلى: خادوم Ubuntu.تنصيب redis، تستطيع اتباع الإعداد الرئيسي master في هذا الدّرس لإعداد Redis (بالرغم من أنّه سيعمل بشكل جيّد مع عنقود تابع ومتبوع master-slave cluster).التحقق من أنّ خادوم Redis قيد التشغيل لدينا.إن تمّ تعيين كلمة سر لخادوم Redis -والذي ننصح به بشدّة- يكون ذلك مفيدًا، توجد كلمة السّر في ملف الإعدادات /etc/redis/redis.confالخطوة الأولى – إيجاد دليل بيانات Redisتقوم Redis بتخزين بياناتها إلى دليل على خادومنا، وهو ما نريده من أجل النّسخ الاحتياطي، نحتاج في البداية لمعرفة مكان هذا الدّليل. يوجد دليل قاعدة بيانات Redis في Ubuntu وتوزيعات لينِكس الأخرى في المسار var/lib/redis/، ولكن إن كُنّا ندير خادوم تم تغيير مكان بيانات Redis فيه، نستطيع تحديد مكانه بكتابة ما يلي: sudo locate *rdbوبإمكاننا بشكل بديل إيجاده عن طريق المُحث prompt الذي يُدعى redis-cli، ولفعل هذا نكتب ما يلي: redis-cliإن لم يكن خادوم Redis قيد التشغيل ستكون الاستجابة التي سنتلقاها هي: Could not connect to Redis at 127.0.0.1:6379: Connection refused not connected>وفي هذه الحالة نقوم بتشغيل Redis وإعادة الاتصال باستخدام الأوامر التالية: sudo service redis-server startredis-cliسيتغير مُحث الـ Shell إلى: 127.0.0.1:6379>في الوقت الذي نكون متصلين فيه إلى Redis سيقوم الأمران التاليان بالاستيثاق authenticate معه والحصول على دليل البيانات: 127.0.0.1:6379> auth insert-redis-password-here 127.0.0.1:6379> 127.0.0.1:6379> config get dirيجب أن يكون خَرْج الأمر الأخير هو دليل بيانات Redis لدينا: 1) "dir" 2) "/var/lib/redis"نلاحظ دليل Redis لدينا فإن كان مختلفًا عن الدّليل الظاهر هنا فيجب أن نحرص على استعماله خلال هذا الدّرس. نستطيع الآن الخروج من واجهة سطر الأوامر لقاعدة البيانات: 127.0.0.1:6379> exitنتحقّق من أنّ هذا هو الدّليل الصحيح: ls /var/lib/redisينبغي أن نرى ملف dump.rdb وهو عبارة عن بيانات Redis، إن تمّ تمكين appendonly فسنرى ملف يُدعى appendonly.aof أو حتى أي ملف aof. آخر، والذي يحتوي على سجل لجميع عمليّات الكتابة التي تم تلقّيها بواسطة الخادوم. قم بقراءة هذا المنشور حول استمرار Redis persistence من أجل النقاش حول الاختلافات بين هذين الملفين. بشكل مُبسَّط فإنّ الملف rdb. هو اللقطة الحاليّة، والملف aof. يقوم بحفظ تاريخ Redis، وكلاهما يستحقّان أخذ نسخة احتياطيّة عنهما. سنبدأ فقط بالملف rdb. وننتهي بنسخة احتياطيّة تلقائيّة لكلا الملفين. الخطوة الثانية (اختيارية) – إضافة عينة sample بياناتسنقوم في هذا القسم بإنشاء عيّنة بيانات لتخزينها في قاعدة بيانات Redis، إن كنتَ تملك مٌسبقًا بيانات على خادومك تستطيع النسخ الاحتياطي للمحتوى الموجود حاليًّا. نقوم بتسجيل الدخول من خلال واجهة سطر الأوامر لقاعدة البيانات: redis-cliنقوم بالاستيثاق بكتابة ما يلي: 127.0.0.1:6379> auth insert-redis-password-hereفلنقم بإضافة عيّنة بيانات، يجب أن نتلقّى استجابة OK بعد كل خطوة. 127.0.0.1:6379> SET shapes:triangles "3 sides" 127.0.0.1:6379> 127.0.0.1:6379> SET shapes:squares "4 sides"نتأكّد من أنّه تمّت إضافة البيانات: 127.0.0.1:6379> GET shapes:triangles 127.0.0.1:6379> 127.0.0.1:6379> GET shapes:squaresوهذا هو الخَرْج output الذي يجب أن نحصل عليه: "3 sides" "4 sides"ولفرض هذه التغييرات على الملف var/lib/redis/dump.rdb/ نقوم بحفظهم: 127.0.0.1:6379> saveنستطيع الآن الخروج: 127.0.0.1:6379> exitبإمكاننا الآن إن كُنّا نرغب التّحقّق من محتويات الملف dump، يجب أن يحتوي على بياناتنا ولو أنّها في شكل مناسب للآلة أكثر: sudo cat /var/lib/redis/dump.rdb REDIS0006?shapes:squares4 sidesshapes:triangles3 sides??o????Cالخطوة الثالثة – النسخ الاحتياطي لبيانات Redisحان الوقت الآن لعمل نسخة احتياطيّة بعد أن أصبحنا نعلم مكان تواجد بيانات Redis لدينا، نجد هذا الاقتباس من موقع Redis الرّسمي: إذًا نستطيع النسخ الاحتياطي أو نسخ ملف قاعدة البيانات أثناء تشغيل خادوم Redis، وعلى افتراض أنّنا نريد النسخ الاحتياطي لها إلى دليل داخل الدّليل الرئيسي لدينا فإنّ القيام بالنسخ الاحتياطي بسيط بكتابة ما يلي: sudo cp /var/lib/redis/dump.rdb /home/sammy/redis-backup-001يحفظ Redis المحتوى هنا بشكل دوري، ممّا يعني أنّ الأمر السابق غير مضمون بالنسبة لنا وأنّنا لا نملك أحدث نسخة احتياطيّة حتى الدقيقة الأخيرة إن كان كل ما نقوم به هو تشغيل هذا الأمر، نحتاج لحفظ البيانات الخاصّة بنا أولًا. ومع ذلك إن كان من المقبول فقدان كمية صغيرة من البيانات فإنّ النّسخ الاحتياطي لهذا الملف فقط سيعمل بشكل جيّد. حفظ حالة قاعدة البياناتللحصول على نسخة أحدث بكثير من بيانات Redis فمن الأفضل النفاذ إلى redis-cli، سطر أوامر Redis. نقوم بالاستيثاق كما شرحنا في الخطوة الأولى. ثمّ نكتب الأمر حفظ save كما يلي: 127.0.0.1:6379> saveينبغي أن يكون الخَرْج مُشابِهًا لهذا: OK (1.08s)نخرج من قاعدة البيانات. نستطيع الآن تشغيل الأمر cp السّابق واثقين من أنّ النسّخة الاحتياطيّة هي أحدث نسخة حتى الآن بشكل كامل. بينما يُزوِّدنا الأمر cp بنسخة احتياطيّة مرّة واحدة من قاعدة البيانات، فإنّ الحل الأنسب هو إعداد وظيفة cron تقوم بأتمتة هذه العمليّة، واستخدام أداة تستطيع تنفيذ تحديثات تزايديّة incremental updates وتستعيد البيانات إن احتجنا لذلك. الخطوة الرابعة – إعداد التحديثات التلقائية باستخدام rdiff-backup وCronسنقوم في هذا القسم بإعداد نسخ احتياطي تلقائي يشمل كامل دليل بيانات Redis لدينا، بما في ذلك كلا ملفي البيانات. توجد العديد من أدوات النسخ الاحتياطي التلقائي المتاحة، سنستخدم أداة جديدة وسهلة الاستخدام تُدعى rdiff-backup. إنّ rdiff-backup هي أداة نسخ احتياطي تعمل عبر سطر الأوامر، من المحتمل أنّ rdiff-backup غير مُثبَّتة على خادومك، لذا يجب عليك تثبيتها أولًا: sudo apt-get install -y rdiff-backupنستطيع الآن بعد تثبيتها أن نختبرها بالنسخ الاحتياطي لبيانات Redis لدينا إلى مجلّد في دليلنا الرئيسي، سنفترض في هذا المثال أنّ الدليل الرئيسي لدينا هو home/sammy/. نلاحظ أنّ الدليل الهدف سيتم إنشاؤه من قبل الـ script إن لم يكن موجودًا، أي بمعنى آخر لا نحتاج إنشاءه بأنفسنا. ومع وجود preserve-numerical-ids-- ستكون الملكيّات نفسها للمجلدات المصدر والوجهة. sudo rdiff-backup --preserve-numerical-ids /var/lib/redis /home/sammy/redisوكما وجدنا مع الأمر cp سابقًا فإنّ هذه نسخة احتياطيّة لمرّة واحدة، ولكنّ الذي تغيّر هو أنّنا نقوم الآن بالنسخ الاحتياطي لكامل الدليل var/lib/redis/ وباستخدام rdiff-backup. سنقوم الآن بأتمتة النّسخ الاحتياطي باستخدام cron بحيث تحدث النسخة الاحتياطيّة في وقت مُحدّد، ولإنجاز هذا نفتح crontab النّظام: sudo crontab -e(إن لم تستخدم crontab على هذا الخادوم من قبل قم باختيار مُحرّر النّصوص المفضل لديك عند سؤالك عنه.) نقوم بإضافة المُدخَل entry التالي في نهاية الملف: 0 0 * * * rdiff-backup --preserve-numerical-ids --no-file-statistics /var/lib/redis /home/sammy/redisسيقوم مُدخَل Cron هذا بعمل نسخة احتياطيّة لـ Redis يوميًّا عند منتصف الليل، سيعطّل التحوّل no-file-statistics-- الكتابة إلى الملف file_statistics في الدّليل rdiff-backup-data، والذي يجعل من rdiff-backup يعمل بشكل أسرع أكثر ويستخدم مساحة قرص أقل بقليل. ونستطيع بشكل بديل استخدام هذا المُدخَل للقيام بنسخ احتياطي يومي: @daily rdiff-backup --preserve-numerical-ids --no-file-statistics /var/lib/redis /home/sammy/redisوكما هو مذكور سيتم عمل نسخة احتياطيّة مرّة في اليوم، لذا بإمكانك العودة غدًا من أجل اختباره لآخر مرّة، أو تستطيع بشكل مؤقّت زيادة وتيرة النّسخ الاحتياطي لكي تتأكّد من أنّه يعمل. ولأنّ الملفّات مملوكة من قبل مستخدم النّظام redis نستطيع التحقّق من أنّها في مكانها باستخدام هذا الأمر.(تأكّد من الانتظار إلى أن يتم تحفيز بدء النسخ الاحتياطي): ls -l /home/sammy/redisينبغي أن يبدو الخَرْج مُشابِهًا لما يلي: total 20 -rw-rw---- 1 redis redis 70 Sep 14 13:13 dump.rdb drwx------ 3 root root 12288 Sep 14 13:49 rdiff-backup-data -rw-r----- 1 redis redis 119 Sep 14 13:09 redis-staging-ao.aofنمتلك الآن نُسَخ احتياطيّة يوميّة لبيانات Redis لدينا مُخزَّنة في الدّليل الرئيسي على نفس الخادوم. الخاتمةإنّ النّسخ الاحتياطي لبيانات Redis بالطرق المذكورة في هذا الدّرس جيّد عندما لا نمانع من النّسخ الاحتياطي للبيانات إلى دليل على نفس الخادوم. يبقى النهج الأكثر أمانًا بالطّبع هو النّسخ الاحتياطي إلى جهاز آخر، تستطيع استكشاف المزيد من خيارات النسخ الاحتياطي بقراءة هذا الدّرس حول النُسَخ الاحتياطيّة: كيفية اختيار استراتيجية فعالة للنسخ الاحتياطي للخادوم الخاص الافتراضي VPS. نستطيع استخدام العديد من طرق النّسخ الاحتياطي هذه مع نفس الملفّات في الدّليل var/lib/redi/. ترجمة -وبتصرّف- لـ How To Back Up Your Redis Data on Ubuntu 14.04 لصاحبه finid.
  10. من المهم عند العمل على خادوم ويب تنفيذ تدابير أمنيّة لحماية موقعنا ومستخدمينا، إنّ حماية مواقع الإنترنت والتّطبيقات لدينا باستخدام سياسات الجّدار النّاري firewall policies وتقييد الوصول إلى بعض المناطق باستخدام استيثاق كلمة السّر password authentication هو نقطة بدء رائعة لتأمين النظام لدينا، ومع ذلك من المُرجَّح أن يجذب أي طلب لكلمة السّر مُتاح للعوام محاولات القوة القاسية brute force من قبل المستخدمين والروبوتات bots الخبيثين. يتمكّن إعداد fail2ban من المساعدة في الحد من هذه المشكلة، فعندما يفشل المستخدمون بالاستيثاق إلى خدمة ما بشكلٍ متكرّر (أو الانخراط في أي نشاط مشبوه آخر) تستطيع fail2ban أن تصدر حظرًا مؤقّتًا على عنوان IP المُهاجِم عن طريق التّعديل بشكل ديناميكي على سياسة الجّدار النّاري التي تعمل حاليًّا. تعمل كل "jail" تابعة لـ fail2ban عن طريق تفحّص السّجلّات المكتوبة من قبل خدمة ما بحثًا عن أنماط patterns تُشير إلى محاولات فاشلة بالاستيثاق. من السّهل إلى حدٍّ ما إعداد fail2ban لكي تراقب سجلّات Nginx باستخدام البعض من مُرشّحات filters الإعداد المُضمَّنة والبعض الآخر الذي سنقوم بكتابته بأنفسنا. سنشرح في هذا الدّرس كيفيّة تثبيت fail2ban وإعدادها لمراقبة سجلّات Nginx بحثًا عن محاولات التّسلّل، سنستخدم خادوم Ubuntu من أجل هذا. المتطلبات الأساسيةينبغي قبل أن نبدأ أن نمتلك خادوم Ubuntu مع إعداد حساب غير جذري non-root، ويجب أن يكون هذا الحساب مُعدًّا بامتيازات sudo من أجل إصدار أوامر إداريّة administrative commands. لكي تتعلّم كيفيّة إعداد مستخدم بامتيازات sudo اتبع دليلنا للإعداد الأولي لخادوم Ubuntu 14.04. تثبيت Nginx وإعداد استيثاق كلمة السرإن كنتَ مهتمًّا بحماية خادوم Nginx باستخدام fail2ban فمن الغالب أنك تملك مسبقًا خادومًا مُعدًّا وقيد التشغيل، وإن لم تكن كذلك تستطيع تثبيت Nginx من خلال مستودعات Ubuntu الافتراضيّة باستخدام apt. فلنقم بتحديث دليل الحِزَم المحلّي وتثبيت Nginx بكتابة ما يلي: sudo apt-get update sudo apt-get install nginxإنّ خدمة fail2ban مفيدة من أجل حماية نقاط تسجيل الدخول، ومن أجل أن يكون هذا مفيدًا لتثبيت Nginx يجب تنفيذ استيثاق كلمة السّر على الأقل لمجموعة فرعيّة من المحتوى على الخادوم، تستطيع اتباع هذا الدّليل لإعداد حماية كلمة السّر من أجل خادوم Nginx لديك. تثبيت Fail2Banبعد أن أصبح خادوم Nginx لدينا قيد التّشغيل وتمّ تمكين استيثاق كلمة السّر عليه نستطيع المضي قدمًا وتثبيت fail2ban (نقوم هنا بإدراج إعادة جلب للمستودع مرّة أخرى في حال قمتَ بالفعل بتثبيت Nginx في الخطوات السّابقة): sudo apt-get update sudo apt-get install fail2banسيقوم هذا بتثبيت برمجيّة fail2ban، والتي هي مُعدَّة افتراضيًّا لكي تحظر فقط محاولات تسجيل دخول SSH الفاشلة، نحتاج إلى تمكين بعض القواعد التي تقوم بإعدادها لكي تتفحّص سجلّات Nginx لدينا بحثًا عن أنماط تشير إلى نشاط خبيث. ضبط الإعدادات العامة داخل Fail2Banنحتاج لكي نبدأ إلى ضبط ملف الإعدادات الذي تستخدمه fail2ban لتحديد سجلّات التطبيقات التي يجب أن تراقبها والإجراءات التي يجب أن يتمّ اتخاذها عند إيجاد مُدخلات مُخالِفة، ومن الموارد الرئيسيّة التي يتم تزويدنا بها لهذا الأمر نجد الملف etc/fail2ban/jail.conf/. ولإجراء التعديلات نحتاج إلى نسخ هذا الملف إلى etc/fail2ban/jail.local/، وهذا يمنع الكتابة فوق التغييرات التي أجريناها إن قام تحديث الحِزمة package بتزويدنا بملف جديد افتراضي: sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localنقوم بفتح الملف الجديد المنسوخ حتى نستطيع إعداد مراقبة سجلّات Nginx لدينا: sudo nano /etc/fail2ban/jail.localتغيير الإعدادات الافتراضيةينبغي أن نبدأ بتقييم المجموعة الافتراضيّة داخل الملف لنرى إن كانت تُلائِم احتياجاتنا، نستطيع إيجاد هذه المجموعة تحت قسم [DEFAULT] داخل الملف. تقوم هذه العناصر بتعيين السّياسة policy العامّة وبإمكاننا تجاوز أي منها في jails مُحدّدة. ومن أوائل العناصر التي يجب أن ننظر إليها هي قائمة العُمَلاء Clients التي لا تخضع لسياسات fail2ban، ويتم تعيينها باستخدام الأمر التّوجيهي ignoreip، من الجّيد أحيانًا إضافة عنوان IP الخاص بنا أو بشبكتنا إلى قائمة الاستثناءات لتجنّب حظر أنفسنا، على الرّغم من أنّ هذا أقل من أن يكون مشكلة مع تسجيلات الدّخول إلى خادوم الويب إن كان بإمكاننا المحافظة على النفاذ للـ Shell، حيث أنّنا دائمًا نستطيع إلغاء الحظر يدويًّا. نستطيع إضافة عناوين IP أو شبكات إضافيّة بفصلها بمسافة Space إلى القائمة الحاليّة: etc/fail2ban/jail.local/ [DEFAULT] . . . ignoreip = 127.0.0.1/8 your_home_IPومن العناصر الأخرى التي قد نرغب بضبطها نجد bantime والذي يتحكّم بعدد الثّواني التي سيتم خلالها حظر العضو المُخالِف، من المثالي تعيينه إلى مدّة طويلة كافية لتكون مُدمِّرة لجهود المستخدم الخبيث، وفي نفس الوقت قصيرة بما فيه الكفاية لتسمح للمستخدمين الشرعيّين لتصحيح أخطائهم، يتم تعيين هذه القيمة افتراضيًّا إلى 600 ثانية (10 دقائق)، قم بزيادتها أو إنقاصها على النحو الذي تراه مناسبًا: etc/fail2ban/jail.local/ [DEFAULT] . . . bantime = 3600يُحدّد العنصران التّاليان نطاق أسطر السّجلّات المستخدمة لتحديد العميل المُخالِف، يُحدِّد findtime المدّة الزمنية مُقدّرةً بالثواني ويُشير الأمر التّوجيهي maxretry إلى عدد المحاولات التي يتم التسامح معها خلال تلك المدّة، فإن قام العميل بعدد محاولات أكثر من maxretry خلال المدّة الزمنيّة المُحدّدة بواسطة findtime فسيتمّ حظره: etc/fail2ban/jail.local/ [DEFAULT] . . . findtime = 3600 # These lines combine to ban clients that fail maxretry = 6 # to authenticate 6 times within a half hourإعداد تنبيهات البريد الإلكتروني (اختياري)نستطيع تمكين تنبيهات البريد الإلكتروني إن كُنّا نرغب باستقبال بريد كلّما حدث حظر، ويتوجب علينا أولًا لفعل هذا أن نقوم بإعداد MTA على خادومنا بحيث يستطيع إرسال بريد إلكتروني، لتتعلّم كيفيّة استخدام Postfix من أجل هذه المهمّة اتبع هذا الدّليل. ويتوجّب علينا بعد الانتهاء من إعداد MTA أن نقوم بضبط بعض الإعدادات الإضافيّة داخل القسم [DEFAULT] من الملف etc/fail2ban/jail.local/. نبدأ بإعداد الأمر التّوجيهي mta، فإن قمنا بإعداد Postfix -كما هو واضح في الدّرس التعليمي المذكور بالأعلى- نُغيّر هذه القيمة إلى “mail”: etc/fail2ban/jail.local/ [DEFAULT] . . . mta = mailيجب أن نختار عنوان البريد الإلكتروني الذي سيتم إرسال التنبيهات إليه ونكتبه داخل الأمر التّوجيهي destemail، بإمكاننا استخدام الأمر التّوجيهي sendername لتعديل حقل المُرسِل Sender في تنبيهات البريد الإلكتروني: etc/fail2ban/jail.local/ [DEFAULT] . . . destemail = youraccount@email.com sendername = Fail2BanAlertsإنّ الإجراء action -بحسب تعبير fail2ban- هو العمليّة التي تتلو فشل العميل بالاستيثاق مرات كثيرة، الإجراء الافتراضي (يُدعى action_) هو ببساطة حظر عنوان الـ IP من المنفذ port قيد الطلب، ويوجد على أيّة حال إجراءان آخران مُعدّان مُسبقًا يُمكن استخدامهما إن كنّا نملك إعداد بريد إلكتروني. نستطيع استخدام الإجراء action_mw لحظر العميل وإرسال تنبيه بريد إلكتروني إلى الحساب المضبوط لدينا مع تقرير “whois” حول عنوان المُخالِف، بإمكاننا أيضًا استخدام الإجراء action_mwl والذي يقوم بنفس العمل ولكن يقوم بتضمين سطور سجلّات المُخالِف والتي قامت بإطلاق عمليّة الحظر: etc/fail2ban/jail.local/ [DEFAULT] . . . action = %(action_mwl)s إعداد Fail2Ban لمراقبة سجلات Nginxبعد أن قمنا بضبط بعض إعدادات fail2ban العامّة في مكانها الصحيح نستطيع التركيز على تمكين بعض jails المرتبطة بـ Nginx والتي ستراقب سجلّات خادوم الويب لدينا بحثًا عن أنماط سلوك مُعيّن. تتميّز كل jails داخل ملف الإعدادات بترويسة header تحتوي اسم الـ jail بين قوسين مربّعين (كل قسم يشير إلى إعدادات jail مُحدّدة ما عدا القسم [DEFAULT])، وافتراضيًّا نجد ssh] jail] هي الوحيدة المُمكّنة. لتمكين مراقبة السّجلّات بحثًا عن محاولات تسجيل دخول Nginx سنقوم بتمكين [jail [nginx-http-auth، نُعدّل الأمر التّوجيهي enabled داخل هذا القسم بحيث يصبح true: etc/fail2ban/jail.local/ [nginx-http-auth] enabled = true filter = nginx-http-auth port = http,https logpath = /var/log/nginx/error.log . . .إنّ jail السّابقة هي jail الوحيدة الخاصّة بـ Nginx التي يتم تضمينها مع حزمة fail2ban الخاصّة بـ Ubuntu. نستطيع على أيّة حال إنشاء jails الخاصّة بنا لإضافة وظائف إضافيّة، نجد في هذا الرابط بعض من تفاصيل تنفيذ jails الإضافيّة هنا وهنا. بإمكاننا إنشاء nginx-noscript] jail] لحظر العملاء الذين يبحثون عن تنفيذ واستغلال Script على الموقع، إن لم نكن نستخدم PHP أو أي لغة برمجة أخرى بالتزامن مع خادوم الويب لدينا فبإمكاننا إضافة هذه الـ jail لحظر من يطلب هذا النوع من الموارد: etc/fail2ban/jail.local/ [nginx-noscript] enabled = true port = http,https filter = nginx-noscript logpath = /var/log/nginx/access.log maxretry = 6 . . .نستطيع إضافة قسم يُدعى [nginx-badbots] لإيقاف بعض أنماط طلبات الروبوتات الخبيثة المعروفة: etc/fail2ban/jail.local/ [nginx-badbots] enabled = true port = http,https filter = nginx-badbots logpath = /var/log/nginx/access.log maxretry = 2وإن لم نكن نستخدم Nginx لتزويدنا بالنفاذ إلى محتوى الويب داخل الدّليل الرئيسي Home directory للمستخدم فبإمكاننا حظر المستخدمين الذين يطلبون هذه الموارد بإضافة nginx-nohome] jail]: etc/fail2ban/jail.local/ [nginx-nohome] enabled = true port = http,https filter = nginx-nohome logpath = /var/log/nginx/access.log maxretry = 2ينبغي علينا حظر العملاء الذين يحاولون استخدام خادوم Nginx لدينا كوسيط مفتوح open proxy، نستطيع إضافة nginx-noproxy] jail] لتتناسب مع هذه الطلبات: etc/fail2ban/jail.local/ [nginx-noproxy] enabled = true port = http,https filter = nginx-noproxy logpath = /var/log/nginx/access.log maxretry = 2بعد أن ننتهي من التعديلات التي نرغب بها نحفظ الملف ونغلقه، يتوجّب علينا الآن إضافة المُرشّحات filters من أجل jails التي قمنا بإنشائها. إضافة المرشحات من أجل Nginx Jails الإضافيةلقد قمنا بتحديث الملف etc/fail2ban/jail.local/ ببعض مواصفات jail الإضافيّة لتتناسب مع حظر مدى كبير من السّلوك السّيء، نحتاج لإنشاء ملفات ترشيح filter من أجل jails التي أنشأناها، حيث تُحدّد هذه الملفات الأنماط التي سنبحث عنها داخل سجلّات Nginx. فلنبدأ بالانتقال إلى دليل المُرشّحات filters: cd /etc/fail2ban/filter.dنريد فعليًّا أن نبدأ بضبط مُرشِّح الاستيثاق المزوّد مُسبقًا مع Nginx لكي يتناسب مع أنماط فشل تسجيل الدّخول الموجودة في السّجلّات، نفتح الملف لتحريره: sudo nano nginx-http-auth.confنُضيف نمط جديد تحت التّخصيص failregex، حيث يتناسب هذا النّمط مع الأسطر التي توافق عدم إدخال المستخدم لاسم مستخدم أو كلمة سر: etc/fail2ban/filter.d/nginx-http-auth.conf/ [Definition] failregex = ^ \[error\] \d+#\d+: \*\d+ user "\S+":? (password mismatch|was not found in ".*"), client: <HOST>, server: \S+, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"\s*$ ^ \[error\] \d+#\d+: \*\d+ no user/password was provided for basic authentication, client: <HOST>, server: \S+, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"\s*$ ignoreregex =بعد الانتهاء نقوم بحفظ وإغلاق الملف. بعد ذلك نستطيع نسخ الملف apache-badbots.conf لاستخدامه مع Nginx، بإمكاننا استخدام الملف كما هو ولكن سنقوم بنسخه إلى اسم آخر من أجل التوضيح، يتطابق هذا مع مرجعيّة المُرشّح التي قمنا بها داخل إعدادات jail: sudo cp apache-badbots.conf nginx-badbots.confننشئ بعد ذلك مُرشّح من أجل nginx-noscript] jail]: sudo nano nginx-noscript.confنلصق التعريف التالي بداخله، ونترك لك الخيار في ضبط اللواحق في الـ Script لكي تزيل ملفّات لغات البرمجة التي يستخدمها الخادوم لديك بشكل شرعي أو لكي تضيف لواحق أخرى: etc/fail2ban/filter.d/nginx-noscript.conf/ [Definition] failregex = ^<HOST> -.*GET.*(\.php|\.asp|\.exe|\.pl|\.cgi|\.scgi) ignoreregex =نقوم بحفظ الملف وإغلاقه. ننشئ بعد ذلك مُرشّحًا من أجل nginx-nohome] jail]: sudo nano nginx-nohome.confنضع معلومات المرشّح التالية في الملف: etc/fail2ban/filter.d/nginx-nohome.conf/ [Definition] failregex = ^<HOST> -.*GET .*/~.* ignoreregex =بعد الانتهاء نقوم بحفظ وإغلاق الملف. بإمكاننا أخيرًا إنشاء المرشّح من أجل nginx-noproxy] jail]: sudo nano nginx-noproxy.confيتوافق تعريف المرشّح مع محاولات استخدام خادومنا كوسيط proxy: etc/fail2ban/filter.d/nginx-noproxy.conf/ [Definition] failregex = ^<HOST> -.*GET http.* ignoreregex =بعد الانتهاء نقوم بحفظ وإغلاق الملف. تفعيل Nginx Jails لدينالكي يتم تنفيذ تغييراتنا على الإعدادات نحتاج إلى إعادة تشغيل خدمة fail2ban، نستطيع فعل ذلك بكتابة ما يلي: sudo service fail2ban restartينبغي أن يتم إعادة تشغيل الخدمة وتنفيذ سياسات الحظر المختلفة التي قمنا بإعدادها. الحصول على معلومات حول Jails التي تم تمكينهانستطيع رؤية جميع jails التي تمّ تمكينها لدينا باستخدام الأمر fail2ban-client: sudo fail2ban-client statusينبغي أن نشاهد قائمة بكامل jails التي قمنا بتمكينها: Status |- Number of jail: 6 `- Jail list: nginx-noproxy, nginx-noscript, nginx-nohome, nginx-http-auth, nginx-badbots, sshنستطيع النظر إلى iptables لكي نرى أنّ fail2ban قامت بتعديل قواعد الجّدار النّاري لدينا لإنشاء إطار عمل لمنع العملاء، وحتى بدون قواعد الجّدار النّاري السابقة سيكون لدينا الآن إطار عمل مُمكّن يسمح لـ fail2ban بحظر العملاء انتقائيًّا عن طريق إضافتهم إلى سلاسل chains مبنيّة لهذا الغرض: sudo iptables -S-P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT -N fail2ban-nginx-badbots -N fail2ban-nginx-http-auth -N fail2ban-nginx-nohome -N fail2ban-nginx-noproxy -N fail2ban-nginx-noscript -N fail2ban-ssh -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-noproxy -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-nohome -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-badbots -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-noscript -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-http-auth -A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh -A fail2ban-nginx-badbots -j RETURN -A fail2ban-nginx-http-auth -j RETURN -A fail2ban-nginx-nohome -j RETURN -A fail2ban-nginx-noproxy -j RETURN -A fail2ban-nginx-noscript -j RETURN -A fail2ban-ssh -j RETURNوإن أردنا رؤية تفاصيل حظر مُطبَّق من قبل أي jail فمن الأسهل ربّما استخدام الأمر fail2ban-client مرة أخرى: sudo fail2ban-client status nginx-http-authStatus for the jail: nginx-http-auth |- filter | |- File list: /var/log/nginx/error.log | |- Currently failed: 0 | `- Total failed: 0 `- action |- Currently banned: 0 | `- IP list: `- Total banned: 0اختبار سياسات Fail2Banمن الهام اختبار سياسات fail2ban لكي نتأكّد من أنها تقوم بحظر نقل البيانات كما هو متوقّع، على سبيل المثال نستطيع إعطاء بيانات خاطئة في مُحث prompt استيثاق Nginx عدّة مرات، وبعد أن نتجاوز الحدّ ينبغي أن يتم حظرنا وألا نكون قادرين على الوصول للموقع، وإن قمنا بإعداد تنبيهات البريد الإلكتروني فيجب أن نرى رسائل حول الحظر في البريد الإلكتروني الذي قمنا باختياره لاستقبال التّنبيهات. عندما ننظر إلى الحالة باستخدام الأمر fail2ban-client سنشاهد أنّ عنوان IP الخاص بنا يتم حظره من الموقع: sudo fail2ban-client status nginx-http-auth Status for the jail: nginx-http-auth |- filter | |- File list: /var/log/nginx/error.log | |- Currently failed: 0 | `- Total failed: 12 `- action |- Currently banned: 1 | `- IP list: 111.111.111.111 `- Total banned: 1وعندما نكون مقتنعين بأنّ قواعدنا تعمل بشكل صحيح نستطيع فك الحظر يدويًّا عن عنوان IP الخاص بنا عن طريق الأمر fail2ban-client بكتابة ما يلي: sudo fail2ban-client set nginx-http-auth unbanip 111.111.111.111 نبغي أن نكون الآن قادرين على محاولة الاستيثاق مرة أخرى. الخاتمةإنّ إعداد fail2ban لحماية خادوم Nginx لدينا هو عمليّة سهلة إلى حدٍّ ما في أبسط الحالات، توفّر fail2ban على أيّة حال قدرًا كبيرًا من المرونة لبناء سياسات تُلائِم احتياجاتنا الأمنيّة، وبإلقاء نظرة على المتغيّرات والأنماط داخل الملف etc/fail2ban/jail.local/ والملفات التي يعتمد عليها داخل الدّليل etc/fail2ban/filter.d/ والدّليل etc/fail2ban/action.d/ نجد العديد من الأجزاء التي يمكننا تطويعها tweak وتغييرها لكي تلبّي احتياجاتنا، إنّ تعلّم أساسيّات كيفيّة حماية خادومنا باستخدام fail2ban يزوّدنا بقدرٍ كبير من الأمان وبأقل جهد. إن كنت ترغب في تعلّم المزيد حول fail2ban قم بزيارة الروابط التالية: كيف تعمل Fail2Ban لحماية الخدمات على خادوم لينِكس.كيفيّة حماية SSH باستخدام Fail2Ban على Ubuntu 14.04.ترجمة -وبتصرّف- لـ How To Protect an Nginx Server with Fail2Ban on Ubuntu 14.04 لصاحبه Justin Ellingwood.
  11. إنّ Redis هو عبارة عن نظام تخزين وذاكرة مؤقتة cache بنمط مفتاح-قيمة key-value مفتوح المصدر، ويتم الإشارة له أيضًا كخادوم بُنية معطيات data structure بسبب دعمه المتقدّم للعديد من أنواع البيانات كالتلبيدات Hashes، اللوائح lists، المجموعات sets والخرائط الثنائيّة Bitmaps من بين الخواديم الأخرى، يدعم أيضًا الحشد clustering والذي يجعل منه مُستخدَمًا عادةً في البيئات ذات التوافر العالي والقابلة للتطوير. سنشاهد في هذا الدّرس كيفيّة تثبيت وإعداد خادوم Redis خارجي لكي يتم استخدامه كمُداوِل للجلسة Session Handler من أجل تطبيق PHP يعمل على Ubuntu. إنّ مُداوِل الجلسة مسؤول عن تخزين واسترجاع البيانات المحفوظة ضمن الجلسات، حيث تستخدم PHP افتراضيًّا الملفّات من أجل هذا، يُمكن استخدام مُداوِل الجلسة الخارجي من أجل إنشاء بيئات PHP قابلة للتطوير خلف مُوازِن الحِمل load balancer، حيث ستتصل جميع عُقَد nodes التّطبيقات إلى خادوم مركزي لتتشارك معلومات الجلسة. المتطلبات الأساسيةسنعمل في هذا الدّرس على خادومين مُنفصلين، ومن الهام من أجل الأداء والأمان أن تتوضّع كلا Droplets الخاصّة بهما في نفس مركز البيانات مع تمكين ربط الشبكات الخاصّة Private networking، وهذا ما سنحتاجه: خادوم ويب PHP يقوم بتشغيل LAMP أو LEMP على Ubuntu – سنقوم بالإشارة لهذا الخادوم بـ web.خادوم Ubuntu آخر حيث سيتم تثبيت Redis – سنقوم بالإشارة لهذا الخادوم بـ redis.سنحتاج نفاذ مناسب عبر SSH إلى كلا الخادومين كمستخدم اعتيادي مع صلاحيّات sudo. نستطيع أيضًا من أجل خادوم Redis استخدام تطبيق Redis بنقرة واحدة والانتقال للخطوة الثانية. الخطوة الأولى – تثبيت خادوم Redisإنّ أول شيء نحتاجه هو الحصول على خادوم Redis يعمل على redis Droplet الخاصّة بنا. سنستخدم مُدير حِزَم Ubuntu الاعتيادي مع مستودع PPA موثوق يتم تزويدنا به بواسطة Chris Lea، وهو ضروري لكي نتأكّد أنّنا نحصل على آخر إصدار مُستَقر من Redis. كنصيحة أمان عامّة ينبغي أن نستخدم PPAs من مصادر موثوقة فقط. نُضيف في البداية مستودع PPA بتنفيذ الأمر التالي: sudo add-apt-repository ppa:chris-lea/redis-serverنضغط Enter للتأكيد. نحتاج الآن لتحديث الذاكرة المؤقتة cache لمدير الحِزَم: sudo apt-get updateفلنقم أخيرًا بتثبيت Redis بتنفيذ الأمر التالي: sudo apt-get updateينبغي الآن أن يكون تم تثبيت Redis على خادومنا، ولاختبار التثبيت نُجرِّب هذا الأمر: redis-cli pingسيقوم هذا الأمر بالاتصال إلى نموذج instance من Redis يعمل على localhost على المنفذ 6379، ويجب أن نتلقّى PONG كاستجابة. الخطوة الثانية – ضبط Redis لكي يقبل اتصالات خارجيةيسمح Redis بالاتصال فقط إلى localhost والذي يعني بشكل أساسي أنّنا نملك النفاذ إليه فقط من داخل الخادوم حيث تمّ تثبيت Redis، نحتاج إلى تغيير هذه الإعدادات للسماح بالاتصالات التي تأتي من خواديم أخرى على نفس الشبكة الخاصّة مثل الخادوم redis. إنّ أول شيء يجب علينا فعله هو معرفة عنوان IP الجهاز Redis على الشبكة الخاصّة، ينبغي تنفيذ الخطوات التالية على الخادوم redis. نقوم بتنفيذ الأمر ifconfig للحصول على معلومات حول واجهات شبكتنا: sudo ifconfigينبغي أن نتلقّى خَرْجًا Output مُشابِهًا لما يلي: eth0 Link encap:Ethernet HWaddr 04:01:63:7e:a4:01 inet addr:188.166.77.33 Bcast:188.166.127.255 Mask:255.255.192.0 inet6 addr: fe80::601:63ff:fe7e:a401/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:3497 errors:0 dropped:0 overruns:0 frame:0 TX packets:3554 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:4895060 (4.8 MB) TX bytes:619070 (619.0 KB) eth1 Link encap:Ethernet HWaddr 04:01:63:7e:a4:02 inet addr:10.133.14.9 Bcast:10.133.255.255 Mask:255.255.0.0 inet6 addr: fe80::601:63ff:fe7e:a402/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:7 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:648 (648.0 B) TX bytes:578 (578.0 B)فلنبحث عن inet_addr المُخصَّص للواجهة eth1، في هذه الحالة نجده 10.133.14.9، وهذا هو عنوان IP الذي سنستخدمه لاحقًا للاتصال إلى الخادوم redis من الخادوم web. نفتح الملف etc/redis/redis.conf/ باستخدام مُحرِّر سطر الأوامر command line editor المُفضَّل لدينا ونبحث عن السّطر الذي يحتوي على التّعريف bind، يجب أن نُضيف عنوان IP للشبكة الخاصّة لدينا إلى هذا السّطر كما يلي: sudo vim /etc/redis/redis.confetc/redis/redis.conf/ bind localhost 10.133.14.9إن وجدنا 127.0.0.1 بدلًا من localhost فليس هناك مشكلة، فقط نضيف عنوان IP الخاص لدينا بعد ما هو موجود. نحتاج الآن لإعادة تشغيل الخدمة Redis لتطبيق التغييرات: sudo service redis-server restartإن قمنا بتثبيت Redis باستخدام تطبيق النقرة الواحدة فسيكون اسم الخدمة redis بدلًا من redis-server. ولإعادة تشغيلها نكتب الأمر: sudo service redis restartبعد هذه التغييرات سيكون أي خادوم داخل نفس الشّبكة الخاصّة قادرًا على الاتصال إلى نموذج Redis. الخطوة الثالثة – تعيين كلمة سر لخادوم Redisلإضافة طبقة أمان إضافيّة إلى تثبيت Redis لدينا فنحن نُشجِّع على تعيين كلمة سر للنفاذ إلى بيانات الخادوم، سنقوم بتحرير نفس ملف الإعدادات الذي قمنا بتحريره في الخطوة السّابقة etc/redis/redis.conf/: sudo vim /etc/redis/redis.confنقوم الآن بإلغاء التّعليق uncomment عن السّطر الذي يحتوي على requirepass ونضع كلمة سر قويّة: etc/redis/redis.conf/ requirepass yourverycomplexpasswordhereنعيد تشغيل خدمة Redis لكي يتم تطبيق التغييرات: sudo service redis-server restart الخطوة الرابعة – اختبار الاتصال إلى Redis والاستيثاق Authenticationلكي نتأكّد من أنّ كافّة التغييرات تعمل كما هو متوقّع نقوم بالاتصال إلى خدمة Redis من داخل الجهاز redis: redis-cli -h 10.133.14.9المخرجة: 10.133.14.9:6379>بالرغم من أنّه ليس من الإجباري هنا تحديد المُعامِل host (بما أنّنا نتصل من localhost)، فقد قمنا بذلك للتأكّد من أنّ خدمة Redis تقبل الاتصالات الموجّهة إلى واجهة الشّبكة الخاصّة. إن كُنّا قد عرّفنا كلمة سر وحاولنا الآن النفاذ إلى البيانات ينبغي أن نتلقّى خطأ AUTH: 10.133.14.9:6379> keys *المخرجة: (error) NOAUTH Authentication required.نحتاج من أجل الاستيثاق أن نقوم فقط بتنفيذ الأمر AUTH مع تزويده بنفس كلمة السّر التي عرّفناها في الملف etc/redis/redis.conf/: 10.133.14.9:6379> AUTH yourverycomplexpasswordhereينبغي أن نتلقّى استجابة OK، والآن إن قمنا بتنفيذ الأمر: 10.133.14.9:6379> keys *يجب أن يكون الخَرْج مُشابِهًا لما يلي: المخرجة: (empty list or set)يعني هذا الخَرْج فقط أنّ خادوم Redis لدينا فارغ، وهو ما كُنّا نتوقّعه تمامًا، حيث أنّ الخادوم web ليس مُعدًّا بعد لاستخدام خادوم Redis هذا كمداوِل للجلسة. فلنحافظ على جلسة SSH هذه مفتوحة ومتّصلة إلى redis-cli بينما نقوم بتنفيذ الخطوات التالية، سنعود إلى المُحِث prompt redis-cli لكي نتحقّق من أنّه يتم تخزين بيانات الجلسة بشكل مناسب، وذلك بعد أن نقوم بالتغييرات الضروريّة للخادوم web. الخطوة الخامسة – تثبيت امتداد Redis Extension على الخادوم webيجب تنفيذ الخطوات التالية على الخادوم web، نحتاج إلى تثبيت الامتداد PHP Redis وإلّا لن تكون PHP قادرة على الاتصال إلى الخادوم Redis. في البداية نقوم بتحديث الذاكرة المؤقتة لمدير الحِزَم بتنفيذ الأمر التالي: sudo apt-get updateنقوم بعدها بتثبيت الحِزمَة php5-redis: sudo apt-get install php5-redisينبغي الآن أن يكون الخادوم web قادرًا على الاتصال إلى Redis. الخطوة السادسة – تعيين Redis كمداول الجلسة الافتراضي على الخادوم webنحتاج الآن لتحرير الملف php.ini على الخادوم web لتغيير مُداوِل الجلسة الافتراضي لـ PHP، يعتمد مسار الملف على استخدامنا LAMP أو LEMP، ففي LAMP على Ubuntu يكون المسار عادةً في etc/php5/apache2/php.ini/، وفي LEMP على Ubuntu يكون المسار عادةً في etc/php5/fpm/php.ini/. إن لم نكن متأكّدين من مسار الملف php.ini نستطيع إيجاده بطريقة سهلة باستخدام الدالّة ()phpinfo، فقط نقوم بوضع الشيفرة code التالية في ملف نسمّيه info.php داخل دليل الويب الجذري root: <?php phpinfo();عند الوصول للـ script من متصفحنا ننظر إلى السطر الذي يحتوي على ملف الإعدادات الذي تمّ تحميله، ينبغي أن نجد المسار الصحيح للملف php.ini قد تمّ تحميله. يجب ألّا ننسى إزالة الملف info.php بعد الانتهاء من هذا، لأنّه يحتوي على معلومات حسّاسة حول البيئة لدينا. نفتح الملف php.ini ونبحث عن السّطر الذي يحتوي على session.save_handler، إنّ القيمة الافتراضيّة له هي files، ينبغي أن نقوم بتغييرها إلى redis. على بيئة LAMP: sudo vim /etc/php5/apache2/php.iniعلى بيئة LEMP: sudo vim /etc/php5/fpm/php.inietc/php5/fpm/php.ini/ session.save_handler = redisينبغي أن نجد الآن السّطر الذي يحتوي على session.save_path، نقوم بإلغاء التعليق عنه وتغيير قيمته بحيث تحتوي مقطع string اتصال Redis، يجب أن يتّبع المحتوى النَّسَق التالي كله في سطر واحد: tcp://IPADDRESS:PORT?auth=REDISPASSWORDetc/php5/fpm/php.ini/ session.save_path = "tcp://10.133.14.9:6379?auth=yourverycomplexpasswordhere"نحتاج فقط إلى تزويد المُعامِل auth إن كُنّنا قد أعددنا كلمة سر عند ضبط Redis. نحفظ الملف ونعيد تشغيل خدمة php. على بيئة LAMP: sudo service apache2 restartعلى بيئة LEMP: sudo service php5-fpm restart الخطوة السابعة – اختبار مداولة Redis للجلسةلكي نتأكّد من أنّ الجلسات لدينا يتم الآن مُداوَلتها من قبل Redis نحتاج PHP script أو تطبيق يقوم بتخزين المعلومات في الجلسات، سنستخدم Script بسيط يقوم بتنفيذ عدّاد Counter، حيث تتم زيادة الرقم كلّما أعدنا تحميل الصّفحة. ننشئ ملف يُدعى test.php على الخادوم web ونضعه داخل المجلّد الجذر للمستند document root folder: sudo vim /usr/share/nginx/html/test.phpلا يجب أن ننسى تغيير usr/share/nginx/html/ بحيث يكون مسار جذر المستند لدينا. usr/share/nginx/html/test.php/ <?php //simple counter to test sessions. should increment on each page reload. session_start(); $count = isset($_SESSION['count']) ? $_SESSION['count'] : 1; echo $count; $_SESSION['count'] = ++$count;نتوجّه في متصفحنا إلى http://web/test.php لكي نصل إلى الـ script، ينبغي أن يقوم بزيادة الرقم كلما قمنا بإعادة تحميل الصّفحة. يجب أن نمتلك الآن معلومات الجلسة مُخزّنة على خادوم Redis، وللتحقّق من ذلك نعود إلى جلسة SSH على الجهاز redis، حيث قُمنا مُسبَقًا بالاتصال إلى خدمة Redis باستخدام redis-cli. نقوم بجلب المحتوى مرّة أخرى باستخدام * keys: 10.133.14.9:6379> keys *ينبغي أن نحصل على خَرْج مُشابِه لهذا: 1) "PHPREDIS_SESSION:j9rsgtde6st2rqb6lu5u6f4h83"وهذا يُظهِر أنّه يتم تخزين معلومات الجلسة على خادوم Redis، ونستطيع الاتصال من خواديم ويب إضافيّة إلى خادوم Redis بطريقة مماثلة. الخاتمةإنّ Redis خدمة تخزين من نمط مفتاح-قيمة سريعة وقويّة نستطيع أيضًا استخدامها كمُداوِل للجلسة في PHP، مما يُمكّننا من الحصول على بيئات PHP قابلة للتطوير عن طريق تزويدها لنا بنظام مُوزَّع لتخزين الجلسة، وللمزيد من المعلومات حول تقييس scaling تطبيقات PHP تستطيع التحقّق من هذا الدّرس: تقييس تطبيقات PHP أفقيًّا. ترجمة -وبتصرّف- للمقال How to Set Up a Redis Server as a Session Handler for PHP on Ubuntu 14.04 لصاحبته Erika Heidi.
  12. phpMyAdmin هي لوحة تحكّم مجانيّة تعمل كواجهة ويب وتستطيع النفاذ إلى قواعد بيانات MySQL المُستضافة على خادومنا وتعديلها، وتتكامل تلقائيًّا مع جميع قواعد البيانات الموجودة حاليًّا والمستقبليّة على خادوم Ajenti لدينا. سنرى في هذا الدّرس كيفيّة دمج phpMyAdmin إلى لوحة تحكّم Ajenti. المتطلبات الأساسيةوجود Ajenti مع تثبيت Ajenti V (اقرأ هنا كيفيّة تثبيت لوحة تحكّم Ajenti وAjenti V على Ubuntu 14.04).اسم مجال domain name مُسجَّل يُشير إلى Droplet الخاصّة بنا (سنستخدم في هذا الدّرس example.com).مجال فرعي subdomain (في مثالنا phpmyadmin.example.com) يقوم بالتحليل resolve إلى droplet الخاصّة بنا.الخطوة الأولى – إنشاء الموقع في Ajenti Vقبل أن نقوم بتثبيت phpMyAdmin يجب أن نُنشِئ الموقع في Ajenti. نقوم في المتصفح الخاص بنا بالانتقال إلى لوحة تحكّم Ajenti على العنوان https://panel.example.com:8000 (مع وضع اسم المجال لدينا بدلًا من example.com) ومن ثمّ نُسجِّل الدّخول، نضغط على Websites الموجودة على اليمين في الشريط الجانبي تحت قسم Web. يوجد تحت قسم New Website حقل نصّي Name، نكتب بداخله phpMyAdmin ونضغط على زر الإنشاء Create. تحت قسم المواقع Websites في نفس الصّفحة نضغط على إدارة Manage الموجودة بجانب السّطر الجّديد phpMyAdmin، نقوم في الصّفحة التي تظهر بإلغاء تحديد المربّع الموجود بجانب وضع الصّيانة Maintenance mode، في قسم ملفّات الموقع Website Files الموجود أسفل ما سبق نُغيّر المسار Path من srv/new-website/ إلى srv/phpMyAdmin/، نضغط على زر التعيين Set الموجود بجانب حقل النّص. نضغط على تطبيق التّغييرات Apply Changes الموجودة في أسفل الشّاشة. وفي أعلى تلك الصفحة نضغط على التّبويب Domains، ثمّ نضغط على Add ونضع phpmyadmin.your_domain_name بدلًا من example.com، نضغط على تطبيق التّغييرات Apply Changes الموجودة في أسفل الشّاشة. نضغط الآن على التّبويب محتويات Content، نقوم بتغيير مربّع القائمة المُنسدِلة إلى PHP FastCGI ونضغط إنشاء Create، والذي يُخبِر Ajenti بشكلٍ أساسي أن يقوم بتمكين PHP لأجل هذا الموقع. نضغط على تطبيق التّغييرات Apply Changes الموجودة في أسفل الشّاشة، اكتملت الإعدادات الآن، ينبغي أن نتمكّن الآن من تثبيت phpMyAdmin. الخطوة الثانية – تثبيت phpMyAdminلتثبيت phpMyAdmin نقوم بالبداية بالذهاب إلى الرّابط www.phpmyadmin.net/downloads وتنزيل الإصدار الأخير من phpMyAdmin في صيغة ملف zip.، والتي تظهر مُحدَّدة باللون الأزرق في لقطة الشاشة screenshot التالية: وبالعودة إلى لوحة تحكّم Ajenti نقوم بالانتقال إلى مُدير الملفّات File Manager في الشّريط الجانبي، نستخدم مُدير الملفّات للانتقال إلى srv/، يُوجد في أسفل الصّفحة قسم الرّفع Upload، نضغط على زر اختيار ملف Choose File ونقوم بانتقاء ملف phpMyAdmin الذي قمنا بتنزيله بصيغة zip، بعد أن ننتهي من الرّفع نضغط على الملف المُضَاف حديثًا والمُسمّى باسم قريب من phpMyAdmin-x.x.xx-all-languages.zip، نضغط في المربّع الذي يظهر على زر Unpack (المُحدّد باللون الأزرق في لقطة الشّاشة التالية). عندما ينتهي نضغط على زر X الموجود بجانب Terminal 0 في أعلى الشّاشة، ينبغي الآن أن نعود إلى مدير الملفّات وهناك يجب أن نجد مُجلّد مُسمّى باسم مشابه لـ phpMyAdmin-x.x.xx-all-languages، نضغط على زر القائمة الموجود على يمين هذا المُجلّد. وفي حقل النّص Name نُعيد تسمية المجلّد إلى phpMyAdmin ونضغط حفظ Save. الخطوة الثالثة – إعداد قاعدة البياناتسنقوم بتغطية كيفيّة إعداد قاعدة بيانات في Ajenti لكي نتمكّن من تسجيل الدخول إلى phpMyAdmin، إن كنت تملك مُسبقًا قاعدة بيانات وتستطيع تسجيل الدخول فبإمكانك أن تتجاوز هذه الخطوة إلى الخطوة الرابعة. يوجد في لوحة تحكّم Ajenti على الشّريط الجّانبي قسم يُدعى البرمجيّات Software، وتحته مباشرةً يوجد خيار قائمة يُدعى MySQL، نضغط عليه للوصول إلى لوحة تحكّم MySQL في Ajenti. نضغط على زر إنشاء Create الموجود تحت قسم قواعد البيانات Databases، سنكون هناك قادرين على إدخال اسم لقاعدة بياناتنا والذي يُمكن أن يكون أي اسم نرغب به، ولا يمكن لأحد سوانا أن يراه. يُمكن تأهيل بقيّة الأقسام تلقائيًّا بقواعد البيانات والمستخدمين الافتراضيّين، ولن نحتاج إلى الاقتراب منهم، نضغط على زر إنشاء Create الموجود تحت قسم المستخدمين Users، نستطيع إدخال القيم التي نريد في الحقلين Username و Password، حيث ستكون هذه القيم هي معلومات الدّخول إلى phpMyAdmin، لذلك ينبغي أن نتذكرها أو نقوم بكتابتها، نكتب localhost في الحقل اسم المُضيف Hostname. هذا هو كل شيء، نستطيع الآن البدء باستخدام phpMyAdmin. الخطوة الرابعة – تسجيل الدخولللوصول إلى واجهة ويب phpMyAdmin ننتقل إلى phpmyadmin.your_domain_name في متصفحنا، ومن أجل الحقلين Username و Password نقوم بإدخال الاعتمادات credentials الخاصّة بمستخدم MySQL لدينا، ومن ثمّ نضغط Go. الخاتمةتهانينا، تمتلك الآن phpMyAdmin مُثبَّت على الخادوم الخاص بك. ترجمة -وبتصرف- للمقال Installing phpMyAdmin on Ajenti V لصاحبه Jonah Aragon.
  13. بالرّغم من أنّ الاتصال إلى الخادوم عبر SSH آمن جدًّا، فإنّ SSH daemon (وهو عمليّة تعمل في خلفيّة النّظام بشكل دائم) بحدّ ذاتها هي خدمة يجب تعريضها إلى الإنترنت لتعمل بشكل صحيح، ويأتي هذا مع بعض المخاطر الكامنة ويخلق ناقلات للهجوم لأي مهاجمين مُحتَملين. إنّ أي خدمة مُعرّضة إلى الشّبكة هي هدف مُحتمل بهذه الطريقة، فإذا ألقينا انتباهنا إلى سجلّات التطبيق لهذه الخدمات سنجد محاولات مُنظّمة ومتكرّرة لتسجيل الدخول والتي تُمثّل هجمات بالقوّة القاسية Brute force attacks عن طريق مستخدمين أو روبوتات bots على حدٍّ سواء. يُمكن الحد من هذه المشكلة عن طريق خدمة تُدعى fail2ban والتي تقوم بإنشاء قواعد تستطيع تبديل إعدادات جدار حماية iptables بناءً على عدد معرّف مُسبقًا من محاولات تسجيل الدخول غير النّاجحة، يسمح هذا لخادومنا بالاستجابة لمحاولات النّفاذ غير الشّرعية من دون أي تدخّل منّا. سنغطّي في هذا الدّرس كيفيّة تثبيت واستخدام fail2ban على خادوم Ubuntu. تثبيت Fail2Ban على Ubuntuإنّ عمليّة التثبيت لهذه الأداة بسيطة لأنّ فريق تحزيم Ubuntu يُحافِظ على الحِزمة Package في المستودعات الافتراضيّة default repositories. نحتاج في البداية لتحديث دليل الحِزَم المحلّي local package index لدينا، وبعدها نستطيع استخدام apt لتنزيل وتثبيت الحِزمة: sudo apt-get update sudo apt-get install fail2banإنّ عملية التثبيت بديهيّة كما نرى، نستطيع الآن البدء بإعداد الأداة لاستخدامنا الشّخصي. إعداد Fail2Ban مع إعدادات الخدمة الخاصة بناتحتفظ خدمة fail2ban بملفّات إعداداتها في الدّليل etc/fail2ban/، يوجد ملف مع إعدادات افتراضيّة يُدعى jail.conf. ولأنّه يُمكن أن يتم تعديل هذا الملف عن طريق ترقية الحِزَم لذلك لا ينبغي علينا تحرير هذا الملف في مكانه، بل من الأفضل أن نقوم بنسخه حتى نستطيع القيام بتغييراتنا بأمان. نحتاج لنسخه إلى ملف يُدعى jail.local حتى يستطيع fail2ban إيجاده: sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localحالما يتم نسخ الملف بإمكاننا فتحه للتحرير لنرى كيف يعمل كل شيء: sudo nano /etc/fail2ban/jail.localيوجد في هذا الملف القليل من الإعدادات التي قد نرغب بضبطها، يتم تطبيق هذه الإعدادات الموجودة تحت قسم [DEFAULT] على جميع الخدمات المُمَكَّنة enabled من أجل fail2ban الذي لا يتم تجاوزه في القسم الخاص بالخدمة: ignoreip = 127.0.0.1/8نستطيع ضبط مصدر العناوين التي يتجاهلها fail2ban عن طريق إضافة قيمة إلى المُعامِل parameter ignoreip. يتم ضبطه افتراضيًّا بأن لا يقوم بمنع أي نقل للبيانات traffic قادم من الجهاز المحلّي، نستطيع إضافة المزيد من العناوين التي نريد تجاهلها عن طريق إلحاقها بنهاية هذا المُعامِل مع الفصل بينها بفراغ Space. bantime = 600يقوم المُعامِل bantime بتعيين المُدّة الزمنيّة التي سيتم خلالها حظر العميل عندما يفشل بالاستيثاق authenticate بشكلٍ صحيح، يتم قياس هذا المُعامِل بالثّواني، وقيمته الافتراضيّة هي 600 ثانية أي 10 دقائق. findtime = 600 maxretry = 3ومن المُعامِلات التي نرغب أن نلقي لها انتباهًا نجد المُعامِلَين findtime و maxretry، وهما يعملان معًا لتأسيس الشّروط التي نستطيع بناءً عليها اعتبار عميل ما مستخدمًا غير قانونيٍ يجب علينا حظره. يقوم المُتغيّر maxretry بتعيين عدد المحاولات التي يجب خلالها أن يقوم العميل بالاستيثاق خلال فترة زمنيّة مُعرّفة بـ findtime وذلك قبل أن يتمّ حظره، تقوم الإعدادات الافتراضيّة لخدمة fail2ban بحظر العميل الذي يقوم بثلاث محاولات غير ناجحة لتسجيل الدخول خلال فترة 10 دقائق. destemail = root@localhost sendername = Fail2Ban mta = sendmailومن بعض الإعدادات الأخرى التي قد نرغب بتعديلها نجد الإعدادات destemail، sendername، و mta إن أردنا ضبط تنبيهات alerts البريد الإلكتروني، يقوم المُعامِل destemail بتعيين عنوان البريد الإلكتروني الذي سيستقبل رسائل الحظر، يقوم المُعامِل sendername بتعيين قيمة الحقل From في البريد الإلكتروني، يُحدّد المُعامِل mta خدمة البريد الإلكتروني التي سيتم استخدامها لإرسال البريد. action = $(action_)sيضبط هذا المُعامل الإجراءات التي يتّخذها fail2ban عندما يريد إقامة حظر، إنّ القيمة _action مُعرَّفة في الملف قبل هذا المُعامِل بقليل، الإجراء الافتراضي هو ببساطة أن يتم ضبط الجّدار النّاري firewall لكي يرفض نقل البيانات من المُضيف Host المُهاجِم حتى تنتهي مُدّة الحظر. إن أردنا ضبط تنبيهات البريد الإلكتروني نستطيع تغيير القيمة من _action إلى action_mw، وإن كُنّا نرغب أن يقوم البريد الإلكتروني بتضمين سطور السّجلات المُتعلّقة بذلك نستطيع تغييرها إلى action_mwl، يجب أن نتأكّد من أنّه يتم ضبط إعدادات البريد المُناسبة إن اخترنا استخدام تنبيهات البريد. 1. إعدادات Jail الفرديةلقد وصلنا أخيرًا إلى الجزء من ملف الإعدادات الذي يتعامل مع الخدمات الفرديّة، والتي يتم تحديدها في القسم headers مثل [SSH]. نستطيع تمكين كل واحد من هذه الأقسام عن طريق تعديل أو إضافة السّطر enabled وتعيينه إلى true: enabled = trueنجد بشكل افتراضي أنّ خدمة SSH مُمكّنة وباقي الخدمات مُعطّلة. تعمل هذه الأقسام عن طريق استخدام القيم الافتراضيّة التي عرّفناها مُسبقًا، وإن أردنا تجاوز override أي قيم نستطيع فعل ذلك في قسم الخدمات، أمّا إن أردنا استخدام القيم الافتراضيّة فلا داعي لإضافة أي شيء. ومن الإعدادات الأخرى التي يُمكن تعيينها هنا هي filter والذي يستخدم ليحدّد إذا ما كان السطر في ملف السّجل يشير إلى استيثاق فاشل، وlogpath الذي يُخبِر fail2ban أين توجد السّجلات لتلك الخدمة بالتحديد. إنّ قيمة filter هي في الواقع إشارة reference إلى ملف يتوضّع في الدّليل etc/fail2ban/filter.d/ مع إزالة لاحقته conf.، يحتوي هذا الملف على التّعابير النمطيّة regular expressions التي تُحدّد إذا ما كان السّطر في ملف السّجل سيّئًا، لن نقوم بالتّحدث بالتفصيل عن هذا الملف في هذا الدّرس، لأنّه مُعقّد إلى حدٍ ما، والإعدادات المُعرّفة مُسبقًا تتوافق مع السطور المُلائمة لها بشكل جيّد. بإمكاننا على أيّة حال أن نرى أنواع المُرشّحات filters المتوفرة من خلال النّظر إلى هذا الدّليل: ls /etc/fail2ban/filter.dعندما نجد ملفًّا مرتبطًا بالخدمة التي نستخدمها ينبغي أن نفتحه باستخدام مُحرّر نصوص. مُعظم هذه الملفّات تحتوي على تعليقات للشرح بشكل جيّد ويجب أن نكون قادرين على الأقل أن نعرف ما هو نوع الشّروط التي تم تصميم الـ script من أجل الحماية ضدّها، تملك أغلب هذه المُرشّحات أقسام (مُعطّلة) مناسبة في ملف jail.local والتي نستطيع تمكينها عند الرغبة بذلك. فلنفترض على سبيل المثال أنّنا نقوم بتخديم موقع باستخدام nginx وأدركنا أنّ قسم منه محمي بكلمة مرور يتعرّض لمحاولات تسجيل دخول، نستطيع إخبار fail2ban أن يستخدم الملف nginx-http-auth.conf لكي يفحص هذا الشّرط من خلال الملف var/log/nginx/error.log/. هذا الشّرط مُعَد مُسبقًا في الواقع ضمن قسم يُدعى [nginx-http-auth] في الملف etc/fail2ban/jail.local/، نحتاج فقط إلى قلب المُعامِل enabled إلى true لحماية الخدمة الخاصّة بنا: [nginx-http-auth] enabled = true filter = nginx-http-auth port = http,https logpath = /var/log/nginx/error.logإن قمنا بتفعيلها نحتاج إلى إعادة تشغيل خدمة fail2ban للتأكّد من أنّ قواعدنا مبنيّة بشكل صحيح. وضع كل ذلك معاالآن وقد فهمنا الفكرة الأساسيّة من وراء fail2ban، فلنقم بتشغيل إعداد أساسي. سنقوم بإعداد سياسة حظر تلقائي من أجل SSH وNginx تمامًا كما وصفنا سابقًا، نريد من fail2ban أن يقوم بإرسال بريد إلكتروني لنا عندما يتم حظر عنوان IP. فلنقم في البداية بتثبيت جميع البرمجيّات المتعلقّة بذلك. إن كُنّا لا نملك nginx يجب علينا تثبيته، لأنّنا سنقوم بمراقبة سجلّاته، سنحتاج أيضًا sendmail لكي يرسل التّنبيهات إلينا، سنقوم بتثبيت iptables-persistent لكي يسمح للخادوم بإعداد قواعد الجّدار النّاري تلقائيًّا عند الإقلاع boot، نستطيع الحصول على كل هذا من مستودعات Ubuntu الافتراضيّة: sudo apt-get update sudo apt-get install nginx sendmail iptables-persistent 1. إنشاء جدار ناري أساسيينبغي علينا بعد الانتهاء من كل هذا إنشاء جدار ناري افتراضي، تستطيع تعلّم كيفيّة إعداد iptables للجدار الناري على Ubuntu من هنا، سنقوم في هذا الدّرس فقط بإنشاء جدار ناري أساسي. سنخبر الجّدار النّاري بالسّماح للاتصالات التي تمّ تأسيسها، نقل البيانات traffic الذي يتم توليده من قبل الخادوم نفسه، مقدار نقل البيانات من أجل SSH لدينا، ومنافذ ports خادوم الوِب، وسنقوم باستبعاد أي نقل بيانات آخر، نستطيع إعداد هذا الجّدار النّاري الأساسي عن طريق كتابة: sudo iptables -A INPUT -i lo -j ACCEPT sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A INPUT -j DROPستقوم هذه الأوامر بتنفيذ السّياسة السّابقة، وبإمكاننا رؤية قواعد الجّدار النّاري الحاليّة عن طريق كتابة: sudo iptables -S -P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT -N fail2ban-ssh -A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -j DROP -A fail2ban-ssh -j RETURN حصلنا هنا على سياستنا الافتراضيّة لكل واحدة من السلاسل لدينا، ومن ثمّ القواعد الخمس التي أنشأناها للتو، إنّ الأسطر التي تحتوي على: -N fail2ban-ssh و -A INPUT -p tcp -m multiport --dports 22 -j fail2ban-sshو -A fail2ban-ssh -j RETURN هي عبارة عن البُنية الافتراضيّة المُعدّة من قبل fail2ban حيث أنّه يقوم مُسبقًا بتنفيذ سياسات حظر SSH بشكل افتراضي. 2. ضبط إعدادات Fail2banنحتاج الآن لضبط إعدادات fail2ban باختيار الإعدادات التي نرغب بها، فلنقم بفتح الملف jail.local: sudo nano /etc/fail2ban/jail.localنستطيع هنا تعيين زمن للحظر أشد طولًا، فلنقم بتغيير الإعداد bantime الموجود تحت الترويسة الافتراضيّة بحيث تقوم خدمتنا بحظر العملاء لمدة نصف ساعة: bantime = 1800نحتاج أيضًا لضبط معلومات تنبيهات البريد الإلكتروني، نقوم في البداية بإيجاد المُعامِل destemail ونضع بداخله عنوان البريد الإلكتروني الذي نرغب باستخدامه لجمع هذه الرسائل: destemail = admin@example.comنستطيع تعيين sendername إلى قيمة أخرى إن أردنا ذلك، على الرغم من أنّه من المفيد أن يكون لها قيمة يُمكن تصفيتها بسهولة باستخدام خدمة البريد الإلكتروني الخاصّة بنا، وإلّا امتلأ صندوق الوارد بالتنبيهات إن كانت هناك الكثير من محاولات الاختراق من أماكن متعدّدة. بالانتقال للأسفل نحتاج لضبط المُعامِل action إلى أحد الإجراءات التي ترسل لنا بريد إلكتروني، الخيارات محصورة بين action_mw والذي يُنشِئ الحظر ومن ثمّ يرسل لنا بريدًا إلكترونيًّا يحتوي على تقرير whois حول المُضيف المخالف، أو action_mwl والذي يقوم بما سبق ولكن يرسل لنا أيضًا سطور السجل المتعلّقة بذلك. سوف نختار action_mwl لأنّ سطور السّجلات ستساعدنا على استكشاف الأخطاء وجمع المزيد من المعلومات إن كانت توجد مشاكل: action = %(action_mwl)sوبالانتقال إلى قسم SSH لدينا، إن أردنا ضبط عدد المحاولات غير الناجحة التي ينبغي أن نسمح بها قبل إنشاء حظر نستطيع تعديل الإدخال maxretry، وإن كُنّا نستخدم منفذ غير 22 سنحتاج لضبط المُعامِل port بشكلٍ مُناسِب، وكما قلنا سابقًا فإنّ هذه الخدمة مُمكّنة مُسبقًا لذلك لا حاجة لتعديل ذلك. فلنبحث بعد ذلك عن القسم nginx-http-auth ونُغيّر المُعامِل enabled ليصبح true: [nginx-http-auth] enabled = true . . .هذا هو كل ما ينبغي علينا فعله في هذا القسم ما لم يكن يعمل خادوم الوِب لدينا على منافذ غير معياريّة أو قمنا بنقل المسار الافتراضي لسجلّات الأخطاء. 3. إعادة تشغيل خدمة Fail2banبعد الانتهاء مما سبق نقوم بحفظ وإغلاق الملف. نقوم الآن ببدء تشغيل أو إعادة تشغيل خدمة fail2ban، من الأفضل أحيانًا إيقاف تشغيل الخدمة بشكلٍ تام ومن ثم تشغيلها مرة أخرى: sudo service fail2ban stopنستطيع الآن إعادة تشغيلها بكتابة ما يلي: sudo service fail2ban startقد تستغرق بضع لحظات لكي يتم ملء جميع قواعد الجّدار النّاري لدينا، على أيّة حال نستطيع بعد ذلك التأكّد من القواعد الجديدة بكتابة: sudo iptables -S -P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT -N fail2ban-nginx-http-auth -N fail2ban-ssh -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-http-auth -A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -j DROP -A fail2ban-nginx-http-auth -j RETURN -A fail2ban-ssh -j RETURNإن الأسطر التي قامت بإنشائها سياسات fail2ban لدينا هي: -N fail2ban-nginx-http-auth -N fail2ban-ssh -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-http-auth -A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh -A fail2ban-nginx-http-auth -j RETURN -A fail2ban-ssh -j RETURN تقوم هذه الأسطر الآن بتوجيه نقل البيانات إلى سلاسل جديدة وفارغة تقريبًا ومن ثمّ تسمح لنقل البيانات بالتدفق والعودة إلى سلسلة الدّخل INPUT. على أيّة حال هذه السلاسل الجديدة هي حيث يتم إضافة قواعد الحظر الجّديدة. 4. اختبار سياسات الحظرنستطيع اختبار القواعد من خادوم آخر -خادوم لا نحتاج له للدخول إلى خادوم fail2ban- عن طريق جعل هذا الخادوم الثاني ينحظر. بعد الدخول إلى الخادوم الثاني نقوم بمحاولة الدخول عن طريق SSH إلى خادوم fail2ban، نستطيع على سبيل المثال محاولة الاتصال باستخدام اسم غير موجود: ssh blah@fail2ban_server_IPفلنقم بإدخال أحرف عشوائيّة في النّافذة التي تطلب منّا كلمة مرور، ومن ثمّ نعيد هذه الخطوة عدّة مرات، سيقوم خادوم fail2ban في نقطة ما بإيقاف الاستجابة مع رسالة تم رفض الإذن Permission denied، وهذا يشير إلى أنه تم حظر الخادوم الثاني من قبل خادوم fail2ban. نستطيع على خادوم fail2ban مشاهدة القواعد الجديدة عن طريق التّحقق مرة أخرى من iptables لدينا: sudo iptables -S -P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT -N fail2ban-nginx-http-auth -N fail2ban-ssh -A INPUT -p tcp -m multiport --dports 80,443 -j fail2ban-nginx-http-auth -A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -j DROP -A fail2ban-nginx-http-auth -j RETURN -A fail2ban-ssh -s 11.111.111.11/32 -j REJECT --reject-with icmp-port-unreachable -A fail2ban-ssh -j RETURNوكما نرى في السّطر: -A fail2ban-ssh -s 11.111.111.11/32 -j REJECT --reject-with icmp-port-unreachableنملك الآن قاعدة جديدة في إعداداتنا ترفض نقل البيانات القادمة من عنوان IP خادومنا الثاني عبر منفذ SSH، ينبغي أيضًا أن نكون قد حصلنا على بريد إلكتروني حول هذا الحظر في الحساب الذي قمنا بإعداده. خاتمةينبغي أن نكون قادرين الآن على إعداد بعض سياسات الحظر الأساسيّة لخدماتنا، من السّهل جدًّا إعداد Fail2ban وهو طريقة رائعة لحماية أي نوع من الخدمات تستخدم الاستيثاق. إن أردت تعلّم المزيد حول كيفيّة عمل fail2ban بإمكانك تفحّص هذا الدّرس التعليمي حول كيفيّة عمل قواعد وملفّات fail2ban. ترجمة -وبتصرّف- للمقال How To Protect SSH with Fail2Ban on Ubuntu 14.04 لصاحبه Justin Ellingwood. حقوق الصورة البارزة: Designed by Freepik.
  14. Sqlite هي عبارة عن محرك SQL مفتوح المصدر سريع وبسيط جدا، يشرح هذا الدرس متى يكون من الأمثل استخدام Sqlite كبديل لأنظمة إدارة قواعد البيانات الارتباطية RDBMS مثل MySQL أو Postgres، بالإضافة إلى كيفية تثبيتها وأمثلة عن استخداماتها الأساسية، تُغطي عمليات CRUD: الإنشاء Create، القراءة Read، التحديث Update، والحذف Delete. مفاهيم خاطئةلا يجب أن ننخدع بالاعتقاد أن Sqlite تستَخدم فقط للاختبار والتطوير، فعلى سبيل المثال تعمل Sqlite بشكل جيد لمواقع الإنترنت التي تتلقى 100,000 زائر يوميا، وهذا هو الحد المُحافظ. إن الحد الأقصى لحجم قاعدة بيانات Sqlite هو 140 تيرابايت (والذي من المفترض أن يكون كافيًا، أليس كذلك؟)، وبإمكانها أن تكون أسرع بكثير من RDBMS، يتم تخزين قاعدة البيانات كاملةمع كافة البيانات الضرورية في ملف عادي في نظام ملفات المضيف Host، ولذلك لا توجد حاجة لعملية خادوم Server منفصلة (الاستغناء عن الحاجة إلى الاتصالات البطيئة بين العمليّات). الاستخدام الأمثل على VPS الخاص بناتركز Sqlite على البساطة، وبما أنها تعمل داخليا internal بشكلٍ تام، فهي غالبًا ما تكون أسرع بكثير من البدائل الأخرى، إن كنا نبحث عن قابلية النقل portability (فيما يتعلق باللغات والمنصّات معًا)، البساطة، السرعة، والاستهلاك القليل للذاكرة فإن Sqlite مثاليّة لهذا، فعيوبها تكون واضحة فقط عند الحاجة لتزامن عال بالقراءة أو الكتابة. حيث تستطيع Sqlite أن تدعم كاتب writer واحد فقط في نفس الوقت، وقد يكون زمن الوصول latency لنظام الملفات المرتَفِع عادة غير مُلائِم إن كانت هناك حاجة لنفاذ access العديد من العملاء إلى قاعدة بيانات Sqlite في نفس الوقت. العيب الأخير المُحتَمل وجوده في Sqlite هو صياغتها syntax الفريدة، بالرغم من تشابهها مع أنظمة SQL الأخرى، ومن البديهي عند الانتقال إلى نظام آخر -إن قمنا باستخدام Sqlite والتي تتطوّر بسرعة- أن نجد بعض العقبات في المرحلة الانتقاليّة. تثبيت Sqlite على VPS الخاص بناإن وحدة sqlite3 module هي جزء من مكتبة بايثون المعيارية، لذلك لا نحتاج لأي تثبيت آخر على توزيعة Ubuntu المعيارية أو على أي نظام آخر مُثبّت عليه بايثون، ولتثبيت واجهة سطر الأوامر لـ Sqlite على Ubuntu نستخدم هذه الأوامر: sudo apt-get update sudo apt-get install sqlite3 libsqlite3-devإن كُنّا نريد تصريفه Compile من المصدر Source يجب علينا الحصول على آخر إصدار من autoconf من الرّابط sqlite.org/download.html، وهو الإصدار المتوفّر وقت كتابة هذا الدّرس: wget http://sqlite.org/2013/sqlite-autoconf-3080100.tar.gz tar xvfz sqlite-autoconf-3080100.tar.gz cd sqlite-autoconf-3080100 ./configure make make installملاحظات من أجل البناء من المصدر: لا يجب أن نقوم بفعل هذا على توزيعة Ubuntu معياريّة لأنّه من المُحتمل أن نتلقّى خطأ عن عدم التّوافق في إصدار التّرويسة Header والمصدر "header and source version mismatch" بسبب التّعارض بين الإصدار المُثبّت حاليًّا والإصدار الجّديد الذي نريد تثبيته.إن كان يبدو أنّ الأمر make ينتظر المزيد من المُدخلات منك فكُن صبورًا فقط، حيث أنّ تصريف Compile المصدر قد يستغرق بعض الوقت.الاستخدامات الأساسية لواجهة سطر الأوامرلإنشاء قاعدة بيانات نقوم بتنفيذ الأمر التالي: sqlite3 database.dbحيث يكون database هو اسم قاعدة البيانات لدينا، وإن كان الملف database.db موجودًا مُسبقًا ستقوم Sqlite بإنشاء اتصال معه، وإن لم يكن موجودًا سيتمّ إنشاؤه، يجب أن يكون الخرج Output مُشابهًا لما يلي: SQLite version 3.8.1 2013-10-17 12:57:35 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite>فلنقم الآن بإنشاء جدول Table وإدخال بعض البيانات إليه، يملك هذا الجدول المُسمَّى الأندية clubs أربعة أعمدة columns، من أجل id، اسم النادي name، مدرّبه coach، وبلد النّادي country، سنقوم بإدخال بيانات ثلاثة أندية كرة قدم إلى قاعدة بياناتنا: CREATE TABLE clubs (id integer, name varchar(30), coach varchar(20), country varchar(20)); INSERT INTO clubs VALUES (1, "Real Madrid", "Benitez", "Spain"); INSERT INTO clubs VALUES (2, "Barcelona", "Enrique", "Spain"); INSERT INTO clubs VALUES (3, "Chelsea", "Mourinho", "England");لقد أنشأنا قاعدة بيانات، جدول، وبعض الإدخالات، نضغط الآن Ctrl+D للخروج من Sqlite ونكتب ما يلي (يجب هنا أيضًا أن نضع اسم قاعدة بياناتنا بدلًا من 'database') والذي سيقوم بإعادة الاتصال إلى قاعدة البيانات التي أنشأناها للتو: sqlite3 database.dbالآن نكتب: SELECT * FROM clubs;يجب أن نرى هنا الإدخالات التي قُمنا بها: 1|Real Madrid|Benitez|Spain 2|Barcelona|Enrique|Spain 3|Chelsea|Mourinho|Englandرائع، هذا هو كلّ شيء فيما يتعلّق بالإنشاء Creating والقراءة Reading، فلنقم الآن بالتّحديث Update والحذف Delete: UPDATE clubs SET country="Spain" WHERE country="England";سيقوم هذا الأمر بتحديث قاعدة البيانات بحيث يجعل الأندية المُدرَجة على أنّها من إنكلترا يتم إدراجها وكأنّها أندية من إسبانيا، فلنتأكّد من النتائج باستخدام الأمر: SELECT * FROM clubs;يجب أن نرى: 1|Real Madrid|Benitez|Spain 2|Barcelona|Enrique|Spain 3|Chelsea|Mourinho|Spainأصبحت لدينا الآن كل الأندية من إسبانيا، فلنقم بحذف Chelsea من قاعدة بياناتنا كونه النادي الوحيد الذي في الحقيقة ليس من إسبانيا: DELETE FROM clubs WHERE id=3; SELECT * FROM clubs;ينبغي أن نجد الآن عدد الأندية لدينا أقل بواحد من السّابق: 1|Real Madrid|Benitez|Spain 2|Barcelona|Enrique|Spainيُغطِّي هذا جميع العمليّات الأساسيّة لقواعد البيانات، وقبل أن ننتهي دعونا نجرّب مثالًا آخر أقل بديهيّة بقليل، والذي يستخدم جدولين وانضمام join أساسي بينهما. فلنخرج الآن من Sqlite باستخدام الأمر Ctrl+D ونعيد الاتصال إلى قاعدة بيانات جديدة باستخدام: sqlite3 database2.dbسنقوم بإنشاء جدول مشابه جدًّا لجدول الأندية clubs ولكنّنا سننشئ أيضًا جدول للدول countries، والذي يقوم بتخزين اسم الدّولة ورئيسها الحالي، فلنقم أولًا بإنشاء جدول الدّول countries وإدخال إسبانيا وفرنسا إليه باستخدام ما يلي (لاحظ أنّنا نستطيع نسخ ولصق عدّة أسطر من شيفرة sqlite دفعة واحدة): CREATE TABLE countries (id integer, name varchar(30), president varchar(30)); INSERT INTO countries VALUES (1, "Spain", "Rajoy Brey"); INSERT INTO countries VALUES(2, "France", "Francois Hollande");ونستطيع بعدها إعادة إنشاء الجدول clubs باستخدام ما يلي: CREATE TABLE clubs (id integer, name varchar(30), country_id integer); INSERT INTO clubs VALUES (1, "Real Madrid", 1); INSERT INTO clubs VALUES (2, "Barcelona", 1); INSERT INTO clubs VALUES (3, "Chelsea", 2);دعونا الآن نرى ما هي الأندية الموجودة في إسبانيا باستخدام: SELECT name FROM clubs JOIN countries ON country_id=countries.id WHERE countries.name="Spain";ينبغي أن نشاهد ما يلي: Real Madrid Barcelonaيُغطّي هذا موضوع الانضمام الأساسي basic join، فلنلاحظ أنّ sqlite تفعل الكثير من أجلنا، ففي التّعبير السّابق يرمز الانضمام Join افتراضيًّا إلى INNER JOIN بالرغم من أنّنا استخدمنا فقط الكلمة المفتاحيّة JOIN، ولا يجب علينا أيضًا تحديد clubs.country_id لأنّها واضحة لا لبس فيها، من ناحية أخرى إن جرّبنا هذا الأمر: SELECT name FROM clubs JOIN countries ON country_id=id WHERE country_id=1;سنتلقّى رسالة خطأ: "Error: ambiguous column name: id" وهو خطأ معقول بما فيه الكفاية لأنّ الجدولين لدينا كلاهما يملكان عمود id، ولكن بشكلٍ عام sqlite متسامحة مع الأخطاء إلى حد ما، فرسائل الأخطاء فيها تميل إلى أن تجعل تحديد مكان أيّ مشاكل وإصلاحها شيئًا بديهيا إلى حد ما، وهذا يُساعد على تسريع عمليّة التّطوير. للمزيد من المساعدة في موضوع الصّياغة Syntax فإنّ الوثائق الرّسميّة لها مليئة بالمخطّطات البيانيّة diagrams مثل هذا sqlite.org/langdelete.html، والتي من الممكن أن تكون مفيدة. وفي الختام، تملك sqlite أغلفة wrappers وتعريفات في جميع اللغات الرئيسيّة، ويُمكن تشغيلها على معظم الأنظمة، نستطيع إيجاد قائمة بالعديد من هذه اللغات هنا، حظًّا سعيدًا واستمتع بوقتك. ترجمة -وبتصرّف- للمقال How and When to Use Sqlite لصاحبه Gareth Dwyer.
  15. إنّ أحد أهم الاعتبارات التي يجب أخذها بالحسبان عند تخزين عملنا وبياناتنا في بيئة رقميّة هو كيفيّة التّأكّد من أنّ المعلومات الخاصّة بنا ستكون متاحة في حال وجود مشكلة، قد يعني هذا أشياء مختلفة بالنظر إلى التطبيقات التي نستخدمها، مدى أهميّة الحصول على فشل فوري ونوعية المشاكل التي نتوقّعها. سنقوم في هذا الدّرس بمناقشة بعض الطرق المختلفة لتوفير النسخ الاحتياطي ووفرة البيانات data redundancy، ولأنّ حالات الاستخدام المختلفة تتطلّب حلولًا مختلفة فلن نكون قادرين على إعطاء إجابة تناسب جميع الحالات، ولكن سنتعلّم ما هو الشيء المهم في حالات مختلفة وما هو التّنفيذ implementation (أو التّنفيذات implementations) الأكثر مُلاءَمة لهذه العمليّة. سنناقش في هذا الدرس الحلول المختلفة التي يُمكننا استخدامها للنسخ الاحتياطي والمزايا النسبيّة لكلّ واحدة منها بحيث نستطيع اختيار الخطّة التي تناسب البيئة التي نعمل عليها. ما الفرق بين وفرة البيانات Redundancy والنسخ الاحتياطي Backing Up؟غالبًا ما نجد تداخل في معظم الحالات بين المصطلحين وفرة البيانات redundant والنسخ الاحتياطي backup، وهما مفهومان مميّزان مرتبطان ببعضهما ولكنّهما مختلفان، وبعض الحلول تُوفِّرهما معًا. 1. وفرة البيانات Redundancyتعني وفرة البيانات وجود تجاوز للفشل failover فوري في حال وجود مشكلة في النّظام، والمقصود من تجاوز الفشل أنّه في حال أصبحت مجموعة من البيانات غير متوفّرة فسيتمّ استبدالها فورًا بنسخة كاملة لتحلّ محلّها، وينتج عن هذا زمن إيقاف تشغيل down time غير مُلاحظ تقريبًا ويستطيع التطبيق أو الموقع مواصلة تخديم الطلبات وكأنّ شيئًا لم يكن، وفي هذه الأثناء يملك مدير النظام الفرصة لإصلاح المشكلة وإعادة النظام إلى الحالة التي يعمل فيها بشكل تام. وبينما يبدو هذا وكأنّه حل رائع لتخديم النسخ الاحتياطي فإنّ هذا في الحقيقة فكرة خاطئة خطيرة، فلا تُزوِّدنا وفرة البيانات بحماية ضدّ الفشل الذي يؤثر على كامل الآلة أو النّظام، على سبيل المثال إن كُنّا نملك mirrored RAID مضبوط (مثل RAID1) فستكون بياناتنا متوافرة فيه وفي حال فشل أحد الأقراص سيبقى الآخر متوافرًا، ولكن إن فشلت الآلة نفسها فقد نفقد جميع البيانات الخاصّة بنا. ومن مساوئ هذا النوع من الإعداد أنّ كل عمليّة يتمّ تنفيذها على كل نسخة من البيانات، ويتضمّن هذا العمليّات الخبيثة malicious أو التي تمّت بغير قصد، يُمكّننا حل النّسخ الاحتياطي الصحيح الاستعادة من نقطة سابقة حيث كانت البيانات معروفة بكونها بحالة جيّدة. 2. النسخ الاحتياطي Backupكما أشرنا سابقًا فإنّه من المُحتّم علينا الحفاظ على نُسَخ احتياطيّة تعمل بشكل جيّد لبياناتنا الهامّة، واعتمادًا على الموقف فقد يعني هذا النسخ الاحتياطي للتطبيق أو لمعلومات المستخدمين أو حتى لكامل الموقع أو الآلة، والفكرة من وراء النُسَخ الاحتياطيّة أنّه في حال حدوث فقدان في النّظام أو الآلة أو البيانات فإنّنا نستطيع استعادة restore، إعادة نشر redeploy، أو الوصول إلى بياناتنا، قد تتطلّب الاستعادة من نسخة احتياطيّة زمن إيقاف تشغيل، ولكن يوجد فرق بين البدء من نقطة في اليوم السابق والبدء من الصفر، أي شيء لا نستطيع تحمل خسارته -بالتعريف- يجب علينا عمل نسخة احتياطية له. ومن حيث الأساليب يوجد عدد قليل من المستويات المختلفة للنُسَخ الاحتياطيّة يُمكن تصنيفها إلى عدّة طبقات بحسب الحاجة إلى حساب أنواع مختلفة من المشاكل، على سبيل المثال ربّما نقوم بالنسخ الاحتياطي لملف الإعدادات configuration file قبل تعديله وذلك لكي نستطيع العودة بسهولة إلى الإعدادات القديمة قبل أن تنشأ المشكلة، يكون هذا مثالي للتغيرات الصغيرة التي نستطيع مراقبتها بشكل فعال، ولكن هذا الإعداد سيفشل على نحو بائس في حال فشل القرص أو أي شيء أكثر تعقيدًا، ينبغي علينا أيضًا الحصول على نُسَخ احتياطيّة بشكل منتظم وتلقائي إلى موقع بعيد remote location. النُّسَخ الاحتياطيّة بحد ذاتها لا تزوّدنا بتجاوز الفشل تلقائيًا، وهذا يعني أنّ الفشل لن يُكلّفنا خسارة أيّة معلومات (على اعتبار أنّ النُسَخ الاحتياطيّة التي نملكها حديثة 100%)، ولكن قد يُكلفنا زمن تشغيل Uptime، وهذا هو أحد الأسباب التي تجعلنا نستخدم وفرة البيانات والنَسخ الاحتياطي جنبًا إلى جنب بدلًا من أن تُلغي كلّ واحدة منهما الأخرى. النسخ الاحتياطي على مستوى الملف File-Level Backupإنّ النَسخ الاحتياطي على مستوى الملف هو واحد من أشيع أشكال النَسخ الاحتياطي، يستخدم هذا النّوع من النَّسخ الاحتياطي أدوات النسخ الاعتياديّة الموجودة مع النّظام لنقل الملفات إلى موقع أو جهاز آخر. 1. كيفية استخدام الأمر cpأبسط أشكال النَّسخ الاحتياطي لآلة تعمل بنظام لينِكس مثل الـ VPS هي عن طريق الأمر cp، ينسخ هذا الأمر ببساطة الملفات من موقع محلّي local إلى موقع آخر، ونستطيع على حاسوب محلّي وصْل mount قُرص قابل للإزالة وبعدها نسخ الملفات إليه: mount /dev/sdc /mnt/my-backup cp -a /etc/* /mnt/my-backup umount /dev/sdcيقوم هذا المثال بوصْل قرص قابل للإزالة ومن ثُمّ ينسخ الدّليل etc/ إلى القرص، وبعدها يقوم بإلغاء وصْل unmount القرص، والذي يُمكننا تخزينه في مكان آخر. 2. كيفية استخدام الأمر Rsyncإنّ الأمر rsync هو بديل أفضل للأمر cp، حيث يُمكّننا من إجراء نُسَخ احتياطيّة محليّة مع قَدْر أكبر من المرونة، نستطيع تنفيذ نفس العمليّات السابقة باستخدام rsync عن طريق الأوامر التالية: mount /dev/sdc /mnt/my-backup rsync -azvP /etc/* /mnt/my-backup umount /dev/sdcوفي حين أنّ هذا يبدو بسيطًا حتى هذه النقطة، إلّا أنّنا سندرك بسرعة أنّ النَّسخ الاحتياطي على نظام ملفّات محلّي مرهق ومُعقّد، حيث يجب علينا فيزيائيًا وصْل وفصْل قرص النَسخ الاحتياطي ونقله إلى مكان آخر إن أردنا الحفاظ على المعلومات في حال حدوث سرقة أو حريق، نستطيع تحقيق الكثير من نفس المزايا باستخدام النَسخ الاحتياطي عبر الشبكة. يستطيع الأمر Rsync تنفيذ نُسخ احتياطيّة عن بُعد remote بنفس السهولة التي يستطيع القيام بها بنُسخ احتياطيّة محليّة، يجب علينا فقط استخدام صيغة بديلة، سيعمل هذا الأمر على أي مُضيف host نستطيع الدخول إليه عن طريق SSH طالما أنّ rsync مُثبّت لدى الطرفين: rsync -azvP /etc/* username@remote_host:/backup/سيقوم هذا الأمر بالنسخ الاحتياطي للدليل etc/ الموجود على الجّهاز المحلّي إلى دليل على remote_host موجود في backup/. سينجح هذا الأمر إن كُنّا نملك صلاحيات للكتابة على هذا الدّليل وتوجد مساحة كافية. للمزيد من المعلومات حول كيفيّة استخدام rsync للنّسخ الاحتياطي اضغط هنا. 3. كيفية استخدام أدوات أخرى للنسخ الاحتياطيبالرغم من بساطة الأمرين cp و rsync وإمكانيّة استخدامهما بسهولة إلّا أنّهما ليسا دومًا الحل المثالي، لجعل النُسخ الاحتياطية مُؤتمتة نحتاج لوضع هاتين الأداتين ضمن Script وكتابة أي شيفرة ضرورية من أجل الدوران والجماليّات الأخرى. لحسن الحظ توجد بعض الأدوات المساعدة التي تقوم بتنفيذ إجراءات مُعقّدة أكثر للنسخ الاحتياطي ببساطة. Baculaإنّ أداة Bacula هي حل مُركّب ومرن يُعزّز نموذج خادوم عميل للنسخ الاحتياطي للمضيفين hosts، تفصل Bacula بين أفكار العملاء، أماكن النسخ الاحتياطي والإدارة directors (المُكوِّن الذي يُنسّق النسخ الاحتياطي الفعلي)، وتقوم أيضًا بضبط كل مهمّة نسخ احتياطي ضمن وحدة تدعى الوظيفة job. يسمح لنا هذا بتضبيط configuration مُحبّب ومرن بشدّة، نستطيع النسخ الاحتياطي للعديد من العملاء إلى جهاز تخزين وحيد، عميل واحد إلى عدّة أجهزة تخزين، وتعديل مُخطط النسخ الاحتياطي بسرعة وسهولة عن طريق إضافة عُقَد أو ضبط تفاصيلهم، تعمل هذه الأداة بشكل جيّد عبر بيئة تحتوي على شبكة، وهي قابلة للتوسيع وتقسيمها إلى وحدات، مما يجعلها رائعة للنسخ الاحتياطي لموقع أو تطبيق مُوزَّع عبر عدّة أجهزة. لكي تتعلّم المزيد حول كيفيّة تضبيط خادوم Bacula للنسخ الاحتياطي وكيفيّة النسخ الاحتياطي للأنظمة عن بعد باستخدام Bacula، قم بزيارة هذه الروابط. BackupPCمن الحلول الشائعة الأخرى هي أداة BackupPC، يُمكن استخدام هذه الأداة للنسخ الاحتياطي لأنظمة لينِكس وويندوز بسهولة، يتم تنصيبها على جهاز أو VPS والذي سيعمل كخادوم للنسخ الاحتياطي، وبعدها يسحب الخادوم البيانات من عملائه باستخدام طرق نقل الملفّات المُعتادة. يُقدّم هذا الإعداد ميزة تنصيب جميع الحِزَم packages المتعلّقة بذلك على جهاز مركزي واحد، والتضبيط الوحيد الذي نحتاجه هو السماح لخادوم النسخ الاحتياطي بالوصول عبر SSH، يُمكن بسهولة إعداد هذا، وباستخدام DigitalOcean نستطيع تضمين مفاتيح SSH لخادوم BackupPC إلى العملاء بينما نقوم بالنشر، يسمح لنا هذا بضبط النسخ الاحتياطيّة من خادوم النسخ الاحتياطي بسهولة ونشر بيئات الإنتاج الخاصّة بنا بشكل نظيف بدون أيّة برمجيّات إضافيّة. لكي تتعلّم كيفيّة تثبيت واستخدام BackupPC على خادوم، اضغط هنا. DuplicityDuplicity هي بديل رائع للأدوات التقليديّة، الميّزة الأساسيّة للتفاضل في Duplicity هي أنها تستخدم تعمية GPG encryption لنقل وتخزين البيانات، ولهذا بعض الفوائد الرائعة. إنّ الفائدة الواضحة من استخدام تشفير GPG للنسخ الاحتياطي للملفّات هي أنّه لا يتم تخزين البيانات بشكل نص مُجرَّد plain text. الشّخص الوحيد الذي يستطيع فكّ تعمية decrypt البيانات هو من يملك مفتاح GPG key، يُوفِّر هذا درجة من الحماية لتعويض تضخّم التدابير الأمنية اللازمة عندما يتم تخزين البيانات في مواقع مُتعدّدة. الفائدة الأخرى التي قد لا تكون واضحة بشكل فوري للأشخاص الذين لا يستخدمون GPG عادةً هي أنّه يتمّ التّحقّق من كل عمليّة نقل لتكون دقيقة تمامًا، تفرض GPG فحص تلبيد Hash صارم للتأكّد من عدم وجود ضياع في البيانات أثناء النقل، ويعني هذا أنّه عندما يحين الوقت لاستعادة البيانات من النُسخة الاحتياطيّة سنكون أقل عُرضة للوقوع في مشاكل تَلَف الملفات. لكي تتعلّم كيفيّة تمكين النُسخ المُشفّرة باستخدام GPG في Duplicity، اتبع هذا الرابط. النسخ الاحتياطي على مستوى الكتلة Block-Level Backupsإنّ النسخ الاحتياطي على مستوى الكُتلة هو أقل شيوعًا من النسخ الاحتياطي على مستوى الملف ولكنّه بديل هام له، يُعرف أيضًا هذا النمط من النسخ الاحتياطي بالتصوير imaging لأنّه من المُمكن استخدامه لاستنساخ duplicate واستعادة كامل الأجهزة. يسمح النسخ الاحتياطي على مستوى الكُتلة بالنسخ على مستوى أعمق من الملف، فبينما يقوم النسخ الاحتياطي على مستوى الملف بنسخ الملف1، الملف2، والملف3 إلى موقع نسخ احتياطي، يقوم النسخ الاحتياطي على مستوى الكُتلة بنسخ كامل الكُتلة Block التي تحتوي على هذه الملفات، ولتفسير المفهوم بطريقة أخرى يمُكننا القول أنّ النسخ الاحتياطي على مستوى الكتلة ينسخ المعلومات بِت bit تلو الآخر، فهو لا يهتم بالملفات المُجرّدة التي قد تُمثّلها هذه البتّات bits (ولكن سيتم نقل الملفّات بشكل كامل خلال هذه العمليّة). إنّ إحدى الفوائد من النسخ الاحتياطي على مستوى الكتلة أنّه عادة ما يكون أسرع، وبينما يقوم النسخ الاحتياطي على مستوى الملف بالبدء بعمليّة نقل جديدة لكل ملف مُنفصل، يقوم النسخ الاحتياطي على مستوى الكُتلة بنقل الكُتَل والتي عادةً ما تكون أكبر حجمًا، وهذا يعني الحاجة للبدء بعمليّات نقل أقل لإتمام النسخ. استخدام الأداة dd لتنفيذ عمليات النسخ الاحتياطي على مستوى الكتلةإنّ أبسط طريقة لتنفيذ عمليّات النسخ الاحتياطي على مستوى الكُتلة هي باستخدام الأداة dd، هذه البرمجيّة مرنة جدًا وتتيح لنا نسخ المعلومات بِت تلو الآخر إلى مكان جديد، ويعني هذا أنّنا نستطيع النسخ الاحتياطي لقسم partition أو قرص disk إلى ملف واحد أو إلى جهاز raw device بدون أي خطوات تمهيدية. أبسط طريقة للنسخ الاحتياطي لقسم أو قرص هي استخدام dd كما يلي: dd if=/path/of/original/device of=/path/to/place/backupفي هذه الحالة تُحدّد =if جهاز الدخل input أو موقع، تُشير =of إلى ملف الخرج output أو موقع، من الهام جدًا تذكّر هذا الفرق، لأنّه من البديهي مسح قرص كامل إن تمّ عكسهما. إن كُنّا نرغب بالنسخ الاحتياطي لقسم يحتوي على مُستنداتنا الموجودة في dev/sda3/ نستطيع إنشاء ملف صورة كما يلي: dd if=/dev/sda3 of=~/documents.imgتُوجد العديد من الحلول الأخرى للنسخ الاحتياطي على مستوى الكتلة متوفّرة على أجهزة لينِكس، ولكنّنا لن نناقشهم هنا. إصدارات النسخ الاحتياطيةإنّ أحد أهم الأسباب الرئيسيّة للنسخ الاحتياطي للبيانات هو القدرة على استعادة إصدار سابق من ملف أو مجموعة ملفّات في حال حدوث تغيير غير مرغوب أو حذف، وبينما تُزوّدنا جميع آليات النسخ الاحتياطي المذكورة حتى الآن بهذا إلى حدّ ما، نستطيع تنفيذ نظام أكثر قوّة باستخدام أدوات إضافيّة. الطريقة اليدويّة لإنجاز هذا هي إنشاء ملف نسخة احتياطية قبل التعديل كما يلي: cp file1 file1.bak nano file1نستطيع أيضًا أتمتة هذه العمليّة عن طريق إنشاء ملفّات مخفيّة ذات ختم زمني timestamped في كل مرّة نقوم فيها بتعديل ملف عن طريق المُحرّر، على سبيل المثال نستطيع وضع ما يلي في ملف bashrc./~ : nano() { cp $1 .${1}.`date +%y-%m-%d_%H.%M.%S`.bak; /usr/bin/nano $1; }عندما نستدعي الآن الأمر nano سيقوم تلقائيًا بإنشاء نُسَخ احتياطيّة. يُوفّر لنا هذا مستوى مُعيَّن من النسخ الاحتياطي، ولكنّها طريقة هشّة جدًّا وقد تملأ القرص بسرعة إن كُنّا نُعدِّل الملفّات كثيرًا، لذلك هي ليست حلًّا رائعًا وربما ينتهي بنا الأمر أسوأ من القيام بالنسخ اليدوي للملفات التي نريد تحريرها. ومن البدائل التي تقوم بحل العديد من المشاكل المُتأصّلة في هذا التصميم هو استخدام git، والتي هي تحديدًا نظام تحكّم بالإصدار، وبالرغم أنّ هذا قد يكون غير واضح نستطيع استخدام git للتحكّم بأي ملف تقريبًا. نستطيع إنشاء مستودع git repository في الدليل الرئيسي فورًا، ببساطة عن طريق كتابة ما يلي: cd ~ git initربّما نحتاج هنا إلى تطويع tweak الإعدادات لاستثناء بعض الملفات، ولكن بشكل عام يقوم بإنشاء إصدارات بشكل فوري، بإمكاننا بعدها إضافة محتويات الدليل الخاص بنا وتضمين الملفّات عن طريق ما يلي: git add . git commit -m "Initializing home directory"نستطيع ببساطة الانتقال إلى موقع بعيد remote location نظام git المُضمَّن أيضًا: git remote add backup_server git://backup_server/path/to/project git push backup_server masterإنّ هذا النظام ليس رائعًا للنسخ الاحتياطي من تلقاء نفسه، ولكن بجمعه مع نظام نسخ احتياطي آخر يتمكّن هذا النمط من التحكّم بالإصدار من تزويدنا بتحكّم جيّد ومُحبّب بشدّة بالتغيرات التي نقوم بها. للتعلّم أكثر حول كيفيّة استخدام git وكيف نستطيع استخدام git لإصدار الملفّات العاديّة، تحقّق من هذه الروابط. النسخ الاحتياطي على مستوى VPS، ومزود DigitalOcean كنموذجفي حين أنّه من المهم إدارة النُسخ الاحتياطيّة بأنفسنا، تُزوّدنا خدمة DigitalOcean مثلا ببعض الآليات لإكمال النسخ الاحتياطيّة الخاصّة بنا. نمتلك دالّة للنسخ الاحتياطي تقوم بانتظام بعمل نُسَخ احتياطيّة تلقائيّة من أجل droplets (مصطلح مقابل لـ VPS على DigitalOcean) التي تُمكّن هذه الخدمة، نستطيع تشغيلها خلال إنشاء droplet عن طريق اختيار صندوق التأشير "تمكين النُسَخ الاحتياطيّة" "Enable Backups": سيقوم هذا بأخذ نُسخة احتياطيّة لكامل صورة الـ VPS، وهذا يعني أنّنا نستطيع بسهولة إعادة النشر من النُسخة الاحتياطيّة أو استخدامها كأساس للـ droplets الجديدة. ولأخذ صورة لمرّة واحدة عن النظام لدينا نستطيع إنشاء لقطات snapshots، والتي تعمل بصورة مشابهة للنُسَخ الاحتياطيّة ولكنّها غير مؤتمتة، نستطيع إنشاءَها عن طريق الذهاب إلى droplet لدينا واختيار "Snapshots" من القائمة العلويّة: ترجمة -وبتصرّف- للمقال How To Choose an Effective Backup Strategy for your VPS لصاحبه Justin Ellingwood. حقوق الصورة البارزة: Designed by Freepik.
  16. إنّ كل مكتبات بايثون (مثل حزم التّطبيقات application packages) التي نقوم بتنزيلها باستخدام مدير الحزم package manager (مثل pip) يتمّ توزيعها باستخدام أداة مساعدة مُخصصة لهذا العمل، تقوم هذه الأدوات المساعدة بإنشاء توزيعات بايثون Python distributions والتي هي أساسا عبارة عن ملفات أرشيف مرقمة بإصدار ومضغوطة، تحتوي هذه الملفّات على جميع العناصر المتعلقة بما يتم توزيعه، مثل ملفات المصادر source files وملفات الموارد resource files. سنقوم في هذا الدرس بالتحدث عن الأدوات الضرورية للتوزيع، وسنتطرق إلى الخطوات الأساسية التي تسمح لنا بحزم المكتبات المفيدة الخاصة بنا، الوحدات modules، أو حتى التطبيقات applications والتي ستكون مفيدة لنا عند توزيع المشروع الخاص بنا على خادوم أو مشاركته على الإنترنت. توزيعات وحزم بايثونحتى ولو كنا قد عملنا قليلًا فقط مع بايثون، فنحن متآلفون مع مفهوم استخدام مدير الحزم (مثل pip ،easy_install) لتنزيل الوحدات والمكتبات (مثل هياكل تطوير التطبيقات application development frameworks) والتي يتم بعدها استيرادها واستخدامها لإنشاء واحدة جديدة. تقوم أدوات إدارة الحِزَم هذه -والتي تعمل محليا- بالاتصال إلى مصدر بعيد source (مثل دليل حزم بايثون Python Package Index – PyPI) وتنفيذ الإجراء المطلوب (كالبحث والتنصيب). تتكوّن طريقة توزيع تطبيق ما من تغليف الدليل directory الخاص به ببعض الملفّات الضّروريّة (مع القليل من الملفّات المُوصى بها)، تحديد العناصر المرتبطة (كالموارد resources والاعتماديات dependencies، إلخ) وإصدارها أو استخدامها في مكان آخر ببساطة. ملاحظة: نشجعك بشدة على العمل على بيئات افتراضيّة لعزل تنزيلات بايثون، الوحدات والتطبيقات التي تعمل عليها. 1. حزم بايثونالحزمة في بايثون هي تقنيا عبارة عن دليل قابل للاستيراد (باستخدام init__.py__ ) يحتوي على ملفات المصادر (كالوحدات)، ولا يجب الخلط بينها وبين حزم نظام التشغيل والتي هي تقنيًّا تطبيقات فعلية (مثل حزمة Debian)، ومع ذلك يجب أن نُلاحظ أنّ توزيعات بايثون في الواقع تدعى أيضًا بالحزم. مثال على بنية الحِزمة: package | |-- __init__.py2. تطبيقات بايثونعلى الرّغم من أنّه يُمكننا اعتبار أي شيء في بايثون كتطبيق وذلك ابتداء من ملف واحد وحتى مئات الملفات المُبعثرة عبر الحزم المُختلفة، فإنّ التطبيق في أغلب الحالات الواقعيّة يتكوّن من العديد من الوحدات والبعض من الاستيرادات الخارجيّة (من المكتبات). مثال على بنية التّطبيق: myapp | |-- __init__.py |-- amodule.py |-- anothermod.py |__ tests | | | |-- __init__.py | |-- .. | |-- . | ..3. مكتبات وأدوات توزيع بايثوننظرا لطبيعة شعبية لغة بايثون ووجود كميّة وافرة من مكتبات وتطبيقات الطرف الثالث third-party المكتوبة لأجلها فقد كان من الضّروري دوما إيجاد طريقة مُوحّدة وأبسط لتوزيعها، تُوجد العديد من المكتبات والأدوات المختلفة المُستخدمة لإنشاء توزيعات بايثون. تمّ إنشاء مجموعة الأدوات المساعدة لتوزيع بايثون والتي تدعى distutils من أجل التعامل مع مهام التوزيع. 4. دليل حزم بايثون (Python Package Index (PyPIدليل حزم بايثون أو PyPI هو مستودع مركزي (على الإنترنت Online) للمشاريع (توزيعات بايثون)، حيث تستخدم أدوات إدارة الحِزم مثل pip هذا المستودع من أجل استضافة، إيجاد وتثبيت الحِزَم. البدءفلنقم في البداية بإنشاء تطبيق بايثون بسيط وعام باستخدام إطار العمل المصغّر flask (إنشاء البنية) والذي يُمكننا لاحقًا تحزيمه. التطبيق عبارة عن تطبيق ويب بسيط جدا، ﻷن الهدف من الدرس هو كيفية التحزيم وليس التطبيق في حد ذاته. إنشاء بنية التطبيقنهدف إلى إنشاء مثال يشابه معظم مشاريع العالم الحقيقي، ولهذا من الأفضل أن نتخيّل حالة تحتوي على وحدات. بُنية المثال: /MyApplication |-- run.py |-- config.py |__ /app |-- __init__.py |-- /module_one |-- __init__.py |-- controllers.py |-- models.py |__ /templates |-- module_one |-- hello.html |__ /static |__ .. |__ .1. إنشاء المجلدات:/MyApplication |-- run.py |-- config.py |__ /app |-- __init__.py |-- /module_one |-- __init__.py |-- controllers.py |-- models.py |__ /templates |-- module_one |-- hello.html |__ /static |__ .. |__ .2. تعديل الملف run.py باستخدام برنامج nano:nano ~/MyApplication/run.pyنضع المحتويات التّالية بداخله: # Run a test server. from app import app app.run(debug=True)نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 3. تعديل الملف config.py باستخدام برنامج nano:nano ~/MyApplication/config.pyنضع المحتويات التّالية بداخله: DEBUG = True THREADS_PER_PAGE = 4 CSRF_ENABLED = True CSRF_SESSION_KEY = "secret"نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 4. تعديل الملف app/init.py باستخدام برنامج nano:nano ~/MyApplication/app/__init__.pyنضع المحتويات التّالية بداخله: from flask import Flask, render_template app = Flask(__name__) app.config.from_object("config") from app.module_one.controllers import module_one app.register_blueprint(module_one) نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 5. تعديل الملف app/module_one/controllers.py باستخدام برنامج nano:nano app/module_one/controllers.pyنضع المحتويات التّالية بداخله: from flask import Blueprint, request, render_template module_one = Blueprint("auth", __name__, url_prefix="/auth") @module_one.route("/hello") def hello(): return render_template("module_one/hello.html")نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 6. تعديل الملف app/templates/module_one/hello.html باستخدام برنامج nano:nano app/templates/module_one/hello.htmlنضع المحتويات التّالية بداخله: <DOCTYPE html> <html lang="en"> <head> <title>{% block title %}My Site{% endblock %}</title> {% block css %} {% endblock %} <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> Hello, world! </body> </html>نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. البدء بتوزيع وحزم التطبيقبعد إنشاء بنية التطبيق المثالية لموقع ويب يستخدم flask، نستطيع المتابعة بالقيام بالخطوة الأولى في إعداد التوزيعة. 1. تبديل بنية المجلدمن أجل حَزْم تطبيقنا بشكل جيّد نحتاج للقيام ببعض الإضافات لبُنية مجلّدنا. /MyApplication |-- run.py |__ /app |-- __init__.py |-- /module_one |-- __init__.py |-- controllers.py |-- models.py |__ /templates |-- module_one |-- hello.html |__ /static |__ .. |__ . |-- setup.py # Distribution setup file |-- README.txt # Read-me file |-- MANIFEST.in # Distribution manifest file |-- CHANGES.txt # Changes logفلنقم بتبديل بنية المجلد لإنشاء الملفات الضروريّة: touch ~/MyApplication/setup.py touch ~/MyApplication/README.py touch ~/MyApplication/MANIFEST.py touch ~/MyApplication/CHANGES.py mv ~/MyApplication/run.py ~/MyApplication/bin/run2. إنشاء الملف setup.pynano ~/MyApplication/setup.pyنضع المحتويات التّالية بداخله: from distutils.core import setup setup( # Application name: name="MyApplication", # Version number (initial): version="0.1.0", # Application author details: author="name surname", author_email="name@addr.ess", # Packages packages=["app"], # Include additional files into the package include_package_data=True, # Details url="http://pypi.python.org/pypi/MyApplication_v010/", # # license="LICENSE.txt", description="Useful towel-related stuff.", # long_description=open("README.txt").read(), # Dependent packages (distributions) install_requires=[ "flask", ], )نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. 3. إنشاء الملف MANIFEST.inإن كنا نحتاج إلى شحن دلائل إضافية (ثابتة static أو قوالب templates) يجب علينا التصريح عنها في manifest لكي يتمّ حَزْمها، سنقوم بفعل هذا في MANIFEST.in. nano ~/MyApplication/MANIFEST.inنضع المحتويات التّالية بداخله: recursive-include app/templates * recursive-include app/static *نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y. هذا هو كل ما نحتاجه ، الآن حِزمة توزيعة بايثون جاهزة ليتمّ تثبيتها وشحنها. 4. ملفات إضافيةيجب دومًا أن نتذكّر أنّه من أجل الحصول على توزيعة كاملة يجب أن يكون الملف/الدليل محتويًا على الملفّات التالية ومربوطًا بها: README.txtMANIFEST.inLICENSE.txtالتعامل مع التطبيق الجاهز للتوزيعبعد أن انتهينا من إنشاء تطبيقنا ومن ثم أجرينا التبديلات الضرورية لبنية الملف لتحضيره لبناء توزيعة لا تحتوي على أيّة أخطاء، نستطيع الآن البدء بالمرور على عمليّات الحَزْم. 1. كيف نقوم بإنشاء ملف التوزيعمن أجل توليد نسخة ملف التوزيع، نقوم بتنفيذ الأمر التالي: cd ~/MyApplication python setup.py sdistسيذهب هذا الأمر إلى إعداداتنا، يطبع العمليات التي يتمّ تنفيذها ويُوَلِّد ملف أرشيف tar داخل الدليل الجديد diet، مشابهًا لما يلي: # root@hostname:~/MyApplication# ls dist # MyApplication-0.1.0.tar.gzملاحظة: بما أنّنا لم نقم بتأهيل جميع المجلدات الفرعية (مثل static) وتعاملنا مع ملفات إضافية (مثل README.txt)، فقد نحصل على بعض التحذيرات أثناء عمليّة الإنشاء. 2. كيفية تثبيت التطبيقيستطيع الآخرون من الآن فصاعدًا تثبيت واستخدام التّطبيق باستخدام ملف setup.py الذي أنشأناه. من أجل تثبيت التطبيق نقوم بتنفيذ الأوامر التالية: python setup.py installإن كان هذا التثبيت من أجل التطوير وأردنا تثبيت المُتطلّبات سنقوم بتنفيذ ما يلي: python setup.py develop3. كيفية مشاركة التطبيقإن أردنا مشاركة الشيفرة على دليل حِزَم بايثون، نستطيع فعل ذلك عن طريق بدء الإجراء register كما يلي: python setup.py registerنستطيع إكمال هذا الإجراء عبر اتّباع التّعليمات التي تظهر على الشّاشة. وإن كنّا نملك تسجيل دخول مسجل registered login من أجل الرفع Upload فقط نستطيع استخدام الأمر التالي: python setup.py sdist upload4. كيفية إنشاء حزم من الإصدارات الجديدة للتطبيقنقوم بتحرير الملف setup.py عن طريق مُحرّر نصوص (مثل nano) وتعيين رقم الإصدار الجديد "version="0.1.1.نقوم بتحرير الملف CHANGES.txt لنعكس التغييرات.نقوم بإجراء التّعديلات الضّروريّة على الملفين LICENSE.txt و README.txt.رفع الشّيفرة بعد الخطوة السّابقة.ترجمة -وبتصرّف- لـلمقال How To Package And Distribute Python Applications لصاحبه O.S. Tezer. حقوق الصورة البارزة: Designed by Freepik.
  17. تعرّفنا في الدرس الأول -من سلسلة الدروس هذه المُكوّنة من درسين- على الأنواع الثّلاثة للمحتوى المُخصّص Custom Content التي نستطيع إنشاءها باستخدام ووردبريس وتحدّثنا عن فائدة كلّ واحدٍ منها. هذه الأنواع هي: المنشورات المُخصّصة Custom posts. أنواع التّصنيفات المُخصّصة Custom taxonomies. الحقول المُخصّصة Custom fields. نظرنا بالتفصيل في ذلك الدّرس إلى أنواع المنشورات المُخصّصة custom post types موضّحين كيفيّة إنشائها وعرضها على موقعنا. سننتقل في الدرس الثاني والأخير من هذه السلسلة إلى أنواع التّصنيفات المُخصّصة Custom taxonomies والحقول المُخصّصة Custom fields، لنتعلّم كيفية إنشائها سواءً باستخدام إضافة plugin أو عبر برمجتها بأنفسنا، وكيفيّة عرضها على واجهة موقعنا، فلنبدأ بأنواع التّصنيفات المُخصّصة. إنشاء Taxonomy مُخصّص كما وجدنا مع أنواع المنشورات المُخصّصة بإمكانك أن تستخدم إضافة لإنشاء Custom Taxonomy أو تقوم ببرمجتها بنفسك في قالبك Theme أو حتى بشكلٍ أفضل أن تجعلها على شكل إضافة، إنّ الإضافات التي تستطيع استخدامها لفعل هذا هي نفسها التي استخدمناها لأنواع المنشورات المُخصّصة: تزوّدك CustomPress بواجهة لإنشاء أنواع المنشورات المُخصّصة، التّصنيفات والحقول المُخصّصة وهي سهلة الاستخدام كثيرًا، إن كنت تريد إنشاء العديد من أنواع المحتوى المُخصّص ستوفر عليك هذه الإضافة عناء تثبيت أكثر من إضافة. إنّ إضافة Custom Post Type UI هي أكثر الإضافات المجانيّة انتشارًا لإضافة أنواع المنشورات المُخصّصة على مستودع الإضافات، فهي تسمح لك بإضافة أنواع المنشورات المُخصّصة وأنواع التّصنيفات ولكن لا تسمح بإنشاء الحقول المُخصّصة، واجهتها ليست سهلة الاستخدام تمامًا مثل واجهة CustomPress، مع المزيد من المصطلحات التقنيّة لكي تتمكّن من فهمها، ولكنّها تقوم بعملها. ولكن إن كنتَ واثقًا من نفسك بما فيه الكفاية لكي تُبرمج Custom taxonomies بنفسك ، فها هي طريقة فعل ذلك. 1. برمجة Custom taxonomy لا تختلف برمجة Custom taxonomy كثيرًا عن برمجة أنواع جديدة من المنشورات المُخصّصة، حيث تعطينا ووردبريس الدالّة ()register_taxonomy لعمل هذا والتي نقوم أيضًا بإرفاقها إلى خطّاف init . تستطيع إمّا إضافة الشّيفرة إلى ملف دالّات قالبك Theme’s Functions file أو إنشاء إضافة منفصلة، من الأفضل إنشاء إضافة لأنّك لو قمت بتغيير قالبك مستقبلًا فلن تخسر نوع تصنيفاتك Taxonomy، وهذا ما سنقوم به هنا. ابدأ بإنشاء ملف فارغ يُدعى taxonomies.php واحفظه إلى مجلّد plugins الموجود داخل مجلّد wp-content. افتح الآن ملفك باستخدام مُحرّر شيفرة Code Editor وأضف إليه ما يلي: <?php /*Plugin Name: Create Product Category Taxonomy Description: This plugin registers the 'product category' taxonomy and applies it to the 'product' post type. Version: 1.0 License: GPLv2 */ ?> تُخبر هذه الشّيفرة ووردبريس باسم إضافتك وتزوّده بوصف description والذي ستراه عندما تقوم بتفعيل إضافتك لاحقًا. الآن أضف ما يلي تحت السطر الذي يحتوي على */ وفوق السطر الذي يحتوي على ?> : function wpmudev_register_taxonomy() { } add_action( 'init', 'wpmudev_register_taxonomy' ); سيقوم هذا بإنشاء دالّة فارغة والتي ستحتوي على شيفرة من أجل نوع تصنيفاتك، ومن ثمّ تُضيفه إلى خطّاف init، إنّ إضافته إلى الخطّاف يجعلك متأكّدًا من أنّ ووردبريس يقوم بتشغيل دالّتك في الوقت المناسب، وبدونه لن يحدث شيء. أضف الآن ما يلي داخل الحاضنتين: // set up labels $labels = array( 'name' => 'Product Categories', 'singular_name' => 'Product Category', 'search_items' => 'Search Product Categories', 'all_items' => 'All Product Categories', 'edit_item' => 'Edit Product Category', 'update_item' => 'Update Product Category', 'add_new_item' => 'Add New Product Category', 'new_item_name' => 'New Product Category', 'menu_name' => 'Product Categories' ); // register taxonomy register_taxonomy( 'productcat', 'product', array( 'hierarchical' => true, 'labels' => $labels, 'query_var' => true, 'show_admin_column' => true ) ); فلنقم بالمرور بالتّفصيل على هذه الشيفرة لنفهم ما تعمله بشكلٍ أفضل. نقوم في البداية بإنشاء مجموعة من labels لـِ Taxonomy الخاصة بك والذي سيتمّ استخدامه في شاشات لوحة التّحكم، على الروابط، الأزرار وعناوين الصّفحات. نستخدم بعد ذلك الدّالّة ()register_taxonomy لتسجيل نوع تصنيفاتك عن طريق هذه المُعاملات parameters: اسم نوع التّصنيفات، productcat، تحتاجه لكي يعمل نوع تصنيفاتك. نوع المنشورات الذي ستُطبِّق عليه نوع تصنيفاتك، قمنا هنا بتحديده كمنتج product ولكن بإمكانك استخدام نوع تصنيفاتك مع أكثر من نوع منشورات (بما فيها أنواع المنشورات المُضَمّنة مثل المنشورات posts والصفحات pages والمرفقات attachments) بتضمينها كلّها في مصفوفة array. Hierarchical: قم بتعيينه إلى true لكي يسلك نوع تصنيفاتك سلوك تصنيفات categories ويكون بشكلٍ شجري hierarchical، إن لم ترغب أن يكون بشكل شجريًا مثل الوسوم tags فقم بتعيينه إلى false. Labels: تُخبر هنا ووردبريس أن يستخدم الـ Labels المُعرّفة مُسبقًا. query_var: يعطيك تعيينه إلى true مرونة أكثر إن كنت ترغب بكتابة استعلام مُخصّص custom query لإيجاد المنتجات التي توافق شرط taxonomy term معيّن. show_admin_column: يعني تعيينه إلى true أنّك تعرض قائمة من منتجاتك في لوحة تحكم ووردبريس، سيملك نوع التّصنيفات عمودًا من أجلك لكي تعرف أيّة شروط taxonomy تنطبق على أيّة منتجات، سنرى كيف يبدو هذا قريبًا. الآن احفظ ملفك ، ستبدو كامل الإضافة كما يلي: <?php /*Plugin Name: Create Product Category Taxonomy Description: This plugin registers the 'product category' taxonomy and applies it to the 'product' post type. Version: 1.0 License: GPLv2 */ // register two taxonomies to go with the post type function wpmudev_register_taxonomy() { // set up labels $labels = array( 'name' => 'Product Categories', 'singular_name' => 'Product Category', 'search_items' => 'Search Product Categories', 'all_items' => 'All Product Categories', 'edit_item' => 'Edit Product Category', 'update_item' => 'Update Product Category', 'add_new_item' => 'Add New Product Category', 'new_item_name' => 'New Product Category', 'menu_name' => 'Product Categories' ); // register taxonomy register_taxonomy( 'productcat', 'product', array( 'hierarchical' => true, 'labels' => $labels, 'query_var' => true, 'show_admin_column' => true ) ); } add_action( 'init', 'wpmudev_register_taxonomy' ); ?> الآن وقد اكتملت إضافتك تحتاج لتفعيلها، في لوحة تحكّم ووردبريس اذهب إلى: Plugins -> Installed Plugins لترى إضافتك معروضة: اضغط على رابط التّفعيل Activate لكي تقوم بتفعيل إضافتك، سترى الآن أنّه عندما تضغط على المنتجات Products في قائمة لوحة التّحكّم سيتمّ عرض النّوع الجّديد للتّصنيف: كلّ ما تحتاج إليه الآن أن تضيف بعضًا من تصنيفات المنتجات بنفس الطريقة التي تضيف بها التّصنيفات العاديّة، سيكون بعدها بإمكانك اختيار تصنيف أو أكثر منها في كلّ مرّة تُضيف بها منتجًا. ملاحظة: إنّ نوع تصنيفاتك الجّديد هو ليس تصنيفًا category، بل هو taxonomy كما التّصنيف هو تصنيف، لكي تستخدمه يجب عليك إضافة شروط terms، شروط نوع تصنيفاتك (على سبيل المثال تصنيفات المنتجات التي تضيفها) مشابهة للتصنيفات ذاتها والتي هي عبارة عن شروط في تصنيف taxonomy. عرض أرشيف شروط taxonomy على موقعك بعد أن أضفت بعض الشروط إلى نوع تصنيفاتك ستحتاج لعرض قائمة من المنتجات لكلّ شرط على موقعك. 1. تحديث الروابط الدائمة Permalinks لن يعرض ووردبريس أرشيف لشروط نوع تصنيفاتك حتى تقوم بتحديث إعدادات الروابط الدائمة. من لوحة تحكّم ووردبريس اذهب إلى: Settings > Permalinks. تأكد من أنّه تم اختيار post name. اضغط على زر حفظ التغييرات Save Changes. سيكون ووردبريس الآن قادرًا على توليد الروابط الصحيحة لشروط نوع تصنيفاتك. ملاحظة: تحتاج فقط لعمل هذا مرّة واحدة بعد إنشاء taxonomy وليس كل مرّة تضيف فيها شرطًا جديدًا. 2. إضافة أرشيف شرط taxonomy إلى قائمة التصفح Navigation Menu إنّ إضافة صفحات أرشيف نوع تصنيفاتك إلى قائمة التصفح أسهل من إضافة أرشيف نوع المنشورات (كما فعلنا في الدرس السابق من هذه السلسلة) ، اتبع هذه الخطوات: من لوحة تحكم ووردبريس اذهب إلى: Appearance > Menus. سترى على يسار الشاشة قائمة أنواع المحتوى التي تستطيع إضافتها إلى قائمتك، ومنها تصنيفات المنتجات Product Categories (إن لم تكن ظاهرة اضغط على نافذة خيارات الشّاشة Screen Options الموجودة بأعلى وأيمن الشاشة ثم ضع صح في خانة التأشير Checkbox عند Product Categories). اضغط على Product Categories لكي تكشف كل الشروط التي أضفتها. أضف كلّ واحد منها إلى القائمة واسحبها إلى المكان الذي تريده. اضغط على حفظ القائمة Save Menu لحفظ التّغييرات، لا تفوّت هذه الخطوة. في هذه الصّورة أضفنا تصنيف منتج وأدخلناه تحت رابط المنتجات Products التي قمنا بإنشائها في الدرس الأول من هذه السّلسلة: عندما تذهب الآن إلى واجهة موقعك وتضغط على روابط أرشيف شروط نوع تصنيفاتك سترى قائمة من المنتجات التي توافق ذلك الشرط : 3. استخدام ملفات قالب Template لأرشيف الشروط إن أردت عرض أرشيف لشروط نوع تصنيفاتك بشكلٍ مختلف عن الطّريقة التي يعرض بها موقعك الأرشيف تستطيع إنشاء ملف template خاص في قالبك Theme أو حتى مجموعة ملفات قالب template لكل واحد من الشروط. عندما يعرض ووردبريس صفحة الأرشيف لشرط نوع التّصنيفات، سيبحث خلال ملفات قالبك باستخدام القالب الشجري template hierarchy ويستخدم أول ملف يصادفه: ملف لعرض الأرشيف بالنسبة لشرط نوع تصنيفات مُحدّد: بالنسبة للشرط الذي يُوافق المنتجات المتميّزة featured يُدعى هذا الملف taxonomy-productcat-featured-products.php، لاحظ أنّنا نستخدم اسم نوع التّصنيف متبوعًا بلاحقة slug لشرط نوع التّصنيف لإنشاء اسم الملف. ملف لعرض أرشيف لشرط نوع التّصنيف لكل الشّروط في taxonomy، يُدعى taxonomy-productcat.php. ملف لعرض أرشيف لكل أنواع التّصنيفات المُخصّصة، يُدعى taxonomy.php. ملف لعرض كل أنواع الأرشيف يُدعى archive.php. ملف عام لكل المحتوى يُدعى index.php. يعمل ووردبريس من خلال هذه القائمة ويستخدم أول ملف يجده، يعمل موقعنا على قالب the twenty fifteen theme والذي يملك ملف يُدعى archive.php لذا يستخدم هذا الملف. إن أردت عرض أرشيف نوع تصنيفاتك بشكلٍ مُختلف عن الأرشيف العادي (على سبيل المثال إزالة المقتطفات excerpts وإضافة صور مميّزة featured images) تستطيع إنشاء نسخة من الملف archive.php في قالبك وتقوم بتسميته taxonomy.php ومن ثمّ تحريره لعرض أرشيفك بالطريقة التي ترغب بها، ولكن حتى لو لم تقم بذلك فالأمر الجيّد هنا أنّ ووردبريس سيجد دومًا ملف قالب template file مناسب لعرض أرشيف لشرطك. فلننتقل الآن إلى النوع الأخير من المحتوى المُخصّص وهو الحقول المُخصّصة. إنشاء حقول مُخصّصة تستطيع إنشاء حقول مُخصّصة بإحدى طريقتين، استخدام الواجهة الافتراضية التي يُزوّدنا بها ووردبريس أو باستخدام إضافة plugin، قد يكون استخدام إضافة أسهل استخدامًا ويُقّدم لك بعضًا من الخيارات القويّة الأخرى لتحرير وعرض حقولك المُخصّصة ولكنّ هذا ليس ضروريًا دومًا. نجد من بين أفضل الإضافات لإنشاء حقول مُخصّصة: CustomPress: بالإضافة إلى أنّها تُمكّنك من إنشاء أنواع منشورات مُخصّصة و taxonomies تستطيع استخدام هذه الإضافة أيضًا لإنشاء حقول مُخصّصة. Advanced Custom Fields: هذه هي الإضافة الأكثر استخدامًا لإنشاء حقول مُخصّصة، الإصدار الأساسي مجاني على مستودع إضافات ووردبريس، تُقدّم لك بعض الميّزات القويّة لتحرير وإنشاء حقول مُخصّصة. إن لم تكن ترغب باستخدام إضافة، تستطيع إنشاء حقول مُخصّصة باستخدام لوحة تحكّم ووردبريس، وهذه هي الطريقة: 1. إنشاء حقول مُخصّصة باستخدام شاشات لوحة التّحكّم الافتراضية إن توجّهت إلى شاشة تعديل المنشورات لواحد من منشوراتك (أو كنت تقوم بإنشاء منشور جديد) فقد ترى مربّع بيانات وصفيّة metabox للحقول المُخصّصة تحت جزء التحرير الرئيسي، تستطيع عرضها إن لم تكن ظاهرة بفتح نافذة إعدادات الشّاشة Screen Options الموجودة بأعلى ويمين الشاشة، اضغط على مربّع Custom Fields، أغلق النافذة وسترى مربّع البيانات الوصفيّة metabox قد ظهر أسفل محتواك: لإضافة حقل مُخصّص تستطيع إمّا اختيار مفتاح موجود مُسبقًا من قائمة منسدلة على الجهة اليسرى أو أضف واحدًا جديدًا بالضّغط على رابط Enter New وكتابته فيها، بعد ذلك تكتب القيمة لحقلك المُخصّص. قمنا هنا بإنشاء حقل مُخصّص لمنتج أضفناه، والذي مفتاحه هو السّعر Price وقيمته 15.00: بعد أن قمت بإضافة المفتاح والقيمة يجب أن تضغط على زر إضافة حقل مُخصّص Add Custom Field لحفظ حقلك المُخصّص، فلن يقوم ووردبريس بحفظه عندما تضغط زر نشر Publish لمنشورك. تستطيع إضافة العدد الذي تحتاجه من الحقول المُخصّصة لمنشوراتك لتخزين بياناتك، لا تنسَ أن تحفظ منشورك بعد أن قمت بحفظ حقولك المُخصّصة. إذاً هذه هي طريقة إضافة حقل مُخصّص باستخدام واجهة لوحة التّحكّم الافتراضية، دعنا الآن نلقي نظرة على كيفيّة عرض حقولك المُخصّصة على واجهة موقعك. عرض الحقول المُخصّصة على موقعك لن يعرض ووردبريس بشكل افتراضي القيم التي أدخلتها في حقولك المُخصّصة ما لم يكن قالبك مُعدًّا لفعل هذا، ربّما تجد أنّ قالبك يأتي مزودًا بدعم للحقول المُخصّصة ويقوم بعرض كل حقولك المُخصّصة على صفحة واحدة لكل منشور، ولكن غالبًا لن يقوم بذلك. لذا ستحتاج لإضافة وسم قالب template tag لفعل هذا. إنّ وسم القالب هو عبارة عن نوع دالّة والتي تُدخلها إلى ملف قالب theme file لتُخبر ووردبريس أن يعرض بعض البيانات. يعطينا ووردبريس خيارًا من وسوم القالب لعرض حقولنا المُخصّصة: ()the_meta يعرض كل أنواع الحقول المُخصّصة لمنشور ما، نستخدمه داخل حلقة loop وسيعرض كل مفاتيح وقيم الحقول المُخصّصة بدون أن يُعطينا قدرة على التّحكّم بذلك. ()get_post_meta يعطينا تحكّمًا أكثر، يملك مُعاملات parameters نستطيع استخدامها لتحديد أيّ الحقول المُخصّصة نريد أن نحصل عليها وإذا ما كنّا نرغب فقط باسترجاع قيمة واحدة إن كان منشورنا يملك عدّة حقول مُخصّصة بنفس المفتاح، لا يقوم فعليًا بعرض حقولنا المُخصّصة بل يقوم فقط بجلبها، ولكي نعرضها يجب أن نستخدم ()echo get_post_meta. ()get_post_custom_values يسمح لنا بجلب كل القيم للحقول المُخصّصة والتي تملك نفس المفتاح الذي نقوم بتحديده، وهي تحتاج أيضًا لاستخدام الأمر echo قبل أن تعرض أي شيء. تقوم بشكل طبيعي بإضافة واحدة منها إلى ملف القالب template file داخل قالبك والذي يقوم بعرض منشورات مفردة أو أرشيف داخل حلقة loop، وإن أردت بشكلٍ بديل أن تعرض حقول مُخصّصة لعدد من المنشورات في مكان آخر من الموقع تستطيع استخدام ()get_post_meta خارج الحلقة. لن نقلق الآن حيال هذا، بل سننظر بدلًا من ذلك إلى كيفيّة فعل هذا داخل الحلقة. إن لم تُصادف الحلقة loop من قبل، فهي كتلة من الشيفرة block of code في داخل template files لقالبك والتي تقوم بجلب العنوان والمحتوى لكل منشور من قاعدة البيانات وتقوم بعرضه. الخطوة الأولى هي أن تفتح ملف single.php في مُحرّر شيفرة code editor وتجد الحلقة، تبدأ الحلقة بسطر من الشيفرة مشابه لهذا: while ( have_posts() ) : the_post(); ستجد تحت هذا السطر وسوم القالب كـ ()the_title و ()the_content، تحتاج لإضافة حقولك المُخصّصة بينها، سنقوم بإضافة حقولنا المُخصّصة فورًا بعد العنوان. ملاحظة: إن كنت تعمل على قالب twenty fifteen ستجد أنّه لا يملك الحلقة في ملف single.php، بدلًا من ذلك يقوم بتضمين ملف يُدعى content.php، لتحرير وعرض نوع منشورات المنتج قم بإنشاء نسخة من ملف content.php وقم بتسميتها content-product.php وحرّرها. لعرض كلّ الحقول المُخصّصة للمنشور أدخل الشيفرة التالية: the_meta(); احفظ ملف قالبك. عندما نزور الآن واجهة موقعنا نستطيع رؤية الحقل المُخصّص الذي أضفناه لمنتجنا: يتم عرضه بشكل افتراضي بطريقة قائمة نقطية bulleted list، تستطيع تنسيق هذه القائمة كما تريد باستخدام CSS. ولكن ماذا لو أردنا أن نتحكّم أكثر بالطّريقة التي يتمّ بها عرض الحقل المُخصّص؟ نستطيع استخدام ()get_post_meta. افتح ملف single.php مرة أخرى وقم بإيجاد الشيفرة التي أضفتها ، قم باستبدالها بما يلي: $price = get_post_meta( get_the_ID(), 'Price', true ); if( ! empty( $price ) ) { echo '<p>Price: $' . $price . '</p>'; } دعنا نلقي نظرة على ما تفعله هذه الشّيفرة: في البداية تحصل على الحقل المُخصّص لهذا المنشور الذي يملك المفتاح Price وتقوم بتخزينه في متغير variable يُدعى price$. تتحقق أنّ الحقل المُخصّص ليس فارغًا. إن لم يكن كذلك تقوم بعرض السّعر price داخل وسم فقرة paragraph tag مع بعض النّص قبله. الآن احفظ الملف وألقِ نظرة على صفحتك ، تبدو الصّفحة لدينا هكذا: كما ترى فقد أعطانا هذا تحكّمًا أكثر، فلن نتمكّن فقط من تحديد أيّ حقل مُخصّص نريد عرضها فيه، بل نستطيع إضافة نص قبلها ووضعها داخل عنصر فقرة إن أردنا ولو كنّا نملك حقول مُخصّصة أكثر لعرضها نستطيع إعادة الشيفرة بأي ترتيب نريده. ملاحظة: لأننا استخدمنا قالب Twenty Fifteen في هذا المثال فلم نقم بتحرير الملف مباشرة داخل القالب بل قمنا بدلًا من ذلك بإنشاء قالب ابن Child Theme وقمنا بعمل ملفات جديدة، يعني هذا أنّه عندما نقوم بتحديث قالب Twenty Fifteen فلن نخسر الملفات الجديدة التي أضفناها، إن كنت ستقوم بنفس الشيء ننصحك باتباع هذا الدّليل الرائع لإنشاء قوالب أبناء child themes. الخلاصة إن تتبّعت كلا الدّرسين من هذه السّلسة ستعرف كم من الممكن أن يكون المحتوى المُخصّص مفيدًا وقويًا في ووردبريس، يملك كلّ واحد من أنواع المنشورات المُخصّصة، أنواع التّصنيفات والحقول المُخصّصة استخداماته وطرقه الخاصّة للحصول على أقصى ما تريد من نوع المحتوى. تعلّمنا في هذا الدرس كيفيّة تسجيل custom taxonomy وعرض صفحات أرشيفه على موقعنا، وكيفية إنشاء حقول مُخصّصة وعرضها على الموقع أيضًا. هل تستخدم custom taxonomies والحقول المُخصّصة في موقع ووردبريس الخاص بك؟ لأيّة أشياء تجدها مفيدة أكثر؟ قم بكتابك كلامك في التعليقات. ترجمة -وبتصرّف لـلمقال Creating Custom Content in WordPress: Taxonomies and Fields لصاحبه Rachel McCollin.
  18. من المتفق عليه عالميًّا الآن أنّ ووردبريس WordPress أكثر من مجرّد منصّة تدوين، بل هو نظام إدارة محتوى Content Management System. ولكن في وجهة نظري أنّ ما يجعل ووردبريس نظام إدارة محتوى قوي هو قدرته على إنشاء محتوى مُخصّص وعرضه بالطريقة التي تُريدها تمامًا. سنتكلّم في هذا الدرس عن الأنواع الثلاثة للمحتوى المُخصّص في ووردبريس وسنرى كيف نقوم بإنشاء ذلك المحتوى، سنقوم بتغطية: أنواع المنشورات المُخصّصة Custom Post Types أنواع التّصنيفات المُخصّصة Custom taxonomies الحقول المُخصّصة Custom fields سنتطرّق في هذا الدرس -وهو الدرس الأول من سلسلة مُكوَّنة من درسين- إلى مفهوم المحتوى المُخصّص في ووردبريس وسنشرح كيفية التّسجيل والاستفادة من أنواع المنشورات المُخصّصة، بالإضافة إلى استكشاف كيف يقوم ووردبريس بعرض المنشورات التي نقوم بإنشائها باستخدام ذلك النوع المُخصّص للمنشورات. فهم واستخدام كل نوع من أنواع المحتوى المُخصّص من المفيد قبل البدء بإنشاء محتوى مُخصّص أن نعرف ما يفعله كلّ نوع منها وفي أيّة حالات قد نستخدمها، فلنبدأ بأنواع المنشورات المُخصّصة. 1. أنواع المنشورات المُخصّصة يأتي ووردبريس مُجهّزًا بشكلٍ افتراضي بمجموعة من أنواع المنشورات وهي: المنشورات Posts. الصفحات Pages. المرفقات Attachments. عناصر قائمة التّصفّح Navigation menu items. المراجعات Revisions. الروابط Links (إن كنتَ تستخدم ميّزة المدوّنات blogroll). تستطيع أيضًا إنشاء أنواع خاصة بك من المنشورات المُخصّصة لتخزين المحتوى الذي لا يندرج تحت أيّ من التصنيفات السابقة، قد تتضمن الأمثلة المنتجات في موقع للتجارة الإلكترونية e-commerce أو الأحداث events في موقع للعروض Listings site، إن كنت استخدمت سابقًا إضافة Plugin لإنشاء متجر، عرض لحدث event listing أو أي نوع آخر من المحتوى الفريد فقد أنشأتَ بالمصادفة نوعًا جديدًا من المنشورات المُخصّصة حتى بدون أن تعرف ذلك. تستخدم العديد من الإضافات أنواع المنشورات المُخصّصة، نذكر على سبيل المثال: MarketPress: تستخدم نوع منشورات مُخصّصة للمنتجات. CoursePress Pro: تستخدم أنواع منشورات مُخصّصة للدروس، المدرّبين والطلّاب. Support System: تستخدم أنواع منشورات مُخصّصة للتذاكر والأسئلة الشائعة FAQs. يوجد العديد من الأمثلة الأخرى ولكن تعطينا الأمثلة السابقة فكرة عن استخدامات أنواع المنشورات المُخصّصة. من الهام أن تتذكر أنّ أنواع المنشورات المُخصّصة هي ليست منشورات، فهي لا تملك أيّة علاقة مباشرة مع المنشورات ويجب أن تفكر بهما بشكل منفصل، يُمكنك إعداد (أو تسجيل) أنواع خاصة بك من المنشورات المُخصّصة لتسلك سلوك المنشورات أو الصفحات، الأمر عائدٌ إليك، فإن تمّ إعدادها كالمنشورات سيكون بإمكانك عرض صفحات الأرشيف الخاصة بها، أمّا إن تمّ إعدادها كالصفحات فستكون بشكلٍ شجري hierarchical، يتم إعداد معظم أنواع المنشورات المُخصّصة لتسلك سلوك المنشورات ولكن لا يعني هذا أنّ أنواعك يجب أن تكون كذلك. 2. أنواع التصنيفات المُخصّصة وكما وجدنا مع أنواع المنشورات المُخصّصة فإنّ أنواع التّصنيفات المُخصّصة تضيف إلى أنواع التّصنيفات الموجودة مسبقًا في ووردبريس، والتي هي: التصنيفات Categories. الوسوم Tags. هيئات المنشور Post Formats. تصنيفات الرابط Link categories (والتي تنطبق على الروابط في المدوّنة blogroll إن كنت تستخدمها). تستطيع أيضًا إنشاء أنواع خاصة بك من التّصنيفات المُخصّصة لترتيب المحتوى بشكل فعال أكثر، من الهام أن تتذكر أنّ نوع التّصنيف المُخصًص هو ليس تصنيف Category ولا يملك أيّة علاقة بالتصنيفات Categories، بدلًا من ذلك فإنّ التصنيف Category هو فقط واحد من أنواع التّصنيفات المستخدمة من قبل ووردبريس. سيعطيك استخدامك للتصنيفات المُضمّنة مع ووردبريس في بعض الأحيان كل ما تحتاجه لترتيب المحتوى لديك، على سبيل المثال إن كنت تحتاج أن تقدّم بنية تصنيفات شجريّة hierarchical category structure، ولكن في بعض الأحيان لن يكون هذا كافيًا بالنسبة لك خاصة إن كنت تريد أن تتمكن من عرض المنشورات باستخدام أكثر من taxonomy واحد أو كنت تستخدم نوع منشورات مُخصّصة وتريد استخدام taxonomy منفصل له. تتضمن الأمثلة ما يلي: على موقع للتجارة الإلكترونية: تكون أنواع التّصنيفات للمنتج Product غالبًا متعددة كاللون والحجم والنسيج بالنسبة لمتجر ألبسة. على موقع لعروض الأحداث: taxonomies لنوع الحدث ومكانه والمزيد من ذلك. على قاعدة المعرفة knowledgebase: إنشاء taxonomies لترتيب البيانات بطريقة شاملة، على سبيل المثال إن كانت قاعدة معرفة لتطوير الوِب فربّما تستخدم taxonomies للغات البرمجة، درجة الصعوبة والمنصّات platforms. نذكر مرّة آخرى أنّ الإضافات تستخدم أنواع التّصنيفات المُخصّصة، يوجد على سبيل المثال في إضافة MarketPress تصنيفات ووسوم للمنتج بشكلٍ مستقل عن تصنيفات ووسوم منشورات المدوّنة Blog posts، يوجد في CoursePress تصنيفات للدرس وفي نظام الدعم توجد أيضًا taxonomies لأنواع التذاكر وتصنيفات للأسئلة الأكثر شيوعًا FAQ. قبل أن تقرر إن كنت بحاجة تسجيل taxonomy مُخصّص فإنّك ستحتاج أن تسأل نفسك إن كان نظام التصنيفات الحالي يقوم بما تحتاجه، إن كان كل ما تحتاج إليه هو القدرة على إضافة شجرة hierarchy إلى تصنيفاتك فبإمكانك فعل هذا حاليًا. فإن كنّنا نقوم بتطوير موقع للتدريب على سبيل المثال وأردنا استخدام تصنيفات لترتيب المنشورات حسب المهارة أو المعلومات التي يتم تدريسها فبإمكاننا استخدام التصنيفات الشجرية hierarchical categories كما يظهر في هذه الصورة، تستطيع أن ترى هنا أننا نملك ثلاثة تصنيفات في المستوى الأعلى وهي: تطوير الإدارة management development، تطوير شخصي personal development ومهارات تقنيّة technical skills، مع وجود كافة التصنيفات الأخرى تحتها في المستوى التالي. ولكن ماذا لو تعقّدت الأمور أكثر قليلًا؟ فلنفرض أنّك أردت إضافة سلسلة من المنشورات حول التواصل مع فريقك. ستكون الأمور أسهل لو استطعنا فصل حقيقة أنّ هذه المنشورات هي للمدراء managers وتتعلّق في نفس الوقت بمهارات التواصل communication skills، لذلك من الأفضل ربّما لو استطعنا إضافة تصنيف taxonomy للجمهور audience واستخدامه لتحديد المنشورات للمدراء managers بدلًا من أن نملك تطوير الإدارة management development كتصنيف، باستطاعتنا إنشاء تصنيف جديد للجماهير audiences، بهذه الطريقة نستطيع تحديد الموضوعات المتعدّدة ومجموعات الجمهور المتعّددة لكل منشور. سنرى كيفية إنشاء taxonomy مثل هذا في الدرس القادم من سلسلة الدروس هذه، حالما نقوم بإنشائها سيكون بإمكاننا الاختيار من كلا المجموعتين categories و audience في شاشة تعديل المنشور كما هو ظاهر في الصورة السابقة. 3. الحقول المُخصّصة النوع الثالث من المحتوى المُخصّص هو الحقل المُخصّص، يتمّ الإشارة له أيضًا بأنّه البيانات الوصفية Metadata للمنشور. يتكون الحقل المُخصّص من عنصرين يُمكنك رؤيتهما وتعديلهما في شاشة تعديل المنشور وهما المفتاح key والقيمة value، بإمكانك استخدام نفس المفتاح عدّة مرات للمنشورات المتعدّدة ولكن تملك كل منها قيمة فريدة يُعطي ووردبريس كل حقل مُخصّص تقوم بإنشائه مُعرّف ID فريد خاص به أيضًا، والذي يعني أنّ كلّ حقل مُخصّص لكل منشور هو فريد من نوعه حتى ولو كانت تملك نفس المفتاح والقيمة. يختلف هذا عن أنواع التّصنيفات المُخصًصة، فبالرغم أنّك تستطيع الاختيار من مفتاح موجود عند إنشاء حقل مُخصّص فلن يكون بإمكانك الاختيار من قيم موجودة استخدمتها سابقًا، يعني هذا بشكل عام أنّ أنواع التّصنيفات أفضل لترتيب وتصنيف البيانات. ملاحظة: تعطيك بعض الإضافات اختيارًا لكي تنتقي قيمة الحقل المُخصّص من صندوق قائمة منسدلة، ولكنها ستستخدم صندوق وصفي مُخصّص metabox يتم إنشاؤه من قبل الإضافة في شاشة تعديل المنشور بدلًا من واجهة الحقول المُخصّصة المعيارية التي يزودنا بها ووردبريس. ولكن توجد بعض الحالات التي يكون فيها استخدام حقل مُخصّص مفيدًا لترتيب البيانات، على سبيل المثال إن كنت تريد تخزين بيانات عدديّة، ففي موقع للتجارة الإلكترونيّة لن ترغب بإنشاء taxonomy لكل سعر محتمل، بل ستقوم بدلًا من ذلك بإدخال هذا في حقل مُخصّص، وتستطيع بعدها استخدام هذه البيانات للسماح للزبائن بتحديد المنتجات ذات السعر الأقل من 20$ على سبيل المثال أو ترتيبها بحسب السعر. تستطيع أيضًا استخدام الحقول المُخصّصة لتخزين البيانات غير العدديّة، مما يعني أنّه يمكن تخزين وعرض بيانات متماثلة بين المنشورات وعرضها بشكل منفصل عن جسم المنشور، على سبيل المثال في موقع عرض للوظائف jobs بإمكانك استخدام حقول مُخصّصة لتخزين الموقع، الراتب وعدد ساعات العمل لمكان شاغر. وهذا ما تفعله إضافة Jobs & Experts، فهي تستخدم تجميعة combination من الحقول المُخصّصة (يُشار إليها بـ “Job Meta”) و taxonomies (يُشار إليها بـ “Category and Skill”) لترتيب البيانات: بمجرّد أن تقوم بإضافة هذه البيانات سيتمكن زوار موقع الوظائف Jobs الخاص بك من ترتيب الوظائف بحسب الميزانية، عرض الأعمال التي لا تزال مفتوحة فقط ورؤية البريد الإلكتروني للاتصال وتاريخ الانتهاء لكل وظيفة معروضة بشكل بارز، يُستخدم نوع التّصنيف للمهارات بحيث نتمكّن من عرض صفحات الأرشيف لكل واحدة منها. سنتعلّم كيفية إنشاء حقولنا المُخصّصة في الدرس التالي من هذه السلسلة، سننتقل في هذا الدرس إلى إنشاء أنواع المنشورات المُخصّصة. إنشاء نوع منشورات مُخصّصة بعد أن قمت بتحديد أنّك تحتاج إلى نوع منشورات مُخصّصة توجد طريقتان لإنجاز هذا الأمر، برمجته بنفسك أو استخدام إضافة plugin، سأقوم قريبًا بشرح الكود الضروري لتسجيل نوع منشورات مُخصّصة في قالب Theme أو إضافة Plugin، ولكن دعنا نلقي نظرة على بعض الإضافات التي تستطيع استخدامها: تزوّدك CustomPress بواجهة لإنشاء أنواع المنشورات المُخصّصة، التصنيفات والحقول المُخصّصة وهي سهلة الاستخدام كثيرًا، إن كنت تريد إنشاء العديد من أنواع المحتوى المُخصّص ستوفر عليك هذه الإضافة عناء تثبيت أكثر من إضافة. إنّ إضافة Custom Post Type UI هي أشيع إضافة مجانيّة لإضافة أنواع المنشورات المُخصّصة على مستودع الإضافة plugin repository، فهي تسمح لك بإضافة أنواع المنشورات المُخصّصة وأنواع التّصنيفات ولكن لا تسمح بإنشاء الحقول المُخصّصة، واجهتها ليست سهلة الاستخدام تمامًا كما في CustomPress، مع المزيد من المصطلحات التقنيّة لكي تتمكّن من فهمها، ولكنّها تقوم بعملها. تستطيع القراءة أكثر عن الإضافات التي تساعدك على إنشاء محتوى مُخصّص في مراجعتنا عن أفضل إضافات أنظمة إدارة المحتوى the best CMS plugins. ولكن إن كنتَ ترتاح ببرمجة الأنواع الخاصّة بك فها هي طريقة تسجيل نوع منشورات مُخصّصة. 1. برمجة نوع المنشورات الخاصة بك يزوّدنا ووردبريس بدالّة تُدعى ()register_post_type تستطيع استخدامها لإنشاء نوع خاص بك من المنشورات المُخصّصة، يجب أن تضيف هذه الدالّة إلى ملف دالّات القالب أو بشكل أفضل إلى إضافة تقوم بإنشائها خصيصًا لهذا الأمر وتقوم بتشغيلها عبر hook init في ووردبريس. ملاحظة: من الأفضل أن تُسجّل النوع الخاص بك من المنشورات المُخصّصة في إضافة بدلًا من عمل ذلك في قالبك، لأنّك إن قمت في الحالة الأخيرة بتغيير قالبك في المستقبل فلن تخسر النوع الخاص بك من المنشورات المُخصّصة. تحتاج لمتابعة هذه التقنيّة إلى الوصول إلى ملفات ووردبريس الخاصة بك وإلى مُحرّر شيفرة Code editor، أوصي بتجربة هذه الطريقة على موقع للتطوير والاختبار وليس على موقعك الموجود على الإنترنت. ابدأ بإنشاء ملف فارغ جديد يُدعى post-types.php وقُم بحفظه في مجلّد plugins الموجود في مجلّد wp-content. أضف الآن الشيفرة التالية إلى ذلك الملف: <?php /*Plugin Name: Create Product Post Type Description: This plugin registers the 'product' post type. Version: 1.0 License: GPLv2 */ ?> تفتح هذه الشيفرة ملف الإضافة وتُخبر ووردبريس أنّها عبارة عن إضافة، تُزوّدنا أيضًا بعنوان title ووصف description والذي سيساعدك في تحديد الإضافة عند تفعيلها على موقعك. أضف الآن هذه الأسطر تحت السطر الذي يحتوي على */ وفوق سطر الإنهاء ?> : function wpmudev_create_post_type() { } add_action( 'init', 'wpmudev_create_post_type' ); سيقوم هذا بإنشاء دالّة تحمل الشيفرة لتسجيل نوع المنشورات الخاصّة بك وسيقوم بإرفاقها إلى init hook باستخدام الدالّة ()add_action، تتأكد هذه الدالّة من أنّ ووردبريس يقوم بتشغيل دالّتك في الوقت المناسب. تحتاج الآن لإضافة شيفرة النوع الخاص بك من المنشورات المُخصّصة داخل الأقواس curly braces: // set up labels $labels = array( 'name' => 'Products', 'singular_name' => 'Product', 'add_new' => 'Add New Product', 'add_new_item' => 'Add New Product', 'edit_item' => 'Edit Product', 'new_item' => 'New Product', 'all_items' => 'All Products', 'view_item' => 'View Product', 'search_items' => 'Search Products', 'not_found' => 'No Products Found', 'not_found_in_trash' => 'No Products found in Trash', 'parent_item_colon' => '', 'menu_name' => 'Products', ); //register post type register_post_type( 'product', array( 'labels' => $labels, 'has_archive' => true, 'public' => true, 'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'thumbnail','page-attributes' ), 'taxonomies' => array( 'post_tag', 'category' ), 'exclude_from_search' => false, 'capability_type' => 'post', 'rewrite' => array( 'slug' => 'products' ), ) ); دعنا نلقي نظرة أقرب على ما تفعله هذه الشيفرة، يخبر المقطع الأول ووردبريس أيّة تسميات labels تريد استخدامها لنوعك من المنشورات، ستقوم هذه التّسميات باستبدال التّسميات الافتراضيّة والتي هي: Posts ،Add Post... إلخ، نقوم بعد ذلك باستدعاء دالّة ()register_post_type والتي تملك المُعامِلات parameters التالية: title: لن تعمل الدالّة بدونه. labels: التّسميات التي قمتَ بتحديدها مُسبقًا. has_archive: عند تعيين قيمته إلى true فأنت تُخبر ووردبريس بأنّه من الممكن إظهار صفحات الأرشفة بالنسبة لنوع المنشور هذا. public: قم بتعيين قيمته إلى true لكي تتأكد أنّه بإمكان الناس رؤية صفحة لكل منتج على موقعك. supports: عناصر مدير نظام ووردبريس WordPress admin التي يدعمها نوع المنشورات المُخصّصة. taxonomies: مصفوفة array من أنواع التّصنيفات التي تريد استخدامها مع نوع المنشورات، لقد قمت باستخدام التصنيفات والوسوم المُضمّنة، على الرغم من أنّك قد ترغب بتركها فارغة وتسجيل taxonomy مُخصّصة للنوع الخاص بك من المنشورات لاحقًا. exclude_from_search: قم بتعيين قيمته إلى false لكي تتأكد أنّه يتم تضمين منتجاتك في نتائج البحث. capability_type: يتم تعيين قيمة هذا الُمعامل كـ post لأنّ منتجاتنا ستسلك سلوك المنشورات وليس الصفحات. rewrite: يُخبر هذا المُعامل ووردبريس ما هو الـ slug بالنسبة لأرشيف نوع المنشورات، والذي هو النص المُستخدم بعد اسم نطاقك domain كرابط له، بتعيين هذا إلى القيمة products سيكون رابط صفحة منتجك: http://mysite.com/products قُم الآن بحفظ ملفك، ستبدو شيفرة الإضافة كاملةً كما يلي: <?php /*Plugin Name: Create Product Post Type Description: This plugin registers the 'product' post type. Version: 1.0 License: GPLv2 */ // register custom post type to work with function wpmudev_create_post_type() { // set up labels $labels = array( 'name' => 'Products', 'singular_name' => 'Product', 'add_new' => 'Add New Product', 'add_new_item' => 'Add New Product', 'edit_item' => 'Edit Product', 'new_item' => 'New Product', 'all_items' => 'All Products', 'view_item' => 'View Product', 'search_items' => 'Search Products', 'not_found' => 'No Products Found', 'not_found_in_trash' => 'No Products found in Trash', 'parent_item_colon' => '', 'menu_name' => 'Products', ); //register post type register_post_type( 'product', array( 'labels' => $labels, 'has_archive' => true, 'public' => true, 'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields', 'thumbnail','page-attributes' ), 'taxonomies' => array( 'post_tag', 'category' ), 'exclude_from_search' => false, 'capability_type' => 'post', 'rewrite' => array( 'slug' => 'products' ), ) ); } add_action( 'init', 'wpmudev_create_post_type' ); ?> ستحتاج إلى تفعيل إضافتك الجديدة لكي يعمل النوع الخاص بك من المنشورات، اذهب إلى صفحة الإضافات Plugins في لوحة تحكم موقعك وقم بإيجاد إضافتك الجديدة: اضغط على رابط التفعيل Activate لكي يتم تفعيلها، سترى الآن نوعًا إضافيًا للمنشورات في قائمة لوحة التحكم: تستطيع الضغط على رابط المنتجات Products والبدء بإضافة منتجات إلى موقعك بنفس الطريقة التي تفعلها مع المنشورات. عرض نوع المنشورات الخاصة بك على واجهة الموقع الأمامية Front End: بمجرّد أن تقوم بإضافة بعض المنتجات ستحتاج أن تكون قادرًا على عرضها على واجهة موقعك. 1. ضبط الروابط الدائمة Permalinks لكي توصلك إلى صفحات نوع المنشورات الخاصة بك تحتاج في البداية لتحديث الروابط الدائمة Permalinks على موقعك بحيث يستخدم ووردبريس الروابط الصحيحة لعرض المنتجات أو أرشيف المنتجات: في لوحة تحكم ووردبريس اذهب إلى إعدادات: Settings -> Permalinks تأكد من أنّه تم اختيار خيار اسم المنشور “post name”. 3.اضغط على زر حفظ التغييرات Save Changes. ملاحظة: تحتاج إلى فعل هذا حتى ولو كنت قد قمت بإعداد الروابط الدائمة مُسبقًا لأنّ ووردبريس يحتاج إلى تحديث هذه الإعدادات لأجل مجموعة الروابط الجديدة لمنتجاتك. 2. إضافة نوع المنشورات الخاصة بك إلى قائمة التصفّح إن كنت ترغب بإضافة منتجات إلى قائمة التصفّح لديك تستطيع الذهاب إلى: Appearance -> Menus وسترى أنّه يتم عرض المنتجات على اليسار، قم ببساطة بسحب أي منتج إلى قائمتك لكي تُضّمنه إليها. إنّ إضافة أرشيف منتج أصعب قليلًا ولعمل هذا تحتاج إلى إضافة رابط مُخصّص Custom Link إلى القائمة: بينما لا تزال في شاشة القوائم اضغط على صندوق القوائم Links box على اليسار. في حقل الـ URL اكتب http://mysite.com/products مستبدلًا mysite.com باسم نطاقك الخاص. في حقل نص الرابط Link text اكتب Products. اضغط على زر إضافة إلى القائمة Add to Menu. بعد أن تمّت إضافة الرابط إلى القائمة قم بنقله إلى المكان المناسب وقم بحفظ القائمة. احفظ تغييراتك بالضغط على Save Menu. Don’t miss this step! عندما تزور الآن واجهة موقعك وتضغط على ذلك الرابط في القائمة سيتم نقلك إلى صفحة أرشيف منتجك، ها هي الصفحة الخاصة بي: 3. قالب Template لنوع المنشورات الخاصة بك يستخدم ووردبريس شيئًا يُدعى شجرة القالب template hierarchy لتحديد أي ملف قالب Template في قالبك Theme يجب أن يستخدمه لعرض نوع محتوى معطى، إنّ وصف كيفية عمل شجرة القالب بالتفصيل هو خارج مجال درسنا هذا، ولكن يساعدك أن تعرف كيف يقوم ووردبريس بعرض النوع الجديد الخاص بك من المنشورات. عندما يقوم ووردبريس بعرض منتج واحد سيبحث في قالبك عن كل واحد من هذه الملفات بالترتيب: ملف لعرض منتج وحيد يُدعى single-product.php. ملف لنشر كل المنشورات المفردة من أي نوع منشور كانت ، يُدعى single.php. الملف العام لنشر كل أنواع المحتوى يُدعى index.php. عندما يعرض ووردبريس أرشيف لمنتج سيعمل من خلال ملفات القالب Template هذه: ملف لعرض أرشيف المنتج يُدعى archive-product.php. قالب أرشيف عام يُدعى archive.php. القالب الافتراضي default template وهو index.php. سيعمل ووردبريس عبر هذه الشجرة hierarchy ويستخدم ملف القالب الذي يصادفه أولًا، لذا إن كنت تريد إنشاء قالب مُخصّص custom template لمنتجاتك فمن الجيّد أن تبدأ بنسخ ملف single.php وتحفظه باسم single-product.php ومن ثمّ تقوم بتعديله. على أيّة حال إن لم تكن ترغب بإنشاء ملفات قالب template files سيقوم ووردبريس بكل سرور باستخدام الملفات الموجودة مُسبقًا ضمن قالبك، وهو ما تمّ عمله بالنسبة لي مع ملفات archive.php و single.php على قالب twenty fifteen theme. ملخّص تجعل القدرة على إنشاء محتوى مُخصّص ووردبريس قويًا جدًا: نستطيع استخدامه لإضافة وعرض العديد من أنواع المحتوى المرنة بالطريقة التي نحتاجها. تعلّمنا في هذا الدرس عن الأنواع الثلاثة للمحتوى المُخصّص، ما هي ومتى نستخدم كلّ واحد منها، تعلّمنا أيضًا كيف نُنشئ أنواع منشورات مُخصّصة ونعرضها على موقعنا. سنتعلّم في الدرس القادم كيف نقوم بإنشاء taxonomies مُخصّصة وحقول مُخصّصة. هل تستخدم أنواع منشورات مُخصًصة في مواقعك؟ هل تفضّل استخدام إضافة أو كتابة الشيفرة الخاصّة بك؟ في أيّة أشياء تستفيد منها؟ دعنا نعلم أفكارك في التعليقات. ترجمة -وبتصرّف- للمقال Creating Custom Content in WordPress: Custom Post Types لصاحبه Rachel McCollin. sse-examples.zip
  19. يُواجه كلّ شخص في وقتٍ ما مشاكل مع خادوم الوِيب Web Server، سيُساعدك تَعلّمك أين تبحث عندما تواجه مشكلة ما وأيّ العناصر هي التي من المحتمل تمّ تخريبها على إصلاح هذه المشاكل (troubleshoot) بسرعة وبإحباط أقل. سنناقش في هذا الدرس كيف نقوم باستكشاف هذه المشاكل بحيث تستطيع الإبقاء على موقعك يعمل بشكل طبيعي. ما هي أنواع المشاكل النموذجية التي من المحتمل أن تواجهها ؟قد تنشأ في بعض الأحيان بعض المشاكل غير النموذجية إلّا أنّ الغالبية العظمى من المشاكل التي ستصادفها أثناء محاولتك لجعل موقعك يعمل بشكل صحيح تقع ضمن مجموعة يُمكن التنبُّؤ بها كثيرًا. سنقوم بالمرور على هذا بشكلٍ مُفصّل في الأقسام اللاحقة ولكن حاليًّا هذه قائمة من الأشياء التي يجب تفحّصها: هل تمّ تنصيب خادوم الوِيب لديك؟هل خادوم الوِيب قيد التشغيل الآن؟هل الصياغة في ملفات ضبط خادوم الوِيب configuration files صحيحة؟هل المنافذ ports التي قمت بضبطها مفتوحة (لم يتم حجبها من الجدار الناري)؟هل تقودك إعدادات الـ DNS إلى المكان الصحيح؟هل يشير جذر المستند document root إلى موقع ملفاتك؟هل يقوم خادوم الوِيب بتخديم ملفات الفهرس index files الصحيحة؟هل أذونات permissions وملكية الملف ownership وبُنى المجلد صحيحة؟هل قُمتَ بمنع الوصول عن طريق ملفات الضبط؟إن كنتَ تملك قاعدة بيانات database في الخلفيّة backend فهل هي تعمل؟هل يستطيع موقعك الاتصال مع قاعدة البيانات بنجاح؟هذه هي بعض أشيع المشاكل التي يُصادفها مُدراء النُّظم عندما لا يعمل الموقع بشكلٍ صحيح، يُمكن عادةً تضييق المشكلة المحددة بإلقاء نظرة على ملفات السّجل Log Files للمكونات المختلفة وعن طريق الرجوع إلى صفحات الخطأ التي تظهر في متصفحك. سنقوم بالمرور في الأسفل على كل من هذه الحالات لكي تستطيع التحقق من أنّ الخدمات مضبوطة بشكلٍ صحيح. التحقق من السّجلات Logsقبل أن تقوم بتعقُّب مشكلة ما بشكلٍ عشوائي حاول أن تتحقق من سجلات خادوم الوِيب Logs لديك ومن أيّة عناصر مرتبطة بذلك، ستجد هذه السّجلات عادةً في المسار var/log/ في مجلّد فرعي مخصّص للخدمة التي تريدها. فعلى سبيل المثال إن كنتَ تملك خادوم Apache يعمل على توزيعة Ubuntu فستجد بشكل افتراضي أنّ السّجلات يتمّ الاحتفاظ بها في المسار var/log/apache2/، قُم بالتحقق من الملفات في هذا المجلد لكي ترى ما نوع رسائل الخطأ التي تمّ توليدها، إن كنت تملك قاعدة بيانات تعمل في الخلفيّة وتسبب لك المشاكل فهي على الأغلب تحتفظ بسجلاتها في المسار var/log/ أيضًا. من الأشياء التي يجب التحقق منها أيضًا أن تتأكد إذا ما كانت العمليّات نفسها تصدر رسائل خطأ عندما تقوم بتشغيل الخدمات، إن كنت تحاول زيارة صفحة وِيب وتلقّيت خطأ فإنّ صفحة الخطأ قد تحتوي على تلميحات عن الخطأ أيضًا (بالرغم من أنّها ليست دقيقة كالسطور في ملفات السّجلات). استخدم محرّك بحث Search Engine لتحاول إيجاد معلومات متعلقة بالموضوع والتي من الممكن أن تقودك في الاتجاه الصحيح، تساعدك الخطوات القادمة في استكشاف الأخطاء أكثر. هل تمّ تنصيب خادوم الوِيب لديك؟إنّ أول شيء تحتاج له لكي تُخدِّم مواقعك بشكل صحيح هو خادوم وِيب. ربّما قام مُعظم الأشخاص فعلًا بتنصيب خادوم قبل الوصول لهذه المرحلة، ولكن في بعض الحالات ربّما تكون أزلت الخادوم عن طريق الخطأ عند تنفيذك لعمليّات على الحزم Packages الأخرى. إذا كنت تعمل على نظام تشغيل Ubuntu أو Debian وترغب بتنصيب خادوم وِيب Apache تستطيع كتابة ما يلي: sudo apt-get update sudo apt-get install apache2تُدعى عمليّة Apache على هذه الأنظمة بـ apache2. إن كنت تعمل على نظام تشغيل Ubuntu أو Debian وترغب بتنصيب خادوم وِيب Nginx تستطيع بدلًا من ذلك كتابة: sudo apt-get update sudo apt-get install nginxتُدعى عمليّة Nginx على هذه الأنظمة بـ nginx. إن كنت تعمل على أنظمة تشغيل CentOS أو Fedora وترغب باستخدام خادوم وِيب Apache فقُم بكتابة التالي وبإمكانك إزالة الأمر "sudo" إن كُنت قد سجّلت الدخول كـ root: sudo yum install httpdتُدعى عمليّة Apache على هذه الأنظمة بـ httpd. إن كنت تعمل على أنظمة تشغيل CentOS أو Fedora وترغب باستخدام خادوم وِيب Nginx تستطيع كتابة الأمر التالي، ومرّة أخرى قم بإزالة الأمر "sudo" إن كُنت قد سجّلت الدخول كـ root: sudo rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm sudo yum install nginxتُدعى عمليّة Nginx على هذه الأنظمة بـ nginx. هل خادوم الوِيب قيد التشغيل الآن؟بعد أن قمت بالتأكد من أنّ خادومك مُنَصّب بالفعل، فهل هو قيد التشغيل؟ تُوجَد العديد من الطّرق لكي تكتشف إذا ما كانت الخدمة قيد التشغيل أم لا، واحدة من هذه الطرق والتي تعمل على منصّات متعدّدة cross-platform هي استخدام الأمر netstat. سيُخبِرك هذا الأمر عن جميع العمليّات التي تستخدم منافذ على الخادوم، بإمكاننا بعد ذلك كتابة الأمر grep لإيجاد اسم العملية التي نبحث عنها: sudo netstat -plunt | grep apache2 tcp6 0 0 :::80 :::* LISTEN 2000/apache2يجب عليك تغيير كلمة "apache2" إلى اسم عمليّة خادوم الوِيب الذي لديك، إن ظهر لك سطر كالموجود بالأعلى فهذا يعني أنّ العمليّة قيد التشغيل، أمّا إن لم تحصل على أيّة خَرج فهذا يعني إمّا أنّك قُمت بالاستعلام عن العمليّة الخطأ أو أنّ خادوم الوِيب لديك لا يعمل. يُمكنك في هذه الحالة بدء تشغيله باستخدام الطريقة المفضّلة لتوزيعتك، فعلى سبيل المثال على Ubuntu تستطيع بدء تشغيل خدمة Apache2 بكتابة: sudo service apache2 startوعلى توزيعة CentOS نكتب هذا الأمر: sudo /etc/init.d/httpd startإذا تمّ بدء تشغيل خادومك فعندها تستطيع التحقق باستخدام الأمر netstat مرّة أخرى لكي تتأكد من انّ كل شيء يعمل بشكل صحيح. هل الصّياغة Syntax في ملفات ضبط خادوم الوِيب صحيحة؟ إذا رفض خادوم الوِيب لديك أن يبدأ التشغيل فهذا يشير عادةً إلى أنّ ملفات الضبط تحتاج إلى بعض الانتباه، يتطلّب Apache و Nginx التزامًا صارمًا بتعليمات الصّياغة syntax لكي يتمّ قراءة الملفات بنجاح. تتواجد ملفات إعدادات الضبط لهذه الخدمات عادةً في المسار etc/ في مجلّد فرعي مُسمّى على اسم العمليّة نفسها. وبهذا نستطيع الوصول إلى المجلّد الرئيسي لإعدادات ضبط Apache على Ubuntu بكتابة: cd /etc/apache2ويمكننا الوصول بطريقة مشابهة إلى مجلّد إعدادات ضبط Apache على CentOS والمُسمّى على اسم تلك العمليّة: cd /etc/httpdتكون إعدادت الضبط مُوزّعة على عدّة ملفات، وعندما يفشل بدء الخدمة فإنها ستشير عادةً إلى ملف إعدادات الضبط وإلى السّطر الذي حدثت فيه المشكلة، قُم بالتحقق من هذا الملف بحثًا عن الأخطاء. يُزوّدك كل واحد من خواديم الوِيب هذه بالقدرة على التحقق من صياغة إعدادات الضبط في ملفاتك. إن كُنتَ تستخدم Apache فبإمكانك استخدام الأمر apache2ctl أو apachectl للتحقق من ملفات إعدادات الضبط بحثاً عن أخطاء الصياغة: apache2ctl configtest AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message Syntax OK لقد تلقيّنا كما ترى في الأعلى رسالة معلومات حول تفاصيل إعدادت الضبط لدينا ولم يكن هناك أيّة أخطاء، هذا جيّد. وإن كنتَ تملك خادوم وِيب Nginx تستطيع البدء باختبار مماثل بكتابة: sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successfulتتحقق هذه العمليّة من صياغتك كما ترى، فإن أزلنا الفاصلة من المنقوطة من نهاية أحد الأسطر في ملف الإعدادات (وهو خطأ شائع بالنسبة لإعدادت ضبط Nginx) فسنحصل على رسالة مماثلة للآتي: sudo nginx -t nginx: [emerg] invalid number of arguments in "tcp_nopush" directive in /etc/nginx/nginx.conf:18 nginx: configuration file /etc/nginx/nginx.conf test failedيُوجد عدد خاطئ من المُعطيات arguments لأنّ Nginx يقوم بالبحث عن الفاصلة المنقوطة لإنهاء الجُمَل، فإن لم يجدها ينتقل للسطر التالي ويفسّر ذلك على أنها مُعطيات إضافية للسطر السابق. بإمكانك إجراء هذه الاختبارات لكي تجد أخطاء الصياغة في ملفاتك، قُم بإصلاح هذه المشاكل التي يُشير إليها إلى أن تستطيع ملفاتك تجاوز الاختبار بنجاح. هل المنافذ الذي قمت بضبطها مفتوحة؟تعمل خواديم الوِيب بشكلٍ عام على المنفذ 80 لاتصالات الوِيب الطبيعية normal web traffic وتستخدم المنفذ 443 للاتصالات المشفّرة باستخدام TLS/SSL، ولكي تصل بشكل صحيح إلى الموقع يجب أن تكون هذه المنافذ قابلة للوصول. تستطيع اختبار إذا ما كان الخادوم لديك يملك منفذًا مفتوحًا باستخدام الأداة netcat على حاسوبك المحلّي Local Machine. تحتاج فقط لاستخدام عنوان الـ IP لخادومك وتخبرها عن رقم المنفذ الذي تريد التحقق منه كما يلي: sudo nc -z 111.111.111.111 80سيقوم هذا الأمر بالتحقق من المنفذ 80 على الخادوم الذي يملك عنوان 111.111.111.111، إن كان مفتوحًا سيخبرك الأمر فورًا بالنتيجة، أمّا إن لم يكن مفتوحًا فسيحاول الأمر باستمرار لإنشاء اتصال مع الخادوم دون جدوى، بإمكانك إيقاف هذه العمليّة بضغط على CTRL-C في واجهة الأوامر. إن لم تكن منافذ الوِيب قابلة للوصول لديك فيجب أن تبحث في إعدادات الجدار الناري لديك، حيث قد تحتاج أن تفتح المنفذ 80 أو المنفذ 443. هل تقودك إعدادات الـ DNS إلى المكان الصحيح؟إن كان بإمكانك الوصول إلى موقعك باستخدام عنوان الـ IP ولا تستطيع ذلك عبر اسم المجال domain name فربّما يجب عليك إلقاء نظرة على إعدادت الـ DNS. لكي يتمكّن زوّار موقعك من الوصول إليه عبر استخدام اسم المجال فيجب أن يكون لديك سِجِل "A" أو "AAAA" يشير إلى عنوان الـ IP الخاص بخادومك في إعدادات الـ DNS، تستطيع الاستعلام عن سِجِل “A” لمجالك باستخدام هذا الأمر: host -t A example.com example.com has address 93.184.216.119يجب أن يتطابق السطر الذي يعود لك مع عنوان الـ IP لخادومك، إن كنتَ تريد التحقق من سِجِل "AAAA" (للاتصالات التي تستخدم IPv6) بإمكانك كتابة: host -t AAAA example.com example.com has IPv6 address 2606:2800:220:6d:26bf:1447:1097:aa7يجب أن تبقي في ذهنك أنّ أيّة تغييرات تقوم بها على سِجِل الـ DNS تأخذ وقتًا طويلًا ليتم تعميمها، ربّما تتلقى نتائج متضاربة بعد التغيير حيث أنّ طلبك يتمّ تلقيه من قبل خواديم مختلفة ليست جميعها مُحدّثة إلى آخر إصدار حتى الآن. إن كنتَ تستخدم موقع DigitalOcean فبإمكانك أن تتعلم أساسيات DNS وأسماء النطاقات. قم بالتأكد من أن ملفات إعدادات الضبط تقوم بالتعامل مع مجالك بشكل صحيح. يبدو المقطع الخاص بملف المضيف الوهمي virtual host file لديك في Apache كما يلي: <VirtualHost *:80> ServerName example.com ServerAlias www.example.com ServerAdmin admin@example.com DocumentRoot /var/www/html ٠٠٠يتم إعداد المضيف الوهمي virtual host لكي يستجيب مع أيّة طلبات على المنفذ 80 من أجل المجال example.com. تبدو القطعة المشابهة لهذا في Nginx كما يلي: server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /usr/share/nginx/html; index index.html index.htm; server_name example.com www.example.com; ٠٠٠يتم إعداد هذه الكتلة Block لكي تستجيب إلى النوع المماثل من الطلبات التي تحدثنا عنها في الأعلى. هل يشير جذر المستند Document Root إلى موقع ملفاتك؟من الاعتبارات الأخرى التي يجب أن نأخذ بها هي إذا ما كان خادوم الويب لديك يشير إلى الموقع الصحيح للملف. يتم إعداد كل خادوم وهمي في Apache أو كتلة خادوم Server Block في Nginx لكي تشير إلى مجلّد محدد، فإن كان مُعدًّا بشكل غير صحيح سيرمي الخادوم رسالة خطأ عندما تحاول الوصول إلى الصفحة. يتم إعداد جذر المستند Document Root في Apache باستخدام التوجيه DocumentRoot : <VirtualHost *:80> ServerName example.com ServerAlias www.example.com ServerAdmin admin@example.com DocumentRoot /var/www/html ...يُخبر هذا السطر Apache أنّه يجب عليه البحث عن الملفات لهذا المجال في المسار var/www/html/، فإن كنت تحتفظ بملفاتك في مكانٍ آخر يجب عليك تعديل هذا السطر لكي يشير إلى الموقع الصحيح. يقوم التوجيه root في Nginx بإعداد نفس الشيء: server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /usr/share/nginx/html; index index.html index.htm; server_name example.com www.example.com; ... يبحث Nginx في إعداد الضبط هذا عن الملفات لهذا المجال في المسار usr/share/nginx/html/ هل يقوم خادوم الوِيب بتخديم ملفات الفهرس Index files الصحيحة؟إذا كان جذر المستند لديك صحيحًا ولا يتم تخديم صفحات الفهرس Index Pages بشكلٍ صحيح عندما تذهب إلى موقعك أو إلى مكان المجلد على موقعك فربّما تم ضبط إعدادات الفهارس بشكل غير صحيح. عندما يقوم زائر ما بطلب مجلد يقوم خادومك نموذجيًا بإعطائه ملف فهرسة، عادةً ما يكون هذا ملف index.html أو ملف index.php وذلك اعتمادًا على على إعدادات الضبط لديك. ربّما تجد في Apache سطرًا في ملف المضيف الافتراضي الذي يقوم بضبط إعدادات ترتيب الفهرس التي سيتم استخدامها لمجلدات معيّنة بشكلٍ صريح كما يلي: <Directory /var/www/html> DirectoryIndex index.html index.php </Directory>هذا يعني أنّه عندما يتم تخديم مجلد فإنّ Apache سيقوم بالبحث أولًا عن ملف يدعى index.html، ويحاول تخديم ملف index.php كاحتياط في حال لم يتم إيجاد الملف الأول. بإمكانك تعيين الترتيب الذي سيتم استخدامه لتخديم ملفات الفهرس لكامل الخادوم عن طريق تعديل ملف mods-enabled/dir.conf والذي يقوم بتعيين الإعدادات الافتراضية للخادوم، إن كان الخادوم لديك لا يُخدّم ملف فهرس فقم بالتأكد أنّك تملك ملف فهرس في مجلّدك الذي يُوافق أحد الخيارات في ملفك. يُدعى التوجيه الذي يقوم بذلك في Nginx بـ “index” ويتمّ استخدامه كما يلي: server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /usr/share/nginx/html; index index.html index.htm; server_name example.com www.example.com; ...هل تمّ تعيين الأذونات والملكية بشكل صحيح؟حتى يتمكن خادوم الوِيب من تخديم الملفات الصحيحة يجب أن يكون قادرًا على قراءة الملفات وأن يمتلك صلاحية الوصول للمجلدات حيث يتم حفظ هذه الملفات، بالإمكان التحكم بهذا عبر أذونات وملكية الملفات والمجلدات. لكي تقرأ الملفات يجب أن تكون المجلدات التي تحتوي المحتوى قابلة للقراءة والتنفيذ من قبل عمليّة خادوم الوِيب، تختلف أسماء المستخدمين والمجموعات التي يتم استخدامها لتشغيل خادوم الوِيب من توزيعة لأخرى. على Ubuntu و Debian يعمل كلًّا من Apache و Nginx كالمستخدم www-data والذي هو عضو من المجموعة www-data. على CentOS و Fedora يعمل Apache تحت مستخدم يُدعى apache والذي ينتمي لمجموعة apache، يعمل Nginx تحت مستخدم يُدعى nginx والذي هو جزء من مجموعة nginx. تستطيع باستخدام هذه المعلومات النظر إلى المجلدات والملفات التي يتألف منها محتوى موقعك: ls -l /path/to/web/rootيجب أن تكون المجلدات قابلة للقراءة والتنفيذ من قبل المستخدم web أو مجموعته، أمّا الملفات فيجب أن تكون قابلة للقراءة لكي يتم قراءة محتواها، وبالإضافة لذلك إن أردنا تحميل، كتابة أو التعديل على المحتوى يجب أن تكون المجلدات والملفات قابلة للكتابة، ولكن احذر عند تعيينك للمجلدات لكي تكون قابلة للكتابة لأنّ هذا يُمكن أن يكون أحد المخاطر الأمنية. لتعديل ملكية ملف ما تستطيع فعل ما يلي: sudo chown user_owner:group_owner /path/to/file تستطيع فعل هذا أيضًا للمجلد، فبإمكانك تغيير ملكية المجلد وكل ما بداخله من ملفات عبر تمرير العَلَم –R: sudo chown -R user_owner:group_owner /path/to/file تستطيع التعلم أكثر عن أذونات لينِكس هنا. هل قُمتَ بمنع الوصول عن طريق ملفات الضبط؟من المحتمل أنّه تم تعيين إعدادات الضبط لديك لكي تمنع الوصول إلى الملفات التي تحاول تخديمها. يتم إعداد هذا الضبط في Apache في ملف المضيف الافتراضي لهذا الموقع أو عبر ملف htaccess. الموجود في المجلد نفسه. من الممكن من خلال هذه الملفات أن تقوم بمنع الوصول بعدّة طرق ، يُمكن منع الوصول للمجلدات في إصدار Apache 2.4 بهذه الطريقة: <Directory /usr/share> AllowOverride None Require all denied </Directory>يقوم هذا السطر بإخبار خادوم الوِيب بألّا يسمح لأي شخص بالوصول لمحتويات هذا المجلد، أمّا في إصدار Apache 2.2 والإصدارات الأقدم منه يمكننا كتابة ذلك كما يلي: <Directory /usr/share> AllowOverride None Require all denied </Directory>إن وجدت توجيهًا كهذا للمجلد المُحتوي للمحتوى الذي تحاول الوصول إليه فإنّ هذا هو ما يمنع نجاحك. تأخذ هذه القيود في Nginx شكل توجيهات deny وتتواجد في كتل خادومك أو في ملفات إعدادات الضبط الرئيسية: location /usr/share { deny all; }إن كنتَ تملك قاعدة بيانات database في الخلفية فهل هي تعمل؟إذا كان موقعك يعتمد على قاعدة بيانات في الخلفية مثل MySQL, PostreSQL, MongoDB, etc فستحتاج أن تتأكد من أنّها قيد التشغيل. بإمكانك فعل هذا بنفس الطريقة التي تأكدت منها بأنّ خادوم الوِيب يعمل، مرّة أخرى نستطيع البحث عن العمليات قيد التشغيل ومن ثم انتقاء اسم العملية التي نبحث عنها كما يلي: sudo netstat -plunt | grep mysql tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 3356/mysqldكما ترى فإن الخدمة قيد التشغيل على هذا الحاسوب، عندما تبحث عن خدمة قُم بالتأكد من أنّك تعرف الاسم الذي تعمل تحته هذه الخدمة. وكبديل لهذا ابحث عن المنفذ الذي تعمل الخدمة عليه إن كنتَ تعلم هذا، ابحث في توثيق documentation قاعدة بياناتك لكي تجد المنفذ الافتراضي الذي تعمل عليه أو تحقق من ملفات إعدادات الضبط. إن كنتَ تملك قاعدة بيانات في الخلفية، فهل يستطيع موقعك الاتصال بنجاح إليها؟الخطوة التالية التي يجب أن تأخذها إن كنت تحاول استكشاف الأخطاء مع وجود قاعدة بيانات في الخلفية هي أن ترى إن كان بإمكانك الاتصال بها بشكلٍ صحيح، يعني هذا عادةً التحقق من الملفات التي يقرؤها موقعك لكي يجد معلومات قاعدة البيانات. على سبيل المثال في موقع WordPress يتم تخزين إعدادات اتصال قاعدة البيانات في ملف يُدعى wp-config.php ، تحتاج للتحقق من أنّ DB_NAME ، DB_USER و DB_PASSWORD صحيحة لكي يتمكن موقعك من الاتصال بقاعدة البيانات. بإمكانك اختبار إذا ما كان الملف يملك المعلومات الصحيحة بمحاولة الاتصال إلى قاعدة البيانات يدويًّا باستخدام ما يلي: mysql -u DB_USER_value -pDB_PASSWORD_value DB_NAME_valueإن لم تتمكّن من الاتصال باستخدام القيم التي وجدتها في الملف فربّما تحتاج إلى إنشاء الحسابات وقواعد البيانات أو تعديل أذونات الوصول لقاعدة بياناتك. هل تمّ ضبط خادوم الوِيب لديك لكي يمرر محتوىً ديناميكيًا إلى معالج نصوص Script Processor؟إن كنت تستخدم قاعدة بيانات في الخلفية، فأنت بكل تأكيد تستخدم لغة برمجة مثل PHP لكي تعالج طلبات للمحتوى الديناميكي، تجلب المحتويات من قاعدة البيانات وتقديم النتائج. إن كانت هذه هي الحالة تحتاج للتأكد من أن خادوم الوِيب لديك مُعَد بشكل صحيح لكي يمرر الطلبات إلى معالج النصوص. يعني هذا بشكل عام في Apache التأكد من تنصيب وتمكين mod_php5، بإمكانك فعل هذا على Ubuntu أو Debian بكتابة: sudo apt-get update sudo apt-get install php5 libapache2-mod-php5 sudo a2enmod php5وفي أنظمة CentOS و Fedora يجب كتابة ما يلي: sudo yum install php php-mysql sudo service httpd restartولكنّ هذا معقّد أكثر قليلًا في Nginx، حيث أنّه لا يملك وحدة PHP ليتمّ تمكينها، لذلك نحتاج أن نتأكد من تنصيب وتمكين php-fpm في إعدادات الضبط. على خادوم Ubuntu أو Debian تأكد أنّه تم تنزيل العناصر بكتابة: sudo apt-get update sudo apt-get install php5-fpm php5-mysqlتستطيع فعل هذا على CentOS أو Fedora بكتابة: sudo yum install php-fpm php-mysql بما أنّ معالج PHP ليس جزءًا من Nginx تحتاج أن تذكر له صراحةً أن يمرر ملفات PHP، اتبع الخطوات الأربعة من هذا الدليل لتتعلم كيف تضبط إعدادات Nginx لكي يمرر ملفات PHP إلى php-fpm، يجب عليك أيضًا أن تلقي نظرة على المقطع من الخطوة الثالثة الذي يتعامل مع إعداد معالج PHP، يجب أن يكون هذا مماثلًا إلى حدٍّ كبير بغض النظر عن توزيعتك. إن فشل كل هذا تحقق من السّجلات مرّة أخرىيجب أن يكون التحقق من السّجلات خطوتك الأولى، ولكنّه من الجيد أن يكون أيضًا خطوتك الأخيرة قبل أن تطلب المزيد من المساعدة. إن بذلت قصارى جهدك في استكشاف الأخطاء بنفسك وتحتاج بعض المساعدة (من صديق، بفتح تذكرة مساعدة، إلخ...) ستحصل على مساعدة بشكل أسرع بتزويد ملفات السجل ورسائل الأخطاء، حيث سيجد مدراء النظم الخبيرون غالبًا فكرة جيّدة عمّا يحصل إن أعطيتهم هذه القطع من المعلومات التي يحتاجونها. الخاتمةآمل أن تكون نصائح استكشاف الأخطاء هذه قد ساعدتك في تعقب وإصلاح بعضًا من أشيع المشاكل التي يواجهها مدراء النظم عند محاولتهم في تشغيل مواقعهم. إن كنت تملك نصائح إضافية عن أشياء يجب التحقق منها وطرق لحل المشاكل قم بمشاركتهم مع المستخدمين الآخرين في التعليقات. ترجمة -وبتصرّف- للمقال How To Troubleshoot Common Site Issues on a Linux Server لصاحبه Justin Ellingwood.
  20. هناك العديد من الأسباب التي تجعلك ترغب في ضغط Compression الملفّات والمجلدات على الحاسوب، واحدة من أبسط الفوائد التي تجعلك تقوم بذلك هي توفير مساحة التّخزين على القرص واستخدام عرض نطاق bandwidth أقل في اتّصالات الشّبكة. سنناقش في هذا الدّرس بعضًا من الطّرق المختلفة لضغط البيانات وسنتحدّث قليلاً عن بعض تفضيلات الطّرق المختلفة، سنتطرّق أيضًا إلى بعض العمليّات المرتبطة بذلك كالأرشفة archiving، والتي تجعل أدوات الضّغط أكثر مرونة. سنقوم باستعراض هذه الأدوات على نظام تشغيل Ubuntu 14.04 ولكنّها ستعمل تمامًا على أي توزيعة لينِكس حديثة. أساسيّات الضّغط والأرشفةقبل أن نذهب إلى الأدوات الفعلية التي سنستخدمها، يجب أن نُعرِّف مصطلحاتنا ونناقش بعضًا من المُميّزات المختلفة للضّغط والأرشفة. الضّغط هو طريقة لتقليل حجم الملف على القرص باستخدام خوارزميات وطرق حسابية مختلفة، تكون الملفّات مُنسّقة بطريقة معيّنة تجعل بنيتها الأساسية مُتوقَّعة بشكلٍ ما حتّى ولو كان محتواها مختلفاً، بل وأكثر من ذلك فإنّ المحتوى بذاته عادةً ما يكون متكرّرًا، لذلك يتيح لنا كلا هذين الأمرين فرصة لتطبيق تقنيات الضّغط. 1- الضّغط الفَقُود والضّغط غير الفَقُود Lossy and Lossless Compressionعندما نناقش موضوع الضّغط بالنّظر إلى الحواسيب وأنواع الملفّات فقد تحمل المصطلحات نفسها معاني مختلفة بحسب المحتوى، فلنأخذ كمثال ملفات الموسيقى التي تحمل صيغة MP3، حيث أنّ ملف الـ MP3 هو ملف صوتي مضغوط يتمّ استخدامُه لإنشاءِ ملفٍ ذي حجمٍ أصغر وذلك اعتماداً على ملفٍ صوتيٍّ ذي حجمٍ أكبر. يختلف هذا النّوع من الضّغط بشكلٍّ أساسيٍّ عمّا نتحدث عنه في هذا الدّرس لأنّ ملف الـ MP3 يتمُّ إنشاؤه عبر تحليل شكل الموجة الصّوتيّة من ملف الصّوت ومحاولة معرفة أيُّ البيانات يُمكنُ حذفها نهائيًا مع المحافظة على صوت الملف الأصلي. وهذا ما يُدعى طريقة الضّغط الفَقُود lossy compression لأنّه فعلًا فقدَ بيانات من الملف الأصلي، وليس بإمكانك تحويل ملف الـ MP3 مرّة أخرى إلى الملف الأصلي لاحقًا. قد لا يُلاحِظ المستخدم عمليّة الضغط ولكنَّها لا تحتوي كامل البيانات من الملف الأصلي، وكلَّما كان معدّل الضّغط أعلى كلَّما بَدأت أجزاء أكثر من الصّوت تتأثر بعمليّة الضّغط. وكمثال آخر على هذا الصّور ذات الصّيغة JPEG، فكلَّما تمَّ ضغطها بشكلٍ أكبر كلَّما تمّت خسارة المزيد من البيانات وكلَّما اتضحت عمليّة الضّغط أكثر، تُحاول أداة ضغط صيغة JPEG إيجاد الحقولِ ذاتِ الألوان المتقاربة لبعضها وتقومُ باستبدالِ الحقلِ كاملًا بلونٍ واحد، كلَّما زادَ معدَّل الضّغط المستخدم كلَّما زاد مدى الألوان الذي يتم تغطيته بهذه الطريقة. بالمقابل تقوم طريقة الضّغط غير الفَقُود lossless compression بإنشاء ملف ذي حجم أصغر من الأصل والذي يمكننا باستخدامه إعادة بناء الملف الأصلي. الضّغط غير الفَقُود هو نوع الضّغط الذي سنقوم بتغطيته في هذا الدّرس، لا يستخدم هذا النّوع من الضّغط القيم التقريبيّة لضغط البيانات، بل يستخدم بدلاً من ذلك خوارزميّات التّعرّف على الأجزاء المتكرّرة من الملف ويقومُ بإزالتها واستبدالها بماسك المكان placeholder، ويتابع ليستبدل لاحقاً حوادث النّمط بمرجعيّات references لنفس ماسك المكان. يسمح هذا للحاسوب بتخزين المعلومات على مساحة أقلّ من القرص، تُشبه هذه العمليّة كإنشاء قائمة من المتغيّرات variables والتي تُعرِّف تركيبة من البيانات ومن ثمّ استخدام هذه المتغيّرات لاحقًا لإنشاء البرنامج، تستخدم كلّ عمليّة ضغط غير فَقُود هاتين المرحلتين الفعليّتين وهما ربط القيم المتكرّرة إلى شيءٍ ما أصغر، والذي يمكن الرّجوع له بسهولة، ومن ثمّ تبديل الأحداث لكل واحدة من هذه القيم بمرجع لها. بل وأكثر من ذلك يُقال عن طرق الضّغط غير الفَقُود أنّها قابلة للتكيّف، هذا يعني أنّها لا تقوم بتحليل كامل الملف في البداية ومن ثمّ تقوم بإنشاء قاموس من البدائل المرجعيّة منه، بل تقوم بدلاً من ذلك بتحليل الملف أثناء عمليّة الضّغط ومن ثم تعيد كتابة القاموس بناءً على البيانات التي تمّ فعلياً تكرارُها، ويُصبح القاموس تدريجيًا أكثر فائدة مع استمرار العمليّة. 2- خلفيّة عن الأرشفةتعني فكرة أرشفة البيانات بشكلٍ عام عمل نسخة احتياطيّة لها وحفظها إلى مكان آمن، عادةً في صيغة مضغوطة، يحمل الأرشيف بشكل عام معنى مختلف قليلاً على نظام لينِكس، حيث عادة ما يشير إلى ملف ذو صيغة tar. تاريخيًّا كان يتمّ النّسخ الاحتياطي للبيانات على شرائط أرشفة tape archives، والتي هي عبارة عن أجهزة أشرطة ممغنطة يُمكِن استخدامها لتخزين البيانات المتتابعة، لا زالت هذه الطريقة هي المفضّلة لدى بعض المجالات، ولكي يتم عمل هذا بشكلٍ فاعل تمّ إنشاء برنامج tar حتى تستطيع التعامل مع العديد من الملفّات في نظام الملفّات بأذونات permissions وبيانات وصفية metadata سليمة كملف واحد، ومن ثم تستطيع استخراج الملف أو كامل نظام الملفّات من الأرشيف. الملف ذو اللاحقة tar بشكل أساسي هو عبارة عن صيغة ملف تقوم بإنشاء طريقة ملائمة لتوزيع وتخزين والنسخ الاحتياطي والتّعامل بمجموعة من الملفّات المرتبطة، سنقوم أيضًا في هذا الدّرس بالتحدث عن الأرشفة لأنه عادة يتم ضغط الملفّات المُؤرشفة خلال عملية الأرشفة وذلك لكي يتم تخزين البيانات بطريقة أكثر فاعلية. المقارنة بين أدوات الأرشفة المختلفةيملك لينِكس العديد من أدوات الأرشفة المختلفة، حيث يُقدّم كلًّا منها تضحيات في بعض المجالات ويملك بعضًّا من مواطن القوة، سنقوم بالميل تجاه مخطّطات الضّغط التي تعمل بالصّيغة tar لأنها أكثر مرونة من الطّرق الأخرى. 1- الضّغط بأداة gzipتمّ تصنيف أداة gzip بشكل نمطي على أنّها الطّريقة الكلاسيكية لضغط البيانات على آلة تعمل بنظام التشغيل لينِكس، فهي موجودة تقريباً منذ العام 1992م وهي لا تزال قيد التطوير ولا يزال لديها الكثير من الأمور لتسير عليها. تستخدم أداة gzip خوارزمية ضغط معروفة بـ DEFLATE، وهي خوارزمية مستخدمة أيضًا في تقنيات شائعة أخرى مثل صيغة الصورة PNG وبروتوكول الوِيب HTTP وبروتوكول القشرة الآمنة SSH secure shell protocol. إنّ السّرعة هي واحدة من أهمّ مزايا هذه الأداة، حيث يُمكن ضغط وفك ضغط البيانات بمعدّل أعلى مقارنةً بتقنيّات منافسة، خاصةً عند مقارنة معظم الصيغ المدمجة لكل أداة، وهي أيضًا أكثر فاعليّة من حيث الموارد resources بالنظر إلى استخدام الذاكرة memory usage خلال الضّغط وفك الضّغط ولا يبدو أنّها تتطلب ذاكرة أكثر عند التطلع إلى عملية الضّغط الأفضل. ونأخذ التوافقية compatibility أيضًا بعين الاعتبار، فحيث أنّ gzip هي أداة قديمة فإنّ معظم أنظمة تشغيل لينِكس بغض النظر عن عمرها ستملك الأداة لكي تتعامل مع البيانات. إنّ أكبر مساوئ هذه الأداة أنّها تضغط البيانات بشكل غير مكتمل تماماً بالمقارنة مع بعض الخيارات الأخرى، لذلك إن كنت تقوم بالكثير من عمليّات الضّغط وفك الضّغط السّريعة فإنّ هذه الصّيغة هي ملائمة بالنسبة لك، ولكن إن كنت تُخطّط لضغط الملف مرّة واحدة ومن ثمّ تخزينه حينها ستجد أنّ الخيارات الأخرى تملك مزايا أكثر. عادةً يتمّ تخزين ملفات gzip باستخدام اللاحقة .gz، تستطيع ضغط الملفّات باستخدام gzip بكتابة الأمر التالي: gzip sourcefileسيقوم هذا الأمر بضغط الملف وتغيير اسمه إلى "sourcefile.gz "على جهازك. إن كنت ترغب بضغط المجلد كاملاً عندها تستطيع تمرير العَلَم –r داخل الأمر كما يلي: gzip -r directory1سيقوم هذا الأمر بالتحرك داخل المجلد وضغط كل ملف على حدا، وهو عادةً شيء غير مفضل ويمكن الحصول على نتيجة أفضل بأرشفة المجلد ومن ثم ضغط الملف الناتج ككل، والتي سنقوم بشرح كيفية عملها قريباً. لإيجاد المزيد من المعلومات حول الملف المضغوط تستطيع تستطيع استخدام العَلَم –l والذي سيقوم بإعطائك بعض الإحصائيات: gzip -l test.gz compressed uncompressed ratio uncompressed_name 5133 14073 63.7% test إذا كنت ترغب بتمرير النّتيجة إلى أداة أخرى بإمكانك إخبار gzip أن يرسل الملف المضغوط إلى مخرج معياري باستخدامك العَلَم –c، سنقوم في هذا المثال ببساطة بتمريره مباشرة إلى ملف آخر: gzip -c test > test.gzبإمكانك ضبط إعدادات الضّغط الأمثل بتمرير علم على شكل رقم في المجال بين الـ 1 والـ 9، العَلَم -1 (يملك Alias المُسمّاة --fast) يُمثّل الطّريقة الأسرع ولكن الأقل تَعمُّقًا في الضّغط، أمّا العَلَم -9 (والـ alias الخاص به هو --best) يمثل الطريقة الأبطأ والأكثر تعمّقًا في الضّغط، إن الخيار الافتراضي هو -6 والذي يشكل أساس متوسط جيد. gzip -9 compressmeلكي تقوم بفك ضغط ملف ببساطة تمرّر العَلَم –d إلى الأمر gzip (يوجد أيضاً عدّة alias مثل gunzip ولكنها تقوم بنفس الفعل): gzip -d test.gz 2- الضّغط بأداة bzip2Bzip2 هي صيغة وأداة شائعة أخرى للضغط، وفي حين أنّها إلى حدٍّ ما أحدث من gzip، حيث تم تقديمها لأول مرة في عام 1996م، إلا أنه تم تنفيذ bzip2 بشكل واسع لتكون البديل التقليدي لـ gzip. بينما يعتمد gzip على خوارزمية "DEFLATE" فإنّ bzip2 هو تنفيذ لخوارزمية تدعى "Burrows-Wheeler algorithm"، ينتج عن هذا الاختلاف في المنهجية مجموعة من نقاط القوة والضعف والتي هي مختلفة تمامًا عن gzip، إنّ أهم شيء يجعل المستخدم يتنازل عن بعض الميزات للحصول على ميزات أخرى هي معدّل الضّغط العالي مقابل وقت أطول لعملية الضّغط، تستطيع أداة bzip2 إنشاء ملفات مدمجة بشكل كبير أكثر من gzip ولكنّها تأخذ وقتًا أطول لتحقيق هذه النتائج نظرًا لوجود خوارزمية أكثر تعقيدًا. لحسن الحظ فإنّ وقت فك الضّغط لا يتأثر بشكل كبير كوقت الضّغط، لذلك ربما يكون من المفيد توزيع الملفّات باستخدام صيغة bzip2 حيث أنّك فقط ستعاني خلال وقت عملية ضغطه وسيكون بإمكانك توزيع ملفات ذات حجم أصغر والتي يمكن فك ضغطها خلال وقت معقول، طبعاً لا يزال وقت فك الضّغط أطول بكثير من صيغة gzip ولكن ليس له تأثير كبير على عملية الضّغط. لا بدّ أيضًا أن نبقي في ذهننا أنّ استهلاك الذاكرة أكبر من gzip، لن يؤثر هذا على معظم الأجهزة ولكن على بعض الأجهزة الصغيرة المدمجة ممكن أن يؤثر هذا على خياراتك، بإمكانك أن تختار تمرير العَلَم –s والذي سينقص حجم الذاكرة المطلوبة تقريبًا إلى النصف، ولكن سيقودك هذا أيضًا إلى معدّل ضغط أقل. يتم إعطاء الملفّات المضغوطة بهذه الآلية لاحقة الملفّات .bz2 بشكل عام. لكي تقوم بإنشاء ملف مضغوط باستخدام bzip2 بإمكانك ببساطة كتابة ما يلي: bzip2 afileسيقوم هذا الأمر بضغط الملف وإعطائه الاسم "afile.bz2". وكما ذكرنا سابقًا تستطيع تمرير العَلَم –s للدلالة على أن الأداة المساعدة يجب أن تعمل في وضع الذاكرة المُخَفَضّة ، لن يقوم هذا بالضّغط بشكل جيد ولكنّه لن يتطلب الكثير من الموارد: bzip2 -s afileبينما تقوم bzip2 بتطبيق الأعلام المرقمة numbered flags إلّا أنها تعني شيئًا مختلفًا عمّا تعنيه في gzip، حيث تمثّل الأعلام المرقّمة هنا حجم الكتلة block size التي تنفّذ الأداة المساعدة ضغطها ، لذلك يعدّ هذا كوسيلة قياس للذاكرة المستخدمة مقابل حجم الملف المضغوط أكثر منه الوقت مقابل حجم الملف المضغوط، إنّ السلوك الافتراضي هو العَلَم -9 والذي يعني استخدامًا أعلى للذاكرة (نسبيًا) مع معدّل ضغط أعلى: bzip2 -1 fileلنتمكن من فك ضغط ملف مضغوط باستخدام bzip2 نقوم بتمرير العَلَم –d كما يلي: bzip2 -d file.bz2سيعطينا هذا ملفًا غير مضغوط اسمه "file". 3- الضّغط باستخدام xzآلية الضّغط باستخدام xz هي الوافد الجديد نسبيًا على الساحة ، تمّ إطلاق هذه الأداة لأول مرة عام 2009م واكتسبت متابعة بشكل ثابت منذ ذلك الحين. تستفيد أدوات الضّغط باستخدام xz من خوارزمية الضّغط المعروفة باسم "LZMA2" ، تمتلك هذه الخوارزمية معّدل ضغط عالٍ أكثر من المثالين السابقين ، والذي يجعل منها صيغة جيدة عندما تحتاج إلى تخزين البيانات على مساحة محدودة من القرص حيث تقوم بإنشاء ملفات أصغر حجمًا. طبعًا يأتي هنا موضوع التكلفة مرة أخرى في معظم نفس المجالات التي تعاني منها bzip2 ، فبينما يكون الملف الذي تنتجه طريقة xz أصغر حجمًا من الأدوات الأخرى إلّا أنّها تأخذ بشكل كبير وقتًا أطول للقيام بالضّغط ، فعلى سبيل المثال عندما نستخدم أعلام الضّغط بمعدّل عالٍ على ملف ذو حجم كبير فإنّ gzip يحتاج تقريبًا حوالي نصف دقيقة ، وbzip2 يحتاج تقريبًا حوالي دقيقة ، أمّا xz ربما تحتاج حوالي 4 أو 5 دقائق. تتلقى أدوات الضّغط باستخدام xz ضربة أيضًا في متطلبات الذاكرة التي تحتاجها ، تصل أحيانًا إلى حجم أكثر من الطرق الأخرى ، ربّما لا تكون هذه مشكلة بالنسبة لك إن كنت على نظام يملك ذاكرة وافرة ، ولكن يجب أن تأخذ هذا الموضوع بعين الاعتبار. بينما يكون وقت الضّغط أطول من المرغوب به ، فإنّ وقت فكّ الضّغط جيّد نسبيًا رغم أنّه لا يقارب gzip بالنظر إلى سرعة فك الضّغط ولكنّه أسرع عادة وبشكل كبير بفك الضّغط من bzip2 ، كما أنّ استهلاك الذاكرة لفك الضّغط ليس هائلًا أيضًا (ولكنّه يبقى مرتفعًا نسبيًا). تجعل هذه المجموعة من المزايا والعيوب من هذه الصّيغة صيغةً جيدةً لتوزيع الملفّات كالبرامج ، سيتوجب عليك مقدمًا أن تعاني في عملية ضغط هذه الملفّات ولكنّ مستهلكي البرامج سيستفيدون كثيرّا ، حيث أنّهم سيملكون ملفاً مدمجاً يتمّ فك ضغطه بسرعة. ومن العيوب غير الملاحظة أيضًا لهذه الصّيغة أنّها ربّما ليست مدعومة على الأنظمة الأقدم نظرًا لحداثة عهدها ، فإن كنت تبحث عن التوافقية العظمى ربّما ستكون مجبرًا بأن تنظر إلى أداة أخرى. تأخذ الملفّات المنشأة بهذه الصّيغة اللاحقة .xz بشكل عام. لكي تقوم بضغط ملف قم باستدعاء الأداة ببساطة من دون أيّة وسائط : xz fileسيقوم هذا الأمر بمعالجة الملف وإنتاج ملف يدعى "file.xz". لكي تعرض إحصائيات statistics عن عمليّة ضغط الملف تستطيع تمرير العَلَم –l على الملف المضغوط كما يلي: xz -l test.xz Strms Blocks Compressed Uncompressed Ratio Check Filename 1 1 5,016 B 13.7 KiB 0.356 CRC64 test.xzإن أردت إرسال خَرْج output عمليّة الضّغط إلى الخَرْج المعياري standard out فبإمكانك الإشارة إلى الأداة المساعدة بذلك عن طريق العَلَم –c، هنا في هذا المثال نستطيع إرسالها مرة أخرى مباشرة إلى ملف: xz -c test > test.xzبالنسبة للأعلام المرقّمة فإنّ xz تستخدم الأرقام الأقل لكي تشير إلى عملية ضغط أسرع، وهي تملك في الواقع العَلَم -0 كالخيار الأسرع، العَلَم -6 هو الافتراضي ويشكل أرضيّة جيدة لأغلب الحالات، أمّا إن كنت ترغب بتوجيه الضّغط إلى الملفّات الأكبر حجمًا تستطيع استخدام أعلامًا ذات أرقام أعلى والتي قد تأخذ وقتًا طويلًا جدًا ولكنّها ستظهر بعض المكاسب. وإن كنت ترغب بمعدّل ضغط أعلى ولا يهمك الوقت أو متطلبات الذاكرة إلخ..، فتستطيع استخدام العَلَم –e والذي يستخدم عملية ضغط بديلة مختلفة وشديدة الفاعلية، يمكن تعديل أداء هذا العَلَم أيضًا باستخدام الأعلام الرقمية معه : xz -e -9 large_fileستستغرق هذه العملية في النهاية وقتًا طويلًا وربّما لن تُقدّم فوائد كبيرة ولكن إن احتجت إلى هذه الوظيفة فالخيار متاح أمامك. لكي تقوم بفك الضّغط عن الملفّات مرّر العَلَم –d مرة ثانية: xz -d large_file.xzسيقوم هذا الأمر بفك ضغط البيانات إلى ملف يدعى "large_file". استخدام أرشفة Tar مع الضّغطفي حين أن أساليب الضّغط الفردية مفيدة بحدّ ذاتها إلّا أنّك في أغلب الأحيان ستجدهم مقترنين مع الصّيغة tar لضغط أرشفة الملفّات، يسمح لنا هذا بالحفاظ على بُنى المجلدات والأذونات إلخ..، للملفات التي نقوم بحزمها. إنّ الأمر tar حريص جدًا وفعليًا على هذه العلاقة، فهو يُضَّمّن أعلام في سطر الأوامر يُمكن استخدامها لاستدعاء أدوات الضّغط المرافقة تلقائيًا بعد أن تتم عمليّة الأرشفة، وكلّ ذلك في خطوة واحدة. 1- استخدام tar مع الصّيغة gzipلإنشاء أرشيف tar والذي يتم ضغطه بأداة gzip تستطيع تمرير العَلَم –z، يشير هذا العَلَم إلى أنّك ترغب باستخدام ضغط بصيغة gzip على الملف المؤرشف، لا تتطلب أعلام tar فعليًا البادئة "-" كما في معظم الأدوات الأخرى، ومن الأساليب الشائعة لإنشاء ملفات مضغوطة مؤرشفة هذا المثال: tar czvf compressed.tar.gz directory1سيقوم هذا الأمر بإنشاء أرشيف (باستخدام العَلَم –c) من المجلد الذي يُدعى "directory1"، حيثُ يُنشئ خَرْجًا مُطوّلًا ويضغط الأرشيف الناتج باستخدام gzip ومن ثُمّ يُعطي الناتج إلى ملف يُدعى "compressed.tar.gz" (وهو ملف tar تم ضغطه). حالما يتم إنشاء الملف نستطيع إلقاء نظرة على محتوياته باستخدام العَلَم –t بدلًا من علم الإنشاء (-c) : tar tzvf compressed.tar.gz drwxr-xr-x demouser/demouser 0 2014-03-19 18:31 directory1/ -rw-r--r-- demouser/demouser 5458 2014-03-19 18:31 directory1/httpd.conf.orig -rw-r--r-- demouser/demouser 2295 2014-03-19 18:31 directory1/nginx.conf.orig -rw-r--r-- demouser/demouser 5458 2014-03-19 18:21 directory1/httpd.confوللقيام بفك ضغط الملف لاحقًا وتوسيع الأرشيف تستطيع استخدام العَلَم –x كما يلي: tar xzvf compressed.tar.gzسيعيد هذا الأمر إنشاء بنية المجلّد في المجلّد الحالي. 2- استخدام tar مع bzip2لاستخدام الأرشفة مع bzip2 قُم باستبدال العَلَم –z (والذي هو خاص بالأمر gzip) بالعَلَم –j، هذا يعني أنّ أمر إنشاء الأرشيف المضغوط سيتم تعديله إلى التالي: tar cjvf bzipcompressed.tar.bz2 directory2مرةً أخرى تستطيع النظر إلى الملفّات المُحتواة في الأرشيف بتمرير العَلَم –t : tar tjvf bzipcompressed.tar.bz2 drwxr-xr-x demouser/demouser 0 2014-03-19 18:31 directory2/ -rw-r--r-- demouser/demouser 5458 2014-03-19 18:31 directory2/httpd.conf.orig -rw-r--r-- demouser/demouser 2295 2014-03-19 18:31 directory2/nginx.conf.orig -rw-r--r-- demouser/demouser 5458 2014-03-19 18:21 directory2/httpd.confتستطيع استخراج الملفّات وبنية المجلد إلى المجلد الحالي بكتابة ما يلي: tar xjvf bzipcompressed.tar.bz23- استخدام tar مع xzأضافت الإصدارات الحديثة من الأداة tar وظيفة مشابهة للضغط باستخدام xz، نستطيع القيام بذلك باستخدام العَلَم –J : tar cJvf xzcompressed.tar.xz directory3ولعرض المعلومات نستخدم نفس الآلية: tar tJvf xzcompressed.tar.xz drwxr-xr-x demouser/demouser 0 2014-03-19 18:31 directory3/ -rw-r--r-- demouser/demouser 5458 2014-03-19 18:31 directory3/httpd.conf.orig -rw-r--r-- demouser/demouser 2295 2014-03-19 18:31 directory3/nginx.conf.orig -rw-r--r-- demouser/demouser 5458 2014-03-19 18:21 directory3/httpd.confنتّبع نفس الأساليب للاستخراج : tar xJvf xzcompressed.tar.xzسيعطيك هذا الأمر بنية المجلد الكامل الخاص بك سليمة كما هي. الخاتمةآمل أنّك تملك الآن معلومات كافية لتتخذ قرارًا مستنيرًا بشأن أي وسيلة ضغط يجب أن تُفضّل في ظروفٍ مختلفة، تمتلك كل مخططات الضّغط التي ناقشناها في هذا المقال نقاط قوة جذّابة اعتمادًا على المتطلبات المحدّدة لحالتك. من الهام الانتباه إلى عيوب الأداء ومشاكل التّوافقيّة التي قد تلازم كلّ واحد من هذه الحلول، يعتمد مدى اهتمامك بهذه المخاوف كلياً على الحواسيب التي تعمل عليها وأيّ نوع من الزبائن يجب أن تدعم، لا يجب أن تعير أغلبية الحواسيب الحديثة اهتمامًا كثيرًا إلى هذه التفاصيل، ولكنّها قد تسبب مشاكل إذا قمت بتطبيق أنواع الضّغط بشكل عشوائي عند التعامل مع حواسيب أقدم. ترجمة -وبتصرّف- للمقال An Introduction to File Compression Tools on Linux Servers لصاحبه Justin Ellingwood.
×
×
  • أضف...