Дочерний процесс
[Стабильно: 2 - Стабильно]
Стабильно: 2 Стабильность: 2 - Стабильно
Исходный код: lib/child_process.js
Модуль node:child_process
предоставляет возможность порождать подпроцессы способом, аналогичным, но не идентичным popen(3)
. Эта возможность в основном предоставляется функцией child_process.spawn()
:
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}`)
})
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()
). В любом случае, если имя файла скрипта содержит пробелы, его необходимо заключить в кавычки.
// ИЛИ...
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) => {
// ...
})
// ИЛИ...
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, обрабатывается непосредственно оболочкой, и специальные символы (различаются в зависимости от оболочки) необходимо обрабатывать соответственно:
const { exec } = require('node:child_process')
exec('"/path/to/test file/test.sh" arg1 arg2')
// Двойные кавычки используются для того, чтобы пробел в пути не интерпретировался как
// разделитель нескольких аргументов.
exec('echo "Переменная \\$HOME равна $HOME"')
// Переменная $HOME экранируется в первом случае, но не во втором.
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
.
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}`)
})
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
.
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()
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
:
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()
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()
. Поскольку оболочка не запускается, такие возможности, как перенаправление ввода-вывода и поиск файлов по шаблону, не поддерживаются.
const { execFile } = require('node:child_process')
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
if (error) {
throw error
}
console.log(stdout)
})
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
.
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()
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
:
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()
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()
'sstdio
. По умолчанию: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
:
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() // Останавливает дочерний процесс
}
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
, не передавайте несанированные пользовательские данные в эту функцию. Любые входные данные, содержащие метасимволы оболочки, могут использоваться для запуска произвольного выполнения команд.
Третий аргумент может быть использован для указания дополнительных параметров, со следующими значениями по умолчанию:
const defaults = {
cwd: undefined,
env: process.env,
}
Используйте cwd
, чтобы указать рабочий каталог, из которого запускается процесс. Если не указано, по умолчанию используется текущий рабочий каталог. Если указано, но путь не существует, дочерний процесс выдает ошибку ENOENT
и немедленно завершается. ENOENT
также выдается, когда команда не существует.
Используйте env
, чтобы указать переменные среды, которые будут видны новому процессу, по умолчанию это process.env
.
Значения undefined
в env
будут игнорироваться.
Пример запуска ls -lh /usr
, захвата stdout
, stderr
и кода выхода:
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}`)
})
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
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}`)
}
})
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
:
const { spawn } = require('node:child_process')
const subprocess = spawn('bad_command')
subprocess.on('error', err => {
console.error('Failed to start subprocess.')
})
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
:
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() // Останавливает дочерний процесс
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
родительского процесса, чтобы игнорировать завершение работы родительского процесса:
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()
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()
В качестве альтернативы можно перенаправить вывод дочернего процесса в файлы:
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()
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 для создания дополнительных каналов между родительским и дочерним процессами. Значение может быть одним из следующих:
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'] })
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()
'sstdio
.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
(без оболочки).
Метод child_process.execFileSync()
в основном идентичен child_process.execFile()
за исключением того, что метод не вернется, пока дочерний процесс полностью не закроется. Когда возникает тайм-аут и отправляется killSignal
, метод не вернется, пока процесс полностью не завершится.
Если дочерний процесс перехватывает и обрабатывает сигнал SIGTERM
и не выходит, родительский процесс все равно будет ждать, пока дочерний процесс не выйдет.
Если процесс истекает по тайм-ауту или имеет ненулевой код выхода, этот метод вызовет ошибку Error
, которая будет включать полный результат базового child_process.spawnSync()
.
Если включена опция shell
, не передавайте в эту функцию необработанный ввод пользователя. Любой ввод, содержащий метасимволы оболочки, может быть использован для запуска произвольного выполнения команд.
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 })
}
}
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()
'sstdio
.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
.
Метод 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()
'sstdio
. По умолчанию:'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
- Расширяет: <EventEmitter>
Экземпляры 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'
, если не удалось породить дочерний процесс.
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}`)
})
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'
err
<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
<Object> Разобранный JSON-объект или примитивное значение.sendHandle
<Handle> | <undefined>undefined
или объектnet.Socket
,net.Server
илиdgram.Socket
.
Событие '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
в противном случае.
const { spawn } = require('node:child_process')
const grep = spawn('grep', ['ssh'])
grep.on('close', (code, signal) => {
console.log(`дочерний процесс завершился из-за получения сигнала ${signal}`)
})
// Отправить сигнал SIGHUP процессу.
grep.kill('SIGHUP')
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
:
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)
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
.
const { spawn } = require('node:child_process')
const grep = spawn('grep', ['ssh'])
console.log(`Spawned child pid: ${grep.pid}`)
grep.stdin.end()
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()
восстановит удаленный счетчик ссылок для дочернего процесса, заставляя родительский процесс ждать завершения дочернего процесса, прежде чем завершиться самому.
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()
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'
.
Сообщение проходит через сериализацию и разбор. Полученное сообщение может отличаться от того, которое было отправлено изначально.
Например, в родительском скрипте:
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' })
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'
, может выглядеть так:
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-сервера дочернему процессу, как показано в примере ниже:
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)
})
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)
})
Дочерний процесс получит объект сервера следующим образом:
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
может быть использован для передачи дескриптора сокета дочернему процессу. В примере ниже создаются два дочерних процесса, каждый из которых обрабатывает соединения с "обычным" или "специальным" приоритетом:
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)
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
получит дескриптор сокета в качестве второго аргумента, переданного функции обратного вызова события:
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
.
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)
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]
. Оба свойства будут ссылаться на одно и то же значение.
const { spawn } = require('node:child_process')
const subprocess = spawn('ls')
subprocess.stdout.on('data', data => {
console.log(`Получен фрагмент ${data}`)
})
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.
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()
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()
.