Skip to content

Procesos secundarios

[Estable: 2 - Estable]

Estable: 2 Estabilidad: 2 - Estable

Código fuente: lib/child_process.js

El módulo node:child_process proporciona la capacidad de generar subprocesos de una manera similar, pero no idéntica, a popen(3). Esta capacidad se proporciona principalmente mediante la función 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(`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}`)
})

De forma predeterminada, se establecen tuberías para stdin, stdout y stderr entre el proceso principal de Node.js y el subproceso generado. Estas tuberías tienen una capacidad limitada (y específica de la plataforma). Si el subproceso escribe en stdout en exceso de ese límite sin que se capture la salida, el subproceso se bloquea esperando a que el búfer de la tubería acepte más datos. Esto es idéntico al comportamiento de las tuberías en el shell. Use la opción { stdio: 'ignore' } si la salida no se va a consumir.

La búsqueda del comando se realiza utilizando la variable de entorno options.env.PATH si env está en el objeto options. De lo contrario, se utiliza process.env.PATH. Si options.env se establece sin PATH, la búsqueda en Unix se realiza en una búsqueda de ruta de búsqueda predeterminada de /usr/bin:/bin (consulte el manual de su sistema operativo para execvpe/execvp), en Windows se utiliza la variable de entorno PATH de los procesos actuales.

En Windows, las variables de entorno no distinguen entre mayúsculas y minúsculas. Node.js ordena lexicográficamente las claves env y utiliza la primera que coincide sin distinción de mayúsculas y minúsculas. Solo la primera entrada (en orden lexicográfico) se pasará al subproceso. Esto puede provocar problemas en Windows al pasar objetos a la opción env que tienen varias variantes de la misma clave, como PATH y Path.

El método child_process.spawn() genera el proceso secundario de forma asíncrona, sin bloquear el bucle de eventos de Node.js. La función child_process.spawnSync() proporciona una funcionalidad equivalente de forma síncrona que bloquea el bucle de eventos hasta que el proceso generado sale o se termina.

Por conveniencia, el módulo node:child_process proporciona un puñado de alternativas sincrónicas y asíncronas a child_process.spawn() y child_process.spawnSync(). Cada una de estas alternativas se implementa sobre child_process.spawn() o child_process.spawnSync().

Para ciertos casos de uso, como la automatización de scripts de shell, las contrapartes sincrónicas pueden ser más convenientes. Sin embargo, en muchos casos, los métodos sincrónicos pueden tener un impacto significativo en el rendimiento debido a la detención del bucle de eventos mientras se completan los procesos generados.

Creación de procesos asíncronos

Los métodos child_process.spawn(), child_process.fork(), child_process.exec(), y child_process.execFile() siguen el patrón de programación asíncrona idiomático típico de otras APIs de Node.js.

Cada uno de los métodos devuelve una instancia ChildProcess. Estos objetos implementan la API EventEmitter de Node.js, permitiendo que el proceso padre registre funciones de escucha que se llaman cuando ocurren ciertos eventos durante el ciclo de vida del proceso hijo.

Los métodos child_process.exec() y child_process.execFile() además permiten que se especifique una función callback opcional que se invoca cuando el proceso hijo termina.

Ejecutando archivos .bat y .cmd en Windows

La importancia de la distinción entre child_process.exec() y child_process.execFile() puede variar según la plataforma. En sistemas operativos de tipo Unix (Unix, Linux, macOS), child_process.execFile() puede ser más eficiente porque no genera un shell de forma predeterminada. Sin embargo, en Windows, los archivos .bat y .cmd no son ejecutables por sí mismos sin una terminal, y por lo tanto no se pueden iniciar usando child_process.execFile(). Al ejecutarse en Windows, los archivos .bat y .cmd se pueden invocar usando child_process.spawn() con la opción shell establecida, con child_process.exec(), o generando cmd.exe y pasando el archivo .bat o .cmd como argumento (que es lo que hace la opción shell y child_process.exec()). En cualquier caso, si el nombre del archivo de script contiene espacios, debe ir entre comillas.

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

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

// Script con espacios en el nombre del archivo:
const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true })
// o:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
  // ...
})
js
// O...
import { exec, spawn } from 'node:child_process'

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

// Script con espacios en el nombre del archivo:
const bat = spawn('"my script.cmd"', ['a', 'b'], { shell: true })
// o:
exec('"my script.cmd" a b', (err, stdout, stderr) => {
  // ...
})

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

[Historial]

VersiónCambios
v15.4.0Se agregó soporte para AbortSignal.
v16.4.0, v14.18.0La opción cwd puede ser un objeto URL de WHATWG usando el protocolo file:.
v8.8.0Ahora se admite la opción windowsHide.
v0.1.90Añadido en: v0.1.90

Genera un shell y luego ejecuta el comando dentro de ese shell, almacenando en búfer cualquier salida generada. La cadena comando pasada a la función exec se procesa directamente por el shell y los caracteres especiales (varían según el shell) deben tratarse en consecuencia:

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

exec('"/path/to/test file/test.sh" arg1 arg2')
// Se utilizan comillas dobles para que el espacio en la ruta no se interprete como
// un delimitador de múltiples argumentos.

exec('echo "The \\$HOME variable is $HOME"')
// La variable $HOME está escapada en la primera instancia, pero no en la segunda.
js
import { exec } from 'node:child_process'

exec('"/path/to/test file/test.sh" arg1 arg2')
// Se utilizan comillas dobles para que el espacio en la ruta no se interprete como
// un delimitador de múltiples argumentos.

exec('echo "The \\$HOME variable is $HOME"')
// La variable $HOME está escapada en la primera instancia, pero no en la segunda.

Nunca pase entrada de usuario no sanitizada a esta función. Cualquier entrada que contenga metacaracteres de shell puede usarse para activar la ejecución de comandos arbitrarios.

Si se proporciona una función callback, se llama con los argumentos (error, stdout, stderr). Si tiene éxito, error será null. Si hay un error, error será una instancia de Error. La propiedad error.code será el código de salida del proceso. Por convención, cualquier código de salida que no sea 0 indica un error. error.signal será la señal que terminó el proceso.

Los argumentos stdout y stderr pasados al callback contendrán la salida stdout y stderr del proceso secundario. De forma predeterminada, Node.js decodificará la salida como UTF-8 y pasará cadenas al callback. La opción encoding se puede usar para especificar la codificación de caracteres utilizada para decodificar la salida stdout y stderr. Si encoding es 'buffer', o una codificación de caracteres no reconocida, se pasarán objetos Buffer al callback en su lugar.

js
const { exec } = require('node:child_process')
exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec 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(`exec error: ${error}`)
    return
  }
  console.log(`stdout: ${stdout}`)
  console.error(`stderr: ${stderr}`)
})

Si timeout es mayor que 0, el proceso principal enviará la señal identificada por la propiedad killSignal (el valor predeterminado es 'SIGTERM') si el proceso secundario se ejecuta durante más de timeout milisegundos.

A diferencia de la llamada al sistema POSIX exec(3), child_process.exec() no reemplaza el proceso existente y usa un shell para ejecutar el comando.

Si este método se invoca como su versión util.promisify(), devuelve una Promise para un Object con las propiedades stdout y stderr. La instancia ChildProcess devuelta se adjunta a la Promise como una propiedad child. En caso de error (incluido cualquier error que resulte en un código de salida que no sea 0), se devuelve una promesa rechazada, con el mismo objeto error dado en el callback, pero con dos propiedades adicionales stdout y 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()

