سرور دیشب برای به‌روزرسانی کرنل ریبوت شده و صبح API شما جواب نمی‌دهد، با اینکه دیروز با pm2 بالا آمده بود. مدیر پروسس برنامه را فقط وقتی بعد از ریبوت برمی‌گرداند که سرویس خودکار ساخته و فهرست برنامه‌ها ذخیره شده باشد، و مسیر Node.js که nvm نصب کرده هنوز سر جایش باشد.

اشتباهنشانهفرمان درست
اجرا با nohup یا screenبعد از ریبوت پروسسی نیستفرمان pm2 startup
سرویس بدون ذخیره فهرستفهرست برنامه‌ها خالی یا قدیمی برمی‌گرددفرمان pm2 save بعد از هر تغییر
ارتقای Node با nvmبرنامه بعد از ریبوت بالا نمی‌آیدفرمان pm2 unstartup و دوباره startup
حالت cluster با session در حافظهکاربر مدام از حساب بیرون می‌افتدنگهداری session در Redis
لاگ بدون چرخشدیسک آرام‌آرام پر می‌شودماژول pm2-logrotate

💡 دو فرمانی که اجرای دائمی را کامل می‌کنند

مدیر پروسس برنامه کرش‌کرده را خودش دوباره اجرا می‌کند؛ برگشتن بعد از ریبوت به سرویس startup و فهرست save نیاز دارد.
✅ بعد از اضافه یا حذف هر برنامه، فهرست را دوباره ذخیره کنید.
✅ خود مدیر پروسس هم با npm نصب می‌شود؛ اگر روی سرور داخلی نصب نشد، مقاله تحریم npm علتش را می‌گوید.

این اشتباه‌ها معمولاً در بدترین لحظه پیدا می‌شوند: ریبوتی که خودتان برنامه‌ریزی نکرده‌اید. بعد از هر رفع، در ساعت کاری یک بار sudo reboot بزنید تا همان لحظه را بی‌خطر بازسازی کنید؛ ریبوت یازده صبح با چای کنار دست، ارزان‌تر از ریبوت سه بامداد است.

نمودار مسیر درخواست از Nginx به چند پروسس Node.js روی یک سرور لینوکس، pm2

نصب Node.js با nvm؛ اشتباهی که بعد از ریبوت پیدا می‌شود

مدیر نسخه nvm برای هر کاربر جدا نصب می‌شود و هر نسخه Node.js را در پوشه‌ای زیر ~/.nvm/versions/node می‌گذارد؛ پکیج‌های سراسری، از جمله pm2، کنار همان نسخه می‌نشینند. پس همه فرمان‌های این مقاله را با همان کاربری بزنید که برنامه را اجرا می‌کند، نه root.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash
source ~/.bashrc   # nvm را در همین شل بارگذاری می‌کند
nvm install --lts
npm install pm2@latest -g

کارت ۱: ارتقای Node و سرویسی که هنوز نسخه قبلی را صدا می‌زند

نشانه: در ترمینال همه‌چیز سالم است، اما بعد از ریبوت برنامه یا بالا نمی‌آید یا با نسخه قبلی Node اجرا می‌شود.

سرویس خودکار مسیر پوشه bin نسخه‌ای را نگه می‌دارد که هنگام ساختنش فعال بوده؛ اگر نسخه قبلی را پاک کنید، به فایلی اشاره می‌کند که دیگر نیست. مستندات Startup Script برای همین حالت می‌گوید بعد از ارتقای Node پیکربندی قبلی را حذف کنید و سرویس تازه بسازید. قدم‌ها: نصب نسخه جدید با پکیج‌های سراسری، پیش‌فرض کردنش، جایگزینی نسخه در حافظه با update و ساختن دوباره سرویس.

nvm install --reinstall-packages-from=current 'lts/*'
nvm alias default node
pm2 update
pm2 unstartup   # خروجی را کپی و اجرا کنید
pm2 startup     # خروجی را کپی و اجرا کنید

کارت ۲: دانلود Node.js که روی سرور تمام نمی‌شود

