Child Process moduli
Bolalar jarayoni moduli nima?
Child Process moduli o‘rnatilgan Node.js moduli bo‘lib, u sizga bolalar jarayonlarini yaratish va boshqarish imkonini beradi.
U tashqi buyruqlarni bajarish va subprocess instances bilan aloqa qilishning bir necha usullarini taqdim etadi.
Bu qobiliyat quyidagi vazifalar uchun zarur:
- Node.js ilovangizdan tizim buyruqlarini ishga tushirish
- Alohida jarayonlarda protsessor talab qiladigan vazifalarni bajarish
- Bir nechta protsessor yadrolaridan foydalanish uchun bir nechta jarayonlarni parallel ravishda bajarish
- Tashqi dasturlar va skriptlar bilan o‘zaro ishlash
Child jarayoni modulini import qilish
Child Process moduli sukut bo‘yicha Node.js tarkibiga kiritilgan.
Siz uni skriptingizda talab qilish orqali foydalanishingiz mumkin:
const childProcess = require('child_process');
// Or using destructuring to access specific methods
const { exec, spawn, fork } = require('child_process');
Bolalar jarayonlarini yaratish usullari
Child Process moduli bolalar jarayonlarini yaratish va boshqarishning to‘rtta asosiy usulini taqdim etadi, ularning har biri turli xatti-harakatlar va foydalanish holatlariga ega:
| Metod | Tavsif | Foydalanish holati |
|---|---|---|
exec() |
Qobiq hosil qiladi va buyruqni bajaradi, natijani buferlaydi | Shell buyrug‘ini ishga tushirish va bir vaqtning o‘zida butun chiqishni olish kerak bo‘lganda |
execFile() |
exec() ga o‘xshaydi, lekin qobiq hosil qilmaydi |
Qobiq talqinisiz faylga asoslangan buyruqlarni bajarish uchun samaraliroq |
spawn() |
Oqimli I/U bilan qobiq yaratmasdan yangi jarayonni yaratadi | Uzoq davom etadigan jarayonlar yoki katta ishlab chiqarish bilan shug‘ullanganda |
fork() |
Node.js jarayonlarini yaratish uchun spawn() ning maxsus holati |
Boshqa Node.js modulini IPC bilan alohida jarayon sifatida ishga tushirishingiz kerak bo‘lganda |
exec() metodi
exec() usuli qobiq hosil qiladi va shu qobiq ichida buyruqni bajaradi.
U butun chiqishni buferlaydi va buyruq tugashi bilan uni callback funksiyasi orqali ta’minlaydi.
const { exec } = require('child_process');
// Execute the 'ls -la' command (or 'dir' on Windows)
const command = process.platform === 'win32' ? 'dir' : 'ls -la';
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${error.message}`);
return;
}
if (stderr) {
console.error(`Command stderr: ${stderr}`);
}
console.log(`Command output:\n${stdout}`);
});
// With options
exec('echo $HOME', {
env: { HOME: '/custom/home/directory' }
}, (error, stdout, stderr) => {
console.log(`Custom home directory: ${stdout.trim()}`);
});
Ogohlantirish: Hech qachon exec() ga tozalanmagan foydalanuvchi ma’lumotlarini o‘tkazmang, chunki u to‘liq qobiq sintaksisi bilan buyruqlarni bajaradi, bu esa buyruqlar kiritish hujumlariga olib kelishi mumkin.
exec() Promise bilan
callback-ni boshqarish uchun Promise paketidan foydalanish:
const { exec } = require('child_process');
const util = require('util');
// Convert exec to a promise-based function
const execPromise = util.promisify(exec);
async function executeCommand(command) {
try {
const { stdout, stderr } = await execPromise(command);
if (stderr) {
console.error(`Command stderr: ${stderr}`);
}
console.log(`Command output:\n${stdout}`);
return stdout;
} catch (error) {
console.error(`Error executing command: ${error.message}`);
throw error;
}
}
// Using the promise-based function
executeCommand('node --version')
.then(version => console.log(`Node.js version: ${version.trim()}`))
.catch(err => console.error('Failed to get Node.js version'));
execFile() metodi
execFile() usuli exec() ga o‘xshaydi, lekin u qobiq hosil qilmaydi.
Bu tashqi ikkilik fayllarni bajarish uchun samaraliroq.
const { execFile } = require('child_process');
// Execute 'node' with arguments
execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
console.error(`Error executing file: ${error.message}`);
return;
}
console.log(`Node.js version: ${stdout.trim()}`);
});
// On Windows, execute a batch file
if (process.platform === 'win32') {
execFile('C:\\Windows\\System32\\cmd.exe', ['/c', 'echo Hello from batch!'], (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
return;
}
console.log(`Output: ${stdout.trim()}`);
});
}
Eslatma: execFile() exec() ga qaraganda foydalanuvchi kiritishi bilan buyruqlarni bajarish uchun xavfsizroq, chunki u qobiq meta-belgilarini qayta ishlamaydi.
spawn() metodi
spawn() usuli berilgan buyruq bilan yangi jarayonni ishga tushiradi.
exec() dan farqli o‘laroq, u chiqishni buferlamaydi, aksincha, stdout va stderr-ga oqimga asoslangan kirishni ta’minlaydi.
const { spawn } = require('child_process');
// Spawn a process to list files
const ls = process.platform === 'win32'
? spawn('cmd', ['/c', 'dir'])
: spawn('ls', ['-la']);
// Handle process output streams
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`Child process exited with code ${code}`);
});
// Spawn with options
const grep = spawn('grep', ['hello', 'input.txt'], {
cwd: '/tmp', // Working directory
env: { ...process.env, CUSTOM_ENV: 'value' },
stdio: 'pipe', // Configure stdio
detached: false, // Process group behavior
shell: false // Whether to run in a shell
});
// Handling errors
grep.on('error', (err) => {
console.error(`Failed to start subprocess: ${err.message}`);
});
spawn() qachon ishlatiladi
spawn() ayniqsa quyidagilar uchun foydalidir:
- Uzoq davom etadigan jarayonlar (masalan, server jarayonlari yoki kuzatuvchilar (watchers))
- Ko‘p miqdorda mahsulot ishlab chiqaradigan jarayonlar
- Tugallanishni kutish o‘rniga, ma’lumotlarni yaratilganidek qayta ishlash kerak bo‘lganda
spawn()’ni stdin bilan ishlatish
const { spawn } = require('child_process');
// Spawn a process that reads from stdin
const process = spawn('wc', ['-w']); // Word count
// Send data to the process's stdin
process.stdin.write('Hello world from Node.js!');
process.stdin.end(); // Signal the end of input
// Capture output
process.stdout.on('data', (data) => {
console.log(`Number of words: ${data}`);
});
fork() metodi
fork() usuli Node.js jarayonlarini yaratish uchun maxsus spawn() ning maxsus holatidir. U ota-ona va bola jarayonlari o‘rtasida xabarlar yuborish imkonini beruvchi IPC kanalini o‘rnatadi.
// In the main file (parent.js)
const { fork } = require('child_process');
// Fork a child process
const child = fork('child.js');
// Send a message to the child
child.send({ message: 'Hello from parent' });
// Receive messages from the child
child.on('message', (message) => {
console.log('Message from child:', message);
});
// Handle child process exit
child.on('close', (code) => {
console.log(`Child process exited with code ${code}`);
});
// In the child file (child.js)
console.log('Child process started', process.pid);
// Listen for messages from the parent
process.on('message', (message) => {
console.log('Message from parent:', message);
// Send a message back to the parent
process.send({ response: 'Hello from child' });
// After 3 seconds, exit the process
setTimeout(() => {
process.exit(0);
}, 8080);
});
fork() afzalliklari
- Har bir vilkali jarayon o‘zining V8 nusxasini va xotirasini oladi
- Protsessor talab qiladigan ishni asosiy voqealar siklidan ajratib turadi
- Xabarlar orqali jarayonlar o‘rtasida aloqa o‘rnatishga imkon beradi
- Bir nechta CPU yadrolaridan foydalanishga yordam beradi
Jarayonlararo aloqa (IPC)
fork() bilan yaratilgan bolalar jarayonlari send() va message hodisasi yordamida o‘rnatilgan IPC kanali orqali ota-ona jarayoni bilan bog‘lanishi mumkin.
Murakkab ma’lumotlarni yuborish
// In parent.js
const { fork } = require('child_process');
const child = fork('worker.js');
// Send different types of data
child.send({
command: 'compute',
data: [1, 2, 3, 4, 5],
options: {
multiply: 2,
subtract: 1
}
});
// Receive the result
child.on('message', (result) => {
console.log('Computation result:', result);
child.disconnect(); // Clean up the IPC channel
});
// In worker.js
process.on('message', (msg) => {
if (msg.command === 'compute') {
const result = msg.data.map(num => num * msg.options.multiply - msg.options.subtract);
// Send the result back to the parent
process.send({ result });
}
});
Eslatma: Xabarlar JSON yordamida ketma-ketlashtiriladi, shuning uchun siz faqat JSON-mos keladigan ma’lumotlarni (obyektlar, massivlar, stringlar, raqamlar, mantiqiy va null) yuborishingiz mumkin.
Bolalar jarayonlarini boshqarish
Bolani o‘ldirish jarayoni
const { spawn } = require('child_process');
// Spawn a long-running process
const child = spawn('node', ['-e', `
setInterval(() => {
console.log('Still running...', Date.now());
}, 1000);
`]);
// Output from the process
child.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
// Kill the process after 5 seconds
setTimeout(() => {
console.log('Killing the child process...');
// Send a SIGTERM signal
child.kill('SIGTERM');
// Alternative: child.kill() - uses SIGTERM by default
}, 5000);
// Handle the exit event
child.on('exit', (code, signal) => {
console.log(`Child process exited with code ${code} and signal ${signal}`);
});
Ajratilgan jarayonlar
Siz ota-onadan mustaqil ravishda ishlashda davom etadigan alohida bolalar jarayonlarini yaratishingiz mumkin:
const { spawn } = require('child_process');
const fs = require('fs');
// Create a detached process
const child = spawn('node', ['long_running_script.js'], {
detached: true,
stdio: ['ignore',
fs.openSync('output.log', 'w'),
fs.openSync('error.log', 'w')
]
});
// Unref the child to allow the parent to exit independently
child.unref();
console.log(`Started detached process with PID: ${child.pid}`);
console.log('Parent will exit while child continues running.');
// The parent can now exit, and the child will continue running
Amaliy misollar
Oddiy vazifa navbatini yaratish
// In tasks.js (parent)
const { fork } = require('child_process');
const numCPUs = require('os').cpus().length;
class TaskQueue {
constructor() {
this.tasks = [];
this.workers = [];
this.maxWorkers = numCPUs;
}
addTask(task) {
this.tasks.push(task);
this.runNext();
}
runNext() {
// If we have tasks and available workers
if (this.tasks.length > 0 && this.workers.length < this.maxWorkers) {
const task = this.tasks.shift();
const worker = fork('worker.js');
console.log(`Starting worker for task ${task.id}`);
this.workers.push(worker);
worker.send(task);
worker.on('message', (result) => {
console.log(`Task ${task.id} completed with result:`, result);
// Remove this worker from our workers list
this.workers = this.workers.filter(w => w !== worker);
// Run the next task if we have one
this.runNext();
});
worker.on('error', (err) => {
console.error(`Worker for task ${task.id} had an error:`, err);
this.workers = this.workers.filter(w => w !== worker);
this.runNext();
});
worker.on('exit', (code) => {
if (code !== 0) {
console.error(`Worker for task ${task.id} exited with code ${code}`);
}
});
}
}
// Usage
const queue = new TaskQueue();
// Add some tasks
for (let i = 1; i <= 10; i++) {
queue.addTask({
id: i,
type: 'calculation',
data: Array.from({ length: 1000000 }, () => Math.random())
});
}
// In worker.js
process.on('message', (task) => {
console.log(`Worker ${process.pid} received task ${task.id}`);
// Simulate CPU-intensive work
let result;
if (task.type === 'calculation') {
// For example, find sum and average
const sum = task.data.reduce((acc, val) => acc + val, 0);
const avg = sum / task.data.length;
result = { sum, avg };
}
// Send result back to parent
process.send({ taskId: task.id, result });
// Exit this worker
process.exit(0);
});
Tashqi ilovalarni ishga tushirish
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
// Function to convert a video using ffmpeg
function convertVideo(inputFile, outputFile, options = {}) {
return new Promise((resolve, reject) => {
// Make sure input file exists
if (!fs.existsSync(inputFile)) {
return reject(new Error(`Input file ${inputFile} does not exist`));
}
// Prepare ffmpeg arguments
const args = ['-i', inputFile];
if (options.scale) {
args.push('-vf', `scale=${options.scale}`);
}
if (options.format) {
args.push('-f', options.format);
}
args.push(outputFile);
// Spawn ffmpeg process
const ffmpeg = spawn('ffmpeg', args);
// Collect output for logging
let stdoutData = '';
let stderrData = '';
ffmpeg.stdout.on('data', (data) => {
stdoutData += data;
});
ffmpeg.stderr.on('data', (data) => {
stderrData += data;
});
// Handle process completion
ffmpeg.on('close', (code) => {
if (code === 0) {
resolve({
inputFile,
outputFile,
stdout: stdoutData,
stderr: stderrData
});
} else {
reject(new Error(`ffmpeg exited with code ${code}\n${stderrData}`));
}
});
// Handle process errors
ffmpeg.on('error', reject);
});
}
// Example usage (commented out)
/*
convertVideo('input.mp4', 'output.webm', {
scale: '640:480',
format: 'webm'
})
.then(result => {
console.log('Video conversion successful!');
console.log(`Output file: ${result.outputFile}`)
;
})
.catch(error => {
console.error('Video conversion failed:', error.message);
});
*/
Eng yaxshi amaliyotlar
- Kirishni tozalash: Buyruqlar kiritish hujumlarining oldini olish uchun har doim foydalanuvchi kiritishlarini, ayniqsa
exec()bilan tozalang. - Resurslarni boshqarish: Bolalar jarayonlari tomonidan foydalaniladigan resurslarni (xotira, fayl deskriptorlari) kuzatib boring va boshqaring.
- Xatolarni hal qilish: Har doim bolalar jarayonlari uchun xatoliklarni to‘g‘ri hal qiling
- Choose the Right Method:
- Chiqish cheklangan oddiy buyruqlar uchun
exec()dan foydalaning - Uzoq davom etadigan jarayonlar yoki katta natijalar uchun
spawn()dan foydalaning - CPU intensiv Node.js operatsiyalari uchun
fork()dan foydalaning
- Chiqish cheklangan oddiy buyruqlar uchun
- Tozalash: Agar kerak bo‘lmasa, bolalar jarayonlarini to‘g‘ri yo‘q qiling
- Bir vaqtning o‘zida chegaralanish: Tizimning ortiqcha yuklanishini oldini olish uchun bir vaqtning o‘zida bo‘lgan bolalar jarayonlari sonini boshqaring
Ogohlantirish: Haddan tashqari ko‘p bolalar jarayonlarini ishga tushirish tizim resurslarini tezda ishlatishi mumkin. Har doim tezlikni cheklash va parallellik nazoratini amalga oshiring.
Xavfsizlik masalalari
- Buyruqni kiritish: Hech qachon tozalanmagan foydalanuvchi ma’lumotlarini bevosita
exec()yokispawn()ga o‘tkazmang - Muhit o‘zgaruvchilari: Muhit o‘zgaruvchilarini bolalar jarayonlariga o‘tkazishda ehtiyot bo‘ling
- Faylga kirish: Bolalar jarayonlari uchun ruxsatlarni tushuning
- Resurs cheklovlari: Bolalar jarayonlari uchun kutish vaqti va xotira chegaralarini joriy qilishni ko‘rib chiqing
W3Schools Pathfinder
Yutuqlaringizni kuzating – bu bepul!