Si la opción signal está habilitada, llamar a .abort() en el AbortController correspondiente es similar a llamar a .kill() en el proceso secundario, excepto que el error pasado al callback será un 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) // un 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) // un AbortError
})
controller.abort()

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

[Historial]

VersiónCambios
v16.4.0, v14.18.0La opción cwd puede ser un objeto URL WHATWG usando el protocolo file:.
v15.4.0, v14.17.0Se agregó soporte para AbortSignal.
v8.8.0Ahora se admite la opción windowsHide.
v0.1.91Añadido en: v0.1.91
  • file <string> El nombre o la ruta del archivo ejecutable que se va a ejecutar.

  • args <string[]> Lista de argumentos de cadena.

  • options <Object>

    • cwd <string> | <URL> Directorio de trabajo actual del proceso hijo.
    • env <Object> Pares clave-valor del entorno. Predeterminado: process.env.
    • encoding <string> Predeterminado: 'utf8'
    • timeout <number> Predeterminado: 0
    • maxBuffer <number> Cantidad máxima de datos en bytes permitidos en stdout o stderr. Si se excede, el proceso hijo se termina y cualquier salida se trunca. Consulte la advertencia en maxBuffer y Unicode. Predeterminado: 1024 * 1024.
    • killSignal <string> | <integer> Predeterminado: 'SIGTERM'
    • uid <number> Establece la identidad de usuario del proceso (ver setuid(2)).
    • gid <number> Establece la identidad de grupo del proceso (ver setgid(2)).
    • windowsHide <boolean> Oculta la ventana de consola del subproceso que normalmente se crearía en sistemas Windows. Predeterminado: false.
    • windowsVerbatimArguments <boolean> No se realiza ninguna comilla ni escape de argumentos en Windows. Se ignora en Unix. Predeterminado: false.
    • shell <boolean> | <string> Si es true, ejecuta command dentro de un shell. Usa '/bin/sh' en Unix y process.env.ComSpec en Windows. Se puede especificar un shell diferente como una cadena. Ver Requisitos del shell y Shell predeterminado de Windows. Predeterminado: false (sin shell).
    • signal <AbortSignal> permite abortar el proceso hijo usando un AbortSignal.
  • callback <Function> Se llama con la salida cuando el proceso termina.

  • Devuelve: <ChildProcess>

La función child_process.execFile() es similar a child_process.exec() excepto que no genera un shell de forma predeterminada. Más bien, el archivo ejecutable file especificado se genera directamente como un nuevo proceso, lo que lo hace ligeramente más eficiente que child_process.exec().

Se admiten las mismas opciones que child_process.exec(). Dado que no se genera un shell, no se admiten comportamientos como la redirección de E/S y la expansión de archivos.

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

Los argumentos stdout y stderr pasados al callback contendrán la salida stdout y stderr del proceso hijo. De forma predeterminada, Node.js decodificará la salida como UTF-8 y pasará cadenas al callback. La opción encoding se puede usar para especificar la codificación de caracteres utilizada para decodificar la salida stdout y stderr. Si encoding es 'buffer', o una codificación de caracteres no reconocida, se pasarán objetos Buffer al callback en su lugar.

Si este método se invoca como su versión util.promisify(), devuelve una Promise para un Object con las propiedades stdout y stderr. La instancia ChildProcess devuelta se adjunta a la Promise como una propiedad child. En caso de error (incluido cualquier error que resulte en un código de salida que no sea 0), se devuelve una promesa rechazada, con el mismo objeto error dado en el callback, pero con dos propiedades adicionales stdout y 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()

Si la opción shell está habilitada, no pase entrada de usuario no desinfectada a esta función. Cualquier entrada que contenga metacaracteres de shell puede usarse para activar la ejecución de comandos arbitrarios.

Si la opción signal está habilitada, llamar a .abort() en el AbortController correspondiente es similar a llamar a .kill() en el proceso hijo, excepto que el error pasado al callback será un 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) // un 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) // un AbortError
})
controller.abort()

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

[Historial]

VersiónCambios
v17.4.0, v16.14.0El parámetro modulePath puede ser un objeto URL WHATWG usando el protocolo file:
v16.4.0, v14.18.0La opción cwd puede ser un objeto URL WHATWG usando el protocolo file:
v15.13.0, v14.18.0Se agregó timeout.
v15.11.0, v14.18.0Se agregó killSignal para AbortSignal.
v15.6.0, v14.17.0Se agregó soporte para AbortSignal.
v13.2.0, v12.16.0Ahora se admite la opción serialization.
v8.0.0La opción stdio ahora puede ser una cadena.
v6.4.0Ahora se admite la opción stdio.
v0.5.0Añadido en: v0.5.0
  • modulePath <string> | <URL> El módulo que se ejecutará en el proceso secundario.

  • args <string[]> Lista de argumentos de cadena.

  • options <Object>

    • cwd <string> | <URL> Directorio de trabajo actual del proceso secundario.
    • detached <boolean> Prepara el proceso secundario para que se ejecute independientemente de su proceso principal. El comportamiento específico depende de la plataforma, consulte options.detached).
    • env <Object> Pares clave-valor del entorno. Predeterminado: process.env.
    • execPath <string> Ejecutable utilizado para crear el proceso secundario.
    • execArgv <string[]> Lista de argumentos de cadena pasados al ejecutable. Predeterminado: process.execArgv.
    • gid <number> Establece la identidad de grupo del proceso (consulte setgid(2)).
    • serialization <string> Especifica el tipo de serialización utilizada para enviar mensajes entre procesos. Los valores posibles son 'json' y 'advanced'. Consulte Serialización avanzada para obtener más detalles. Predeterminado: 'json'.
    • signal <AbortSignal> Permite cerrar el proceso secundario usando un AbortSignal.
    • killSignal <string> | <integer> El valor de la señal que se utilizará cuando el proceso generado sea eliminado por tiempo de espera o señal de aborto. Predeterminado: 'SIGTERM'.
    • silent <boolean> Si es true, stdin, stdout y stderr del proceso secundario se canalizarán al proceso principal; de lo contrario, se heredarán del proceso principal, consulte las opciones 'pipe' e 'inherit' para child_process.spawn()'s stdio para obtener más detalles. Predeterminado: false.
    • stdio <Array> | <string> Consulte child_process.spawn()'s stdio. Cuando se proporciona esta opción, anula silent. Si se utiliza la variante de matriz, debe contener exactamente un elemento con el valor 'ipc' o se lanzará un error. Por ejemplo [0, 1, 2, 'ipc'].
    • uid <number> Establece la identidad de usuario del proceso (consulte setuid(2)).
    • windowsVerbatimArguments <boolean> No se realiza ninguna comilla ni escape de argumentos en Windows. Se ignora en Unix. Predeterminado: false.
    • timeout <number> En milisegundos, la cantidad máxima de tiempo que se permite que se ejecute el proceso. Predeterminado: undefined.
  • Devuelve: <ChildProcess>

El método child_process.fork() es un caso especial de child_process.spawn() utilizado específicamente para generar nuevos procesos de Node.js. Al igual que child_process.spawn(), se devuelve un objeto ChildProcess. El ChildProcess devuelto tendrá un canal de comunicación adicional integrado que permite que los mensajes se pasen de un lado a otro entre el padre e hijo. Consulte subprocess.send() para obtener más detalles.

Tenga en cuenta que los procesos secundarios de Node.js generados son independientes del principal, con la excepción del canal de comunicación IPC que se establece entre los dos. Cada proceso tiene su propia memoria, con sus propias instancias de V8. Debido a las asignaciones de recursos adicionales necesarias, no se recomienda generar una gran cantidad de procesos secundarios de Node.js.

