Bun 进程与子进程 #

概述 #

Bun 提供了强大的进程管理能力,包括 process 全局对象、Bun.spawn() 子进程创建和 Shell 命令执行功能。

process 全局对象 #

进程信息 #

typescript
// 进程 ID
console.log(process.pid);       // 当前进程 ID
console.log(process.ppid);      // 父进程 ID

// 进程标题
console.log(process.title);

// 版本信息
console.log(process.version);   // Node.js 版本字符串
console.log(process.versions);  // 版本详情

// 平台信息
console.log(process.platform);  // "darwin", "linux", "win32"
console.log(process.arch);      // "x64", "arm64"

// 运行时信息
console.log(process.uptime());  // 进程运行时间(秒)

环境变量 #

typescript
// 读取环境变量
console.log(process.env.NODE_ENV);
console.log(process.env.PATH);
console.log(process.env.HOME);

// 设置环境变量
process.env.MY_VAR = "value";

// 删除环境变量
delete process.env.MY_VAR;

// 遍历所有环境变量
for (const [key, value] of Object.entries(process.env)) {
  console.log(`${key}=${value}`);
}

命令行参数 #

typescript
// 完整参数列表
console.log(process.argv);
// ["/path/to/bun", "/path/to/script.js", "arg1", "arg2"]

// 获取脚本参数
const args = process.argv.slice(2);
console.log(args);

// 当前工作目录
console.log(process.cwd());

// 切换工作目录
process.chdir("/tmp");

标准流 #

typescript
// 标准输入
process.stdin.on("data", (chunk) => {
  console.log("Received:", chunk.toString());
});

// 标准输出
process.stdout.write("Hello, stdout!\n");

// 标准错误
process.stderr.write("Error message\n");

// 快捷方法
console.log("To stdout");
console.error("To stderr");

进程退出 #

typescript
// 正常退出
process.exit(0);

// 异常退出
process.exit(1);

// 设置退出码(不立即退出)
process.exitCode = 1;

// 退出事件
process.on("exit", (code) => {
  console.log(`Process exiting with code ${code}`);
});

进程事件 #

typescript
// 未捕获异常
process.on("uncaughtException", (error) => {
  console.error("Uncaught exception:", error);
  process.exit(1);
});

// 未处理的 Promise 拒绝
process.on("unhandledRejection", (reason, promise) => {
  console.error("Unhandled rejection:", reason);
});

// 警告
process.on("warning", (warning) => {
  console.warn("Warning:", warning);
});

// 信号处理
process.on("SIGINT", () => {
  console.log("Received SIGINT");
  process.exit(0);
});

process.on("SIGTERM", () => {
  console.log("Received SIGTERM");
  process.exit(0);
});

Bun.spawn() #

基本用法 #

typescript
// 创建子进程
const proc = Bun.spawn(["echo", "Hello, Bun!"]);

// 等待进程结束
await proc.exited;

// 获取退出码
console.log(proc.exitCode);

捕获输出 #

typescript
const proc = Bun.spawn(["echo", "Hello"], {
  stdout: "pipe",
});

// 读取输出
const text = await new Response(proc.stdout).text();
console.log(text);  // "Hello\n"

提供输入 #

typescript
const proc = Bun.spawn(["cat"], {
  stdin: "pipe",
  stdout: "pipe",
});

// 写入输入
proc.stdin.write("Hello from stdin");
proc.stdin.end();

// 读取输出
const output = await new Response(proc.stdout).text();
console.log(output);  // "Hello from stdin"

环境变量 #

typescript
const proc = Bun.spawn(["env"], {
  env: {
    ...process.env,
    MY_VAR: "custom_value",
  },
  stdout: "pipe",
});

const output = await new Response(proc.stdout).text();
console.log(output);

工作目录 #

typescript
const proc = Bun.spawn(["pwd"], {
  cwd: "/tmp",
  stdout: "pipe",
});

const output = await new Response(proc.stdout).text();
console.log(output);  // "/tmp"