نشانه: فرمان nvm install روی دریافت فایل می‌ماند.

نشانی پیش‌فرض https://nodejs.org/dist است و متغیر NVM_NODEJS_ORG_MIRROR آن را عوض می‌کند؛ میرری را بگذارید که به آن اعتماد دارید.

export NVM_NODEJS_ORG_MIRROR=https://MIRROR.EXAMPLE/dist
nvm install --lts

سرویس را بعد از ریبوت زنده نگه دارید؛ startup و save

سرویس را بعد از ریبوت زنده نگه دارید؛ startup و save

فرمان startup در pm2 یک سرویس systemd می‌سازد که هنگام بوت، فهرست ذخیره‌شده برنامه‌ها را برمی‌گرداند و save همان فهرست را روی دیسک می‌نویسد. اگر یکی از این دو را جا بیندازید، ریبوت بعدی برنامه را خاموش رها می‌کند.

در پایانه اتوبوسرانی، مسئول حرکت اتوبوس خراب را با اتوبوس دیگری روی همان خط عوض می‌کند و در دفتر می‌نویسد؛ مدیر پروسس با برنامه کرش‌کرده همین کار را می‌کند. صبح هم فقط خط‌های فهرست روی میز، یعنی dump.pm2، راه می‌افتند.

کارت ۳: برنامه‌ای که با nohup یا screen اجرا شده

نشانه: برنامه تا اولین کرش یا ریبوت کار می‌کند و بعد کسی برش نمی‌گرداند.

pm2 start app.js --name api
pm2 startup   # خط sudo چاپ‌شده را کپی و اجرا کنید
pm2 save

مستندات می‌خواهد startup را بدون sudo بزنید؛ خروجی‌اش خطی با sudo است که مسیر Node، نام کاربر (-u) و پوشه خانه (--hp) را دارد.

🔸 فرمان startup چه چیزی روی دیسک می‌نویسد

روی سیستم‌های systemd فایل /etc/systemd/system/pm2-USER.service ساخته و فعال می‌شود. در قالب کد منبع پروژه، خط Environment=PATH پوشه bin همان نسخه Node را نگه می‌دارد و ExecStart فرمان resurrect را اجرا می‌کند. نسخه سرور خودتان را با systemctl cat pm2-$USER ببینید.

کارت ۴: برنامه جدید اضافه شده، ولی فهرست ذخیره نشده

نشانه: بعد از ریبوت فقط برنامه‌های قدیمی برمی‌گردند یا برنامه حذف‌شده دوباره ظاهر می‌شود.

دستور save فهرست فعلی را در ~/.pm2/dump.pm2 می‌نویسد و resurrect هنگام بوت همین فایل را می‌خواند؛ هر start یا delete بعد از آخرین save، با ریبوت گم می‌شود. آزمون نهایی:

sudo reboot
# بعد از اتصال دوباره
pm2 list
journalctl -u pm2-$USER

حالت cluster همیشه سریع‌تر نیست

حالت cluster در pm2 چند نسخه از برنامه را با ماژول cluster خود Node.js روی هسته‌های پردازنده پخش می‌کند تا همه روی یک پورت گوش بدهند. روی سرور تک‌هسته‌ای یا برنامه‌ای با session در حافظه، دردسرش از سرعتش بیشتر است.

فرمان خام در برابر فایل ecosystem

این خط cluster را روشن می‌کند، اما تنظیماتش جایی ثبت نمی‌شود. اگر api از کارت ۳ هنوز اجراست، با پیام Script already launched متوقف می‌شود:

pm2 start app.js --name api -i max --max-memory-restart 300M

همان تنظیم در ecosystem.config.js؛ برنامه پورت را از process.env.PORT می‌خواند:

module.exports = {
  apps: [{
    name: "api",
    script: "./app.js",
    instances: "max",
    exec_mode: "cluster",
    max_memory_restart: "300M",
    env: {
      PORT: 3000
    },
    env_production: {
      NODE_ENV: "production",
      PORT: 3000
    }
  }]
}

