Child Processes


Стабильность: 2 – Стабильно

Модуль 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}`);
});
  

По умолчанию пути для stdin, stdout и stderr установлены между родительским процессом Node.js и порожденным дочерним процессом. Возможно передавать потоки данных по этим путям с отсутствующей блокировкой. Следует заметить, однако, что некоторые программы используют буферизацию строк ввода-вывода. Это никак не влияет на 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() работают по асинхронному программному шаблону, характерному прочим Node.js API.

Каждый метод возвращает экземпляр ChildProcess. Эти объекты реализуют Node.js EventEmitter API, позволяя родительскому процессу регистрировать функции, которые вызываются тогда, когда имеют место определенные события в жизненном цикле дочернего процесса.

Методы 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 файлы не выполняются сами без терминала, и, следовательно, не могут быть запущены с помощью code>child_process.execFile(). При запуске на Windows, .bat и .cmd файлы могут запускаться с помощью child_process.spawn() c оболочкой shell, посредством child_process.exec(), или созданием cmd.exe, которому передаются .bat и .cmd в качестве аргументов (то, что делает функция оболочки и 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 <Число> Устанавливает идентификатор пользователя процесса
    • gid <Число> Устанавливает групповой идентификатор процесса
  • callback <Функция> Вызывается на выходе, когда процесс завершен
    • error <Ошибка>
    • stdout <Строка> | <Буфер>
    • stderr <Строка>; | <Буфер>
  • Return <ChildProcess>

Создает оболочку, после чего выполняет command в этой оболочке, буферизируя все сгенерированные выходы (output).

    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', вместо строк функции обратного вызова будут передаваться объекты буфера.

Аргумент options может быть передан как второй аргумент, чтобы кастомизировать создание процесса. По умолчанию:

{
  encoding: 'utf8',

  timeout: 0,

  maxBuffer: 200*1024,

  killSignal: 'SIGTERM',

  cwd: null,

  env: null
}
  

Если timeout больше 0, родительский процесс будет отправлять сигнал, определенный свойством killSignal (по умолчанию 'SIGTERM'), в случае, когда дочерний процесс запущен дольше, чем задано в timeout.

Примечание: в отличие от системного вызова POSIX exec(3), child_process.exec() не заменяет существующий процесс и использует оболочку для выполнения команды.

child_process.execFile(file[, args][, options][, callback])

  • file <Строка> Имя выполняемого файла или путь к нему
  • args <Массив> Массив строчных аргументов
  • options <Объект>
    • cwd <Строка> Текущая рабочая директория дочернего процесса
    • env <Объект> Пара среды ключ-значение
    • encoding <Строка> (По умолчанию: 'utf8')
    • timeout <Число> (По умолчанию: 0)
    • maxBuffer <Число> Наибольшее количество данных (в байтах), дозволенное stdout или stderr, при превышении которого дочерний процесс будет завершен. (По умолчанию: 200\ *1024)
    • killSignal <Строка> (По умолчанию: 'SIGTERM')
    • uid <Число> Устанавливает идентификатор пользователя процесса
    • gid <Число> Устанавливает групповой идентификатор процесса
  • callback <Функция> Вызывается на выходе, когда процесс завершен
    • error <Ошибка>
    • stdout <Строка> | <Буфер>;
    • stderr <Строка> | <Буфер>
  • Return <ChildProcess>

Функция child_process.execFile () подобна child_process.exec () за исключением того, что она не растягивает оболочку. Скорее всего, указанный исполняемый файл вызывает новый процесс, что делает его немного более эффективным, чем 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', то вместо строк фукнции обратного вызова будут переданы объекты буфера.

child_process.fork(modulePath[, args][, options])

  • modulePath <Строка> Модуль, запускаемый в дочернем процессе
  • args <Массив> Перечень аргументов строки
  • options <Объект>
  • cwd <Строка> Текущая рабочая директория дочернего процесса
  • env <Объект> Пары ключ-значение
  • execPath <Строка> Выполняемая функция для создания дочернего процесса
  • execArgv <Массив> Перечень аргументов строки, передаваемых выполняемой функции (по умолчанию: process.execArgv)
  • silent <Boolean> Если значение true, то stdin, stdout и stderr дочернего процесса будут передаваться к родительскому процессе, в противном случае они будут наследоваться от родительского процесса. См. опции 'pipe' и 'inherit' из child_process.spawn() для более детальной информации. (По умолчанию: false)
  • uid <Число> Устанавливает пользователя процесса
  • gid <Число> Устанавливает группу пользователей процесса
  • Return: <Дочерний процесс>

Метод child_process.fork() является частным случаем child_process.spawn(), который используется определенно для создания новых процессов Node.js. Подобно child_process.spawn(), в итоге возвращается объект ChildProcess. Возвращаемый ChildProcess имеет дополнительные каналы связи, которые позволяют сообщениям передаваться по обоим направлениям (вперед-назад) между родительским и дочерним процессом.

Важно иметь в виду, что созданные дочерние процессы в Node.js являются независимыми от родительских, за исключением канала связи IPC, который устанавливается между ними. Каждый процесс имеет собственную память, с собственными экземплярами V8. Из-за требований к дополнительному выделению ресурсов, не рекомендуется создание большого количества дочерних процессов.

По умолчанию, child_process.fork() создает новые экземпляры Node.js, используя process.execPath из родительского процесса. Свойство execPath в объекте позволяет использовать альтернативный путь выполнения.

Процессы Node.js, зпапускаемые с помощью кастомного execPath сообщаются с родительским процессом через файловый дескриптор (fd), который определяется переменной окружения NODE_CHANELL_FD в дочернем процессе. Входом и выходом в этом дескрипторе являются объекты JSON, разделенные строкой.

Примечание: В отличие от fork(2) POSIX системного вызова, child_process.fork() не клонирует текущий процесс.

child_process.spawn(command[, args][, options])

  • command <Строка> Команда запуска
  • args <Массив> Перечень аргументов строки
  • options <Объект>
  • cwd <Строка> Текущая рабочая директория дочернего процесса
  • env <Объект> Пары ключ-значение
  • stdio <Массив> | <Строка> Конфигурация stdio дочернего процесса
  • detached <Boolean> Подготавливает дочерний процесс к запуску независимо от родительского. Поведение определяется в зависимости от платформы (см. options.stdio)
  • uid <Число> Устанавливает пользователя процесса (см. setuid(2))
  • gid <Число> Устанавливает группу пользователей процесса (см. setgid(2))
  • shell <Boolean> | <Строка> При значении true, запускает command внутри оболочки. На UNIX: '/bin/sh', Windows: 'cmd.exe'. Любая другая оболочка может быть определена как строка. Оболочка должна понимать свитч -c на UNIX и /s /c на Windows. По умолчанию: false (без оболочки)
  • Return: <Дочерний процесс>

Метод child_process.spawn() создает новый процесс, используя заданную command с аргументами командной строки args. Если это не указано, args по умолчанию содержит пустой массив.

Третий аргумент может использоваться для задания дополнительных опций и параметров с такими параметрами по умолчанию:

{
  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}`);
  }
});

