process — argv, env, exit, uncaughtException, SIGINT

~20 daq · Node.js · Process

process nima?

Siz Node.js skriptini ishga tushirasiz:

node app.js

Operatsion tizim bu skript uchun alohida process (jarayon) yaratadi. Xuddi siz kompyuterda Word ochsangiz — u alohida jarayon bo'lgani kabi. Har bir jarayonning o'z xotirasi, o'z holati bor.

process — Node.js da o'sha joriy jarayonni ifodalovchi global ob'ekt. Uni import qilish shart emas — har qayerda mavjud. U orqali jarayonning hamma narsasini boshqarish mumkin: qanday argumentlar bilan ishga tushirilgan, qanday muhit o'zgaruvchilari bor, qanday to'xtatish kerak.


process.argv — buyruq qatori argumentlari

Tasavvur qiling: siz fayl konvertatsiya qiluvchi skript yozdingiz. Har safar skript ichida fayl nomini o'zgartirish — noqulay. Yaxshisi, terminaldan bering:

node convert.js input.txt output.pdf

process.argv — shu argumentlarni massiv sifatida beradi:

console.log(process.argv);
// [
//   '/usr/bin/node',   ← [0] node ning o'zi
//   '/home/user/convert.js', ← [1] skript fayli
//   'input.txt',       ← [2] birinchi argument
//   'output.pdf'       ← [3] ikkinchi argument
// ]

Birinchi ikki element har doim bir xil — node va skript yo'li. Sizning argumentlaringiz [2] dan boshlanadi:

const args = process.argv.slice(2);
// ['input.txt', 'output.pdf']

const input  = args[0]; // 'input.txt'
const output = args[1]; // 'output.pdf'

if (!input || !output) {
  console.error('Ishlatish: node convert.js <input> <output>');
  process.exit(1);
}

console.log(`${input} → ${output} ga konvertatsiya qilinmoqda`);

process.env — muhit o'zgaruvchilari

Parol, API kalit, ma'lumotlar bazasi manzili — bularni kod ichiga yozmaslik kerak. Sababi: kod GitHub ga chiqadi, parol oshkor bo'ladi.

Yechim — muhit o'zgaruvchilari (environment variables). Ular operatsion tizim darajasida saqlanadi, kod ichida emas.

# Terminalda o'rnatish:
export DATABASE_URL="postgresql://localhost/mydb"
export JWT_SECRET="super-secret-key"
export PORT=3000

node app.js

Kod ichida o'qish:

const dbUrl    = process.env.DATABASE_URL;
const secret   = process.env.JWT_SECRET;
const port     = process.env.PORT || 3000; // bo'lmasa standart qiymat

console.log(`Server ${port}-portda ishlamoqda`);

Amalda .env fayli ishlatiladi — har safar export yozmaslik uchun:

# .env fayli
DATABASE_URL=postgresql://localhost/mydb
JWT_SECRET=super-secret-key
PORT=3000
// dotenv paketi .env faylini o'qib, process.env ga yuklaydi
require('dotenv').config();

console.log(process.env.DATABASE_URL); // 'postgresql://localhost/mydb'

⚠️ .env faylini hech qachon GitHub ga chiqarmang. .gitignore ga qo'shing.


process.exit — jarayonni to'xtatish