De forma predeterminada, child_process.fork() generará nuevas instancias de Node.js utilizando process.execPath del proceso principal. La propiedad execPath en el objeto options permite el uso de una ruta de ejecución alternativa.

Los procesos Node.js iniciados con un execPath personalizado se comunicarán con el proceso principal utilizando el descriptor de archivo (fd) identificado mediante la variable de entorno NODE_CHANNEL_FD en el proceso secundario.

A diferencia de la llamada al sistema POSIX fork(2), child_process.fork() no clona el proceso actual.

La opción shell disponible en child_process.spawn() no es compatible con child_process.fork() y se ignorará si está configurada.

Si la opción signal está habilitada, llamar a .abort() en el AbortController correspondiente es similar a llamar a .kill() en el proceso secundario, excepto que el error pasado a la devolución de llamada será un AbortError:

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

if (process.argv[2] === 'child') {
  setTimeout(() => {
    console.log(`Hello from ${process.argv[2]}!`)
  }, 1_000)
} else {
  const controller = new AbortController()
  const { signal } = controller
  const child = fork(__filename, ['child'], { signal })
  child.on('error', err => {
    // Esto se llamará con err siendo un AbortError si el controlador aborta
  })
  controller.abort() // Detiene el proceso secundario
}
js
import { fork } from 'node:child_process'
import process from 'node:process'

if (process.argv[2] === 'child') {
  setTimeout(() => {
    console.log(`Hello from ${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 => {
    // Esto se llamará con err siendo un AbortError si el controlador aborta
  })
  controller.abort() // Detiene el proceso secundario
}

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

[Historial]

VersiónCambios
v16.4.0, v14.18.0La opción cwd puede ser un objeto URL WHATWG usando el protocolo file:
v15.13.0, v14.18.0Se agregó el tiempo de espera (timeout).
v15.11.0, v14.18.0Se agregó killSignal para AbortSignal.
v15.5.0, v14.17.0Se agregó soporte para AbortSignal.
v13.2.0, v12.16.0Ahora se admite la opción serialization.
v8.8.0Ahora se admite la opción windowsHide.
v6.4.0Ahora se admite la opción argv0.
v5.7.0Ahora se admite la opción shell.
v0.1.90Añadido en: v0.1.90
  • command <string> El comando a ejecutar.

  • args <string[]> Lista de argumentos de cadena.

  • options <Object>

    • cwd <string> | <URL> Directorio de trabajo actual del proceso secundario.
    • env <Object> Pares clave-valor del entorno. Predeterminado: process.env.
    • argv0 <string> Establece explícitamente el valor de argv[0] enviado al proceso secundario. Se establecerá en command si no se especifica.
    • stdio <Array> | <string> Configuración de stdio del proceso secundario (ver options.stdio).
    • detached <boolean> Prepara el proceso secundario para que se ejecute independientemente de su proceso principal. El comportamiento específico depende de la plataforma, consulte options.detached).
    • uid <number> Establece la identidad de usuario del proceso (ver setuid(2)).
    • gid <number> Establece la identidad de grupo del proceso (ver setgid(2)).
    • serialization <string> Especifica el tipo de serialización utilizada para enviar mensajes entre procesos. Los valores posibles son 'json' y 'advanced'. Consulte Serialización avanzada para obtener más detalles. Predeterminado: 'json'.
    • shell <boolean> | <string> Si es true, ejecuta command dentro de un shell. Utiliza '/bin/sh' en Unix y process.env.ComSpec en Windows. Se puede especificar un shell diferente como una cadena. Consulte Requisitos del shell y Shell predeterminado de Windows. Predeterminado: false (sin shell).
    • windowsVerbatimArguments <boolean> No se realiza ninguna comilla ni escape de argumentos en Windows. Se ignora en Unix. Esto se establece en true automáticamente cuando se especifica shell y es CMD. Predeterminado: false.
    • windowsHide <boolean> Oculta la ventana de consola del subproceso que normalmente se crearía en sistemas Windows. Predeterminado: false.
    • signal <AbortSignal> permite abortar el proceso secundario usando un AbortSignal.
    • timeout <number> En milisegundos, la cantidad máxima de tiempo que se permite que se ejecute el proceso. Predeterminado: undefined.
    • killSignal <string> | <integer> El valor de señal que se utilizará cuando el proceso generado se elimine por tiempo de espera o señal de aborto. Predeterminado: 'SIGTERM'.
  • Devuelve: <ChildProcess>

El método child_process.spawn() genera un nuevo proceso usando el command dado, con argumentos de línea de comandos en args. Si se omite, args se establece de forma predeterminada en una matriz vacía.

Si la opción shell está habilitada, no pase entrada de usuario no desinfectada a esta función. Cualquier entrada que contenga metacaracteres de shell puede utilizarse para desencadenar la ejecución de comandos arbitrarios.

Se puede utilizar un tercer argumento para especificar opciones adicionales, con estos valores predeterminados:

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

Utilice cwd para especificar el directorio de trabajo desde el que se genera el proceso. Si no se proporciona, el valor predeterminado es heredar el directorio de trabajo actual. Si se proporciona, pero la ruta no existe, el proceso secundario emite un error ENOENT y sale inmediatamente. ENOENT también se emite cuando el comando no existe.

Utilice env para especificar las variables de entorno que estarán visibles para el nuevo proceso; el valor predeterminado es process.env.

Los valores undefined en env se ignorarán.

Ejemplo de ejecución de ls -lh /usr, capturando stdout, stderr y el código de salida:

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

Ejemplo: Una forma muy elaborada de ejecutar 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}`)
  }
})

Ejemplo de comprobación de spawn fallido:

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.')
})

Ciertas plataformas (macOS, Linux) utilizarán el valor de argv[0] para el título del proceso, mientras que otras (Windows, SunOS) utilizarán command.

Node.js sobrescribe argv[0] con process.execPath al inicio, por lo que process.argv[0] en un proceso secundario de Node.js no coincidirá con el parámetro argv0 pasado a spawn desde el proceso principal. Recupérelo con la propiedad process.argv0 en su lugar.

Si la opción signal está habilitada, llamar a .abort() en el AbortController correspondiente es similar a llamar a .kill() en el proceso secundario, excepto que el error pasado a la devolución de llamada será un 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 => {
  // Esto se llamará con err siendo un AbortError si el controlador aborta
})
controller.abort() // Detiene el proceso secundario
js
import { spawn } from 'node:child_process'
const controller = new AbortController()
const { signal } = controller
const grep = spawn('grep', ['ssh'], { signal })
grep.on('error', err => {
  // Esto se llamará con err siendo un AbortError si el controlador aborta
})
controller.abort() // Detiene el proceso secundario

options.detached

Añadido en: v0.7.10

En Windows, establecer options.detached en true permite que el proceso hijo continúe ejecutándose después de que el padre finalice. El proceso hijo tendrá su propia ventana de consola. Una vez habilitado para un proceso hijo, no se puede deshabilitar.

En plataformas que no son Windows, si options.detached se establece en true, el proceso hijo se convertirá en el líder de un nuevo grupo de procesos y sesión. Los procesos hijos pueden continuar ejecutándose después de que el padre finalice, independientemente de si están separados o no. Consulte setsid(2) para obtener más información.