Пример проверки на неудавшийся запуск:

const spawn = require('child_process').spawn;
const child = spawn('bad_command');

child.on('error', (err) => {
  console.log('Failed to start child process.');
});

options.detached

На Windows задание options.detached значения true делает возможным продолжение запуска дочернего процесса после того, как завершается родительский. Дочерний будет иметь собственное консольное окно. После запуска дочернего процесса, он не может быть прерван.

На других платформах, если options.detached задано значение true, дочерний процесс будет основным в группе новых процессов и сессий. Заметьте, что дочерний процесс может продолжать запуск после завершения родительского вне зависимости от того, разделены они или нет. Для более подробной информации см. setsid(2).

По умолчанию, родительский процесс должен ждать отделения от дочернего, чтобы завершиться. Чтобы предотвратить ожидание, следует использовать метод child.unref(). Выполнение этого метода исключит из родительского событийного цикла дочерний процесс, позволяя родителю завершиться отдельно от дочернего, несмотря на установленный между ними канал связи IPC.

При использовании опции detached для старта долговыполняемого процесса, процесс не будет запущен на фоне после завершения родительского, если только он не содержит stdio конфигурацию, которая не коннектится к родителю. Если же stdio наследуется от родителя, дочерний процесс останется прикрепленным к управляющему терминалу.