برنامه‌ای که با همین نام در حالت fork اجراست، با start از فایل به cluster تبدیل نمی‌شود و بی‌صدا ری‌استارت می‌خورد. حذفش کنید، از فایل اجرا کنید و فهرست را دوباره ذخیره کنید:

pm2 delete api
pm2 start ecosystem.config.js --env production
pm2 save
pm2 list   # ستون mode باید cluster باشد

🔸 فایل ecosystem یا فلگ‌های خط فرمان

مستندات فایل پیکربندی شرط می‌گذارد که نام فایل به .config.js ختم شود تا مدیر پروسس آن را فایل تنظیمات بشناسد. مقادیر env بر متغیرهای شل غلبه دارند و --env production سراغ env_production می‌رود.

کارت ۵: همه هسته‌ها برای برنامه‌ای که حالت دارد

نشانه: بعد از روشن کردن cluster، کاربر هر چند درخواست یک بار از حساب بیرون می‌افتد، چون درخواست بعدی به پروسسی می‌رسد که او را نمی‌شناسد.

مقدار max یک پروسس برای هر هسته می‌سازد؛ روی سرور یک vCPU یعنی همان یک پروسس. پخش بار بین چند سرور در مقاله لود بالانسر چیست آمده است.

⚠️ session در حافظه با cluster کنار نمی‌آید

مستندات حالت cluster می‌گوید برنامه باید stateless باشد. session و اتصال WebSocket در حافظه یک پروسس بین نسخه‌ها مشترک نیست؛ آن را در Redis یا دیتابیس نگه دارید، یا با یک instance اجرا کنید.

فرمان reload به‌جای restart بعد از هر استقرار

فرمان restart پروسس را می‌کشد و دوباره اجرا می‌کند، ولی reload در حالت cluster بدون قطعی انجام می‌شود. هنگام توقف، اول SIGINT می‌رسد و اگر برنامه ظرف ۱.۶ ثانیه بسته نشود، SIGKILL می‌گیرد؛ برای بستن آرام اتصال دیتابیس، این مهلت را با kill_timeout بالا ببرید.

pm2 reload ecosystem.config.js --only api

لاگ‌ها و Nginx جلوی PM2 کجا کار را خراب می‌کنند؟

لاگ‌ها و Nginx جلوی PM2 کجا کار را خراب می‌کنند؟

خروجی برنامه در پوشه ~/.pm2/logs جمع می‌شود و طبق مستندات، چرخاندن و محدود کردن فضای آن کار ماژولی جداگانه است. Nginx هم با تنظیم پیش‌فرض، هدرهای WebSocket را به برنامه نمی‌رساند.

کارت ۶: لاگی که هیچ‌وقت چرخانده نمی‌شود

نشانه: فرمان df -h دیسک را نزدیک به پر نشان می‌دهد و بزرگ‌ترین فایل‌ها لاگ‌های برنامه‌اند.

pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:compress true
pm2 conf

در README ماژول، پیش‌فرض‌ها چرخش در حجم 10M، نگهداری ۳۰ فایل (retain) و چرخش اجباری هر نیمه‌شب است و فشرده‌سازی خاموش است. ماژول از مخزن npm دانلود می‌شود؛ اگر نصبش خطا داد، همان تنظیم registry مقاله تحریم npm این‌جا هم کار می‌کند.

کارت ۷: پروکسی Nginx بدون هدر Upgrade

نشانه: صفحه باز می‌شود، اما WebSocket وصل نمی‌شود یا بعد از ۶۰ ثانیه سکوت قطع می‌شود.

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 240s;
    }
}

طبق مستندات ماژول proxy در nginx، پیش‌فرض proxy_http_version تا پیش از نسخه 1.29.7 برابر 1.0 بود و از این نسخه 1.1 است؛ نسخه مخزن توزیع ممکن است قدیمی‌تر باشد، پس خط را صریح بنویسید. پیش‌فرض proxy_read_timeout ۶۰ ثانیه است.