生命周期 #

typescript
const proc = Bun.spawn(["sleep", "10"]);

// 检查是否运行中
console.log(proc.killed);  // false

// 等待退出
const exitPromise = proc.exited;

// 终止进程
proc.kill();

// 使用信号
proc.kill("SIGTERM");
proc.kill("SIGKILL");

await exitPromise;
console.log(proc.exitCode);

完整示例 #

typescript
async function runCommand(cmd: string, args: string[] = []) {
  const proc = Bun.spawn([cmd, ...args], {
    stdout: "pipe",
    stderr: "pipe",
  });

  const [stdout, stderr] = await Promise.all([
    new Response(proc.stdout).text(),
    new Response(proc.stderr).text(),
  ]);

  await proc.exited;

  return {
    exitCode: proc.exitCode,
    stdout,
    stderr,
  };
}

const result = await runCommand("ls", ["-la"]);
console.log(result.stdout);

Shell 命令 (Bun.$) #

基本用法 #

typescript
import { $ } from "bun";

// 执行命令
await $`echo "Hello, Bun!"`;

// 获取输出
const result = await $`ls -la`;
console.log(result.text());

// 获取 JSON 输出
const json = await $`echo '{"name":"Bun"}'`.json();
console.log(json);

命令输出 #

typescript
// 文本输出
const text = await $`echo "Hello"`.text();
console.log(text);

// 行数组
const lines = await $`ls`.lines();
console.log(lines);

// Buffer
const buffer = await $`cat /etc/hosts`.buffer();

// JSON
const data = await $`echo '{"key":"value"}'`.json();

命令链 #

typescript
// 管道
const result = await $`echo "hello" | tr 'a-z' 'A-Z'`;
console.log(result.text());  // "HELLO"

// 链式命令
await $`mkdir -p dist && cp -r src/* dist/`;

环境变量 #

typescript
// 设置环境变量
await $`echo $MY_VAR`.env({ MY_VAR: "hello" });

// 使用当前环境
await $`echo $HOME`.env(process.env);

工作目录 #

typescript
// 设置工作目录
await $`pwd`.cwd("/tmp");

// 链式调用
await $`pwd`.cwd("/tmp").env({ MY_VAR: "value" });

错误处理 #

typescript
try {
  await $`exit 1`;
} catch (error) {
  console.error("Command failed:", error);
}

// 忽略错误
await $`maybe-fails || true`;

输入重定向 #

typescript
// 从文件输入
await $`cat < input.txt`;

// 从字符串输入
await $`cat`.stdin("Hello from stdin");

// 从 Buffer 输入
const buffer = new TextEncoder().encode("Hello");
await $`cat`.stdin(buffer);

输出重定向 #

typescript
// 输出到文件
await $`echo "Hello" > output.txt`;

// 追加输出
await $`echo "World" >> output.txt`;

// 重定向 stderr
await $`some-command 2>&1`;

交互式命令 #

typescript
// 不捕获输出(直接输出到终端)
await $`vim file.txt`.quiet();

// 实时输出
const proc = $`npm install`;
for await (const line of proc.lines()) {
  console.log(line);
}

进程池 #

并行执行 #

typescript
async function runParallel(commands: string[][]) {
  const processes = commands.map((cmd) => Bun.spawn(cmd, { stdout: "pipe" }));

  const results = await Promise.all(
    processes.map(async (proc) => {
      const output = await new Response(proc.stdout).text();
      await proc.exited;
      return { exitCode: proc.exitCode, output };
    })
  );

  return results;
}

const results = await runParallel([
  ["echo", "task1"],
  ["echo", "task2"],
  ["echo", "task3"],
]);

console.log(results);

限制并发 #

