Skip to content

Дочерний процесс

[Стабильно: 2 - Стабильно]

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

Исходный код: lib/child_process.js

Модуль node:child_process предоставляет возможность порождать подпроцессы способом, аналогичным, но не идентичным popen(3). Эта возможность в основном предоставляется функцией child_process.spawn():

js
const { spawn } = require('node:child_process')
const ls = spawn('ls', ['-lh', '/usr'])

ls.stdout.on('data', data => {
  console.log(`stdout: ${data}`)
})

ls.stderr.on('data', data => {
  console.error(`stderr: ${data}`)
})

ls.on('close', code => {
  console.log(`дочерний процесс завершился с кодом ${code}`)
})
js
import { spawn } from 'node:child_process'
const ls = spawn('ls', ['-lh', '/usr'])

ls.stdout.on('data', data => {
  console.log(`stdout: ${data}`)
})

ls.stderr.on('data', data => {
  console.error(`stderr: ${data}`)
})

ls.on('close', code => {
  console.log(`дочерний процесс завершился с кодом ${code}`)
})

По умолчанию между родительским процессом Node.js и порожденным подпроцессом устанавливаются каналы для stdin, stdout и stderr. Эти каналы имеют ограниченную (и зависящую от платформы) емкость. Если подпроцесс записывает в stdout больше этого лимита без перехвата вывода, подпроцесс блокируется в ожидании, пока буфер канала не примет больше данных. Это идентично поведению каналов в оболочке. Используйте параметр { stdio: 'ignore' }, если вывод не будет использован.

Поиск команды выполняется с использованием переменной окружения options.env.PATH, если env находится в объекте options. В противном случае используется process.env.PATH. Если options.env установлен без PATH, поиск в Unix выполняется по пути поиска по умолчанию /usr/bin:/bin (см. руководство вашей операционной системы по execvpe/execvp), в Windows используется переменная окружения текущего процесса PATH.

В Windows переменные окружения не чувствительны к регистру. Node.js лексикографически сортирует ключи env и использует первый, который не чувствителен к регистру. Только первая (в лексикографическом порядке) запись будет передана подпроцессу. Это может привести к проблемам в Windows при передаче объектов в параметр env, которые имеют несколько вариантов одного и того же ключа, например PATH и Path.

Метод child_process.spawn() порождает дочерний процесс асинхронно, не блокируя цикл событий Node.js. Функция child_process.spawnSync() предоставляет эквивалентную функциональность синхронно, блокируя цикл событий до тех пор, пока порожденный процесс не завершится или не будет завершен.

Для удобства модуль node: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. Эти объекты реализуют API EventEmitter Node.js, позволяя родительскому процессу регистрировать функции-слушатели, которые вызываются при возникновении определенных событий во время жизненного цикла дочернего процесса.

Методы child_process.exec() и child_process.execFile() дополнительно позволяют указать необязательную функцию callback, которая вызывается при завершении дочернего процесса.

Запуск файлов .bat и .cmd в Windows

Важность различия между child_process.exec() и child_process.execFile() может варьироваться в зависимости от платформы. В операционных системах Unix (Unix, Linux, macOS) 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()). В любом случае, если имя файла скрипта содержит пробелы, его необходимо заключить в кавычки.

js
// ИЛИ...
const { exec, spawn } = require('node:child_process')

exec('my.bat', (err, stdout, stderr) => {
  if (err) {
    console.error(err)
    return
  }
  console.log(stdout)
})

// Скрипт с пробелами в имени файла:
const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true })
// или:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
  // ...
})
js
// ИЛИ...
import { exec, spawn } from 'node:child_process'

exec('my.bat', (err, stdout, stderr) => {
  if (err) {
    console.error(err)
    return
  }
  console.log(stdout)
})

// Скрипт с пробелами в имени файла:
const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true })
// или:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
  // ...
})

child_process.exec(command[, options][, callback])

[История]

ВерсияИзменения
v15.4.0Добавлена поддержка AbortSignal.
v16.4.0, v14.18.0Опция cwd может быть объектом WHATWG URL с использованием протокола file:.
v8.8.0Теперь поддерживается опция windowsHide.
v0.1.90Добавлено в: v0.1.90
  • command <string> Команда для запуска, с аргументами, разделёнными пробелами.

  • options <Object>

    • cwd <string> | <URL> Текущий рабочий каталог дочернего процесса. По умолчанию: process.cwd().
    • env <Object> Пары ключ-значение окружения. По умолчанию: process.env.
    • encoding <string> По умолчанию: 'utf8'
    • shell <string> Оболочка для выполнения команды. См. Требования к оболочке и Оболочка Windows по умолчанию. По умолчанию: '/bin/sh' в Unix, process.env.ComSpec в Windows.
    • signal <AbortSignal> позволяет прервать дочерний процесс с помощью AbortSignal.
    • timeout <number> По умолчанию: 0
    • maxBuffer <number> Максимальное количество данных в байтах, допустимое в stdout или stderr. В случае превышения, дочерний процесс завершается, и любой вывод обрезается. См. предостережение в maxBuffer и Unicode. По умолчанию: 1024 * 1024.
    • killSignal <string> | <integer> По умолчанию: 'SIGTERM'
    • uid <number> Устанавливает идентификатор пользователя процесса (см. setuid(2)).
    • gid <number> Устанавливает идентификатор группы процесса (см. setgid(2)).
    • windowsHide <boolean> Скрывает консольное окно подпроцесса, которое обычно создается в системах Windows. По умолчанию: false.
  • callback <Function> вызывается с выводом при завершении процесса.

  • Возвращает: <ChildProcess>

Запускает оболочку, а затем выполняет command в этой оболочке, буферизируя любой сгенерированный вывод. Строка command, переданная функции exec, обрабатывается непосредственно оболочкой, и специальные символы (различаются в зависимости от оболочки) необходимо обрабатывать соответственно:

js
const { exec } = require('node:child_process')

exec('"/path/to/test file/test.sh" arg1 arg2')
// Двойные кавычки используются для того, чтобы пробел в пути не интерпретировался как
// разделитель нескольких аргументов.

exec('echo "Переменная \\$HOME равна $HOME"')
// Переменная $HOME экранируется в первом случае, но не во втором.
js
import { exec } from 'node:child_process'

exec('"/path/to/test file/test.sh" arg1 arg2')
// Двойные кавычки используются для того, чтобы пробел в пути не интерпретировался как
// разделитель нескольких аргументов.

exec('echo "Переменная \\$HOME равна $HOME"')
// Переменная $HOME экранируется в первом случае, но не во втором.

Никогда не передавайте в эту функцию непроверенный пользовательский ввод. Любой ввод, содержащий метасимволы оболочки, может быть использован для запуска произвольного выполнения команд.

Если предоставлена функция callback, она вызывается с аргументами (error, stdout, stderr). В случае успеха, error будет null. В случае ошибки, error будет экземпляром Error. Свойство error.code будет кодом выхода процесса. По соглашению, любой код выхода, отличный от 0, указывает на ошибку. error.signal будет сигналом, который завершил процесс.

