Дочерние процессы
Дочерний процесс — другая программа, которую запускает ваша: git, архиватор, конвертер картинок или ещё один скрипт на Node.js. Модуль node:child_process позволяет запустить её, передать аргументы и получить результат. Это нужно, когда готовая утилита уже умеет то, что вам требуется.
execFile: получить результат
execFile() запускает программу, ждёт её завершения и отдаёт весь вывод. В связке с promisify() из node:util её можно ждать через await:
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
const run = promisify(execFile);
const { stdout } = await run(process.execPath, ['--version']);
console.log(`Версия Node.js: ${stdout.trim()}`);process.execPath — полный путь к программе node. Пример запускает её с флагом --version и выводит, например, «Версия Node.js: v22.12.0». stdout — то, что программа напечатала.
Запуск своего скрипта
Тем же способом запускают другой скрипт и передают ему аргументы:
import { execFile } from 'node:child_process';
import { writeFile } from 'node:fs/promises';
import { promisify } from 'node:util';
const run = promisify(execFile);
await writeFile('count.mjs', 'console.log(process.argv.slice(2).length);');
const { stdout } = await run(process.execPath, ['count.mjs', 'a', 'b', 'c']);
console.log(`Аргументов: ${stdout.trim()}`); // Аргументов: 3Пример сначала создаёт маленький скрипт count.mjs, затем запускает его как отдельную программу.
Ошибка в дочернем процессе
Если программа завершилась с кодом не 0, промис отклоняется. В ошибке есть код завершения и всё, что программа вывела:
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
const run = promisify(execFile);
try {
await run(process.execPath, ['-e', 'process.exit(3)']);
} catch (error) {
console.log(`Программа завершилась с кодом ${error.code}`); // 3
}spawn: долгие команды
spawn() не копит вывод, а передаёт его по мере появления. Параметр stdio: 'inherit' выводит всё прямо в ваш терминал — удобно для сборки или установки пакетов:
// scripts/backup.js
import { spawn } from 'node:child_process';
const child = spawn('git', ['log', '--oneline', '-5'], { stdio: 'inherit' });
child.on('close', (code) => {
console.log(`git завершился с кодом ${code}`);
});node scripts/backup.js покажет пять последних коммитов проекта, а затем код завершения.
| Функция | Когда использовать |
|---|---|
execFile() | Короткий вывод, нужен целиком |
spawn() | Долгая работа, большой вывод |
exec() | Нужна строка оболочки с && или перенаправлением |
Частая ошибка
exec() выполняет строку через командную оболочку. Если вставить в неё данные от пользователя, он сможет дописать свою команду:
// src/server.js
// Опасно: exec(`convert ${fileName} out.png`)
// fileName = 'a.jpg; rm -rf ~' выполнит вторую командуИспользуйте execFile() или spawn() с массивом аргументов: каждый аргумент передаётся программе как есть и не разбирается оболочкой.