Пример долговыполняемого процесса с отделением и игнорированием файловых дескрипторов stdio родительского процесса:

const spawn = require('child_process').spawn;

const child = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: ['ignore']
});

child.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  child = spawn('prg', [], {
 detached: true ,
 stdio: [ 'ignore', out, err ]
});

child.unref();

options.stdio

Опция options.stdio предназначена для конфигурирования каналов, настроенных между родительскими и дочерними процессами. По умолчанию, дочерние stdin, stdout и stderr перенаправляются на соответствующие стримы child.stdin, child.stdout и child.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]

В ином случае, значение options.stdio является массивом, где каждый индекс относится к файловому дескриптору дочернего процесса. Дескрипторы 0, 1, 2 ссылаются на stdin, stdout и stderr соответственно. Можно задать дополнительный дескриптор для создания дополнительных каналов между родителем и дочерним процессом. Значение будет одним из следующих:

  1. 'pipe' – создает канал между дочерним и родительским процессом. Конец канала со стороны рродителя является свойством объекта child_process как child.stdio[fd]. Каналы устанавливаются под дескрипторами 0–2 и могут ссылаться на child.stdin, child.stdout и child.stderr соответственно.
  2. 'ipc' – создает канал IPC для передачи сообщений/файловых дескрипторов от родителя к дочернему процессу и в обратном порядке. ChildProcess может иметь не более одного IPC stdio файлового дескриптора. Установка этой опции делает возможным выполнение метода child.send(). Если дочерний процесс записывает JSON сообщение в файловый дескриптор, обработчик события child.on('message') будет запущен и в родительском процессе. Если дочерний является процессом Node.js, то наличие IPC канала позволяет выполняться методам process.send(), process.disconnect(), process.on('disconnect'), и process.on('message') в дочернем процессе.
  3. 'ignore' – заставляет Node.js игнорировать файловый дескриптор в дочернем процессе. Так как Node.js всегда оставляет открытыми дескрипторы 0–2 для порожденных им же процессов, установка дескриптора на 'ignore' заставит Node.js открыть /dev/null и назначить как дескриптор дочернего процесса.
  4. <Stream> объект – расшаривает открытый для чтения или записи стрим, который ссылается на tty, файл, сокет или канал с дочерним процессом. Основной дескриптор стрима дублируется в дочерний процесс как файловый дескриптор, который соотносится с индексом массива stdio. Следует заметить, что стрим должен иметь базовый (основной) дескриптор (файловые стримы не имеют его, пока не запущено событие 'open')
  5. Положительное число – целое значение, которое интерпретируется как файловый дескриптор, на данный момент открытый родительскому процессу. Он расшаривается на дочерний процесс так же, как и объекты <Stream>.
  6. null, undefined – используюь значение по умолчанию. Для дескрипторов stdio 0, 1 и 2 (иными словами, stdin, stdout и stderr) создается канал. Для дескрипторов от 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') . Это позволяет дочернему процессу нормально завершиться без привязки к открытому IPC каналу.

Создание синхронных процессов

Методы child_process.spawnSync(), child_process.execSync() и child_process.execFileSync() являются синхронными и будут блокировать цикл событий Node.js, приостанавливая выполнение любого добавочного кода, пока завершается созданный процесс.

Блокировка вызовов по такому типу используется в основном для упрощения общецелевых скриптовых задач, а также для упрощения загрузки/обработки конфигурации приложения при запуске.