De forma predeterminada, el padre esperará a que el proceso hijo separado finalice. Para evitar que el proceso padre espere a que un subprocess dado finalice, utilice el método subprocess.unref(). Al hacerlo, se hará que el bucle de eventos del proceso padre no incluya el proceso hijo en su recuento de referencias, permitiendo que el proceso padre finalice independientemente del proceso hijo, a menos que exista un canal IPC establecido entre los procesos hijo y padre.

Cuando se utiliza la opción detached para iniciar un proceso de larga duración, el proceso no permanecerá ejecutándose en segundo plano después de que el padre finalice a menos que se le proporcione una configuración stdio que no esté conectada al padre. Si se hereda el stdio del proceso padre, el proceso hijo permanecerá conectado a la terminal de control.

Ejemplo de un proceso de larga duración, separándolo e ignorando también los descriptores de archivo stdio de su padre, para ignorar la terminación del padre:

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()

Alternativamente, se puede redirigir la salida del proceso hijo a archivos:

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

[Historial]

VersiónCambios
v15.6.0, v14.18.0Se agregó la bandera overlapped de stdio.
v3.3.1Ahora se acepta el valor 0 como descriptor de archivo.
v0.7.10Añadido en: v0.7.10

La opción options.stdio se utiliza para configurar las tuberías que se establecen entre el proceso principal y el proceso secundario. De forma predeterminada, la entrada estándar (stdin), la salida estándar (stdout) y la salida de error estándar (stderr) del secundario se redirigen a las secuencias correspondientes subprocess.stdin, subprocess.stdout y subprocess.stderr en el objeto ChildProcess. Esto es equivalente a establecer options.stdio igual a ['pipe', 'pipe', 'pipe'].

Para mayor comodidad, options.stdio puede ser una de las siguientes cadenas:

  • 'pipe': equivalente a ['pipe', 'pipe', 'pipe'] (el valor predeterminado)
  • 'overlapped': equivalente a ['overlapped', 'overlapped', 'overlapped']
  • 'ignore': equivalente a ['ignore', 'ignore', 'ignore']
  • 'inherit': equivalente a ['inherit', 'inherit', 'inherit'] o [0, 1, 2]

De lo contrario, el valor de options.stdio es una matriz donde cada índice corresponde a un fd en el secundario. Los fd 0, 1 y 2 corresponden a stdin, stdout y stderr, respectivamente. Se pueden especificar fd adicionales para crear tuberías adicionales entre el proceso principal y el secundario. El valor es uno de los siguientes:

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

// El secundario utilizará las stdios del principal.
spawn('prg', [], { stdio: 'inherit' })

// Generar secundario compartiendo solo stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] })

// Abrir un fd=4 adicional, para interactuar con programas que presentan una
// interfaz de estilo startd.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] })
js
import { spawn } from 'node:child_process'
import process from 'node:process'

// El secundario utilizará las stdios del principal.
spawn('prg', [], { stdio: 'inherit' })

// Generar secundario compartiendo solo stderr.
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] })

// Abrir un fd=4 adicional, para interactuar con programas que presentan una
// interfaz de estilo startd.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] })

Cabe destacar que cuando se establece un canal IPC entre los procesos principal y secundario, y el proceso secundario es una instancia de Node.js, el proceso secundario se inicia con el canal IPC sin referencia (utilizando unref()) hasta que el proceso secundario registra un controlador de eventos para el evento 'disconnect' o el evento 'message'. Esto permite que el proceso secundario salga normalmente sin que el proceso se mantenga abierto por el canal IPC abierto. Ver también: child_process.exec() y child_process.fork().

Creación de procesos sincrónicos

Los métodos child_process.spawnSync(), child_process.execSync() y child_process.execFileSync() son sincrónicos y bloquearán el bucle de eventos de Node.js, pausando la ejecución de cualquier código adicional hasta que el proceso generado termine.

Las llamadas de bloqueo como estas son principalmente útiles para simplificar las tareas de scripting de propósito general y para simplificar la carga/procesamiento de la configuración de la aplicación al inicio.

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

[Historial]

VersiónCambios
v16.4.0, v14.18.0La opción cwd puede ser un objeto URL WHATWG usando el protocolo file:
v10.10.0La opción input ahora puede ser cualquier TypedArray o un DataView.
v8.8.0La opción windowsHide ahora es compatible.
v8.0.0La opción input ahora puede ser un Uint8Array.
v6.2.1, v4.5.0La opción encoding ahora puede establecerse explícitamente en buffer.
v0.11.12Añadido en: v0.11.12
  • file <string> El nombre o la ruta del archivo ejecutable que se va a ejecutar.

  • args <string[]> Lista de argumentos de cadena.

  • options <Object>

    • cwd <string> | <URL> Directorio de trabajo actual del proceso hijo.
    • input <string> | <Buffer> | <TypedArray> | <DataView> El valor que se pasará como stdin al proceso generado. Si stdio[0] se establece en 'pipe', proporcionar este valor anulará stdio[0].
    • stdio <string> | <Array> Configuración de stdio del hijo. Ver child_process.spawn() stdio. stderr por defecto se mostrará en el stderr del proceso padre a menos que se especifique stdio. Predeterminado: 'pipe'.
    • env <Object> Pares clave-valor del entorno. Predeterminado: process.env.
    • uid <number> Establece la identidad de usuario del proceso (ver setuid(2)).
    • gid <number> Establece la identidad de grupo del proceso (ver setgid(2)).
    • timeout <number> En milisegundos, la cantidad máxima de tiempo que se permite que el proceso se ejecute. Predeterminado: undefined.
    • killSignal <string> | <integer> El valor de la señal que se utilizará cuando se elimine el proceso generado. Predeterminado: 'SIGTERM'.
    • maxBuffer <number> Cantidad máxima de datos en bytes permitidos en stdout o stderr. Si se excede, el proceso hijo se termina. Ver advertencia en maxBuffer y Unicode. Predeterminado: 1024 * 1024.
    • encoding <string> La codificación utilizada para todas las entradas y salidas de stdio. Predeterminado: 'buffer'.
    • windowsHide <boolean> Oculta la ventana de consola del subproceso que normalmente se crearía en sistemas Windows. Predeterminado: false.
    • shell <boolean> | <string> Si es true, ejecuta command dentro de un shell. Usa '/bin/sh' en Unix y process.env.ComSpec en Windows. Se puede especificar un shell diferente como una cadena. Ver Requisitos del shell y Shell predeterminado de Windows. Predeterminado: false (sin shell).
  • Devuelve: <Buffer> | <string> El stdout del comando.

El método child_process.execFileSync() es generalmente idéntico a child_process.execFile() con la excepción de que el método no devolverá nada hasta que el proceso hijo se haya cerrado completamente. Cuando se ha encontrado un tiempo de espera y se envía killSignal, el método no devolverá nada hasta que el proceso haya salido completamente.

Si el proceso hijo intercepta y maneja la señal SIGTERM y no sale, el proceso padre seguirá esperando hasta que el proceso hijo haya salido.

Si el proceso se agota el tiempo o tiene un código de salida distinto de cero, este método lanzará un Error que incluirá el resultado completo del subyacente child_process.spawnSync().

Si la opción shell está habilitada, no pase entrada de usuario no sanitizada a esta función. Cualquier entrada que contenga metacaracteres de shell puede usarse para activar la ejecución de comandos arbitrarios.

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