typescript
async function runWithConcurrency(
  commands: string[][],
  concurrency: number
) {
  const results: Array<{ exitCode: number; output: string }> = [];
  
  for (let i = 0; i < commands.length; i += concurrency) {
    const batch = commands.slice(i, i + concurrency);
    const batchResults = await Promise.all(
      batch.map(async (cmd) => {
        const proc = Bun.spawn(cmd, { stdout: "pipe" });
        const output = await new Response(proc.stdout).text();
        await proc.exited;
        return { exitCode: proc.exitCode!, output };
      })
    );
    results.push(...batchResults);
  }
  
  return results;
}

实用工具 #

执行脚本 #

typescript
async function runScript(script: string, args: string[] = []) {
  const proc = Bun.spawn(["bun", "run", script, ...args], {
    stdout: "pipe",
    stderr: "pipe",
  });

  const [stdout, stderr] = await Promise.all([
    new Response(proc.stdout).text(),
    new Response(proc.stderr).text(),
  ]);

  await proc.exited;

  if (proc.exitCode !== 0) {
    throw new Error(`Script failed: ${stderr}`);
  }

  return stdout;
}

执行 Git 命令 #

typescript
async function git(command: string, ...args: string[]) {
  const proc = Bun.spawn(["git", command, ...args], {
    stdout: "pipe",
    stderr: "pipe",
  });

  const [stdout, stderr] = await Promise.all([
    new Response(proc.stdout).text(),
    new Response(proc.stderr).text(),
  ]);

  await proc.exited;

  return { stdout, stderr, exitCode: proc.exitCode };
}

// 使用
const { stdout } = await git("status", "--short");
console.log(stdout);

const { stdout: log } = await git("log", "--oneline", "-10");
console.log(log);

执行 npm/bun 命令 #

typescript
async function install(packages: string[], dev = false) {
  const args = ["add", ...packages];
  if (dev) args.push("--dev");

  const proc = Bun.spawn(["bun", ...args], {
    stdout: "inherit",
    stderr: "inherit",
  });

  await proc.exited;
  return proc.exitCode === 0;
}

await install(["react", "react-dom"]);
await install(["typescript"], true);

进程监控 #

typescript
function monitorProcess(proc: ReturnType<typeof Bun.spawn>) {
  const startTime = Date.now();

  proc.exited.then(() => {
    const duration = Date.now() - startTime;
    console.log(`Process exited with code ${proc.exitCode} after ${duration}ms`);
  });

  return proc;
}

const proc = monitorProcess(Bun.spawn(["sleep", "5"]));

守护进程 #

后台运行 #

typescript
function daemonize(command: string[]) {
  const proc = Bun.spawn(command, {
    detached: true,
    stdin: "ignore",
    stdout: "ignore",
    stderr: "ignore",
  });

  proc.unref();
  return proc.pid;
}

const pid = daemonize(["bun", "run", "server.ts"]);
console.log(`Started daemon with PID ${pid}`);

进程管理器 #

typescript
class ProcessManager {
  private processes: Map<string, ReturnType<typeof Bun.spawn>> = new Map();

  start(name: string, command: string[]) {
    if (this.processes.has(name)) {
      throw new Error(`Process ${name} already running`);
    }

    const proc = Bun.spawn(command, {
      stdout: "pipe",
      stderr: "pipe",
    });

    this.processes.set(name, proc);
    console.log(`Started ${name} with PID ${proc.pid}`);

    proc.exited.then(() => {
      this.processes.delete(name);
      console.log(`${name} exited`);
    });

    return proc;
  }

  stop(name: string) {
    const proc = this.processes.get(name);
    if (proc) {
      proc.kill();
      this.processes.delete(name);
      console.log(`Stopped ${name}`);
    }
  }

  list() {
    return [...this.processes.keys()];
  }

  stopAll() {
    for (const name of this.processes.keys()) {
      this.stop(name);
    }
  }
}

const pm = new ProcessManager();
pm.start("server", ["bun", "run", "server.ts"]);
pm.start("worker", ["bun", "run", "worker.ts"]);

console.log(pm.list());

下一步 #

现在你已经了解了 Bun 的进程管理功能,接下来学习 包管理器 深入了解 Bun 的包管理功能。

最后更新:2026-03-29