child_process.execFileSync(file[, args][, options])

  • file <Строка> Имя пути, по которому находится выполняемый файл для запуска
  • args <Массив> Перечень аргументов строки
  • options <Объект>
    • cwd <Строка> Текущая рабочая директория дочернего процесса
    • input <Строка>; | <Буфер> Значение, которое будет передаваться как stdin созданному процессу (это значение будет перезаписывать stdio[0])
    • stdio <Массив> Конфигурация stdio дочернего процесса. По умолчанию: 'pipe'
    • stderr по умолчанию является выходом stderr родительского процесса, если не задано stdio
    • env <Объект> Пара среды ключ-значение
    • uid <Число> Устанавливает идентификатор пользователя процесса
    • gid <Число> Устанавливает групповой идентификатор процесса
    • encoding <Строка> (По умолчанию: 'utf8')
    • timeout <Число> (По умолчанию: undefined)
    • maxBuffer <Число> Наибольшее количество данных (в байтах), дозволенное stdout или stderr, при превышении которого дочерний процесс будет завершен.
    • killSignal <Строка> (По умолчанию: 'SIGTERM')
  • encoding <Строка> (По умолчанию: 'utf8')
  • Return <Строка> | <Буфер> stdout из command

  • Метод child_process.execFileSync() в общем идентичен child_process.execFile(), за исключением того, что этот метод не возвращает значение, пока процесс полностью не закроется. Когда выйдет время timeout и будет отправлен killSignal, метод не возвращает ничего, пока процее полностью не будет завершен. Заметьте, что если дочерний процесс перехватывает сигнал SIGTERM, и при этом не завершается, родительский процесс будет приостановлен до тех пор, пока не завершится дочерний процесс.

    Если вышло время выполнения процесса, или он имеет непустой код выхода, этот метод будет выдавать ошибку. Объект Error будет содержать весь результат из child_process.spawnSync()


    child_process.execSync(command[, options])

    • file <Строка>; Имя пути, по которому находится выполняемый файл для запуска
    • args <Массив> Перечень аргументов строки
    • options <Объект>
      • cwd <Строка> Текущая рабочая директория дочернего процесса
      • input <Строка> | <Буфер> Значение, которое будет передаваться как stdin созданному процессу (это значение будет перезаписывать stdio[0])
      • stdio <Массив> Конфигурация stdio дочернего процесса. По умолчанию: 'pipe'
      • stderr по умолчанию является выходом stderr родительского процесса, если не задано stdio
      • env <Объект> Пара среды ключ-значение
      • shell <Строка>; Оболочка для выполнения команды. По умолчанию: на UNIX: '/bin/sh', Windows: 'cmd.exe'. Любая другая оболочка может быть определена как строка. Оболочка должна понимать свитч -c на UNIX и /s /c на Windows. На Windows парсинг командной строки должен быть совместим с cmd.exe
      • uid <Число> Устанавливает идентификатор пользователя процесса
      • gid <Число> Устанавливает групповой идентификатор процесса
      • encoding <Строка> (По умолчанию: 'utf8')
      • timeout <Число> (По умолчанию: undefined)
      • maxBuffer <Число> Наибольшее количество данных (в байтах), дозволенное stdout или stderr, при превышении которого дочерний процесс будет завершен.
      • killSignal <Строка> (По умолчанию: 'SIGTERM')
    • encoding <Строка>; (По умолчанию: 'utf8')
  • Return <Строка>; | <Буфер> stdout из command

  • Метод child_process.execSync() в общем идентичен child_process.exec(), за исключением того, что этот метод не возвращает значение, пока процесс полностью не закроется. Когда выйдет время timeout и будет отправлен killSignal, метод не возвращает ничего, пока процесс полностью не будет завершен. Заметьте, что если дочерний процесс перехватывает сигнал SIGTERM, и при этом не завершается, родительский процесс будет приостановлен до тех пор, пока не завершится дочерний процесс.

    Если вышло время выполнения процесса, или он имеет непустой код выхода, этот метод будет выдавать ошибку. Объект Error будет содержать весь результат из child_process.spawnSync()


    child_process.spawnSync(command[, args][, options])

    • file <Строка> Имя пути, по которому находится выполняемый файл для запуска
    • args <Массив> Перечень аргументов строки
    • options <Объект>
      • cwd <Строка> Текущая рабочая директория дочернего процесса
      • input <Строка> | <Буфер> Значение, которое будет передаваться как stdin созданному процессу (это значение будет перезаписывать stdio[0])
      • stdio <Массив> Конфигурация stdio дочернего процесса. По умолчанию: 'pipe'
      • stderr по умолчанию является выходом stderr родительского процесса, если не задано stdio
      • env <Объект> Пара среды ключ-значение
      • uid <Число> Устанавливает идентификатор пользователя процесса
      • gid <Число> Устанавливает групповой идентификатор процесса
      • encoding <Строка> (По умолчанию: 'utf8')
      • timeout <Число>; В миллисекундах - максимальное время, в пределах которого может быть запущен процесс (По умолчанию: undefined)
      • maxBuffer <Число> Наибольшее количество данных (в байтах), дозволенное stdout или stderr, при превышении которого дочерний процесс будет завершен.
      • killSignal <Строка> (По умолчанию: 'SIGTERM')
    • encoding <Строка>; (По умолчанию: 'utf8')
    • shell <Boolean> | <Строка> При значении true, запускает command внутри оболочки. На UNIX: '/bin/sh', Windows: 'cmd.exe'. Любая другая оболочка может быть определена как строка. Оболочка должна понимать свитч -c на UNIX и /s /c на Windows. По умолчанию: false (без оболочки)
    • Return <Строка> | <Буфер> stdout из command
      • pid <Число> Pid дочернего процесса
      • output <Массив> Массив результатов из выхода stdio
      • stdout <Буфер> | <Строка> Содержимое output[1]
      • stderr <Буфер> | <Строка> Содержимое output[2]
      • status <Число> Код выхода дочернего процесса
      • signal <Строка> Сигнал для прерывания дочернего процесса
      • error <Ошибка>; Ошибка, выдаваемая в случае, когда дочерний процесс неудачно запущен или время выполнения вышло

    Метод child_process.spawnSync() в общем идентичен child_process.spawn() , за исключением того, что этот метод не возвращает значение, пока процесс полностью не закроется. Когда выйдет время timeout и будет отправлен killSignal, метод не возвращает ничего, пока процесс полностью не будет завершен. Заметьте, что если дочерний процесс перехватывает сигнал SIGTERM, и при этом не завершается, родительский процесс будет приостановлен до тех пор, пока не завершится дочерний процесс.

    Если вышло время выполнения процесса, или он имеет непустой код выхода, этот метод будет выдавать ошибку. Объект Error будет содержать весь результат из child_process.spawnSync()

    Class: ChildProcess

    Экземплярами класса ChildProcess являются ивент-эмиттеры (EventEmitters), которые относятся к созданному дочернему процессу.

    Экземпляры ChildProcess не должны создаваться напрямую. Скорее, нужно использовать методы child_process.spawn(), child_process.exec(), child_process.execFile(), или child_process.fork() для их создания.

    Event: 'close'

    • code <Число> Код выхода дочернего процесса, если процесс завершился самостоятельно
    • signal <Строка> Сигнал для завершения дочернего процесса

    Событие 'close' запускается, когда потоки stdio дочернего процесса были закрыты. Это событие отличается от 'exit', так как множественные процессы могут разделять одни и те же stdio потоки.

    Event: 'disconnect'

    Событие 'disconnect' запускается после вызова метода child.disconnect() в родительском процессе или process.disconnect() в дочернем. После разъединения больше невозможно отправлять или получать сообщения , а также свойство child.connected будет false

    Event: 'error'

    • err <Ошибка>

    'error' может быть запущено когда угодно:

    1. Когда процесс не может быть создан, или
    2. Когда процесс не может быть "убит", или
    3. Не удалась отправка сообщения дочернему процессу.

    Следует заметить, что событие 'exit' может или не может произойти после того, как выпала ошибка. Если вы ожидаете оба события, важно быть начеку по отношению к случайному многоразовому вызову функции обработчика.

    См. тажже child.kill() и child.send().

    Event: 'exit'

    • code <Число> Код выхода дочернего процесса, если процесс завершился самостоятельно
    • signal <Строка> Сигнал для завершения дочернего процесса

    Событие 'exit' вызывается после завершения дочернего процесса. Если процесс окончен, конечным кодом выхода процесса является code, во всех других случаях - null. Если процесс был прекращен по сигналу, названием строки сигнала будет signal, в противном случае - null. Какое-то одно из этих двух значений всегда будет не null.

    Примечание: когда запускается событие 'exit', потоки stdio дочернего процесса могут все еще быть открытыми.

    Также, следует заметить, что Node.js устанавливает обработчики сигналов для SIGINT и SIGTERM и процессы Node.js не будут прекращены немедленно по этим сигналам. Скорее, Node.js выполнит последовательность действий по очистке и затем перезапустит обработанные сигналы.

    См. waitpid(2)

    Event: 'message'

    • message <Объект> парсируемый JSON объект или примитивное значение
    • sendHandle <Обработчик> объект net.Socket или net.Server, также может быть незаданным

    Событие 'message' запускается, когда дочерний процесс использует process.send() для отправки сообщений.

    child.connected

    • <Boolean> После вызова child.disconnect становится false

    Свойство child.connected показывает, возможно ли еще отправлять и получать сообщения от дочернего процесса. Когда child.connected - false, это означает, что обмен сообщениями с дочерним процессом больше невозможен.

    child.disconnect()

    Закрывает IPC канал между родителем и дочерним процессом, позволяя дочернему процессу звершиться без препятствий при отсутствии работающих соединений. После вызова этого метода, свойстваchild.connected и process.connected в родительском и дочернем процессе соответственно будут установлены на false, и дальнейший обмен сообщениями между процессами больше не будет возможным.

    Событие 'disconnect' запускается, когда нет получения сообщений. Чаще всего оно срабатывает сразу после вызова child.disconnect.

    Следует заметить, что когда дочерний процесс является экземпляром Node.js (т.е. создан с помощью chuld_process.fork()), метод process.disconnect() может быть вызван в дочернем процессе, чтобы закрыть IPC канал.

    child.kill([signal])

    • signal <Строка>

    Методы child.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 дочерний процесс (или процессы) не могут быть прекращены, пока есть команда kill для их родительских процессов. Такое может случиться при запуске нового процесса в оболочке или с использованием опции shell в ChildProcess, как, например:

    
    'use strict';
    
    const spawn = require('child_process').spawn;
    
    let child = spawn('sh', ['-c',
      `node -e "setInterval(() => {
          console.log(process.pid + 'is alive')
        }, 500);"`
      ], {
        stdio: ['inherit', 'inherit', 'inherit']
      });
    
    setTimeout(() => {
      child.kill(); // does not terminate the node process in the shell
    }, 2000);
    

    child.pid

    • <Число> Целое число

    Возвращает идентификатор дочернего процесса (PID).

    Пример:

    
    const spawn = require('child_process').spawn;
    const grep = spawn('grep', ['ssh']);
    
    console.log(`Spawned child pid: ${grep.pid}`);
    grep.stdin.end();
    

    child.send(message[, sendHandle[, options]][, callback])

    • message <Объект>
    • sendhandle <Обработчик>
    • options <Объект>
    • callback <Функция>
    • Return: <Boolean>

    Когда установлен IPC канал между родителем и дочерним процессом (при использовании child_process.fork()), можно использовать метод child.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, который может быть передан child.send(), существует для

    передачи TCP сервера или объекта сокета дочернему процессу. Дочерний процесс может получить объект как второй аргумент, переданный функции обратного вызова, что была зарегистрирована в событии process.on('message'). Любые полученные и отправленные в буфер данные сокета не будут отправляться дочернему процессу.

    Аргумент options, если он существует, является объектом для параметризации отправки определенных типов обработчиков. options поддерживает следующие свойства:

    • keepOpen – значение boolean, которое может использоваться при передаче экземпляров new.Socket. Если оно true, сокет остается открытым в процессе отправки. По умолчанию: false.

    callback – это функция, которая вызывается после того, как сообщение было отправлено, но до того, как дочерний процесс его получит. Функция вызывается с одним единственным аргументом: null в случае удачного запуска и объектом Error в противном случае.

    Если нет функции callback и сообщение не может быть отправлено, событие 'error' выпоняется объектом ChildProcess. Такое может произойти, например, когда дочерний процесс уже завершился.

    child.send() будет возвращать false в случае, когда закрыт канал, а также если бэклог неотправленных сообщений превышает порог, выше которого нецелесообразна отправка сообщений в дальнейшем.В ином случае, метод возвращает true. Функцию callback можно использовать для реализации контроля потоков.


    Пример: отправка объекта сервера

    Аргумент sendHandle можно использовать, например, для передаче обработчика объекта TCP сервера дочернему процессу (как показано ниже):

    
    const child = require('child_process').fork('child.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, () => {
      child.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 может быть использован для передачи обработчика сокета дочернему процессу. Пример ниже показывает создание двух "детей", каждый из которых обрабатывает соединения с приоритетами "normal" и "special":

    
    const normal = require('child_process').fork('child.js', ['normal']);
    const special = require('child_process').fork('child.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);
    

    child.js будет получать обработчик сокета как второй аргумент, передаваемый событию функции обратного вызова:

    
    process.on('message', (m, socket) => {
      if (m === 'socket') {
        socket.end(`Request handled with ${process.argv[2]} priority`);
      }
    });
    

    После того, как сокет был передан дочернему процессу, родитель больше не имеет возможности отслеживать, где сокеты уничтожаются. Для определения этого, свойство .connections становится null. Рекомендуется не использовать .maxConnections, если попадается.

    Примечание: эта функция использует внутри JSON.stringify() для сериализации сообщений.

    child.stderr

    • <Стрим>

    Readable Stream (открытый для чтения стрим), что представляет stderr дочернего процесса.

    Если дочерний процесс был создан с stdio[2], установленным на что угодно, кроме 'pipe', значит, значение по умолчанию будет undefined.

    child.stderr является "союзником" child.stdio[2]. Оба свойства ссылаются на одно и то же значение.

    child.stdin

    • <Стрим>

    Writable Stream (открытый для записи стрим), что представляет stdin дочернего процесса.

    Важно: если дочерний процесс ожидает чтения всех своих входов, он не сможет продолжиться пока этот стрим не будет закрыт посредством end().

    Если дочерний процесс был создан с stdio[0], установленным на что угодно, кроме 'pipe', значит, значение по умолчанию будет undefined.

    child.stdin является "союзником" child.stdio[0]. Оба свойства ссылаются на одно и то же значение.

    child.stdio

    • <Массив>

    "Разбросанный" массив каналов (pipes), ведущих к дочернему процессу, который ссылается на позиции опций stdio, переданных child_process.spawn(), которым было задано значение 'pipe'. Следует заметить, что child.stdio[0], child.stdio[1], и child.stdio[2] – то же самое, что и child.stdin, child.stdout, и child.stderr, соответственно.

    В следующем примере демонстрируется, как только файловый дескриптор дочернего процесса 1 (stdout) конфигурируется как канал, так, что только родительский child.stdio[1] является стримом, все остальные значения в массиве null.

    
    const assert = require('assert');
    const fs = require('fs');
    const child_process = require('child_process');
    
    const child = 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(child.stdio[0], null);
    assert.equal(child.stdio[0], child.stdin);
    
    assert(child.stdout);
    assert.equal(child.stdio[1], child.stdout);
    
    assert.equal(child.stdio[2], null);
    assert.equal(child.stdio[2], child.stderr);
    

    child.stdout

    • <Стрим>

    Readable Stream (открытый для чтения стрим), что представляет stdout дочернего процесса.

    Если дочерний процесс был создан с stdio[1], установленным на что угодно, кроме 'pipe', значит, значение по умолчанию будет undefined.

    child.stdout является "союзником" child.stdio[1]. Оба свойства ссылаются на одно и то же значение.

    maxBuffer и Юникод

    Важно помнить, что опция maxBuffer задает самое больше число октетов, допустимых в stdout и stderr. Если это значение превосходит заданное, дочерний процесс прерывается. Это практически влияет на выходы, которые включают в себя мультибайтовые кодировки символов, такие как UTF-8 или UTF-16. Например, следующий пример выводит 13 закодированных в UTF-8 октетов на stdout, хотя мы видим только 4 символа.

    
    console.log('中文测试');