الفكرة
PM2 عنده حاجة جاهزة للموضوع ده، وهي خطوتين: startup وsave.
بيخلي PM2 نفسه يقوم مع الـ boot.
بيقول لـ PM2 أنهي apps يرجّعها لما يقوم.
واحدة من غير التانية مش كفاية. startup من غير save يعني PM2 هيقوم فاضي. وsave من غير startup يعني القائمة محفوظة ومحدش هيقراها.
١. خلي PM2 يقوم مع السيستم
pm2 startupالأمر ده بيعرف نوع الـ init system عندك (غالبًا systemd على Ubuntu)، وبيطبعلك أمر جاهز يبدأ بـ sudo، شكله كده:
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u ubuntu --hp /home/ubuntu- انسخ الأمر اللي طلعلك إنت بالظبط ونفذه، متكتبوش من دماغك. الأمر فيه مسار الـ node واسم اليوزر والـ home بتوعك.
- الأمر ده بيعمل service اسمها
pm2-<username>، بتقوم مع الـ boot. - شغّل
pm2 startupنفسه من غير sudo. هو بس اللي بيطبع الأمر، والأمر المطبوع هو اللي فيه sudo.
٢. احفظ الـ apps الشغالة
شغّل الـ apps الأول، وبعدين احفظ القائمة:
pm2 start ecosystem.config.jspm2 saveالأمر pm2 save بيكتب الـ apps الشغالة حاليًا في ملف ~/.pm2/dump.pm2. ولما السيرفر يقوم، PM2 بيقرأ الملف ده ويرجّع كل حاجة زي ما كانت.
٣. اتأكد إن الـ service شغالة
اسم الـ service هو pm2- وبعده اسم اليوزر اللي نفّذ أمر الـ startup. يوزر ubuntu يبقى pm2-ubuntu. يوزر saeed يبقى pm2-saeed.
whoamisystemctl is-enabled pm2-$(whoami)systemctl is-active pm2-$(whoami)systemctl status pm2-$(whoami)is-enabled: هتقوم مع الـ boot ولا لأ. الناتج المطلوبenabled.is-active: شغالة دلوقتي ولا لأ.activeيعني systemd هو اللي ماسك الـ daemon.inactiveأول مرة بعدpm2 startupمش دايمًا مشكلة، لأنك ممكن تكون شغّلت الـ apps بإيدك والـ service لسه متعملهاشstart. بعد أول reboot المفروض تبقىactive.status: يجمع الاتنين، ويعرض آخر سطور من اللوج. لو وقعت، دور علىfailed.
بعد reboot، pm2 list من نفس اليوزر لازم يوريك الـ apps. systemctl بيقول إن المنبّه صحّى البواب. pm2 list بيقول إن السكان رجعوا.
كل يوزر له service
الـ service مش بتاع السيرفر كله. مربوطة باليوزر في تلات حتت:
- الاسم:
pm2-<username>. - سطر
User=جوه ملف الـ service، وفيPM2_HOME=/home/<username>/.pm2. - القائمة:
pm2 resurrectبيقراdump.pm2اللي في الهوم ده بس.
لو على الجهاز يوزر ubuntu ويوزر deploy، وكل واحد شغّل pm2 startup وبعدين pm2 save، هيبقى فيه خدمتين:
| الـ service | بتقوم بإيه |
|---|---|
pm2-ubuntu | تطبيقات /home/ubuntu/.pm2/dump.pm2 |
pm2-deploy | تطبيقات /home/deploy/.pm2/dump.pm2 |
مفيش واحدة فيهم بتشوف تطبيقات التانية. كل يوزر لازم ينفّذ pm2 startup وpm2 save وهو داخل بحسابه. pm2 list من غير sudo يوريك بتوعك بس.
systemctl list-units --type=service 'pm2-*'ls /etc/systemd/system/pm2-*.serviceلو عملت pm2 save بحساب وstartup بحساب تاني، الـ service هتقوم وتلاقي قائمة فاضية أو قائمة قديمة بتاعة الحساب التاني.
حاجات لازم تاخد بالك منها
- بعد أي تغيير في الـ apps: ضفت app أو مسحت واحدة أو غيرت الإعدادات أو عدد الـ instances، اعمل
pm2 saveتاني. وإلا هيرجع للنسخة القديمة بعد الـ restart. - نفس اليوزر في
startupوفيsave. الـ service بتقرا هوم اليوزر المكتوب في اسمها، مش هوم اليوزر التاني. - لو بتستخدم nvm وغيرت نسخة Node: اعمل
pm2 unstartupوبعدهاpm2 startupتاني، لأن الـ service فيها مسار الـ node القديم (في سطرEnvironment=PATH=...). - لو حدّثت PM2 نفسه: اعمل
pm2 updateعشان الـ daemon اللي شغال يتحدث. تحديث الـ package بس مش بيغيّر الـ daemon اللي في الـ memory. - الـ env variables (زي
SSL_PUBLIC_KEYوSERVERHTTPS): الأضمن تحطها في الـ ecosystem file أو في.envيتقري من الكود، مش في الـ shell، عشان تبقى موجودة بعد الـ reboot.
pm2 unstartup # هيطبع أمر sudo يشيل الـ service القديمة، نفّذهpm2 startup # هيطبع أمر sudo جديد بمسار الـ node الجديد، نفّذهpm2 resurrect # لو الـ apps وقفت مع الـ unstartuppm2 savemodule.exports = { apps: [ { name: "LMS::backend", script: "./bin/www", cwd: "/home/ubuntu/lms-backend", // عشان .env يتقري من مكان ثابت exec_mode: "cluster", instances: "max", env: { NODE_ENV: "production", PORT: 4000, SERVERHTTPS: "1" }, }, ],};والأسرار نفسها، زي مسار الـ private key أو باسوورد الداتابيز، متتحطش في Git. حطها في .env على السيرفر بصلاحيات 600، والكود يقراها.
لو عايز تلغيه
pm2 unstartupده بيطبع أمر sudo، والأمر ده بيعمل systemctl stop وبعدين disable وبعدين بيمسح ملف الـ service.