متن را در فایلی .conf بگذارید که nginx.conf آن را include می‌کند؛ nginx -T پیکربندی بارشده را نشان می‌دهد. برای HTTPS، listen 443 ssl و مسیر گواهی را اضافه کنید.

sudo nginx -t && sudo nginx -s reload

سرور Node.js بدون host روی همه نشانی‌ها گوش می‌دهد؛ با app.listen(process.env.PORT, '127.0.0.1') درخواست فقط از Nginx می‌رسد.

مدیر پروسس را یک بار راه انداخته‌اید و ته دلتان مطمئن نیستید بعد از ریبوت برگردد؟ این سوال‌ها شب قبل از ریبوت به ذهن می‌رسند.

بعد از ریبوت سرور، برنامه‌های Node.js خودکار برمی‌گردند؟

فقط وقتی سرویس خودکار ساخته شده و فهرست بعد از آخرین تغییر ذخیره شده باشد؛ یک ریبوت دستی جواب قطعی می‌دهد.

بدون sudo. خروجی آن خطی با sudo است که مسیر Node و نام کاربر شما را دارد؛ همان را اجرا کنید.

نسخه جدید را پیش‌فرض کنید، update بزنید، پیکربندی قبلی را با unstartup حذف کنید و سرویس را دوباره بسازید.

در ~/.pm2/logs. در حالت fork نام فایل api-out.log است و در حالت cluster شماره پروسس هم می‌آید: api-out-0.log، api-out-1.log. دستور pm2 logs api --lines 200 همه را یک‌جا نشان می‌دهد.

خیر. این حالت برای سرورهای شبکه‌ای است و برنامه باید stateless باشد؛ اسکریپت غیر JavaScript از نسخه 7.1.0 با هشدار به fork برمی‌گردد.

فرمان unstartup دستور حذف سرویس را چاپ می‌کند؛ آن را اجرا کنید. فایل dump روی دیسک می‌ماند.

اجباری نیست، اما راهنمای Nginx در مستندات رسمی همین مدیر پروسس این چیدمان را پیشنهاد می‌کند: Nginx فایل ثابت و SSL را مدیریت و ترافیک را به برنامه منتقل می‌کند.

جمع‌بندی؛ ریبوت را قبل از سرور خودتان امتحان کنید اجرای دائمی با pm2 روی دو فرمان بنا شده است: startup که سرویس systemd را می‌سازد و save که فهرست برنامه‌ها را روی دیسک می‌نویسد. بیشتر خرابی‌های بعد از ریبوت به همین دو برمی‌گردد، یا به مسیری از nvm که دیگر وجود ندارد. بعد از هر ارتقای Node سرویس را دوباره بسازید، cluster را فقط برای برنامه stateless روشن کنید و چرخش لاگ و هدرهای Upgrade را پیش از ترافیک واقعی تنظیم کنید. بعد یک ریبوت دستی بزنید و فهرست پروسس‌ها را ببینید.

🚀 وقتی npm install روی سرور داخلی گیر می‌کند

سروری که به registry npm نرسد، نه ماژول لاگ را نصب می‌کند نه نسخه تازه مدیر پروسس را؛ میرور جایگزین در راهنمای زیر آمده است.

برنامه Node شما با کدام روش زنده می‌ماند و تا حالا بعد از ریبوتی برنگشته؟ تعریفش کنید؛ شاید کارت هشتم باشد.

منابع

وب داده
وب داده

جدید ترین مطالب آموزشی و کاربردی را در اینجا بخوانید !
ما با بهره‌گیری از دانش روز و تجربه متخصصان حوزه فناوری، مجموعه‌ای از آموزش‌های کاربردی و مقالات تخصصی را گردآوری کرده‌ایم که هر یک، پاسخی دقیق به پرسش‌های شماست. ؛ از مفاهیم پایه تا پیچیده‌ترین تکنیک‌های حرفه‌ای. اینجا، دانش با زبانی ساده اما عمیق در اختیار شما قرار می‌گیرد.

مقاله‌ها: 262
پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *