Working with Child Processes
1. Executing Commands (child_process.exec)
Example
import { exec } from "node:child_process";
import { promisify } from "node:util";
const { stdout } = await promisify(exec)("git rev-parse HEAD");
Warning: Never interpolate user input into a shell string — use execFile/spawn with array args.
2. Executing Files (child_process.execFile)
Example
execFile("ls", ["-l", "/tmp"], (err, stdout) => { /* ... */ });
| Diff vs exec | Detail |
| No shell | Safer, faster |
| Args as array | No injection |
3. Spawning Processes (child_process.spawn)
Example: Stream stdout
const cp = spawn("ffmpeg", ["-i", "in.mp4", "out.mp3"]);
cp.stdout.pipe(process.stdout);
cp.on("exit", (code) => console.log("done", code));
4. Forking Processes (child_process.fork)
| API | Use |
fork(modulePath, args) | Spawn another Node process |
| IPC | Auto-set up via process.send / "message" |
5. Handling Child Process Events
| Event | Fires |
spawn | Process started |
exit | Process exited (no streams flushed yet) |
close | All stdio closed |
error | Couldn't spawn |
message | IPC (only with fork / { stdio: "ipc" }) |
6. Piping Standard I/O
| stdio Option | Effect |
"pipe" | Default; cp.stdout available |
"inherit" | Share parent's stdio |
"ignore" | Drop output |
| Array | Per-stream config (e.g. ["pipe","inherit","pipe"]) |
7. Communicating with IPC
Example
// parent
const child = fork("./worker.js");
child.send({ task: "compute", n: 100 });
child.on("message", (msg) => console.log("result", msg));
// worker.js
process.on("message", (m) => process.send({ ok: true, value: m.n * 2 }));
8. Setting Working Directory
| Option | Use |
cwd: "/path" | Run in a specific dir |
9. Configuring Environment Variables
| Option | Use |
env: { ...process.env, FOO: "1" } | Inherit + override |
env: { FOO: "1" } | Replace fully |
10. Detaching Child Processes
Example: Long-running daemon
const cp = spawn("node", ["server.js"], {
detached: true,
stdio: "ignore"
});
cp.unref(); // parent can exit
11. Killing Child Processes
| API | Effect |
cp.kill("SIGTERM") | Default polite termination |
cp.kill("SIGKILL") | Force kill |
cp.killed | Boolean |
12. Using Promisified Exec (util.promisify)
| Helper | Use |
promisify(exec) | Returns {stdout, stderr} |
execa (npm) | Better defaults, cross-platform |