try {
  const stdout = execFileSync('my-script.sh', ['my-arg'], {
    // Capturar stdout y stderr del proceso hijo. Anula el
    // comportamiento predeterminado de transmitir el stderr del hijo al stderr del padre
    stdio: 'pipe',

    // Usar codificación utf8 para tuberías stdio
    encoding: 'utf8',
  })

  console.log(stdout)
} catch (err) {
  if (err.code) {
    // Falló la generación del proceso hijo
    console.error(err.code)
  } else {
    // El hijo fue generado pero salió con un código de salida distinto de cero
    // El error contiene cualquier stdout y stderr del hijo
    const { stdout, stderr } = err

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

try {
  const stdout = execFileSync('my-script.sh', ['my-arg'], {
    // Capturar stdout y stderr del proceso hijo. Anula el
    // comportamiento predeterminado de transmitir el stderr del hijo al stderr del padre
    stdio: 'pipe',

    // Usar codificación utf8 para tuberías stdio
    encoding: 'utf8',
  })

  console.log(stdout)
} catch (err) {
  if (err.code) {
    // Falló la generación del proceso hijo
    console.error(err.code)
  } else {
    // El hijo fue generado pero salió con un código de salida distinto de cero
    // El error contiene cualquier stdout y stderr del hijo
    const { stdout, stderr } = err

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

child_process.execSync(command[, options])

[Historial]

VersiónCambios
v16.4.0, v14.18.0La opción cwd puede ser un objeto URL WHATWG usando el protocolo file:
v10.10.0La opción input ahora puede ser cualquier TypedArray o un DataView.
v8.8.0La opción windowsHide ahora es compatible.
v8.0.0La opción input ahora puede ser un Uint8Array.
v0.11.12Añadido en: v0.11.12
  • command <string> El comando a ejecutar.

  • options <Object>

    • cwd <string> | <URL> Directorio de trabajo actual del proceso hijo.
    • input <string> | <Buffer> | <TypedArray> | <DataView> El valor que se pasará como stdin al proceso generado. Si stdio[0] se establece en 'pipe', proporcionar este valor anulará stdio[0].
    • stdio <string> | <Array> Configuración stdio del hijo. Consulte la configuración stdio de child_process.spawn(). stderr por defecto se mostrará en el stderr del proceso padre a menos que se especifique stdio. Predeterminado: 'pipe'.
    • env <Object> Pares clave-valor del entorno. Predeterminado: process.env.
    • shell <string> Shell para ejecutar el comando. Consulte Requisitos del shell y Shell predeterminado de Windows. Predeterminado: '/bin/sh' en Unix, process.env.ComSpec en Windows.
    • uid <number> Establece la identidad de usuario del proceso. (Ver setuid(2)).
    • gid <number> Establece la identidad de grupo del proceso. (Ver setgid(2)).
    • timeout <number> En milisegundos, la cantidad máxima de tiempo que se permite que el proceso se ejecute. Predeterminado: undefined.
    • killSignal <string> | <integer> El valor de señal que se utilizará cuando se elimine el proceso generado. Predeterminado: 'SIGTERM'.
    • maxBuffer <number> La mayor cantidad de datos en bytes permitidos en stdout o stderr. Si se excede, el proceso hijo se termina y cualquier salida se trunca. Consulte la advertencia en maxBuffer y Unicode. Predeterminado: 1024 * 1024.
    • encoding <string> La codificación utilizada para todas las entradas y salidas de stdio. Predeterminado: 'buffer'.
    • windowsHide <boolean> Oculta la ventana de consola de subprocesos que normalmente se crearía en sistemas Windows. Predeterminado: false.
  • Devuelve: <Buffer> | <string> El stdout del comando.

El método child_process.execSync() es generalmente idéntico a child_process.exec() con la excepción de que el método no devolverá nada hasta que el proceso hijo se haya cerrado completamente. Cuando se ha encontrado un tiempo de espera y se envía killSignal, el método no devolverá nada hasta que el proceso haya salido completamente. Si el proceso hijo intercepta y maneja la señal SIGTERM y no sale, el proceso principal esperará hasta que el proceso hijo haya salido.

Si el proceso se agota el tiempo o tiene un código de salida distinto de cero, este método lanzará una excepción. El objeto Error contendrá todo el resultado de child_process.spawnSync().

Nunca pase entrada de usuario no desinfectada a esta función. Cualquier entrada que contenga metacaracteres de shell puede usarse para activar la ejecución de comandos arbitrarios.

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

[Historial]

VersiónCambios
v16.4.0, v14.18.0La opción cwd puede ser un objeto URL WHATWG usando el protocolo file:
v10.10.0La opción input ahora puede ser cualquier TypedArray o un DataView.
v8.8.0La opción windowsHide ahora es compatible.
v8.0.0La opción input ahora puede ser un Uint8Array.
v5.7.0La opción shell ahora es compatible.
v6.2.1, v4.5.0La opción encoding ahora se puede establecer explícitamente en buffer.
v0.11.12Añadido en: v0.11.12
  • command <string> El comando a ejecutar.

  • args <string[]> Lista de argumentos de cadena.

  • options <Object>

    • cwd <string> | <URL> Directorio de trabajo actual del proceso hijo.
    • input <string> | <Buffer> | <TypedArray> | <DataView> El valor que se pasará como stdin al proceso generado. Si stdio[0] está configurado en 'pipe', proporcionar este valor anulará stdio[0].
    • argv0 <string> Establece explícitamente el valor de argv[0] enviado al proceso hijo. Se establecerá en command si no se especifica.
    • stdio <string> | <Array> Configuración de stdio del hijo. Consulte la configuración stdio de child_process.spawn(). Predeterminado: 'pipe'.
    • env <Object> Pares clave-valor del entorno. Predeterminado: process.env.
    • uid <number> Establece la identidad de usuario del proceso (ver setuid(2)).
    • gid <number> Establece la identidad de grupo del proceso (ver setgid(2)).
    • timeout <number> En milisegundos, la cantidad máxima de tiempo que se permite que el proceso se ejecute. Predeterminado: undefined.
    • killSignal <string> | <integer> El valor de señal que se utilizará cuando se elimine el proceso generado. Predeterminado: 'SIGTERM'.
    • maxBuffer <number> Cantidad máxima de datos en bytes permitidos en stdout o stderr. Si se excede, el proceso hijo se termina y cualquier salida se trunca. Consulte la advertencia en maxBuffer y Unicode. Predeterminado: 1024 * 1024.
    • encoding <string> La codificación utilizada para todas las entradas y salidas de stdio. Predeterminado: 'buffer'.
    • shell <boolean> | <string> Si es true, ejecuta command dentro de un shell. Usa '/bin/sh' en Unix y process.env.ComSpec en Windows. Se puede especificar un shell diferente como una cadena. Consulte los Requisitos del shell y el Shell predeterminado de Windows. Predeterminado: false (sin shell).
    • windowsVerbatimArguments <boolean> No se realiza ninguna comilla o escape de argumentos en Windows. Se ignora en Unix. Esto se establece en true automáticamente cuando se especifica shell y es CMD. Predeterminado: false.
    • windowsHide <boolean> Oculta la ventana de consola del subproceso que normalmente se crearía en sistemas Windows. Predeterminado: false.
  • Devuelve: <Object>

    • pid <number> Pid del proceso hijo.
    • output <Array> Matriz de resultados de la salida de stdio.
    • stdout <Buffer> | <string> El contenido de output[1].
    • stderr <Buffer> | <string> El contenido de output[2].
    • status <number> | <null> El código de salida del subproceso, o null si el subproceso terminó debido a una señal.
    • signal <string> | <null> La señal utilizada para eliminar el subproceso, o null si el subproceso no terminó debido a una señal.
    • error <Error> El objeto de error si el proceso hijo falló o se agotó el tiempo de espera.

El método child_process.spawnSync() es generalmente idéntico a child_process.spawn() con la excepción de que la función no devolverá nada hasta que el proceso hijo se haya cerrado completamente. Cuando se ha encontrado un tiempo de espera y se envía killSignal, el método no devolverá nada hasta que el proceso haya salido completamente. Si el proceso intercepta y maneja la señal SIGTERM y no sale, el proceso principal esperará hasta que el proceso hijo haya salido.

Si la opción shell está habilitada, no pase entrada de usuario no sanitizada a esta función. Cualquier entrada que contenga metacaracteres de shell puede usarse para activar la ejecución de comandos arbitrarios.

Clase: ChildProcess

Añadido en: v2.2.0

Las instancias de ChildProcess representan procesos secundarios generados.

No se pretende que las instancias de ChildProcess se creen directamente. En su lugar, utilice los métodos child_process.spawn(), child_process.exec(), child_process.execFile() o child_process.fork() para crear instancias de ChildProcess.

Evento: 'close'

Añadido en: v0.7.7

  • code <number> El código de salida si el proceso secundario terminó por sí solo.
  • signal <string> La señal por la que se terminó el proceso secundario.

El evento 'close' se emite después de que un proceso ha finalizado y se han cerrado los flujos stdio de un proceso secundario. Esto es distinto del evento 'exit', ya que varios procesos podrían compartir los mismos flujos stdio. El evento 'close' siempre se emitirá después de que ya se haya emitido 'exit', o 'error' si el proceso secundario no se pudo generar.

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

Evento: 'disconnect'

Añadido en: v0.7.2

El evento 'disconnect' se emite después de llamar al método subprocess.disconnect() en el proceso padre o process.disconnect() en el proceso hijo. Después de desconectar, ya no es posible enviar o recibir mensajes, y la propiedad subprocess.connected es false.

Evento: 'error'

El evento 'error' se emite siempre que:

  • No se pudo generar el proceso.
  • No se pudo eliminar el proceso.
  • Falló el envío de un mensaje al proceso hijo.
  • El proceso hijo fue abortado a través de la opción signal.

El evento 'exit' puede o no activarse después de que se haya producido un error. Al escuchar tanto los eventos 'exit' como 'error', protéjase contra la invocación accidental de las funciones de manejo varias veces.

Véase también subprocess.kill() y subprocess.send().

Evento: 'exit'

Añadido en: v0.1.90

  • code <número> El código de salida si el proceso hijo finalizó por sí solo.
  • signal <cadena> La señal por la cual se terminó el proceso hijo.

El evento 'exit' se emite después de que finaliza el proceso hijo. Si el proceso finalizó, code es el código de salida final del proceso, de lo contrario null. Si el proceso terminó debido a la recepción de una señal, signal es el nombre de la señal en forma de cadena, de lo contrario null. Uno de los dos siempre será distinto de null.

Cuando se activa el evento 'exit', las transmisiones stdio del proceso hijo pueden seguir abiertas.

Node.js establece controladores de señales para SIGINT y SIGTERM, y los procesos de Node.js no terminarán inmediatamente debido a la recepción de esas señales. Más bien, Node.js realizará una secuencia de acciones de limpieza y luego volverá a generar la señal manejada.

Ver waitpid(2).

Evento: 'message'

Añadido en: v0.5.9

El evento 'message' se activa cuando un proceso hijo usa process.send() para enviar mensajes.

El mensaje pasa por serialización y análisis. El mensaje resultante podría no ser el mismo que el enviado originalmente.

Si la opción serialization se estableció en 'advanced' al generar el proceso hijo, el argumento message puede contener datos que JSON no puede representar. Consulte Serialización avanzada para obtener más detalles.

Evento: 'spawn'

Añadido en: v15.1.0, v14.17.0

El evento 'spawn' se emite una vez que el proceso hijo se ha generado correctamente. Si el proceso hijo no se genera correctamente, el evento 'spawn' no se emite y se emite el evento 'error' en su lugar.

Si se emite, el evento 'spawn' precede a todos los demás eventos y antes de que se reciban datos a través de stdout o stderr.

El evento 'spawn' se activará independientemente de si se produce un error dentro del proceso generado. Por ejemplo, si bash some-command se genera correctamente, el evento 'spawn' se activará, aunque bash pueda fallar al generar some-command. Esta advertencia también se aplica cuando se utiliza { shell: true }.

subprocess.channel

[Historial]

VersiónCambios
v14.0.0El objeto ya no expone accidentalmente enlaces nativos de C++.
v7.1.0Añadido en: v7.1.0
  • <Objeto> Una tubería que representa el canal IPC al proceso hijo.

La propiedad subprocess.channel es una referencia al canal IPC del hijo. Si no existe ningún canal IPC, esta propiedad es undefined.

subprocess.channel.ref()

Añadido en: v7.1.0

Este método hace que el canal IPC mantenga el bucle de eventos del proceso principal en ejecución si se ha llamado a .unref() anteriormente.

subprocess.channel.unref()

Añadido en: v7.1.0

Este método hace que el canal IPC no mantenga el bucle de eventos del proceso principal en ejecución, y le permite finalizar incluso mientras el canal está abierto.

subprocess.connected

Añadido en: v0.7.2

  • <boolean> Se establece en false después de llamar a subprocess.disconnect().

La propiedad subprocess.connected indica si todavía es posible enviar y recibir mensajes de un proceso hijo. Cuando subprocess.connected es false, ya no es posible enviar o recibir mensajes.

subprocess.disconnect()

Añadido en: v0.7.2

Cierra el canal IPC entre los procesos principal e hijo, permitiendo que el proceso hijo se cierre correctamente una vez que no haya otras conexiones que lo mantengan vivo. Después de llamar a este método, las propiedades subprocess.connected y process.connected tanto en el proceso principal como en el hijo (respectivamente) se establecerán en false, y ya no será posible pasar mensajes entre los procesos.

El evento 'disconnect' se emitirá cuando no haya mensajes en proceso de recepción. Esto se activará con mayor frecuencia inmediatamente después de llamar a subprocess.disconnect().

Cuando el proceso hijo es una instancia de Node.js (por ejemplo, generado usando child_process.fork()), el método process.disconnect() se puede invocar dentro del proceso hijo para cerrar el canal IPC también.

subprocess.exitCode

La propiedad subprocess.exitCode indica el código de salida del proceso hijo. Si el proceso hijo aún se está ejecutando, el campo será null.

subprocess.kill([signal])

Añadido en: v0.1.90

El método subprocess.kill() envía una señal al proceso hijo. Si no se proporciona ningún argumento, se enviará al proceso la señal 'SIGTERM'. Consulte signal(7) para obtener una lista de señales disponibles. Esta función devuelve true si kill(2) tiene éxito, y false en caso contrario.

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

grep.on('close', (code, signal) => {
  console.log(`child process terminated due to receipt of signal ${signal}`)
})

// Enviar SIGHUP al proceso.
grep.kill('SIGHUP')
js
import { spawn } from 'node:child_process'
const grep = spawn('grep', ['ssh'])

grep.on('close', (code, signal) => {
  console.log(`child process terminated due to receipt of signal ${signal}`)
})

// Enviar SIGHUP al proceso.
grep.kill('SIGHUP')

El objeto ChildProcess puede emitir un evento 'error' si la señal no se puede entregar. Enviar una señal a un proceso hijo que ya ha salido no es un error, pero puede tener consecuencias imprevistas. Específicamente, si el identificador de proceso (PID) se ha reasignado a otro proceso, la señal se entregará a ese proceso en su lugar, lo que puede tener resultados inesperados.

Si bien la función se llama kill, la señal entregada al proceso hijo puede no terminar realmente el proceso.

Consulte kill(2) como referencia.

En Windows, donde no existen las señales POSIX, el argumento signal se ignorará, excepto para 'SIGKILL', 'SIGTERM', 'SIGINT' y 'SIGQUIT', y el proceso siempre se eliminará de forma forzosa y abrupta (similar a 'SIGKILL'). Consulte Eventos de señal para obtener más detalles.

En Linux, los procesos hijos de los procesos hijos no se terminarán al intentar eliminar a sus padres. Es probable que esto suceda al ejecutar un nuevo proceso en un shell o con la opción shell de ChildProcess:

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

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

setTimeout(() => {
  subprocess.kill() // No termina el proceso Node.js en el shell.
}, 2000)
js
import { spawn } from 'node:child_process'

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

setTimeout(() => {
  subprocess.kill() // No termina el proceso Node.js en el shell.
}, 2000)

subprocess[Symbol.dispose]()

Añadido en: v20.5.0, v18.18.0

[Estable: 1 - Experimental]

Estable: 1 Estabilidad: 1 - Experimental

Llama a subprocess.kill() con 'SIGTERM'.

subprocess.killed

Añadido en: v0.5.10

  • <boolean> Se establece en true después de que subprocess.kill() se use para enviar correctamente una señal al proceso hijo.

La propiedad subprocess.killed indica si el proceso hijo recibió correctamente una señal de subprocess.kill(). La propiedad killed no indica que el proceso hijo haya sido terminado.

subprocess.pid

Añadido en: v0.1.90

Devuelve el identificador de proceso (PID) del proceso hijo. Si el proceso hijo no se genera debido a errores, el valor es undefined y se emite 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()

Añadido en: v0.7.10

Llamar a subprocess.ref() después de llamar a subprocess.unref() restaurará el recuento de referencias eliminado para el proceso hijo, forzando al proceso padre a esperar a que el proceso hijo termine antes de terminar él mismo.

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])

[Historial]

VersiónCambios
v5.8.0Ahora se admite el parámetro options, y la opción keepOpen en particular.
v5.0.0Este método ahora devuelve un booleano para el control de flujo.
v4.0.0Ahora se admite el parámetro callback.
v0.5.9Añadido en: v0.5.9
  • message <Object>

  • sendHandle <Handle> | <undefined> undefined, o un objeto net.Socket, net.Server, o dgram.Socket.

  • options <Object> El argumento options, si está presente, es un objeto que se utiliza para parametrizar el envío de ciertos tipos de manejadores. options admite las siguientes propiedades:

    • keepOpen <boolean> Un valor que se puede utilizar al pasar instancias de net.Socket. Cuando es true, el socket se mantiene abierto en el proceso de envío. Predeterminado: false.
  • callback <Function>

  • Devuelve: <boolean>

Cuando se ha establecido un canal IPC entre los procesos padre e hijo (es decir, cuando se utiliza child_process.fork()), el método subprocess.send() se puede utilizar para enviar mensajes al proceso hijo. Cuando el proceso hijo es una instancia de Node.js, estos mensajes se pueden recibir a través del evento 'message'.

El mensaje pasa por la serialización y el análisis. El mensaje resultante puede no ser el mismo que el que se envió originalmente.

Por ejemplo, en el script principal:

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

forkedProcess.on('message', message => {
  console.log('PADRE recibió el mensaje:', message)
})

// Hace que el hijo imprima: HIJO recibió el mensaje: { 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('PADRE recibió el mensaje:', message)
})

