Процесс-дочерний процесс
Модуль child_process предоставляет возможность запуска дочерних процессов способом, аналогичным, но не идентичным, popen(3). Эта возможность в основном обеспечивается функцией child_process.spawn():
const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
По умолчанию, между родительским процессом Node.js и запущенным дочерним процессом устанавливаются каналы для stdin, stdout и stderr. Данные можно передавать через эти каналы потоково и асинхронно. Обратите внимание, что некоторые программы используют внутренне буферизацию ввода-вывода по строкам. Это не влияет на Node.js, но может означать, что данные, отправленные дочернему процессу, могут не быть немедленно обработаны.
Метод child_process.spawn() запускает дочерний процесс асинхронно, не блокируя цикл событий Node.js. Функция child_process.spawnSync() предоставляет эквивалентную функциональность синхронным способом, блокируя цикл событий до тех пор, пока запущенный процесс не завершит свою работу или не будет прерван.
Для удобства, модуль child_process предоставляет несколько синхронных и асинхронных альтернатив child_process.spawn() и child_process.spawnSync(). Обратите внимание, что каждая из этих альтернатив реализована на основе child_process.spawn() или child_process.spawnSync().
-
child_process.exec(): запускает оболочку и выполняет команду в этой оболочке, передаваяstdoutиstderrв функцию обратного вызова при завершении. -
child_process.execFile(): аналогичноchild_process.exec()за исключением того, что оно запускает команду непосредственно без предварительного запуска оболочки. -
child_process.fork(): запускает новый процесс Node.js и вызывает указанный модуль с установленным каналом IPC, который позволяет отправлять сообщения между родительским и дочерним процессами. -
child_process.execSync(): синхронная версияchild_process.exec(), которая будет блокировать цикл событий Node.js. -
child_process.execFileSync(): синхронная версияchild_process.execFile(), которая будет блокировать цикл событий Node.js.
В некоторых случаях, таких как автоматизация сценариев оболочки, синхронные аналоги могут быть более удобными. Однако во многих случаях синхронные методы могут существенно повлиять на производительность из-за приостановки цикла событий во время завершения работы запущенных процессов.
Асинхронное создание процессов
Методы child_process.spawn(), child_process.fork(), child_process.exec(), и child_process.execFile() следуют типовой асинхронной модели программирования, характерной для других API Node.js.
Каждый из методов возвращает экземпляр ChildProcess. Эти объекты реализуют Node.js API EventEmitter, позволяя родительскому процессу регистрировать обработчики событий, которые вызываются при определенных событиях в течение жизненного цикла дочернего процесса.
Методы child_process.exec() и child_process.execFile() дополнительно позволяют указать опциональную функцию callback , которая вызывается при завершении дочернего процесса.
Запуск файлов .bat и .cmd в Windows
Значение различий между child_process.exec() и child_process.execFile() может варьироваться в зависимости от платформы. В операционных системах типа Unix (Unix, Linux, OSX) child_process.execFile() может быть более эффективным, поскольку не запускает оболочку. Однако в Windows файлы .bat и .cmd не являются исполняемыми сами по себе без терминала и, следовательно, не могут быть запущены с помощью child_process.execFile(). При работе в Windows файлы .bat и .cmd могут быть вызваны с помощью child_process.spawn() с установленным параметром shell, с child_process.exec(), или путём запуска cmd.exe и передачи файла .bat или .cmd в качестве аргумента (что делают параметры shell и child_process.exec()).
// On Windows Only ...
const spawn = require('child_process').spawn;
const bat = spawn('cmd.exe', ['/c', 'my.bat']);
bat.stdout.on('data', (data) => {
console.log(data);
});
bat.stderr.on('data', (data) => {
console.log(data);
});
bat.on('exit', (code) => {
console.log(`Child exited with code ${code}`);
});
// OR...
const exec = require('child_process').exec;
exec('my.bat', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
child_process.exec(command[, options][, callback])
-
command<Строка> Команда для выполнения, с разделителями пробелов для аргументов -
options<Объект>-
cwd<Строка> Текущая рабочая директория дочернего процесса -
env<Объект> Параметры окружения в формате ключ-значение -
encoding<Строка> (По умолчанию: 'utf8') -
shell<Строка> Оболочка для выполнения команды (По умолчанию: '/bin/sh' в UNIX, 'cmd.exe' в Windows, Оболочка должна понимать переключатель-cв UNIX или/s /cв Windows. В Windows, синтаксический анализ командной строки должен быть совместим сcmd.exe.) -
timeout<Число> (По умолчанию: 0) -
maxBuffer<Число> максимальный объём данных (в байтах) разрешённый на stdout или stderr – превышение этого значения приводит к убийству дочернего процесса (По умолчанию:200*1024) -
killSignal<Строка> | <Целое> (По умолчанию: 'SIGTERM') -
uid<Число> Устанавливает идентификатор пользователя процесса. (См. setuid(2).) -
gid<Число> Устанавливает идентификатор группы процесса. (См. setgid(2).)
-
-
callback<Функция> вызывается с результатом при завершении процесса - Возвращает: <Процесс-дочерний процесс>
Запускает оболочку, затем выполняет command в этой оболочке, буферизируя любой сгенерированный вывод.
Обратите внимание: никогда не передавайте необработанные данные пользователя в эту функцию. Любой ввод, содержащий метасимволы оболочки, может быть использован для запуска произвольных команд.
const exec = require('child_process').exec;
exec('cat *.js bad_file | wc -l', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
Если функция callback предоставлена, она вызывается с аргументами (error, stdout, stderr). В случае успеха, error будет null. В случае ошибки, error будет экземпляром Error. Свойство error.code будет кодом завершения дочернего процесса, в то время как error.signal будет установлено в сигнал, который завершил процесс. Любой код выхода, кроме 0, считается ошибкой.
Аргументы stdout и stderr , передаваемые в обратный вызов, содержат вывод stdout и stderr дочернего процесса. По умолчанию Node.js будет декодировать вывод как UTF-8 и передавать строки в обратный вызов. Параметр encoding может быть использован для указания кодировки символов, используемой для декодирования вывода stdout и stderr. Если encoding является 'buffer', или кодировка символов не распознана, вместо этого в обратный вызов будут переданы объекты Buffer.
Аргумент options может быть передан во втором аргументе для настройки способа запуска процесса. Параметры по умолчанию:
{
encoding: 'utf8',
timeout: 0,
maxBuffer: 200*1024,
killSignal: 'SIGTERM',
cwd: null,
env: null
}
Если значение timeout больше, чем 0, родительский процесс отправит сигнал, идентифицированный свойством killSignal (по умолчанию 'SIGTERM'), если дочерний процесс работает дольше, чем timeout миллисекунд.
Параметр maxBuffer определяет максимальный объем данных (в байтах) разрешенный на stdout или stderr; при превышении этого значения дочерний процесс завершается.
Примечание: в отличие от вызова POSIX exec(), child_process.exec() не заменяет существующий процесс и использует оболочку для выполнения команды.
child_process.execFile(file[, args][, options][, callback])
-
file<String> Имя или путь к исполняемому файлу для запуска -
args<Array> Список строковых аргументов -
options<Object>-
cwd<String> Текущий рабочий каталог дочернего процесса -
env<Object> Параметры окружения в виде пар ключ-значение -
encoding<String> (По умолчанию: 'utf8') -
timeout<Число> (По умолчанию: 0) -
maxBuffer<Число> Максимальный объём данных (в байтах) для stdout или stderr. При превышении этого значения дочерний процесс убивается (По умолчанию: 200*1024) -
killSignal<Строка> | <Целое число> (По умолчанию: 'SIGTERM') -
uid<Число> Устанавливает идентификатор пользователя процесса. (См. setuid(2).) -
gid<Число> Устанавливает идентификатор группы процесса. (См. setgid(2).)
-
-
callback<Функция> вызывается с результатом завершения процесса - Возвращает: <Дочерний процесс>
Функция child_process.execFile() похожа на child_process.exec(), за исключением того, что она не запускает оболочку. Вместо этого, указанный исполняемый файл file запускается непосредственно как новый процесс, что делает её немного более эффективной, чем child_process.exec().
Поддерживаются те же параметры, что и у child_process.exec(). Поскольку оболочка не запускается, такие действия, как перенаправление ввода-вывода и подстановка файлов, не поддерживаются.
const execFile = require('child_process').execFile;
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
Аргументы stdout и stderr, передаваемые в обратный вызов, будут содержать вывод stdout и stderr дочернего процесса. По умолчанию Node.js декодирует вывод как UTF-8 и передаёт строки в обратный вызов. Параметр encoding может быть использован для указания кодировки символов, используемой для декодирования вывода stdout и stderr. Если encoding имеет значение 'buffer', или это неизвестная кодировка символов, в обратный вызов будут переданы объекты Buffer.
child_process.fork(modulePath[, args][, options])
-
modulePath<Строка> Модуль для запуска в дочернем процессе -
args<Массив> Список строковых аргументов -
options<Объект>-
cwd<Строка> Текущий рабочий каталог дочернего процесса -
env<Объект> Параметры окружения в виде пар ключ-значение -
execPath<Строка> Исполняемый файл, используемый для создания дочернего процесса -
execArgv<Массив> Список строковых аргументов, передаваемых исполняемому файлу (По умолчанию:process.execArgv) -
silent<Булево> Если true, stdin, stdout и stderr дочернего процесса будут переданы родителю, иначе будут унаследованы от родителя. См. параметры'pipe'и'inherit'дляchild_process.spawn()'sstdioдля более подробной информации (по умолчанию false) -
uid<Число> Устанавливает идентификатор пользователя процесса. (См. setuid(2).) -
gid<Число> Устанавливает идентификатор группы процесса. (См. setgid(2).)
-
- Возвращает: <Дочерний процесс>
Метод child_process.fork() является специальным случаем child_process.spawn(), используемым для запуска новых процессов Node.js. Как и child_process.spawn(), возвращается объект ChildProcess. Возвращаемый ChildProcess будет иметь встроенный дополнительный канал связи, который позволяет передавать сообщения между родителем и ребенком. См. ChildProcess#send() для подробностей.
Важно помнить, что запущенные дочерние процессы Node.js независимы от родителя за исключением канала IPC, созданного между ними. Каждый процесс имеет свою память со своими экземплярами V8. Из-за дополнительных требуемых ресурсов не рекомендуется запускать большое количество дочерних процессов Node.js.
По умолчанию child_process.fork() будет запускать новые экземпляры Node.js, используя process.execPath родительского процесса. Свойство execPath в объекте options позволяет использовать альтернативный путь выполнения.
Процессы Node.js, запущенные с пользовательским execPath, будут общаться с родительским процессом, используя дескриптор файла (fd), идентифицированный переменной среды NODE_CHANNEL_FD в дочернем процессе. Ввод и вывод в этом fd ожидаются в виде объектов JSON, разделенных по строкам.
Примечание: В отличие от системного вызова fork() POSIX, child_process.fork() не клонирует текущий процесс.
child_process.spawn(command[, args][, options])
-
command<String> Команда для выполнения -
args<Array> Список строковых аргументов -
options<Object>-
cwd<String> Текущая рабочая директория дочернего процесса -
env<Object> Параметры среды в формате ключ-значение -
stdio<Array> | <String> Конфигурация stdio дочернего процесса. (См.options.stdio) -
detached<Boolean> Подготовка дочернего процесса к независимому выполнению от родительского процесса. Конкретное поведение зависит от платформы, см.options.detached) -
uid<Number> Устанавливает идентификатор пользователя процесса. (См. setuid(2).) -
gid<Number> Устанавливает идентификатор группы процесса. (См. setgid(2).) -
shell<Boolean> | <String> Еслиtrue, выполняетcommandвнутри оболочки. Использует '/bin/sh' в UNIX и 'cmd.exe' в Windows. Можно указать другую оболочку как строку. Оболочка должна понимать переключатель-cв UNIX или/s /cв Windows. По умолчаниюfalse(без оболочки).
-
- Возвращает: <ChildProcess>
Метод child_process.spawn() запускает новый процесс, используя заданные command, с аргументами командной строки в args. Если опущено, args по умолчанию является пустым массивом.
Примечание: Если опция shell включена, не передавайте необработанные данные пользователя в эту функцию. Любой ввод, содержащий символы метаязыка оболочки, может быть использован для запуска произвольного командного выполнения.
Третий аргумент может быть использован для задания дополнительных опций, с указанными значениями по умолчанию:
{
cwd: undefined,
env: process.env
}
Используйте cwd для задания рабочей директории, из которой запускается процесс. Если не указано, используется текущая рабочая директория.
Используйте env для задания переменных среды, которые будут видны новому процессу, по умолчанию process.env.
Пример запуска ls -lh /usr, захвата stdout, stderr, и кода завершения:
const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
Пример: Очень сложный способ запуска 'ps ax | grep ssh'
const spawn = require('child_process').spawn;
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);
ps.stdout.on('data', (data) => {
grep.stdin.write(data);
});
ps.stderr.on('data', (data) => {
console.log(`ps stderr: ${data}`);
});
ps.on('close', (code) => {
if (code !== 0) {
console.log(`ps process exited with code ${code}`);
}
grep.stdin.end();
});
grep.stdout.on('data', (data) => {
console.log(`${data}`);
});
grep.stderr.on('data', (data) => {
console.log(`grep stderr: ${data}`);
});
grep.on('close', (code) => {
if (code !== 0) {
console.log(`grep process exited with code ${code}`);
}
});
Пример проверки на ошибку exec:
const spawn = require('child_process').spawn;
const subprocess = spawn('bad_command');
subprocess.on('error', (err) => {
console.log('Failed to start subprocess.');
});
options.detached
В Windows, установка options.detached в true позволяет дочернему процессу продолжать работу после завершения родительского. Дочерний процесс будет иметь собственное окно консоли. После включения для дочернего процесса, его нельзя отключить.
На платформах, отличных от Windows, если options.detached установлено в true, дочерний процесс станет лидером новой группы процессов и сессии. Обратите внимание, что дочерние процессы могут продолжать работать после завершения родительского процесса независимо от того, откреплены они или нет. См. setsid(2) для дополнительной информации.
По умолчанию родительский процесс будет ожидать завершения открепленного дочернего процесса. Чтобы предотвратить ожидание родительского процесса для данного subprocess, используйте метод subprocess.unref(). Это приведет к тому, что цикл событий родительского процесса не будет включать дочерний процесс в свой счетчик ссылок, позволяя родительскому процессу выйти независимо от дочернего, если не установлен канал IPC между дочерним и родительским процессом.
При использовании опции detached для запуска долго выполняемого процесса, процесс не будет оставаться в фоновом режиме после выхода родителя, если он не настроен с конфигурацией stdio, которая не подключена к родителю. Если родительский stdio унаследован, дочерний процесс останется подключенным к управляющему терминалу.
Пример долго выполняемого процесса, с откреплением и игнорированием родительских stdio дескрипторов файлов для игнорирования завершения родителя:
const spawn = require('child_process').spawn;
const subprocess = spawn(process.argv[0], ['child_program.js'], {
detached: true,
stdio: 'ignore'
});
subprocess.unref();
В качестве альтернативы, можно перенаправить вывод дочернего процесса в файлы:
const fs = require('fs');
const spawn = require('child_process').spawn;
const out = fs.openSync('./out.log', 'a');
const err = fs.openSync('./out.log', 'a');
const subprocess = spawn('prg', [], {
detached: true,
stdio: [ 'ignore', out, err ]
});
subprocess.unref();
options.stdio
Опция options.stdio используется для настройки каналов, установленных между родительским и дочерним процессом. По умолчанию stdin, stdout и stderr дочернего процесса перенаправляются в соответствующие потоки subprocess.stdin, subprocess.stdout, и subprocess.stderr объекта ChildProcess. Это эквивалентно установке options.stdio в ['pipe',
'pipe', 'pipe'].
Для удобства, options.stdio может быть одной из следующих строк:
-
'pipe'- эквивалентно['pipe', 'pipe', 'pipe'](по умолчанию) -
'ignore'- эквивалентно['ignore', 'ignore', 'ignore'] -
'inherit'- эквивалентно[process.stdin, process.stdout, process.stderr]или[0,1,2]
В противном случае, значение option.stdio - массив, где каждый индекс соответствует fd в дочернем процессе. Fd 0, 1 и 2 соответствуют stdin, stdout и stderr соответственно. Дополнительные fd могут быть указаны для создания дополнительных каналов между родительским и дочерним процессами. Значение может быть следующим:
-
'pipe'- Создает канал между дочерним процессом и родительским. Родительская часть канала доступна в родительском процессе как свойство объектаchild_processкакChildProcess.stdio[fd]. Каналы, созданные для fd 0-2, также доступны как ChildProcess.stdin, ChildProcess.stdout и ChildProcess.stderr соответственно. -
'ipc'- Создает канал IPC для передачи сообщений/дескрипторов файлов между родительским и дочерним процессом. Дочерний процесс может иметь не более одного дескриптора stdio IPC. Установка этого параметра активирует метод ChildProcess.send(). Если дочерний процесс записывает JSON-сообщения в этот дескриптор, в родительском процессе будет сработан обработчик событияChildProcess.on('message'). Если дочерний процесс - процесс Node.js, наличие канала IPC позволит использоватьprocess.send(),process.disconnect(),process.on('disconnect'), иprocess.on('message')внутри дочернего процесса. -
'ignore'- Указывает Node.js проигнорировать fd в дочернем процессе. Хотя Node.js всегда открывает fd 0-2 для запускаемых процессов, установка fd в'ignore'заставит Node.js открыть/dev/nullи подключить его к fd дочернего процесса. -
Streamобъект - Поделиться потоком чтения или записи, относящимся к tty, файлу, сокету или каналу с дочерним процессом. Базовый дескриптор потока дублируется в дочернем процессе на fd, соответствующему индексу в массивеstdio. Обратите внимание, что у потока должен быть базовый дескриптор (файловые потоки не имеют его, пока не наступит событие'open'). - Положительное целое число - Целое число интерпретируется как дескриптор файла, который открыт в родительском процессе. Он делится с дочерним процессом, аналогично тому, как можно разделить объекты
Stream. -
null,undefined- Использовать значение по умолчанию. Для stdio fd 0, 1 и 2 (т.е. stdin, stdout и stderr) создается канал. Для fd 3 и выше, значение по умолчанию'ignore'.
Пример:
const spawn = require('child_process').spawn;
// Child will use parent's stdios
spawn('prg', [], { stdio: 'inherit' });
// Spawn child sharing only stderr
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });
// Open an extra fd=4, to interact with programs presenting a
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
Стоит отметить, что когда между родительским и дочерним процессами установлен канал IPC, и дочерний процесс является процессом Node.js, дочерний процесс запускается с неинициализированным каналом IPC (используя unref()) до тех пор, пока дочерний процесс не зарегистрирует обработчик события process.on('disconnect') или события process.on('message'). Это позволяет дочернему процессу завершиться нормально без блокировки процесса открытым каналом IPC.
См. также: child_process.exec() и child_process.fork()
Синхронное создание процесса
Методы child_process.spawnSync(), child_process.execSync(), и child_process.execFileSync() являются синхронными и БЛОКИРУЮТ цикл событий Node.js, приостанавливая выполнение любого дополнительного кода до завершения порожденного процесса.
Блокирующие вызовы, такие как эти, в основном полезны для упрощения задач обычного скриптинга и для упрощения загрузки/обработки конфигурации приложения при запуске.
child_process.execFileSync(file[, args][, options])
-
file<String> Имя или путь к исполняемому файлу для запуска -
args<Array> Список строковых аргументов -
options<Object>-
cwd<String> Текущая рабочая директория дочернего процесса -
input<String> | <Buffer> Значение, которое будет передано как stdin дочернему процессу- предоставление этого значения переопределит
stdio[0]
- предоставление этого значения переопределит
-
stdio<String> | <Array> Настройка stdio дочернего процесса. (По умолчанию: 'pipe')-
stderrпо умолчанию будет выведено в stderr родительского процесса, еслиstdioне указано
-
-
env<Object> Параметры окружения в формате ключ-значение -
uid<Number> Устанавливает идентификатор пользователя процесса. (См. setuid(2).) -
gid<Number> Устанавливает идентификатор группы процесса. (См. setgid(2).) -
timeout<Number> Максимальное время выполнения процесса в миллисекундах. (По умолчанию: undefined) -
killSignal<String> | <Integer> Значение сигнала, используемого для завершения дочернего процесса. (По умолчанию: 'SIGTERM') -
maxBuffer<Number> Максимальный объем данных (в байтах) для stdout или stderr; при превышении лимита дочерний процесс завершается -
encoding<String> Кодировка, используемая для всех вводов-выводов stdio. (По умолчанию: 'buffer')
-
- Возвращает: <Buffer> | <String> Выходные данные команды stdout
Метод child_process.execFileSync() в целом идентичен методу child_process.execFile(), за исключением того, что метод не возвращается, пока дочерний процесс не завершит работу полностью. Когда таймаут достигнут и отправлен killSignal, метод не вернется, пока процесс не завершится полностью. Обратите внимание, что если дочерний процесс перехватывает и обрабатывает сигнал SIGTERM и не завершается, родительский процесс все равно будет ждать завершения дочернего процесса.
Если процесс превысил таймаут или имеет код возврата не равный нулю, этот метод выбросит исключение. Объект Error будет содержать весь результат из child_process.spawnSync()
child_process.execSync(command[, options])
-
command<String> Команда для выполнения -
options<Object>-
cwd<String> Текущая рабочая директория дочернего процесса -
input<String> | <Buffer> Значение, которое будет передано как stdin дочернему процессу- предоставление этого значения переопределит
stdio[0]
- предоставление этого значения переопределит
-
stdio<String> | <Array> Настройка stdio дочернего процесса. (По умолчанию: 'pipe')-
stderrпо умолчанию будет выведено в stderr родительского процесса, еслиstdioне указано
-
-
env<Object> Параметры окружения в формате ключ-значение -
shell<String> Оболочка для выполнения команды (По умолчанию: '/bin/sh' в UNIX, 'cmd.exe' в Windows, Оболочка должна понимать переключатель-cв UNIX или/s /cв Windows. В Windows синтаксический анализ командной строки должен быть совместим сcmd.exe.) -
uid<Number> Устанавливает идентификатор пользователя процесса. (См. setuid(2).) -
gid<Number> Устанавливает идентификатор группы процесса. (См. setgid(2).) -
timeout<Number> Максимальное время выполнения процесса в миллисекундах. (По умолчанию: undefined) -
killSignal<String> | <Integer> Значение сигнала, используемого для завершения дочернего процесса. (По умолчанию: 'SIGTERM') -
maxBuffer<Number> Максимальный объем данных (в байтах) для stdout или stderr; при превышении лимита дочерний процесс завершается -
encoding<String> Кодировка, используемая для всех вводов-выводов stdio. (По умолчанию: 'buffer')
-
- Возвращает: <Buffer> | <String> Выходные данные команды stdout
Метод child_process.execSync() в целом идентичен методу child_process.exec(), за исключением того, что метод не возвращается, пока дочерний процесс не завершит работу полностью. Когда таймаут достигнут и отправлен killSignal, метод не вернется, пока процесс не завершится полностью. Обратите внимание, что если дочерний процесс перехватывает и обрабатывает сигнал SIGTERM и не завершается, родительский процесс будет ждать завершения дочернего процесса.
Если процесс превысил таймаут или имеет код возврата не равный нулю, этот метод выбросит исключение. Объект Error будет содержать весь результат из child_process.spawnSync()
Примечание: никогда не передавайте необработанные данные пользователя в эту функцию. Любые данные, содержащие метасимволы оболочки, могут быть использованы для запуска произвольных команд.
child_process.spawnSync(command[, args][, options])
-
command<Строка> Команда для выполнения -
args<Массив> Список строковых аргументов -
options<Объект>-
cwd<Строка> Текущий рабочий каталог дочернего процесса -
input<Строка> | <Буфер> Значение, которое будет передано в stdin запущенному процессу- передача этого значения переопределит
stdio[0]
- передача этого значения переопределит
-
stdio<Строка> | <Массив> Настройка stdio дочернего процесса. (По умолчанию: 'pipe') -
env<Объект> Параметры окружения (ключ-значение) -
uid<Число> Устанавливает идентификатор пользователя процесса. (См. setuid(2).) -
gid<Число> Устанавливает идентификатор группы процесса. (См. setgid(2).) -
timeout<Число> Максимальное время выполнения процесса в миллисекундах. (По умолчанию: undefined) -
killSignal<Строка> | <Целое> Значение сигнала, используемого для завершения запущенного процесса. (По умолчанию: 'SIGTERM') -
maxBuffer<Число> Максимальный объём данных (в байтах) на stdout или stderr; при превышении этого значения дочерний процесс завершается. -
encoding<Строка> Кодировка, используемая для всех вводов-выводов stdio. (По умолчанию: 'buffer') -
shell<Булево> | <Строка> Еслиtrue, запускаетcommandвнутри оболочки. Использует '/bin/sh' в UNIX и 'cmd.exe' в Windows. Другая оболочка может быть указана как строка. Оболочка должна понимать переключатель-cв UNIX или/s /cв Windows. По умолчаниюfalse(без оболочки).
-
- Возвращает: <Объект>
-
pid<Число> Идентификатор процесса (PID) дочернего процесса -
output<Массив> Массив результатов вывода stdio -
stdout<Буфер> | <Строка> Содержимоеoutput[1] -
stderr<Буфер> | <Строка> Содержимоеoutput[2] -
status<Число> Код завершения дочернего процесса -
signal<Строка> Сигнал, использованный для завершения дочернего процесса -
error<Ошибка> Объект ошибки, если дочерний процесс завершился с ошибкой или истекло время ожидания
-
Метод child_process.spawnSync() в целом идентичен методу child_process.spawn(), за исключением того, что функция не вернётся, пока дочерний процесс не завершит работу полностью. При возникновении таймаута и отправке сигнала killSignal, функция не вернётся, пока процесс не завершит работу полностью. Обратите внимание, что если процесс перехватывает и обрабатывает сигнал SIGTERM и не завершается, родительский процесс будет ожидать завершения дочернего процесса.
Примечание: Если включён параметр shell, не передавайте необработанные данные пользователя в эту функцию. Любой ввод, содержащий символы метаязыка оболочки, может быть использован для запуска произвольных команд.
Класс: ChildProcess
Экземпляры класса ChildProcess являются EventEmitters, представляющие запущенные дочерние процессы.
Экземпляры ChildProcess не предназначены для непосредственного создания. Вместо этого используйте методы child_process.spawn(), child_process.exec(), child_process.execFile() или child_process.fork() для создания экземпляров ChildProcess.
Событие: 'close'
-
code<Число> код завершения, если дочерний процесс завершился самостоятельно. -
signal<Строка> сигнал, с помощью которого был завершён дочерний процесс.
Событие 'close' срабатывает, когда потоки stdio дочернего процесса закрыты. Это отличается от события 'exit', так как несколько процессов могут использовать одни и те же потоки stdio.
Событие: 'disconnect'
Событие 'disconnect' срабатывает после вызова метода ChildProcess.disconnect() в родительском или дочернем процессе. После разъединения больше невозможно отправлять или получать сообщения, и свойство ChildProcess.connected становится false.
Событие: 'error'
-
err<Ошибка> ошибка.
Событие 'error' срабатывает в следующих случаях:
- Процесс не может быть запущен,
- Процесс не может быть завершен,
- Отправка сообщения дочернему процессу не удалась.
Обратите внимание, что событие 'exit' может или не может сработать после возникновения ошибки. Если вы слушаете оба события 'exit' и 'error', важно учитывать возможность многократного вызова обработчиков событий.
См. также ChildProcess#kill() и ChildProcess#send().
Событие: 'exit'
-
code<Число> код завершения, если дочерний процесс завершился самостоятельно. -
signal<Строка> сигнал, с помощью которого был завершён дочерний процесс.
Событие 'exit' срабатывает после завершения дочернего процесса. Если процесс завершился, code — это конечный код завершения процесса, иначе null. Если процесс завершился из-за получения сигнала, signal — это строковое имя сигнала, иначе null. Одно из двух всегда будет не нулевым.
Обратите внимание, что при срабатывании события 'exit', потоки stdio дочернего процесса могут оставаться открытыми.
Также обратите внимание, что Node.js устанавливает обработчики сигналов для SIGINT и SIGTERM, и процессы Node.js не завершатся немедленно при получении этих сигналов. Вместо этого Node.js выполнит последовательность действий по очистке и затем повторно сгенерирует обработанный сигнал.
См. waitpid(2).
Событие: 'message'
-
message<Объект> разобранный JSON-объект или примитивное значение. -
sendHandle<Дескриптор> объектnet.Socketилиnet.Server, или undefined.
Событие 'message' срабатывает, когда дочерний процесс использует process.send() для отправки сообщений.
subprocess.connected
-
<Булево> Устанавливается в false после вызова
.disconnect
Свойство subprocess.connected указывает, возможно ли посылать и получать сообщения из дочернего процесса. Когда subprocess.connected равно false, посылать и получать сообщения больше невозможно.
subprocess.disconnect()
Закрывает канал IPC между родительским и дочерним процессами, позволяя дочернему процессу завершиться корректно, когда нет других соединений, которые поддерживают его активность. После вызова этого метода свойства subprocess.connected и process.connected в родительском и дочернем процессе (соответственно) будут установлены в false, и посылать или получать сообщения между процессами больше не удастся.
Событие 'disconnect' будет выброшено, когда нет сообщений в процессе получения. Это чаще всего произойдет сразу после вызова subprocess.disconnect().
Обратите внимание, что когда дочерний процесс представляет собой экземпляр Node.js (например, порождённый с помощью child_process.fork()), метод process.disconnect() может быть вызван внутри дочернего процесса для закрытия канала IPC.
subprocess.kill([signal])
-
signal<Строка>
Метод subprocess.kill() посылает сигнал дочернему процессу. Если аргумент не указан, процессу посылается сигнал 'SIGTERM'. Список доступных сигналов см. в signal(7).
const spawn = require('child_process').spawn;
const grep = spawn('grep', ['ssh']);
grep.on('close', (code, signal) => {
console.log(
`child process terminated due to receipt of signal ${signal}`);
});
// Send SIGHUP to process
grep.kill('SIGHUP');
Объект ChildProcess может выбросить событие 'error' если сигнал не может быть доставлен. Отправка сигнала дочернему процессу, который уже завершил работу, не является ошибкой, но может иметь непредсказуемые последствия. В частности, если идентификатор процесса (PID) был переназначен другому процессу, сигнал будет перенаправлен на этот процесс, что может привести к непредвиденным результатам.
Обратите внимание, что хотя функция называется kill, сигнал, переданный дочернему процессу, может не привести к завершению процесса.
См. kill(2) для справки.
Также обратите внимание: в Linux дочерние процессы дочерних процессов не будут завершены при попытке убить их родительский процесс. Это может произойти при запуске нового процесса в оболочке или при использовании параметра shell функции ChildProcess, как показано в этом примере:
'use strict';
const spawn = require('child_process').spawn;
let subprocess = spawn('sh', ['-c',
`node -e "setInterval(() => {
console.log(process.pid, 'is alive')
}, 500);"`
], {
stdio: ['inherit', 'inherit', 'inherit']
});
setTimeout(() => {
subprocess.kill(); // does not terminate the node process in the shell
}, 2000);
subprocess.killed
-
<логическое> Устанавливается в
trueпосле успешного завершения дочернего процесса с помощьюsubprocess.kill().
Свойство subprocess.killed указывает, был ли дочерний процесс успешно завершен с помощью subprocess.kill().
subprocess.pid
- <Число> Целое число
Возвращает идентификатор процесса (PID) дочернего процесса.
Пример:
const spawn = require('child_process').spawn;
const grep = spawn('grep', ['ssh']);
console.log(`Spawned child pid: ${grep.pid}`);
grep.stdin.end();
subprocess.send(message[, sendHandle[, options]][, callback])
-
message<Объект> -
sendHandle<Дескриптор> -
callback<Функция> - Возвращает: <Логическое значение>
Когда между родительским и дочерним процессами установлен канал IPC (например, при использовании child_process.fork()), метод subprocess.send() может быть использован для отправки сообщений дочернему процессу. Если дочерний процесс — экземпляр Node.js, эти сообщения могут быть получены через событие process.on('message').
Например, в родительском скрипте:
const cp = require('child_process');
const n = cp.fork(`${__dirname}/sub.js`);
n.on('message', (m) => {
console.log('PARENT got message:', m);
});
n.send({ hello: 'world' });
А затем дочерний скрипт, 'sub.js' может выглядеть так:
process.on('message', (m) => {
console.log('CHILD got message:', m);
});
process.send({ foo: 'bar' });
Дочерние процессы Node.js имеют собственный метод process.send(), который позволяет дочернему процессу отправлять сообщения обратно родителю.
Есть специальный случай при отправке сообщения {cmd: 'NODE_foo'}. Все сообщения, содержащие префикс NODE_ в свойстве cmd предназначены для использования в ядре Node.js и не будут выброшены в событие process.on('message') дочернего процесса. Вместо этого такие сообщения выброшены с помощью события process.on('internalMessage') и обрабатываются внутри Node.js. Приложения должны избегать использования таких сообщений или прослушивания событий 'internalMessage', так как они могут быть изменены без предварительного уведомления.
Дополнительный аргумент sendHandle, который может быть передан методу subprocess.send(), предназначен для передачи объекта TCP-сервера или сокета в дочерний процесс. Дочерний процесс получит объект в качестве второго аргумента, переданного функции обратного вызова, зарегистрированной на событии process.on('message') . Любые данные, полученные и буферизованные в сокете, не будут отправлены дочернему процессу.
Необязательный аргумент callback — это функция, которая вызывается после отправки сообщения, но до того, как дочерний процесс его получит. Функция вызывается с одним аргументом: null при успехе или объектом Error при ошибке.
Если функция callback не указана и сообщение не может быть отправлено, событие 'error' будет выброшено объектом ChildProcess . Это может произойти, например, когда дочерний процесс уже завершил работу.
subprocess.send() вернёт false, если канал закрыт или когда буфер неосланных сообщений превысил порог, при котором отправка дополнительных сообщений нецелесообразна. В противном случае метод возвращает true. Функция callback может быть использована для реализации управления потоком.
Пример: отправка объекта сервера
Аргумент sendHandle может использоваться, например, для передачи дескриптора объекта TCP-сервера в дочерний процесс, как показано в примере ниже:
const subprocess = require('child_process').fork('subprocess.js');
// Open up the server object and send the handle.
const server = require('net').createServer();
server.on('connection', (socket) => {
socket.end('handled by parent');
});
server.listen(1337, () => {
subprocess.send('server', server);
});
Дочерний процесс затем получит объект сервера как:
process.on('message', (m, server) => {
if (m === 'server') {
server.on('connection', (socket) => {
socket.end('handled by child');
});
}
});
После того как сервер теперь общ для родительского и дочернего процесса, некоторые соединения могут обрабатываться родителем, а некоторые — дочерним процессом.
Хотя в примере выше используется сервер, созданный с помощью модуля net, серверы модуля dgram используют точно такой же рабочий процесс за исключением прослушивания события 'message' вместо 'connection' и использования server.bind вместо server.listen. Однако в настоящее время это поддерживается только на платформах UNIX.
Пример: отправка объекта сокета
Аналогично, аргумент sendHandler может использоваться для передачи дескриптора сокета в дочерний процесс. В примере ниже генерируются два дочерних процесса, каждый из которых обрабатывает соединения с приоритетом "нормальный" или "специальный":
const normal = require('child_process').fork('subprocess.js', ['normal']);
const special = require('child_process').fork('subprocess.js', ['special']);
// Open up the server and send sockets to child
const server = require('net').createServer();
server.on('connection', (socket) => {
// If this is special priority
if (socket.remoteAddress === '74.125.127.100') {
special.send('socket', socket);
return;
}
// This is normal priority
normal.send('socket', socket);
});
server.listen(1337);
Дочерний процесс получит дескриптор сокета как второй аргумент, переданный функции обратного вызова события:
process.on('message', (m, socket) => {
if (m === 'socket') {
socket.end(`Request handled with ${process.argv[2]} priority`);
}
});
После того, как сокет передан дочернему процессу, родительский процесс больше не может отслеживать момент уничтожения сокета. Для указания этого, свойство .connections становится null . Рекомендуется не использовать .maxConnections в такой ситуации.
Примечание: в этой функции используется JSON.stringify() для сериализации message.
subprocess.stderr
Поток, представляющий стандартный вывод ошибок дочернего процесса.
Если дочерний процесс был запущен с stdio[2] установленным в любое значение, отличное от 'pipe', этот поток будет undefined.
subprocess.stderr является псевдонимом для subprocess.stdio[2] . Оба свойства будут ссылаться на одно и то же значение.
subprocess.stdin
Поток, представляющий стандартный ввод дочернего процесса.
Обратите внимание, что если дочерний процесс ожидает чтения всего своего ввода, дочерний процесс не продолжится, пока этот поток не будет закрыт с помощью end().
Если дочерний процесс был запущен с stdio[0] установленным в любое значение, отличное от 'pipe', этот поток будет undefined.
subprocess.stdin является псевдонимом для subprocess.stdio[0] . Оба свойства будут ссылаться на одно и то же значение.
subprocess.stdio
Разреженный массив каналов к дочернему процессу, соответствующий позициям в параметре stdio, переданном в child_process.spawn(), которые были установлены в значение 'pipe'. Обратите внимание, что subprocess.stdio[0], subprocess.stdio[1], и subprocess.stdio[2] также доступны как subprocess.stdin, subprocess.stdout, и subprocess.stderr, соответственно.
В следующем примере только fd 1 (stdout) дочернего процесса настроен как канал, поэтому только subprocess.stdio[1] родительского процесса является потоком, все остальные значения в массиве равны null.
const assert = require('assert');
const fs = require('fs');
const child_process = require('child_process');
const subprocess = child_process.spawn('ls', {
stdio: [
0, // Use parents stdin for child
'pipe', // Pipe child's stdout to parent
fs.openSync('err.out', 'w') // Direct child's stderr to a file
]
});
assert.equal(subprocess.stdio[0], null);
assert.equal(subprocess.stdio[0], subprocess.stdin);
assert(subprocess.stdout);
assert.equal(subprocess.stdio[1], subprocess.stdout);
assert.equal(subprocess.stdio[2], null);
assert.equal(subprocess.stdio[2], subprocess.stderr);
subprocess.stdout
Поток, представляющий стандартный вывод дочернего процесса.
Если дочерний процесс был запущен с stdio[1] установленным в любое значение, отличное от 'pipe', этот поток будет undefined.
subprocess.stdout — псевдоним для subprocess.stdio[1]. Оба свойства будут ссылаться на одно и то же значение.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v4.x/docs/api/child_process.html