process.exit() — jarayonni darhol to'xtatadi. Argument sifatida exit code beriladi:

  • 0 — muvaffaqiyatli tugadi
  • 1 (yoki boshqa nol bo'lmagan son) — xato bilan tugadi

Bu nima uchun muhim? Boshqa skriptlar yoki CI/CD tizimlari exit code ni tekshiradi. 0 bo'lsa — davom etadi. 1 bo'lsa — to'xtaydi, xato deb belgilaydi.

const fs = require('fs');

const configPath = process.argv[2];

if (!configPath) {
  console.error('Xato: config fayl yo\'li berilmadi');
  process.exit(1); // xato bilan to'xtat
}

if (!fs.existsSync(configPath)) {
  console.error(`Xato: ${configPath} fayl topilmadi`);
  process.exit(1);
}

console.log('Config yuklandi');
process.exit(0); // muvaffaqiyatli to'xtat

⚠️ process.exit() hamma narsani darhol to'xtatadi — asinxron operatsiyalar ham. Fayl yozilayotgan bo'lsa, ma'lumotlar bazasiga yozilayotgan bo'lsa — hammasi bekor bo'ladi. Shuning uchun faqat haqiqatan kerak bo'lganda ishlatiladi.


process.on('uncaughtException') — ushlanmagan xatolar

Kod ichida try/catch bilan ushlanmagan xato chiqsa — Node.js jarayonni to'xtatadi va stack trace chiqaradi. Bu production da yomon — server o'chib qoladi.

uncaughtException eventi bu xatolarni ushlab qoladi:

process.on('uncaughtException', (err) => {
  console.error('Ushlanmagan xato:', err.message);
  console.error(err.stack);

  // Logga yozish, monitoring ga xabar berish...

  process.exit(1); // keyin to'xtatish
});

// Endi bu xato serverni o'chirmaydi:
setTimeout(() => {
  throw new Error('Kutilmagan xato!');
}, 1000);

Muhim nuance: uncaughtException dan keyin jarayon noaniq holatda bo'ladi — xotira buzilgan bo'lishi mumkin. Shuning uchun xatoni log qilib, jarayonni to'xtatish kerak. PM2 yoki cluster uni qayta ishga tushiradi.

Asinxron xatolar uchun — unhandledRejection:

process.on('unhandledRejection', (reason, promise) => {
  console.error('Ushlanmagan Promise xatosi:', reason);
  process.exit(1);
});

// Bu xato ushlanadi:
Promise.reject(new Error('Promise xatosi'));

process.on('SIGINT') va 'SIGTERM' — to'xtatish signallari

Siz terminalda Ctrl+C bosganda — operatsion tizim jarayonga SIGINT signali yuboradi. Standart bo'yicha Node.js darhol to'xtaydi.

Lekin ba'zan to'xtatishdan oldin tozalash kerak: ma'lumotlar bazasi ulanishini yopish, fayllarni saqlash, so'rovlarni tugatish.

const db = require('./database');

// Ctrl+C bosilganda:
process.on('SIGINT', async () => {
  console.log('\nTo\'xtatilmoqda...');

  await db.close();           // ma'lumotlar bazasini yop
  console.log('DB yopildi');

  process.exit(0);
});

// Docker/Kubernetes to'xtatganda (SIGTERM):
process.on('SIGTERM', async () => {
  console.log('SIGTERM qabul qilindi');
  await db.close();
  process.exit(0);
});

console.log('Server ishlamoqda. To\'xtatish uchun Ctrl+C');

SIGTERM — kill <pid> buyrug'i yoki Docker stop berganda keladi. Production da har doim SIGTERM ham ushlanadi.


process.cwd va process.chdir

process.cwd() — hozirgi ishchi papka (current working directory). Skript qaysi papkadan ishga tushirilgan.

console.log(process.cwd());
// '/home/user/project'  ← node buyrug'i qayerdan ishga tushirilgan

__dirname bilan farqi: __dirname — faylning o'z papkasi. process.cwd() — node qayerdan ishga tushirilgan. Agar siz /home/user dan node project/app.js deb ishga tushirsangiz:

// app.js fayli /home/user/project/ da

console.log(__dirname);    // '/home/user/project'  ← fayl papkasi
console.log(process.cwd()); // '/home/user'          ← ishga tushirilgan papka

Fayl yo'llarini hisoblashda __dirname ishlatiladi — process.cwd() emas.


process.memoryUsage va process.cpuUsage

Monitoring uchun foydali — jarayon qancha resurs sarflayapti:

const mem = process.memoryUsage();

console.log(`RSS:       ${(mem.rss       / 1024 / 1024).toFixed(1)} MB`);
console.log(`Heap jami: ${(mem.heapTotal / 1024 / 1024).toFixed(1)} MB`);
console.log(`Heap ishlatilgan: ${(mem.heapUsed / 1024 / 1024).toFixed(1)} MB`);

// RSS       — jarayon uchun ajratilgan jami xotira
// heapTotal — V8 heap ning jami hajmi
// heapUsed  — hozir ishlatilayotgan heap

Tez-tez uchraydigan xatolar

process.exit() ni asinxron operatsiya ichida chaqirish:

process.on('SIGINT', () => {
  db.close(); // asinxron — tugamasdan...
  process.exit(0); // ...darhol to'xtatiladi
});

// To'g'ri:
process.on('SIGINT', async () => {
  await db.close(); // tugashini kut
  process.exit(0);
});

uncaughtException dan keyin davom etish:

process.on('uncaughtException', (err) => {
  console.error(err);
  // process.exit() yo'q — jarayon davom etadi
  // Lekin holat noaniq, xotira buzilgan bo'lishi mumkin
});

uncaughtException dan keyin har doim process.exit(1) chaqiriladi.


Xulosa

process — joriy Node.js jarayonini boshqarish uchun global ob'ekt.

Nima qiladi
process.argv Buyruq qatori argumentlari
process.env Muhit o'zgaruvchilari (parol, kalit)
process.exit(code) Jarayonni to'xtatish
uncaughtException Ushlanmagan xatolarni tutish
unhandledRejection Ushlanmagan Promise xatolarini tutish
SIGINT Ctrl+C signali
SIGTERM Tizim to'xtatish signali
process.cwd() Hozirgi ishchi papka

Keyingi dars

21-dars: child_process — exec, spawn, fork