// Hace que el hijo imprima: HIJO recibió el mensaje: { hello: 'world' }
forkedProcess.send({ hello: 'world' })

Y luego el script hijo, 'sub.js', podría verse así:

js
process.on('message', message => {
  console.log('HIJO recibió el mensaje:', message)
})

// Hace que el padre imprima: PADRE recibió el mensaje: { foo: 'bar', baz: null }
process.send({ foo: 'bar', baz: NaN })

Los procesos hijos de Node.js tendrán un método process.send() propio que permite al proceso hijo enviar mensajes de vuelta al proceso padre.

Hay un caso especial cuando se envía un mensaje {cmd: 'NODE_foo'}. Los mensajes que contienen un prefijo NODE_ en la propiedad cmd están reservados para su uso en el núcleo de Node.js y no se emitirán en el evento 'message' del hijo. Más bien, esos mensajes se emiten utilizando el evento 'internalMessage' y son consumidos internamente por Node.js. Las aplicaciones deben evitar el uso de dichos mensajes o la escucha de eventos 'internalMessage' ya que están sujetos a cambios sin previo aviso.

El argumento opcional sendHandle que se puede pasar a subprocess.send() es para pasar un objeto de servidor o socket TCP al proceso hijo. El proceso hijo recibirá el objeto como el segundo argumento pasado a la función de devolución de llamada registrada en el evento 'message'. Los datos que se reciben y almacenan en búfer en el socket no se enviarán al hijo. El envío de sockets IPC no es compatible con Windows.

