child_process
child_process ejecuta programas externos desde Node; prefiere spawn con arrays de argumentos explícitos, comprende los modos stdio y evita la inyección de shell al envolver herramientas CLI.
Busca en todas las páginas de la documentación
child_process ejecuta programas externos desde Node; prefiere spawn con arrays de argumentos explícitos, comprende los modos stdio y evita la inyección de shell al envolver herramientas CLI.
import { spawn } from 'node:child_process';
const child = spawn('git', ['rev-parse', 'HEAD'], { stdio: ['ignore', 'pipe', 'pipe'] });import { promisify } from 'node:util';
import { execFile } from 'node:child_process';
const execFileAsync = promisify(execFile);
const { stdout } = await execFileAsync('node', ['--version']);Cuándo usarlo:
ffmpeg CLIimport { spawn } from 'node:child_process';
import { once } from 'node:events';
async function runGitHash(): Promise<string> {
const child = spawn('git', ['rev-parse', 'HEAD'], {
stdio: ['ignore', 'pipe', 'pipe'],
});
let stdout = '';
child.stdout.on('data', (chunk: Buffer) => {
stdout += chunk.toString('utf8');
});
const [code] = await once(child, 'exit');
if (code !== 0) throw new Error(`git exited ${code}`);
return stdout.trim();
}
// Peligroso - no hagas esto con entrada de usuario:
// spawn(`git rev-parse ${userBranch}`, { shell: true });import { pipeline } from 'node:stream/promises';
import { spawn } from 'node:child_process';
import { createWriteStream } from 'node:fs';
async function compressWithGzip(input: string, output: string): Promise<void> {
const gzip = spawn('gzip', ['-c', input], { stdio: ['ignore', 'pipe', 'inherit'] });
await pipeline(gzip.stdout, createWriteStream(output));
const code = await new Promise<number>((res) => gzip.on('exit', res));
if (code !== 0) throw new Error(`gzip failed ${code}`);
}Lo que esto demuestra:
execve sin interpretación de shellexec para salida grandepipeline para contrapresiónshell: true solo para comandos fijos confiables, nunca con cadenas de usuariospawn - transmite stdio, regresa inmediatamente, evento exit con código.exec - almacena stdout/stderr en búfer, invoca shell por defecto - riesgo de inyección.execFile - sin shell, salida almacenada en búfer con maxBuffer por defecto de 1MB.fork - hijo especial de Node con canal IPC - patrón heredado antes de worker_threads.| API | Shell | Salida | Uso |
|---|---|---|---|
| spawn | No (por defecto) | Stream | Salida larga, pipes |
| exec | Sí (por defecto) | Almacenado en búfer | Comandos pequeños y confiables |
| execFile | No | Almacenado en búfer | Array de argumentos pequeños |
| fork | No | IPC | Workers solo de Node (heredado) |
import type { ChildProcess } from 'node:child_process';
export function killProcessTree(child: ChildProcess): void {
if (child.pid) process.kill(-child.pid, 'SIGTERM');
}Específico de la plataforma: los grupos de procesos de Linux necesitan detached: true en spawn.
shell: true + entrada de usuario - inyección de comandos. Solución: spawn(cmd, [arg1, arg2]) sin shell.exec maxBuffer excedido - lanza un error en stdout grande. Solución: spawn con streams.exit o esperar la salida en supervisores de larga duración.stdio: 'ignore' para trabajos en segundo plano.| Alternativa | Cuándo usar | Cuándo NO usar |
|---|---|---|
| worker_threads | CPU JS en el mismo tiempo de ejecución | Necesita un binario separado o un proceso de SO sandbox |
| Librería Node pura | ffmpeg wasm, sharp vs CLI | CLI maduro ya scriptado |
| Container exec | Trabajo K8s por tarea | Script local simple |
Mocks de prueba node:child_process | Pruebas unitarias | Orquestación de producción |
spawn para streaming y seguridad; exec para comandos de shell rápidos, pequeños y confiables solo en scripts de desarrollo.
El hijo comparte la consola del padre; bueno para herramientas CLI que muestran salida en vivo a la terminal.
spawn(cmd, args, { env: { ...process.env, FOO: 'bar' } }).
Sí - stdio: ['pipe', 'pipe', 'pipe'] y escribe a child.stdin.
code es nulo y signal se establece al matar; maneja SIGTERM en scripts hijos.
setTimeout + child.kill('SIGKILL') con limpieza; o usa timers/promises + patrones AbortSignal en wrappers.
No eliminado; prefiere worker_threads para CPU; fork para código heredado de IPC de Node.
Busca shell: true y comandos concatenados con cadenas en PRs.
Redirige stderr al logger - stdio: ['ignore', 'pipe', 'pipe'] y etiqueta las líneas de stderr del hijo.
cluster bifurca workers de Node; spawn ejecuta ejecutables arbitrarios.
execFile('git', ['diff', '--name-only']) - seguro y determinista.
Los archivos .cmd pueden necesitar shell: true; prefiere node/npm con rutas explícitas documentadas para el equipo.
Versiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS activa), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.
Revisado por Chris St. John·Última actualización: 19 jul 2026