التشغيل · فصل ٦

أوامر PM2 اليومية والـ Reload من غير Downtime

start · list · logs · monit · reload · restart · SIGINT
🎯 الهدف: تفك الأمر الطويل، وتنقله لـ ecosystem file، وتعرف إمتى reload بيبقى فعلًا من غير downtime.

فك الأمر الطويل

terminal
pm2 start ./bin/www -i 8 --merge-logs --time --name ".COM::backend"
  • ./bin/www: ملف التشغيل بتاع Express.
  • -i 8: يعني 8 instances. ومع Node app بيحوّل لـ cluster لوحده.
  • --merge-logs: كل الـ instances بيكتبوا في نفس ملف الـ out ونفس ملف الـ error، بدل ملف لكل instance برقمها.
  • --time: بيحط timestamp قدام كل سطر log.
  • --name: الاسم اللي هتستخدمه في باقي الأوامر.

نفس الأمر في ecosystem file

الأمر الطويل بيضيع في الـ shell history. الملف ده بيتحط في Git وأي حد يقدر يراجعه:

ecosystem.config.js
module.exports = {  apps: [    {      name: ".COM::backend",      script: "./bin/www",      exec_mode: "cluster",      instances: "max", // بدل 8 ثابتة      merge_logs: true,      time: true,      env: { NODE_ENV: "production", PORT: 4000 },    },  ],};

الأوامر اللي هتستخدمها كل يوم

terminal
pm2 start ecosystem.config.jspm2 list                          # كل الـ apps والـ mode والـ memorypm2 logs ".COM::backend" --lines 100pm2 monit                         # CPU وmemory لايفpm2 describe ".COM::backend"      # المسارات والـ env وعدد الـ restartspm2 scale ".COM::backend" 4       # غيّر عدد الـ workerspm2 stop ".COM::backend"pm2 delete ".COM::backend"

Restart ولا Reload؟

  • pm2 restart: بيقفل الكل وبعدين يشغّلهم تاني، فبيحصل downtime ولو ثواني.
  • pm2 reload: في cluster، بيشغّل worker جديد، ولما يجهز يقفل القديم، وهكذا واحد واحد. ده اللي بيخليه zero-downtime.
  • في fork، reload بيبقى restart عادي.
استخدم reload للـ deploy، وrestart لما تحتاج تبدأ من الصفر.

reload بيبقى من غير downtime بشرطين

  • أولًا: التطبيق يقفل بأدب. PM2 بيبعت SIGINT، فاقفل السيرفر وخلّص الـ requests اللي شغالة:
bin/www (إضافة)
process.on("SIGINT", () => {  server.close(() => process.exit(0)); // بيستنى الـ requests المفتوحة});
  • ثانيًا: الـ worker الجديد يكون جاهز قبل ما القديم يقفل. لو التطبيق بيحتاج وقت عشان يتصل بالداتابيز، استخدم wait_ready: true وابعت process.send("ready") لما يخلص.
  • لو الـ worker القديم مقفلش خلال kill_timeout، PM2 بيقفله بالعافية. ولو الجديد مبعتش ready خلال listen_timeout، PM2 بيكمل برضه. وفي الحالتين ممكن requests تضيع، فاختبر الـ reload على staging.

خلّصت الفصل لما

🧠 اختبر نفسك
١) --merge-logs بتخلي out وerror في ملف واحد؟
لأ. بتدمج الـ instances بس، والـ out والـ error يفضلوا منفصلين.
٢) الـ deploy بتاعك بيستخدم pm2 restart. إيه المشكلة؟
فيه downtime. استخدم pm2 reload في cluster.
٣) pm2 reload على تطبيق fork. هيبقى zero-downtime؟
لأ. في fork بيبقى restart عادي.