Аргументы stdout и stderr, переданные в callback, будут содержать stdout и stderr вывод дочернего процесса. По умолчанию, Node.js будет декодировать вывод как UTF-8 и передавать строки в callback. Опция encoding может быть использована для указания кодировки символов, используемой для декодирования вывода stdout и stderr. Если encoding равно 'buffer', или является нераспознанной кодировкой символов, вместо этого в callback будут переданы объекты Buffer.

js
const { exec } = require('node:child_process')
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`ошибка выполнения: ${error}`)
    return
  }
  console.log(`stdout: ${stdout}`)
  console.error(`stderr: ${stderr}`)
})
js
import { exec } from 'node:child_process'
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`ошибка выполнения: ${error}`)
    return
  }
  console.log(`stdout: ${stdout}`)
  console.error(`stderr: ${stderr}`)
})

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

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

Если этот метод вызывается как его версия, полученная с помощью util.promisify(), он возвращает Promise для Object со свойствами stdout и stderr. Возвращаемый экземпляр ChildProcess прикреплен к Promise в качестве свойства child. В случае ошибки (включая любую ошибку, приводящую к коду выхода, отличному от 0), возвращается отклоненный промис, с тем же объектом error, что и в callback, но с двумя дополнительными свойствами stdout и stderr.

js
const util = require('node:util')
const exec = util.promisify(require('node:child_process').exec)

async function lsExample() {
  const { stdout, stderr } = await exec('ls')
  console.log('stdout:', stdout)
  console.error('stderr:', stderr)
}
lsExample()
js
import { promisify } from 'node:util'
import child_process from 'node:child_process'
const exec = promisify(child_process.exec)

async function lsExample() {
  const { stdout, stderr } = await exec('ls')
  console.log('stdout:', stdout)
  console.error('stderr:', stderr)
}
lsExample()

Если включена опция signal, вызов .abort() на соответствующем AbortController аналогичен вызову .kill() на дочернем процессе, за исключением того, что ошибка, переданная в callback, будет AbortError:

js
const { exec } = require('node:child_process')
const controller = new AbortController()
const { signal } = controller
const child = exec('grep ssh', { signal }, error => {
  console.error(error) // an AbortError
})
controller.abort()
js
import { exec } from 'node:child_process'
const controller = new AbortController()
const { signal } = controller
const child = exec('grep ssh', { signal }, error => {
  console.error(error) // an AbortError
})
controller.abort()

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

[История]

ВерсияИзменения
v16.4.0, v14.18.0Опция cwd может быть объектом WHATWG URL с использованием протокола file:.
v15.4.0, v14.17.0Добавлена поддержка AbortSignal.
v8.8.0Теперь поддерживается опция windowsHide.
v0.1.91Добавлено в: v0.1.91
  • file <string> Имя или путь к исполняемому файлу для запуска.

  • args <string[]> Список строковых аргументов.

  • options <Object>

    • cwd <string> | <URL> Текущий рабочий каталог дочернего процесса.
    • env <Object> Пары ключ-значение переменных окружения. По умолчанию: process.env.
    • encoding <string> По умолчанию: 'utf8'
    • timeout <number> По умолчанию: 0
    • maxBuffer <number> Максимальный объем данных в байтах, разрешенный в stdout или stderr. Если превышен, дочерний процесс завершается, а вывод обрезается. См. предостережение в maxBuffer и Unicode. По умолчанию: 1024 * 1024.
    • killSignal <string> | <integer> По умолчанию: 'SIGTERM'
    • uid <number> Устанавливает идентификатор пользователя процесса (см. setuid(2)).
    • gid <number> Устанавливает идентификатор группы процесса (см. setgid(2)).
    • windowsHide <boolean> Скрыть консольное окно подпроцесса, которое обычно создается в системах Windows. По умолчанию: false.
    • windowsVerbatimArguments <boolean> Отмена экранирования аргументов в Windows. Игнорируется в Unix. По умолчанию: false.
    • shell <boolean> | <string> Если true, запускает command внутри оболочки. Использует '/bin/sh' в Unix и process.env.ComSpec в Windows. Другая оболочка может быть указана в виде строки. См. Требования к оболочке и Оболочка Windows по умолчанию. По умолчанию: false (без оболочки).
    • signal <AbortSignal> позволяет прервать дочерний процесс с помощью AbortSignal.
  • callback <Function> Вызывается с выводом после завершения процесса.

  • Возвращает: <ChildProcess>

Функция child_process.execFile() похожа на child_process.exec(), за исключением того, что она не запускает оболочку по умолчанию. Вместо этого указанный исполняемый file запускается непосредственно как новый процесс, что делает его немного более эффективным, чем child_process.exec().

Поддерживаются те же параметры, что и child_process.exec(). Поскольку оболочка не запускается, такие возможности, как перенаправление ввода-вывода и поиск файлов по шаблону, не поддерживаются.

js
const { execFile } = require('node:child_process')
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    throw error
  }
  console.log(stdout)
})
js
import { execFile } from 'node:child_process'
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.

Если этот метод вызывается как его util.promisify()-версия, он возвращает Promise для Object со свойствами stdout и stderr. Возвращенный экземпляр ChildProcess прикрепляется к Promise как свойство child. В случае ошибки (включая любую ошибку, приводящую к коду выхода, отличному от 0), возвращается отклоненное обещание с тем же объектом error, что и в обратном вызове, но с двумя дополнительными свойствами stdout и stderr.

js
const util = require('node:util')
const execFile = util.promisify(require('node:child_process').execFile)
async function getVersion() {
  const { stdout } = await execFile('node', ['--version'])
  console.log(stdout)
}
getVersion()
js
import { promisify } from 'node:util'
import child_process from 'node:child_process'
const execFile = promisify(child_process.execFile)
async function getVersion() {
  const { stdout } = await execFile('node', ['--version'])
  console.log(stdout)
}
getVersion()

Если параметр shell включен, не передавайте несанированные пользовательские данные в эту функцию. Любые входные данные, содержащие метасимволы оболочки, могут быть использованы для запуска произвольного выполнения команд.

Если включена опция signal, вызов .abort() для соответствующего AbortController аналогичен вызову .kill() для дочернего процесса, за исключением того, что ошибка, передаваемая в обратный вызов, будет AbortError:

js
const { execFile } = require('node:child_process')
const controller = new AbortController()
const { signal } = controller
const child = execFile('node', ['--version'], { signal }, error => {
  console.error(error) // an AbortError
})
controller.abort()
js
import { execFile } from 'node:child_process'
const controller = new AbortController()
const { signal } = controller
const child = execFile('node', ['--version'], { signal }, error => {
  console.error(error) // an AbortError
})
controller.abort()

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

[История]

ВерсияИзменения
v17.4.0, v16.14.0Параметр modulePath может быть объектом WHATWG URL с использованием протокола file:.
v16.4.0, v14.18.0Параметр cwd может быть объектом WHATWG URL с использованием протокола file:.
v15.13.0, v14.18.0Добавлен параметр timeout.
v15.11.0, v14.18.0Добавлен параметр killSignal для AbortSignal.
v15.6.0, v14.17.0Добавлена поддержка AbortSignal.
v13.2.0, v12.16.0Теперь поддерживается параметр serialization.
v8.0.0Параметр stdio теперь может быть строкой.
v6.4.0Теперь поддерживается параметр stdio.
v0.5.0Добавлено в: v0.5.0
  • modulePath <string> | <URL> Модуль для запуска в дочернем процессе.

  • args <string[]> Список строковых аргументов.

  • options <Object>

    • cwd <string> | <URL> Текущий рабочий каталог дочернего процесса.
    • detached <boolean> Подготавливает дочерний процесс для независимого запуска от родительского процесса. Конкретное поведение зависит от платформы, смотрите options.detached).
    • env <Object> Пары ключ-значение окружения. По умолчанию: process.env.
    • execPath <string> Исполняемый файл, используемый для создания дочернего процесса.
    • execArgv <string[]> Список строковых аргументов, передаваемых исполняемому файлу. По умолчанию: process.execArgv.
    • gid <number> Устанавливает групповой идентификатор процесса (см. setgid(2)).
    • serialization <string> Указывает тип сериализации, используемый для отправки сообщений между процессами. Возможные значения: 'json' и 'advanced'. Дополнительные сведения см. в разделе Расширенная сериализация. По умолчанию: 'json'.
    • signal <AbortSignal> Позволяет закрыть дочерний процесс с помощью AbortSignal.
    • killSignal <string> | <integer> Сигнал, используемый при завершении порожденного процесса по тайм-ауту или сигналу прерывания. По умолчанию: 'SIGTERM'.
    • silent <boolean> Если true, stdin, stdout и stderr дочернего процесса будут перенаправлены в родительский процесс, иначе они будут унаследованы от родительского процесса. Подробнее см. параметры 'pipe' и 'inherit' для child_process.spawn()'s stdio. По умолчанию: false.
    • stdio <Array> | <string> См. stdio для child_process.spawn(). Если этот параметр предоставлен, он переопределяет silent. Если используется вариант массива, он должен содержать ровно один элемент со значением 'ipc', в противном случае будет выдана ошибка. Например, [0, 1, 2, 'ipc'].
    • uid <number> Устанавливает идентификатор пользователя процесса (см. setuid(2)).
    • windowsVerbatimArguments <boolean> На Windows не выполняется экранирование или заключение в кавычки аргументов. Игнорируется на Unix. По умолчанию: false.
    • timeout <number> Максимальное время работы процесса в миллисекундах. По умолчанию: undefined.
  • Возвращает: <ChildProcess>

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

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

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

Процессы Node.js, запущенные с пользовательским execPath, будут взаимодействовать с родительским процессом, используя файловый дескриптор (fd), идентифицированный с помощью переменной среды NODE_CHANNEL_FD в дочернем процессе.

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

Параметр shell, доступный в child_process.spawn(), не поддерживается child_process.fork() и будет проигнорирован, если он установлен.

Если параметр signal включен, вызов .abort() для соответствующего AbortController аналогичен вызову .kill() для дочернего процесса, за исключением того, что ошибка, переданная в обратный вызов, будет AbortError:

js
const { fork } = require('node:child_process')
const process = require('node:process')

if (process.argv[2] === 'child') {
  setTimeout(() => {
    console.log(`Привет от ${process.argv[2]}!`)
  }, 1_000)
} else {
  const controller = new AbortController()
  const { signal } = controller
  const child = fork(__filename, ['child'], { signal })
  child.on('error', err => {
    // Это будет вызвано с err, являющимся AbortError, если контроллер прервется
  })
  controller.abort() // Останавливает дочерний процесс
}
js
import { fork } from 'node:child_process'
import process from 'node:process'

if (process.argv[2] === 'child') {
  setTimeout(() => {
    console.log(`Привет от ${process.argv[2]}!`)
  }, 1_000)
} else {
  const controller = new AbortController()
  const { signal } = controller
  const child = fork(import.meta.url, ['child'], { signal })
  child.on('error', err => {
    // Это будет вызвано с err, являющимся AbortError, если контроллер прервется
  })
  controller.abort() // Останавливает дочерний процесс
}

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

[История]

ВерсияИзменения
v16.4.0, v14.18.0Опция cwd может быть объектом WHATWG URL с использованием протокола file:.
v15.13.0, v14.18.0Добавлен таймаут.
v15.11.0, v14.18.0Добавлен killSignal для AbortSignal.
v15.5.0, v14.17.0Добавлена поддержка AbortSignal.
v13.2.0, v12.16.0Теперь поддерживается опция serialization.
v8.8.0Теперь поддерживается опция windowsHide.
v6.4.0Теперь поддерживается опция argv0.
v5.7.0Теперь поддерживается опция shell.
v0.1.90Добавлено в: v0.1.90
  • command <string> Команда для запуска.

  • args <string[]> Список строковых аргументов.

  • options <Object>

    • cwd <string> | <URL> Текущий рабочий каталог дочернего процесса.
    • env <Object> Пары ключ-значение переменных среды. По умолчанию: process.env.
    • argv0 <string> Явно задайте значение argv[0], отправляемое дочернему процессу. Если не указано, будет установлено значение command.
    • stdio <Array> | <string> Конфигурация stdio дочернего процесса (см. options.stdio).
    • detached <boolean> Подготовьте дочерний процесс для работы независимо от родительского процесса. Конкретное поведение зависит от платформы, см. options.detached).
    • uid <number> Устанавливает идентификатор пользователя процесса (см. setuid(2)).
    • gid <number> Устанавливает идентификатор группы процесса (см. setgid(2)).
    • serialization <string> Укажите тип сериализации, используемый для отправки сообщений между процессами. Возможные значения: 'json' и 'advanced'. Подробнее см. Продвинутая сериализация. По умолчанию: 'json'.
    • shell <boolean> | <string> Если true, запускает command внутри оболочки. Использует '/bin/sh' в Unix и process.env.ComSpec в Windows. Другая оболочка может быть указана в виде строки. См. Требования к оболочке и Оболочка Windows по умолчанию. По умолчанию: false (без оболочки).
    • windowsVerbatimArguments <boolean> В Windows не выполняется заключение аргументов в кавычки или экранирование. В Unix игнорируется. Автоматически устанавливается в true, когда указан shell и это CMD. По умолчанию: false.
    • windowsHide <boolean> Скрыть окно консоли подпроцесса, которое обычно создается в системах Windows. По умолчанию: false.
    • signal <AbortSignal> позволяет прервать дочерний процесс с помощью AbortSignal.
    • timeout <number> Максимальное время в миллисекундах, в течение которого процессу разрешено работать. По умолчанию: undefined.
    • killSignal <string> | <integer> Значение сигнала, которое будет использоваться, когда запущенный процесс будет остановлен по таймауту или сигналу прерывания. По умолчанию: 'SIGTERM'.
  • Возвращает: <ChildProcess>

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

Если включена опция shell, не передавайте несанированные пользовательские данные в эту функцию. Любые входные данные, содержащие метасимволы оболочки, могут использоваться для запуска произвольного выполнения команд.

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

js
const defaults = {
  cwd: undefined,
  env: process.env,
}

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

Используйте env, чтобы указать переменные среды, которые будут видны новому процессу, по умолчанию это process.env.

Значения undefined в env будут игнорироваться.

Пример запуска ls -lh /usr, захвата stdout, stderr и кода выхода:

js
const { spawn } = require('node:child_process')
const ls = spawn('ls', ['-lh', '/usr'])

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}`)
})
js
import { spawn } from 'node:child_process'
const ls = spawn('ls', ['-lh', '/usr'])

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

Пример: очень сложный способ запуска ps ax | grep ssh

js
const { spawn } = require('node:child_process')
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.error(`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.toString())
})

grep.stderr.on('data', data => {
  console.error(`grep stderr: ${data}`)
})

grep.on('close', code => {
  if (code !== 0) {
    console.log(`grep process exited with code ${code}`)
  }
})
js
import { spawn } from 'node:child_process'
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.error(`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.toString())
})

grep.stderr.on('data', data => {
  console.error(`grep stderr: ${data}`)
})

grep.on('close', code => {
  if (code !== 0) {
    console.log(`grep process exited with code ${code}`)
  }
})

Пример проверки неудачного spawn:

js
const { spawn } = require('node:child_process')
const subprocess = spawn('bad_command')

subprocess.on('error', err => {
  console.error('Failed to start subprocess.')
})
js
import { spawn } from 'node:child_process'
const subprocess = spawn('bad_command')

subprocess.on('error', err => {
  console.error('Failed to start subprocess.')
})

Некоторые платформы (macOS, Linux) будут использовать значение argv[0] для заголовка процесса, в то время как другие (Windows, SunOS) будут использовать command.

Node.js перезаписывает argv[0] на process.execPath при запуске, поэтому process.argv[0] в дочернем процессе Node.js не будет совпадать с параметром argv0, переданным в spawn из родительского. Получите его с помощью свойства process.argv0.

Если включена опция signal, вызов .abort() на соответствующем AbortController аналогичен вызову .kill() на дочернем процессе, за исключением того, что ошибка, переданная в обратный вызов, будет AbortError:

js
const { spawn } = require('node:child_process')
const controller = new AbortController()
const { signal } = controller
const grep = spawn('grep', ['ssh'], { signal })
grep.on('error', err => {
  // Этот обратный вызов будет вызван с err, являющимся AbortError, если контроллер прервет
})
controller.abort() // Останавливает дочерний процесс
js
import { spawn } from 'node:child_process'
const controller = new AbortController()
const { signal } = controller
const grep = spawn('grep', ['ssh'], { signal })
grep.on('error', err => {
  // Этот обратный вызов будет вызван с err, являющимся AbortError, если контроллер прервет
})
controller.abort() // Останавливает дочерний процесс

options.detached

Добавлено в: v0.7.10

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

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

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

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

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

js
const { spawn } = require('node:child_process')
const process = require('node:process')

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

subprocess.unref()
js
import { spawn } from 'node:child_process'
import process from 'node:process'

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

subprocess.unref()

В качестве альтернативы можно перенаправить вывод дочернего процесса в файлы:

js
const { openSync } = require('node:fs')
const { spawn } = require('node:child_process')
const out = openSync('./out.log', 'a')
const err = openSync('./out.log', 'a')

const subprocess = spawn('prg', [], {
  detached: true,
  stdio: ['ignore', out, err],
})

subprocess.unref()
js
import { openSync } from 'node:fs'
import { spawn } from 'node:child_process'
const out = openSync('./out.log', 'a')
const err = openSync('./out.log', 'a')

const subprocess = spawn('prg', [], {
  detached: true,
  stdio: ['ignore', out, err],
})

subprocess.unref()

options.stdio

[История]

ВерсияИзменения
v15.6.0, v14.18.0Добавлен флаг overlapped для stdio.
v3.3.1Значение 0 теперь принимается как файловый дескриптор.
v0.7.10Добавлено в: v0.7.10

Параметр options.stdio используется для настройки каналов, устанавливаемых между родительским и дочерним процессами. По умолчанию stdin, stdout и stderr дочернего процесса перенаправляются в соответствующие потоки subprocess.stdin, subprocess.stdout и subprocess.stderr объекта ChildProcess. Это эквивалентно установке options.stdio равным ['pipe', 'pipe', 'pipe'].

Для удобства, options.stdio может быть одной из следующих строк:

  • 'pipe': эквивалентно ['pipe', 'pipe', 'pipe'] (по умолчанию)
  • 'overlapped': эквивалентно ['overlapped', 'overlapped', 'overlapped']
  • 'ignore': эквивалентно ['ignore', 'ignore', 'ignore']
  • 'inherit': эквивалентно ['inherit', 'inherit', 'inherit'] или [0, 1, 2]

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

js
const { spawn } = require('node:child_process')
const process = require('node:process')

// Дочерний процесс будет использовать stdios родительского процесса.
spawn('prg', [], { stdio: 'inherit' })

// Запустить дочерний процесс, разделяющий только stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] })

// Открыть дополнительный fd=4 для взаимодействия с программами, предоставляющими
// интерфейс в стиле startd.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] })
js
import { spawn } from 'node:child_process'
import process from 'node:process'

// Дочерний процесс будет использовать stdios родительского процесса.
spawn('prg', [], { stdio: 'inherit' })

// Запустить дочерний процесс, разделяющий только stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] })

// Открыть дополнительный fd=4 для взаимодействия с программами, предоставляющими
// интерфейс в стиле startd.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] })

Стоит отметить, что когда между родительским и дочерним процессами устанавливается IPC-канал, а дочерний процесс является экземпляром Node.js, дочерний процесс запускается с неразмеченным IPC-каналом (с использованием unref()) до тех пор, пока дочерний процесс не зарегистрирует обработчик событий для события 'disconnect' или события '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])

[История]

ВерсияИзменения
v16.4.0, v14.18.0Опция cwd может быть объектом WHATWG URL с использованием протокола file:.
v10.10.0Опция input теперь может быть любым TypedArray или DataView.
v8.8.0Теперь поддерживается опция windowsHide.
v8.0.0Опция input теперь может быть Uint8Array.
v6.2.1, v4.5.0Опцию encoding теперь можно явно установить в buffer.
v0.11.12Добавлено в: v0.11.12
  • file <string> Имя или путь к исполняемому файлу, который нужно запустить.

  • args <string[]> Список строковых аргументов.

  • options <Object>

    • cwd <string> | <URL> Текущий рабочий каталог дочернего процесса.
    • input <string> | <Buffer> | <TypedArray> | <DataView> Значение, которое будет передано как stdin порожденному процессу. Если stdio[0] установлено в 'pipe', то предоставление этого значения переопределит stdio[0].
    • stdio <string> | <Array> Конфигурация stdio дочернего процесса. См. child_process.spawn()'s stdio. stderr по умолчанию будет выводиться в stderr родительского процесса, если не указано stdio. По умолчанию: 'pipe'.
    • env <Object> Пары "ключ-значение" среды. По умолчанию: process.env.
    • uid <number> Устанавливает идентификатор пользователя процесса (см. setuid(2)).
    • gid <number> Устанавливает идентификатор группы процесса (см. setgid(2)).
    • timeout <number> Максимальное количество времени в миллисекундах, в течение которого процессу разрешено работать. По умолчанию: undefined.
    • killSignal <string> | <integer> Значение сигнала, которое будет использоваться при завершении порожденного процесса. По умолчанию: 'SIGTERM'.
    • maxBuffer <number> Максимальный объем данных в байтах, разрешенный в stdout или stderr. При превышении дочерний процесс завершается. См. предостережение в maxBuffer и Unicode. По умолчанию: 1024 * 1024.
    • encoding <string> Кодировка, используемая для всех вводов и выводов stdio. По умолчанию: 'buffer'.
    • windowsHide <boolean> Скрыть окно консоли подпроцесса, которое обычно создается в системах Windows. По умолчанию: false.
    • shell <boolean> | <string> Если true, запускает command внутри оболочки. Использует '/bin/sh' в Unix и process.env.ComSpec в Windows. Другая оболочка может быть указана в виде строки. См. Требования к оболочке и Оболочка Windows по умолчанию. По умолчанию: false (без оболочки).
  • Возвращает: <Buffer> | <string> stdout из команды.

Метод child_process.execFileSync() в основном идентичен child_process.execFile() за исключением того, что метод не вернется, пока дочерний процесс полностью не закроется. Когда возникает тайм-аут и отправляется killSignal, метод не вернется, пока процесс полностью не завершится.

Если дочерний процесс перехватывает и обрабатывает сигнал SIGTERM и не выходит, родительский процесс все равно будет ждать, пока дочерний процесс не выйдет.

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

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

js
const { execFileSync } = require('node:child_process')

try {
  const stdout = execFileSync('my-script.sh', ['my-arg'], {
    // Захват stdout и stderr из дочернего процесса. Переопределяет
    // поведение по умолчанию потоковой передачи stderr дочернего процесса в stderr родительского
    stdio: 'pipe',

    // Использовать кодировку utf8 для каналов stdio
    encoding: 'utf8',
  })

  console.log(stdout)
} catch (err) {
  if (err.code) {
    // Не удалось породить дочерний процесс
    console.error(err.code)
  } else {
    // Дочерний процесс был порожден, но вышел с ненулевым кодом выхода
    // Ошибка содержит любой stdout и stderr от дочернего процесса
    const { stdout, stderr } = err

    console.error({ stdout, stderr })
  }
}
js
import { execFileSync } from 'node:child_process'

try {
  const stdout = execFileSync('my-script.sh', ['my-arg'], {
    // Захват stdout и stderr из дочернего процесса. Переопределяет
    // поведение по умолчанию потоковой передачи stderr дочернего процесса в stderr родительского
    stdio: 'pipe',

    // Использовать кодировку utf8 для каналов stdio
    encoding: 'utf8',
  })

  console.log(stdout)
} catch (err) {
  if (err.code) {
    // Не удалось породить дочерний процесс
    console.error(err.code)
  } else {
    // Дочерний процесс был порожден, но вышел с ненулевым кодом выхода
    // Ошибка содержит любой stdout и stderr от дочернего процесса
    const { stdout, stderr } = err

    console.error({ stdout, stderr })
  }
}

child_process.execSync(command[, options])

[История]

ВерсияИзменения
v16.4.0, v14.18.0Опция cwd может быть объектом WHATWG URL с использованием протокола file:.
v10.10.0Опция input теперь может быть любым TypedArray или DataView.
v8.8.0Теперь поддерживается опция windowsHide.
v8.0.0Опция input теперь может быть Uint8Array.
v0.11.12Добавлено в: v0.11.12
  • command <string> Команда для выполнения.

  • options <Object>

    • cwd <string> | <URL> Текущая рабочая директория дочернего процесса.
    • input <string> | <Buffer> | <TypedArray> | <DataView> Значение, которое будет передано как stdin порожденному процессу. Если stdio[0] установлено значение 'pipe', предоставление этого значения переопределит stdio[0].
    • stdio <string> | <Array> Конфигурация stdio дочернего процесса. См. child_process.spawn()'s stdio. stderr по умолчанию будет выводиться в stderr родительского процесса, если не указано stdio. По умолчанию: 'pipe'.
    • env <Object> Пары ключ-значение среды. По умолчанию: process.env.
    • shell <string> Оболочка для выполнения команды. См. Требования к оболочке и Оболочка Windows по умолчанию. По умолчанию: '/bin/sh' в Unix, process.env.ComSpec в Windows.
    • uid <number> Устанавливает идентификатор пользователя процесса. (См. setuid(2)).
    • gid <number> Устанавливает идентификатор группы процесса. (См. setgid(2)).
    • timeout <number> Максимальное время в миллисекундах, в течение которого разрешено выполнение процесса. По умолчанию: undefined.
    • killSignal <string> | <integer> Значение сигнала, которое будет использоваться при завершении порожденного процесса. По умолчанию: 'SIGTERM'.
    • maxBuffer <number> Максимальный объем данных в байтах, разрешенный для stdout или stderr. При превышении дочерний процесс завершается, и любой вывод усекается. См. предостережение в maxBuffer и Unicode. По умолчанию: 1024 * 1024.
    • encoding <string> Кодировка, используемая для всех вводов и выводов stdio. По умолчанию: 'buffer'.
    • windowsHide <boolean> Скрыть окно консоли подпроцесса, которое обычно создается в системах Windows. По умолчанию: false.
  • Возвращает: <Buffer> | <string> Вывод stdout из команды.

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

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

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

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

[История]

ВерсияИзменения
v16.4.0, v14.18.0Опция cwd может быть объектом WHATWG URL с использованием протокола file:.
v10.10.0Опция input теперь может быть любым TypedArray или DataView.
v8.8.0Теперь поддерживается опция windowsHide.
v8.0.0Опция input теперь может быть Uint8Array.
v5.7.0Теперь поддерживается опция shell.
v6.2.1, v4.5.0Опция encoding теперь может быть явно установлена в значение buffer.
v0.11.12Добавлено в: v0.11.12
  • command <string> Команда для запуска.

  • args <string[]> Список строковых аргументов.

  • options <Object>

    • cwd <string> | <URL> Текущий рабочий каталог дочернего процесса.
    • input <string> | <Buffer> | <TypedArray> | <DataView> Значение, которое будет передано как stdin в запущенный процесс. Если stdio[0] установлено в 'pipe', то предоставление этого значения переопределит stdio[0].
    • argv0 <string> Явно устанавливает значение argv[0], отправляемое дочернему процессу. Если не указано, то будет установлено значение command.
    • stdio <string> | <Array> Конфигурация stdio дочернего процесса. См. child_process.spawn()'s stdio. По умолчанию: 'pipe'.
    • env <Object> Пары ключ-значение среды. По умолчанию: process.env.
    • uid <number> Устанавливает идентификатор пользователя процесса (см. setuid(2)).
    • gid <number> Устанавливает идентификатор группы процесса (см. setgid(2)).
    • timeout <number> В миллисекундах максимальное количество времени, в течение которого разрешено выполняться процессу. По умолчанию: undefined.
    • killSignal <string> | <integer> Значение сигнала, которое будет использоваться, когда запущенный процесс будет завершен. По умолчанию: 'SIGTERM'.
    • maxBuffer <number> Наибольший объем данных в байтах, разрешенный в stdout или stderr. Если превышен, дочерний процесс завершается, а любой вывод усекается. См. предостережение в maxBuffer и Unicode. По умолчанию: 1024 * 1024.
    • encoding <string> Кодировка, используемая для всех вводов и выводов stdio. По умолчанию: 'buffer'.
    • shell <boolean> | <string> Если true, запускает command внутри оболочки. Использует '/bin/sh' в Unix и process.env.ComSpec в Windows. В качестве строки можно указать другую оболочку. См. Требования к оболочке и Оболочка Windows по умолчанию. По умолчанию: false (без оболочки).
    • windowsVerbatimArguments <boolean> В Windows не выполняется заключение аргументов в кавычки или экранирование. Игнорируется в Unix. Это автоматически устанавливается в true, когда указана shell и это CMD. По умолчанию: false.
    • windowsHide <boolean> Скрыть окно консоли подпроцесса, которое обычно создается в системах Windows. По умолчанию: false.
  • Возвращает: <Object>

    • pid <number> PID дочернего процесса.
    • output <Array> Массив результатов вывода stdio.
    • stdout <Buffer> | <string> Содержимое output[1].
    • stderr <Buffer> | <string> Содержимое output[2].
    • status <number> | <null> Код выхода подпроцесса или null, если подпроцесс завершился из-за сигнала.
    • signal <string> | <null> Сигнал, использованный для завершения подпроцесса, или null, если подпроцесс не завершился из-за сигнала.
    • error <Error> Объект ошибки, если дочерний процесс не удался или истекло время ожидания.

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

Если опция shell включена, не передавайте в эту функцию непроверенный пользовательский ввод. Любой ввод, содержащий метасимволы оболочки, может быть использован для запуска произвольных команд.

Класс: ChildProcess

Добавлено в: v2.2.0

Экземпляры ChildProcess представляют порожденные дочерние процессы.

Экземпляры ChildProcess не предназначены для прямого создания. Вместо этого используйте методы child_process.spawn(), child_process.exec(), child_process.execFile() или child_process.fork() для создания экземпляров ChildProcess.

Событие: 'close'

Добавлено в: v0.7.7

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

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

js
const { spawn } = require('node:child_process')
const ls = spawn('ls', ['-lh', '/usr'])

ls.stdout.on('data', data => {
  console.log(`stdout: ${data}`)
})

ls.on('close', code => {
  console.log(`child process close all stdio with code ${code}`)
})

ls.on('exit', code => {
  console.log(`child process exited with code ${code}`)
})
js
import { spawn } from 'node:child_process'
const ls = spawn('ls', ['-lh', '/usr'])

ls.stdout.on('data', data => {
  console.log(`stdout: ${data}`)
})

ls.on('close', code => {
  console.log(`child process close all stdio with code ${code}`)
})

ls.on('exit', code => {
  console.log(`child process exited with code ${code}`)
})

Событие: 'disconnect'

Добавлено в: v0.7.2

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

Событие: 'error'

Событие 'error' возникает в следующих случаях:

  • Процесс не удалось запустить.
  • Процесс не удалось завершить.
  • Отправка сообщения дочернему процессу не удалась.
  • Дочерний процесс был прерван с помощью параметра signal.

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

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

Событие: 'exit'

Добавлено в: v0.1.90

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

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

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

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

См. waitpid(2).

Событие: 'message'

Добавлено в: v0.5.9

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

Сообщение проходит через сериализацию и разбор. Полученное сообщение может отличаться от того, что было отправлено изначально.

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

Событие: 'spawn'

Добавлено в: v15.1.0, v14.17.0

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

Если событие 'spawn' испускается, оно происходит перед всеми другими событиями и перед тем, как какие-либо данные будут получены через stdout или stderr.

Событие 'spawn' сработает независимо от того, произошла ли ошибка внутри порожденного процесса. Например, если bash some-command успешно порождается, событие 'spawn' сработает, хотя bash может не породить some-command. Это предостережение также применяется при использовании { shell: true }.

subprocess.channel

[История]

ВерсияИзменения
v14.0.0Объект больше не предоставляет случайно собственные C++ привязки.
v7.1.0Добавлено в: v7.1.0
  • <Object> Канал, представляющий канал IPC к дочернему процессу.

Свойство subprocess.channel является ссылкой на канал IPC дочернего процесса. Если канал IPC не существует, это свойство имеет значение undefined.

subprocess.channel.ref()

Добавлено в: v7.1.0

Этот метод заставляет IPC-канал поддерживать работу цикла событий родительского процесса, если ранее был вызван метод .unref().

subprocess.channel.unref()

Добавлено в: v7.1.0

Этот метод заставляет IPC-канал не поддерживать работу цикла событий родительского процесса и позволяет ему завершиться, даже если канал открыт.

subprocess.connected

Добавлено в: v0.7.2

  • <boolean> Устанавливается в false после вызова subprocess.disconnect().

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

subprocess.disconnect()

Добавлено в: v0.7.2

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

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

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

subprocess.exitCode

Свойство subprocess.exitCode указывает код выхода дочернего процесса. Если дочерний процесс еще выполняется, поле будет null.

subprocess.kill([signal])

Добавлено в: v0.1.90

Метод subprocess.kill() отправляет сигнал дочернему процессу. Если аргумент не указан, процессу будет отправлен сигнал 'SIGTERM'. См. signal(7) для списка доступных сигналов. Эта функция возвращает true, если kill(2) выполнена успешно, и false в противном случае.

js
const { spawn } = require('node:child_process')
const grep = spawn('grep', ['ssh'])

grep.on('close', (code, signal) => {
  console.log(`дочерний процесс завершился из-за получения сигнала ${signal}`)
})

// Отправить сигнал SIGHUP процессу.
grep.kill('SIGHUP')
js
import { spawn } from 'node:child_process'
const grep = spawn('grep', ['ssh'])

grep.on('close', (code, signal) => {
  console.log(`дочерний процесс завершился из-за получения сигнала ${signal}`)
})

// Отправить сигнал SIGHUP процессу.
grep.kill('SIGHUP')

Объект ChildProcess может сгенерировать событие 'error', если сигнал не может быть доставлен. Отправка сигнала дочернему процессу, который уже завершился, не является ошибкой, но может иметь непредвиденные последствия. В частности, если идентификатор процесса (PID) был переназначен другому процессу, сигнал будет доставлен этому процессу, что может привести к неожиданным результатам.

Хотя функция называется kill, сигнал, доставленный дочернему процессу, может фактически не завершить процесс.

См. kill(2) для справки.

В Windows, где сигналы POSIX не существуют, аргумент signal будет игнорироваться, за исключением 'SIGKILL', 'SIGTERM', 'SIGINT' и 'SIGQUIT', и процесс всегда будет завершен принудительно и резко (аналогично 'SIGKILL'). См. События сигналов для получения более подробной информации.

В Linux дочерние процессы дочерних процессов не будут завершены при попытке завершить их родительский процесс. Это может произойти, когда запускается новый процесс в оболочке или с использованием параметра shell для ChildProcess:

js
const { spawn } = require('node:child_process')

const subprocess = spawn(
  'sh',
  [
    '-c',
    `node -e "setInterval(() => {
      console.log(process.pid, 'живет')
    }, 500);"`,
  ],
  {
    stdio: ['inherit', 'inherit', 'inherit'],
  }
)

setTimeout(() => {
  subprocess.kill() // Не завершает процесс Node.js в оболочке.
}, 2000)
js
import { spawn } from 'node:child_process'

const subprocess = spawn(
  'sh',
  [
    '-c',
    `node -e "setInterval(() => {
      console.log(process.pid, 'живет')
    }, 500);"`,
  ],
  {
    stdio: ['inherit', 'inherit', 'inherit'],
  }
)

setTimeout(() => {
  subprocess.kill() // Не завершает процесс Node.js в оболочке.
}, 2000)

subprocess[Symbol.dispose]()

Добавлено в: v20.5.0, v18.18.0

[Стабильность: 1 - Экспериментально]

Стабильность: 1 Стабильность: 1 - Экспериментально

Вызывает subprocess.kill() с 'SIGTERM'.

subprocess.killed

Добавлено в: v0.5.10

  • <boolean> Устанавливается в true после того, как subprocess.kill() успешно отправляет сигнал дочернему процессу.

Свойство subprocess.killed указывает, успешно ли дочерний процесс получил сигнал от subprocess.kill(). Свойство killed не указывает на то, что дочерний процесс был завершен.

subprocess.pid

Добавлено в: v0.1.90

Возвращает идентификатор процесса (PID) дочернего процесса. Если дочерний процесс не запускается из-за ошибок, то значение будет undefined и будет сгенерировано событие error.

js
const { spawn } = require('node:child_process')
const grep = spawn('grep', ['ssh'])

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

console.log(`Spawned child pid: ${grep.pid}`)
grep.stdin.end()

subprocess.ref()

Добавлено в: v0.7.10

Вызов subprocess.ref() после вызова subprocess.unref() восстановит удаленный счетчик ссылок для дочернего процесса, заставляя родительский процесс ждать завершения дочернего процесса, прежде чем завершиться самому.

js
const { spawn } = require('node:child_process')
const process = require('node:process')

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

subprocess.unref()
subprocess.ref()
js
import { spawn } from 'node:child_process'
import process from 'node:process'

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

subprocess.unref()
subprocess.ref()

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

[История]

ВерсияИзменения
v5.8.0Теперь поддерживаются параметр options и, в частности, опция keepOpen.
v5.0.0Теперь этот метод возвращает логическое значение для управления потоком.
v4.0.0Теперь поддерживается параметр callback.
v0.5.9Добавлено в: v0.5.9
  • message <Object>

  • sendHandle <Handle> | <undefined> undefined, или объект net.Socket, net.Server или dgram.Socket.

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

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

  • Возвращает: <boolean>

Когда между родительским и дочерним процессами установлен IPC-канал (т.е. при использовании child_process.fork()), метод subprocess.send() можно использовать для отправки сообщений дочернему процессу. Когда дочерний процесс является экземпляром Node.js, эти сообщения можно получить через событие 'message'.

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

Например, в родительском скрипте:

js
const { fork } = require('node:child_process')
const forkedProcess = fork(`${__dirname}/sub.js`)

forkedProcess.on('message', message => {
  console.log('PARENT got message:', message)
})

// Вызывает вывод дочерним процессом: CHILD got message: { hello: 'world' }
forkedProcess.send({ hello: 'world' })
js
import { fork } from 'node:child_process'
const forkedProcess = fork(`${import.meta.dirname}/sub.js`)

forkedProcess.on('message', message => {
  console.log('PARENT got message:', message)
})

// Вызывает вывод дочерним процессом: CHILD got message: { hello: 'world' }
forkedProcess.send({ hello: 'world' })

А затем дочерний скрипт, 'sub.js', может выглядеть так:

js
process.on('message', message => {
  console.log('CHILD got message:', message)
})

// Вызывает вывод родительским процессом: PARENT got message: { foo: 'bar', baz: null }
process.send({ foo: 'bar', baz: NaN })

Дочерние процессы Node.js будут иметь свой метод process.send(), который позволяет дочернему процессу отправлять сообщения обратно родительскому процессу.

Существует особый случай при отправке сообщения {cmd: 'NODE_foo'}. Сообщения, содержащие префикс NODE_ в свойстве cmd, зарезервированы для использования в ядре Node.js и не будут генерироваться в событии 'message' дочернего процесса. Скорее, такие сообщения генерируются с использованием события 'internalMessage' и потребляются внутри Node.js. Приложения должны избегать использования таких сообщений или прослушивания событий 'internalMessage', поскольку они могут быть изменены без предварительного уведомления.

Необязательный аргумент sendHandle, который может быть передан в subprocess.send(), предназначен для передачи TCP-сервера или сокетного объекта дочернему процессу. Дочерний процесс получит объект в качестве второго аргумента, переданного в функцию обратного вызова, зарегистрированную в событии 'message'. Любые данные, которые получены и буферизованы в сокете, не будут отправлены дочернему процессу. Отправка IPC-сокетов не поддерживается в Windows.

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

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

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

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

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

js
const { fork } = require('node:child_process')
const { createServer } = require('node:net')

const subprocess = fork('subprocess.js')

// Открываем объект сервера и отправляем дескриптор.
const server = createServer()
server.on('connection', socket => {
  socket.end('обработано родителем')
})
server.listen(1337, () => {
  subprocess.send('server', server)
})
js
import { fork } from 'node:child_process'
import { createServer } from 'node:net'

const subprocess = fork('subprocess.js')

// Открываем объект сервера и отправляем дескриптор.
const server = createServer()
server.on('connection', socket => {
  socket.end('обработано родителем')
})
server.listen(1337, () => {
  subprocess.send('server', server)
})

Дочерний процесс получит объект сервера следующим образом:

js
process.on('message', (m, server) => {
  if (m === 'server') {
    server.on('connection', socket => {
      socket.end('обработано дочерним')
    })
  }
})

После того, как сервер становится общим для родительского и дочернего процессов, некоторые соединения могут обрабатываться родительским, а некоторые — дочерним процессом.

В то время как в приведенном выше примере используется сервер, созданный с использованием модуля node:net, серверы модуля node:dgram используют точно такой же рабочий процесс, за исключением прослушивания события 'message' вместо 'connection' и использования server.bind() вместо server.listen(). Однако это поддерживается только на платформах Unix.

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

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

js
const { fork } = require('node:child_process')
const { createServer } = require('node:net')

const normal = fork('subprocess.js', ['normal'])
const special = fork('subprocess.js', ['special'])

// Открываем сервер и отправляем сокеты дочернему процессу. Используем pauseOnConnect, чтобы предотвратить
// чтение сокетов до их отправки в дочерний процесс.
const server = createServer({ pauseOnConnect: true })
server.on('connection', socket => {
  // Если это специальный приоритет...
  if (socket.remoteAddress === '74.125.127.100') {
    special.send('socket', socket)
    return
  }
  // Это обычный приоритет.
  normal.send('socket', socket)
})
server.listen(1337)
js
import { fork } from 'node:child_process'
import { createServer } from 'node:net'

