Bun 中的命令和脚本执行系统处理三项核心职责:脚本执行、环境管理和进程创建。该系统使开发人员能够直接运行 JavaScript/TypeScript 文件(bun file.js)、执行 package.json 脚本(bun run start)以及在设置好适当的环境后创建外部进程。本文档详细介绍了涵盖脚本解析、环境变量管理、进程生命周期和执行流程的内部架构。
有关测试运行器的信息,请参阅 测试命令。
命令和脚本执行系统在 Bun 代码库的多个关键组件中实现。
脚本执行
RunCommand 结构体处理 package.json 脚本的解析和执行。Run 结构体管理 JavaScript/TypeScript 文件的直接执行。runPackageScriptForeground() 处理并执行包脚本。runBinary() 创建外部可执行文件并传递参数。环境管理
DotEnv.Loader 管理从 .env 文件加载环境变量。env_loader.zig 提供全面的环境设置和配置。进程创建
bun.spawn 模块处理跨平台进程创建。Process 结构体管理进程生命周期和退出处理。findShell() 和系统 shell 发现进行 Shell 集成。来源: src/cli/run_command.zig262-411 src/bun_js.zig176-288
运行 JavaScript 或 TypeScript 文件时,Bun 会初始化 JavaScript VM,设置运行时环境,并执行文件。此过程包括:
来源: src/bun_js.zig176-288 src/bun_js.zig290-315
运行 package.json 中定义的脚本时,Bun 会:
来源: src/cli/run_command.zig262-411
对于二进制执行(例如 node_modules/.bin 可执行文件),Bun 会:
在 Windows 上,还会额外处理 .bunx 文件格式,这是一种特殊的二进制可执行文件 shim。
来源: src/cli/run_command.zig432-547
环境管理是处理环境变量加载、继承和所有执行上下文配置的关键组成部分。
DotEnv.Loader 管理一个分层的环境变量系统:
| 优先级 | 来源 | 示例 |
|---|---|---|
| 1(最高) | 进程参数 | NODE_ENV=production bun run build |
| 2 | .env.local | 本地覆盖 |
| 3 | .env.{NODE_ENV}.local | 特定于环境的本地文件 |
| 4 | .env.{NODE_ENV} | 特定于环境的文件 |
| 5(最低) | .env | 基础环境 |
对于 package.json 脚本,系统会设置特定的环境变量。
来源: src/env_loader.zig22-317 src/cli/run_command.zig254-256 src/bun_js.zig254-269
进程创建处理不同执行上下文中的子进程的创建和管理。
创建系统根据目标使用不同的策略。
系统处理平台在进程创建方面的差异。
| 平台 | 方法 | 实现 |
|---|---|---|
| POSIX | posix.fork() + exec() | 直接系统调用 |
| Windows | CreateProcessW | Win32 API,支持 UTF-16 |
| 所有 | bun.spawn.spawnProcess() | 统一接口 |
每个创建的进程都通过 Process 结构体进行管理。
来源: src/bun.js/api/bun/process.zig144-217 src/cli/run_command.zig317-392
命令执行需要找到并使用合适的 shell 来执行 package.json 脚本。
脚本可以根据配置在系统 shell 中执行,也可以使用 Bun 的内置 shell 解释器执行。
来源: src/cli/run_command.zig62-101 src/cli/run_command.zig324-368
为了提高兼容性和性能,Bun 会替换脚本中的包管理器命令。
npm run 变为 bun runyarn run 变为 bun runpnpm run 变为 bun runnpx 变为 bun xpnpx 变为 bun x这样,为 npm/yarn/pnpm 编写的脚本无需修改即可与 Bun 配合使用。
来源: src/cli/run_command.zig140-258
二进制执行涉及解析可执行文件路径,并使用适当的参数传递和环境继承来创建进程。
runBinary() 函数遵循系统的解析方法。
在 Windows 上,Bun 使用复杂的 shim 系统来处理可执行文件解析。
| 组件 | 目的 | 位置 |
|---|---|---|
bun_shim_impl.exe | 通用 shim 可执行文件 | 嵌入在 Bun 二进制文件中 |
.bunx 文件 | Shim 配置文件数据 | 位于目标可执行文件旁边 |
BinLinkingShim | Shim 创建逻辑 | 链接时生成 |
二进制执行会保留参数结构和环境。
createNullDelimitedEnvMap() 创建。来源: src/cli/run_command.zig412-606 src/install/windows-shim/bun_shim_impl.zig1-42 src/install/windows-shim/BinLinkingShim.zig1-28
该系统在所有执行路径中实现了全面的错误处理,保留了退出码和信号,以便与 CI/CD 正确集成。
退出码在整个执行链中被仔细保留。
信号通过特定于平台的机制正确传播。
| 信号 | POSIX 处理 | Windows 处理 |
|---|---|---|
| SIGINT | Global.raiseIgnoringPanicHandler() | 转换为退出码 |
| SIGTERM | 传播到父进程 | 由进程终止处理 |
| SIGKILL | 无法捕获 | 立即终止 |
系统对不同错误类型进行分类和处理
ProcessExitHandler 管理不同类型的子进程
Subprocess:JavaScript 子进程管理LifecycleScriptSubprocess:包管理器生命周期脚本ShellSubprocess:Shell 命令执行ProcessHandle:通用进程管理来源: src/cli/run_command.zig453-606 src/bun.js/api/bun/process.zig86-141 src/bun_js.zig453-468
运行命令在执行测试文件时与测试运行器协调。当一个文件被识别为测试文件时,它会被交给测试运行器执行,而不是直接运行。
这种交接发生在命令解析级别,CLI 根据提供的命令和参数决定是使用运行命令还是测试命令。
以下是运行命令的一些常见用法模式
bun file.jsbun file.tsbun run startbun run eslintbun run test -- --verbose运行命令的设计直观易懂,开发者从 Node.js、npm、yarn 或 pnpm 环境迁移过来能快速上手,同时提供了增强的性能和功能。