La función callback opcional es una función que se invoca después de que se envía el mensaje pero antes de que el proceso hijo lo haya recibido. La función se llama con un solo argumento: null en caso de éxito, o un objeto Error en caso de fallo.

Si no se proporciona ninguna función callback y no se puede enviar el mensaje, se emitirá un evento 'error' en el objeto ChildProcess. Esto puede suceder, por ejemplo, cuando el proceso hijo ya ha salido.

subprocess.send() devolverá false si el canal se ha cerrado o cuando la acumulación de mensajes no enviados supera un umbral que hace que no sea prudente enviar más. De lo contrario, el método devuelve true. La función callback se puede utilizar para implementar el control de flujo.

Ejemplo: enviando un objeto de servidor

El argumento sendHandle puede usarse, por ejemplo, para pasar el manejador de un objeto de servidor TCP al proceso hijo como se ilustra en el ejemplo a continuación:

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

const subprocess = fork('subprocess.js')

// Abre el objeto servidor y envía el manejador.
const server = createServer()
server.on('connection', socket => {
  socket.end('handled by parent')
})
server.listen(1337, () => {
  subprocess.send('server', server)
})
js
import { fork } from 'node:child_process'
import { createServer } from 'node:net'

const subprocess = fork('subprocess.js')

// Abre el objeto servidor y envía el manejador.
const server = createServer()
server.on('connection', socket => {
  socket.end('handled by parent')
})
server.listen(1337, () => {
  subprocess.send('server', server)
})

El proceso hijo recibiría entonces el objeto servidor como:

js
process.on('message', (m, server) => {
  if (m === 'server') {
    server.on('connection', socket => {
      socket.end('handled by child')
    })
  }
})

Una vez que el servidor es compartido entre el padre e hijo, algunas conexiones pueden ser manejadas por el padre y otras por el hijo.

Si bien el ejemplo anterior utiliza un servidor creado con el módulo node:net, los servidores del módulo node:dgram utilizan exactamente el mismo flujo de trabajo, con las excepciones de escuchar en un evento 'message' en lugar de 'connection' y usar server.bind() en lugar de server.listen(). Sin embargo, esto solo es compatible con plataformas Unix.

Ejemplo: enviar un objeto socket

De manera similar, el argumento sendHandler se puede usar para pasar el manejador de un socket al proceso hijo. El ejemplo a continuación genera dos hijos que manejan las conexiones con prioridad "normal" o "especial":

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

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