const normal = fork('subprocess.js', ['normal'])
const special = fork('subprocess.js', ['special'])

// Открываем сервер и отправляем сокеты дочернему процессу. Используем pauseOnConnect, чтобы предотвратить
// чтение сокетов до их отправки в дочерний процесс.
const server = createServer({ pauseOnConnect: true })
server.on('connection', socket => {
  // Если это специальный приоритет...
  if (socket.remoteAddress === '74.125.127.100') {
    special.send('socket', socket)
    return
  }
  // Это обычный приоритет.
  normal.send('socket', socket)
})
server.listen(1337)

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

js
process.on('message', (m, socket) => {
  if (m === 'socket') {
    if (socket) {
      // Проверьте, что клиентский сокет существует.
      // Возможно, что сокет будет закрыт в промежутке времени между отправкой и получением в дочернем процессе.
      socket.end(`Запрос обработан с ${process.argv[2]} приоритетом`)
    }
  }
})

Не используйте .maxConnections на сокете, который был передан в подпроцесс. Родитель не может отслеживать, когда сокет уничтожается.

Любые обработчики 'message' в подпроцессе должны проверять, существует ли socket, поскольку соединение могло быть закрыто во время, необходимое для отправки соединения дочернему процессу.

subprocess.signalCode

Свойство subprocess.signalCode указывает на сигнал, полученный дочерним процессом, если таковой был, иначе null.

subprocess.spawnargs

Свойство subprocess.spawnargs представляет полный список аргументов командной строки, с которыми был запущен дочерний процесс.

subprocess.spawnfile

Свойство subprocess.spawnfile указывает имя исполняемого файла дочернего процесса, который запускается.

Для child_process.fork() его значение будет равно process.execPath. Для child_process.spawn() его значение будет именем исполняемого файла. Для child_process.exec() его значение будет именем оболочки, в которой запускается дочерний процесс.

subprocess.stderr

Добавлено в: v0.1.90

Readable Stream, представляющий stderr дочернего процесса.

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

subprocess.stderr является псевдонимом для subprocess.stdio[2]. Оба свойства будут ссылаться на одно и то же значение.

Свойство subprocess.stderr может быть null или undefined, если дочерний процесс не удалось успешно породить.

subprocess.stdin

Добавлено в: v0.1.90

Writable Stream, представляющий stdin дочернего процесса.

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

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

subprocess.stdin является псевдонимом для subprocess.stdio[0]. Оба свойства будут ссылаться на одно и то же значение.

Свойство subprocess.stdin может быть null или undefined, если дочерний процесс не удалось успешно запустить.

subprocess.stdio

Добавлено в: v0.7.10

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

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

js
const assert = require('node:assert')
const fs = require('node:fs')
const child_process = require('node:child_process')

const subprocess = child_process.spawn('ls', {
  stdio: [
    0, // Использовать stdin родительского процесса для дочернего.
    'pipe', // Направить stdout дочернего процесса в родительский.
    fs.openSync('err.out', 'w'), // Направить stderr дочернего процесса в файл.
  ],
})

assert.strictEqual(subprocess.stdio[0], null)
assert.strictEqual(subprocess.stdio[0], subprocess.stdin)

assert(subprocess.stdout)
assert.strictEqual(subprocess.stdio[1], subprocess.stdout)

assert.strictEqual(subprocess.stdio[2], null)
assert.strictEqual(subprocess.stdio[2], subprocess.stderr)
js
import assert from 'node:assert'
import fs from 'node:fs'
import child_process from 'node:child_process'

const subprocess = child_process.spawn('ls', {
  stdio: [
    0, // Использовать stdin родительского процесса для дочернего.
    'pipe', // Направить stdout дочернего процесса в родительский.
    fs.openSync('err.out', 'w'), // Направить stderr дочернего процесса в файл.
  ],
})

assert.strictEqual(subprocess.stdio[0], null)
assert.strictEqual(subprocess.stdio[0], subprocess.stdin)

assert(subprocess.stdout)
assert.strictEqual(subprocess.stdio[1], subprocess.stdout)

assert.strictEqual(subprocess.stdio[2], null)
assert.strictEqual(subprocess.stdio[2], subprocess.stderr)

Свойство subprocess.stdio может быть undefined, если дочерний процесс не удалось успешно запустить.

subprocess.stdout

Добавлено в: v0.1.90

Readable Stream, представляющий stdout дочернего процесса.

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

subprocess.stdout является псевдонимом для subprocess.stdio[1]. Оба свойства будут ссылаться на одно и то же значение.

js
const { spawn } = require('node:child_process')

const subprocess = spawn('ls')

subprocess.stdout.on('data', data => {
  console.log(`Получен фрагмент ${data}`)
})
js
import { spawn } from 'node:child_process'

const subprocess = spawn('ls')

subprocess.stdout.on('data', data => {
  console.log(`Получен фрагмент ${data}`)
})

Свойство subprocess.stdout может быть null или undefined, если дочерний процесс не удалось успешно запустить.

subprocess.unref()

Добавлено в: v0.7.10

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

js
const { spawn } = require('node:child_process')
const process = require('node:process')

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

subprocess.unref()
js
import { spawn } from 'node:child_process'
import process from 'node:process'

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

subprocess.unref()

maxBuffer и Unicode

Опция maxBuffer указывает наибольшее количество байтов, разрешенных в stdout или stderr. Если это значение превышено, то дочерний процесс завершается. Это влияет на вывод, который включает многобайтовые кодировки символов, такие как UTF-8 или UTF-16. Например, console.log('中文测试') отправит 13 байтов в кодировке UTF-8 в stdout, хотя там всего 4 символа.

Требования к оболочке

Оболочка должна понимать ключ -c. Если оболочка — 'cmd.exe', она должна понимать ключи /d /s /c, а также должна быть совместима с синтаксическим анализом командной строки.

Оболочка Windows по умолчанию

Хотя Microsoft указывает, что %COMSPEC% должен содержать путь к 'cmd.exe' в корневой среде, дочерние процессы не всегда подчиняются тому же требованию. Таким образом, в функциях child_process, где может быть запущен шелл, 'cmd.exe' используется в качестве резервного варианта, если process.env.ComSpec недоступен.

Расширенная сериализация

Добавлено в: v13.2.0, v12.16.0

Дочерние процессы поддерживают механизм сериализации для IPC, основанный на API сериализации модуля node:v8, основанном на алгоритме структурированного клонирования HTML. Обычно он более мощный и поддерживает больше встроенных типов объектов JavaScript, таких как BigInt, Map и Set, ArrayBuffer и TypedArray, Buffer, Error, RegExp и т. д.

Однако этот формат не является полным супермножеством JSON, и, например, свойства, установленные для объектов таких встроенных типов, не будут переданы через шаг сериализации. Кроме того, производительность может быть не эквивалентна производительности JSON в зависимости от структуры передаваемых данных. Поэтому для использования этой функции необходимо выбрать ее, установив для параметра serialization значение 'advanced' при вызове child_process.spawn() или child_process.fork().