// Abre el servidor y envía sockets al hijo. Usa pauseOnConnect para evitar
// que los sockets se lean antes de que se envíen al proceso hijo.
const server = createServer({ pauseOnConnect: true })
server.on('connection', socket => {
  // Si esto es prioridad especial...
  if (socket.remoteAddress === '74.125.127.100') {
    special.send('socket', socket)
    return
  }
  // Esta es la prioridad normal.
  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'])

// Abre el servidor y envía sockets al hijo. Usa pauseOnConnect para evitar
// que los sockets se lean antes de que se envíen al proceso hijo.
const server = createServer({ pauseOnConnect: true })
server.on('connection', socket => {
  // Si esto es prioridad especial...
  if (socket.remoteAddress === '74.125.127.100') {
    special.send('socket', socket)
    return
  }
  // Esta es la prioridad normal.
  normal.send('socket', socket)
})
server.listen(1337)

El subprocess.js recibiría el manejador del socket como el segundo argumento pasado a la función de devolución de llamada del evento:

js
process.on('message', (m, socket) => {
  if (m === 'socket') {
    if (socket) {
      // Comprueba que el socket del cliente exista.
      // Es posible que el socket se cierre entre el momento en que se envía
      // y el momento en que se recibe en el proceso hijo.
      socket.end(`Solicitud manejada con prioridad ${process.argv[2]}`)
    }
  }
})

No uses .maxConnections en un socket que se haya pasado a un subproceso. El padre no puede rastrear cuándo se destruye el socket.

Cualquier manejador 'message' en el subproceso debe verificar que socket exista, ya que la conexión puede haberse cerrado durante el tiempo que lleva enviar la conexión al hijo.

subprocess.signalCode

La propiedad subprocess.signalCode indica la señal recibida por el proceso hijo, si la hay; de lo contrario, null.

subprocess.spawnargs

La propiedad subprocess.spawnargs representa la lista completa de argumentos de línea de comandos con los que se inició el proceso hijo.

subprocess.spawnfile

La propiedad subprocess.spawnfile indica el nombre del archivo ejecutable del proceso hijo que se inicia.

Para child_process.fork(), su valor será igual a process.execPath. Para child_process.spawn(), su valor será el nombre del archivo ejecutable. Para child_process.exec(), su valor será el nombre del shell en el que se inicia el proceso hijo.

subprocess.stderr

Añadido en: v0.1.90

Una corriente Readable que representa el stderr del proceso hijo.

Si el proceso hijo se generó con stdio[2] establecido en algo que no sea 'pipe', entonces esto será null.

subprocess.stderr es un alias para subprocess.stdio[2]. Ambas propiedades referirán al mismo valor.

La propiedad subprocess.stderr puede ser null o undefined si el proceso hijo no se pudo generar correctamente.

subprocess.stdin

Añadido en: v0.1.90

Una corriente Writable que representa el stdin del proceso hijo.

Si un proceso hijo espera leer toda su entrada, el proceso hijo no continuará hasta que esta corriente se haya cerrado mediante end().

Si el proceso hijo se generó con stdio[0] establecido en algo que no sea 'pipe', entonces esto será null.

subprocess.stdin es un alias para subprocess.stdio[0]. Ambas propiedades referirán al mismo valor.

La propiedad subprocess.stdin puede ser null o undefined si el proceso hijo no se pudo generar correctamente.

subprocess.stdio

Añadido en: v0.7.10

Una matriz dispersa de tuberías al proceso hijo, que corresponde con las posiciones en la opción stdio pasada a child_process.spawn() que se han establecido en el valor 'pipe'. subprocess.stdio[0], subprocess.stdio[1], y subprocess.stdio[2] también están disponibles como subprocess.stdin, subprocess.stdout, y subprocess.stderr, respectivamente.

En el siguiente ejemplo, solo el fd 1 del hijo (stdout) se configura como una tubería, por lo que solo el subprocess.stdio[1] del padre es una secuencia, todos los demás valores de la matriz son 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, // Usar la stdin del padre para el hijo.
    'pipe', // Conectar el stdout del hijo al padre.
    fs.openSync('err.out', 'w'), // Dirigir el stderr del hijo a un archivo.
  ],
})

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, // Usar la stdin del padre para el hijo.
    'pipe', // Conectar el stdout del hijo al padre.
    fs.openSync('err.out', 'w'), // Dirigir el stderr del hijo a un archivo.
  ],
})

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)

La propiedad subprocess.stdio puede ser undefined si el proceso hijo no pudo generarse correctamente.

subprocess.stdout

Añadido en: v0.1.90

Un flujo Readable Stream que representa la salida estándar (stdout) del proceso hijo.

Si el proceso hijo se generó con stdio[1] establecido en algo diferente a 'pipe', entonces esto será null.

subprocess.stdout es un alias para subprocess.stdio[1]. Ambas propiedades harán referencia al mismo valor.

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

const subprocess = spawn('ls')

subprocess.stdout.on('data', data => {
  console.log(`Received chunk ${data}`)
})
js
import { spawn } from 'node:child_process'

const subprocess = spawn('ls')

subprocess.stdout.on('data', data => {
  console.log(`Received chunk ${data}`)
})

La propiedad subprocess.stdout puede ser null o undefined si el proceso hijo no pudo generarse correctamente.

subprocess.unref()

Añadido en: v0.7.10

Por defecto, el proceso padre esperará a que el proceso hijo separado termine. Para evitar que el proceso padre espere a que un subprocess dado termine, use el método subprocess.unref(). Al hacerlo, el bucle de eventos del padre no incluirá el proceso hijo en su recuento de referencias, permitiendo que el padre termine independientemente del hijo, a menos que exista un canal IPC establecido entre los procesos hijo y padre.

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 y Unicode

La opción maxBuffer especifica el mayor número de bytes permitidos en stdout o stderr. Si se excede este valor, el proceso hijo se termina. Esto afecta a la salida que incluye codificaciones de caracteres multibyte como UTF-8 o UTF-16. Por ejemplo, console.log('中文测试') enviará 13 bytes codificados en UTF-8 a stdout aunque solo haya 4 caracteres.

Requisitos del shell

El shell debe comprender el modificador -c. Si el shell es 'cmd.exe', debe comprender los modificadores /d /s /c y el análisis de la línea de comandos debe ser compatible.

Shell predeterminado de Windows

Aunque Microsoft especifica que %COMSPEC% debe contener la ruta a 'cmd.exe' en el entorno raíz, los procesos secundarios no siempre están sujetos al mismo requisito. Por lo tanto, en las funciones de child_process donde se puede generar un shell, se utiliza 'cmd.exe' como alternativa si process.env.ComSpec no está disponible.

Serialización avanzada

Añadido en: v13.2.0, v12.16.0

Los procesos secundarios admiten un mecanismo de serialización para IPC que se basa en la API de serialización del módulo node:v8, basado en el algoritmo de clonación estructurada HTML. Esto es generalmente más potente y admite más tipos de objetos JavaScript integrados, como BigInt, Map y Set, ArrayBuffer y TypedArray, Buffer, Error, RegExp, etc.

Sin embargo, este formato no es un superconjunto completo de JSON, y por ejemplo, las propiedades establecidas en objetos de dichos tipos integrados no se pasarán a través del paso de serialización. Además, el rendimiento puede no ser equivalente al de JSON, dependiendo de la estructura de los datos pasados. Por lo tanto, esta función requiere la activación mediante la configuración de la opción serialization en 'advanced' al llamar a child_process.spawn() o child_process.fork().