Skip to main content
Bun Shell 让使用 JavaScript 和 TypeScript 编写 shell 脚本变得有趣。它是一个支持 JavaScript 互操作的跨平台类 bash shell。 快速开始:
index.ts

特性

  • 跨平台:可在 Windows、Linux 和 macOS 上运行。无需安装 rimraf 或 cross-env,你可以使用 Bun Shell。它原生实现了 ls、cd 和 rm 等常见 shell 命令。
  • 熟悉易用:Bun Shell 是一个类似 bash 的 shell,支持重定向、管道和环境变量。
  • Glob:Bun Shell 原生支持 glob 模式,包括 **、* 和 {expansion}。
  • 模板字面量:模板字面量可执行 shell 命令,并插入变量和表达式。
  • 安全性:Bun Shell 默认会转义所有字符串,防止 shell 注入攻击。
  • JavaScript 互操作:使用 Response、ArrayBuffer、Blob、Bun.file(path) 和其他 JavaScript 对象作为 stdin、stdout 和 stderr。
  • Shell 脚本:Bun Shell 可运行 shell 脚本(.sh 文件)。
  • 自定义解释器:Bun Shell 是一种使用 Rust 编写的小型编程语言,拥有自己的词法分析器、解析器和解释器。

快速入门

从 echo 开始。要运行它,请使用 $ 模板字面量标签:
默认情况下,shell 命令打印到 stdout。如需关闭输出,可调用 .quiet():
要将命令的输出读取为文本,请使用 .text():
默认情况下,使用 await 会将 stdout 和 stderr 作为 Buffer 返回。

错误处理

默认情况下,非零退出码会抛出错误。ShellError 包含有关已运行命令的信息。
.nothrow() 会禁用错误抛出。请自行检查结果的 exitCode。
要更改所有命令的默认行为,请在 $ 函数本身上调用 .nothrow() 或 .throws(boolean)。

重定向

使用 Bash 中常见的操作符重定向命令的 输入 或 输出:
  • < 重定向 stdin
  • > 或 1> 重定向 stdout
  • 2> 重定向 stderr
  • &> 同时重定向 stdout 和 stderr
  • >> 或 1>> 重定向 stdout,将内容_追加_到目标位置,而不是覆盖
  • 2>> 重定向 stderr,将内容_追加_到目标位置,而不是覆盖
  • &>> 同时重定向 stdout 和 stderr,将内容_追加_到目标位置,而不是覆盖
  • 1>&2 将 stdout 重定向到 stderr(写入 stdout 的内容将转而写入 stderr)
  • 2>&1 将 stderr 重定向到 stdout(写入 stderr 的内容将转而写入 stdout)
Bun Shell 还支持 JavaScript 对象之间的重定向。

示例:重定向输出到 JavaScript 对象 (>)

使用 > 操作符将 stdout 重定向到 JS 对象:
你可以将输出重定向到以下 JavaScript 对象:
  • Buffer、Uint8Array、Uint16Array、Uint32Array、Int8Array、Int16Array、Int32Array、Float32Array、Float64Array、ArrayBuffer、SharedArrayBuffer(写入底层缓冲区)
  • Bun.file(path)、Bun.file(fd)(写入文件)

示例:从 JavaScript 对象重定向输入 (<)

要将 JavaScript 对象用作 stdin,请使用 < 操作符:
你可以从以下 JavaScript 对象重定向输入:
  • Buffer、Uint8Array、Uint16Array、Uint32Array、Int8Array、Int16Array、Int32Array、Float32Array、Float64Array、ArrayBuffer、SharedArrayBuffer(从底层缓冲区读)
  • Bun.file(path)、Bun.file(fd)(从文件读)
  • Response(从 body 读)

示例:重定向 stdin -> 文件

示例:重定向 stdout -> 文件

示例:重定向 stderr -> 文件

示例:重定向 stderr -> stdout

示例:重定向 stdout -> stderr

管道 (|)

和 bash 类似,你可以将一个命令的输出通过管道传给另一个命令:
你也可以用 JavaScript 对象做管道:

命令替换 ($(...))

命令替换会将另一个命令的输出插入当前脚本中:
Bun Shell 会将输出作为文本插入,因此你可以用它来声明 shell 变量:
由于 Bun 在内部使用输入模板字面量上的特殊 raw 属性,因此使用反引号语法进行命令替换不起作用:
不会打印:
它会打印:
请改用 $(...) 语法。

环境变量

像在 bash 中一样设置环境变量:
使用字符串插值来设置值:
Bun Shell 默认会转义输入,防止 shell 注入攻击:

修改环境变量

默认情况下,所有命令都使用 process.env 作为其环境变量。 要修改单个命令的环境变量,请调用 .env():
要修改所有命令的默认环境变量,请调用 $.env:
要将环境变量重置为默认值,请不带参数调用 $.env():

修改工作目录

要修改命令的工作目录,请将字符串传递给 .cwd():
要修改所有命令的默认工作目录,请调用 $.cwd:

读取输出

使用 .text() 以字符串形式读取命令输出:

读取 JSON 格式的输出

使用 .json() 读取命令的 JSON 输出:

按行读取输出

使用 .lines() 按行读取命令输出:
你也可以在管道命令上使用 .lines():

将输出读取为 Blob

使用 .blob() 以 Blob 形式读取输出:

内置命令

为了兼容跨平台环境,除了从 PATH 环境变量中读取命令外,Bun Shell 还实现了一组内置命令。
  • cd:切换工作目录
  • ls:列出目录文件
  • rm:删除文件和目录
  • echo:打印文本
  • pwd:打印当前工作目录
  • bun:在 bun 中运行 bun
  • cat
  • touch
  • mkdir
  • which
  • mv
  • exit
  • true
  • false
  • yes
  • seq
  • dirname
  • basename
尚未实现,但已列入计划:

工具函数

Bun Shell 也实现了一些用于处理 shell 的工具函数。

$.braces(花括号扩展)

$.braces 为 shell 命令实现了花括号扩展:

$.escape(转义字符串)

暴露了 Bun Shell 的字符串转义逻辑:
若要跳过转义,请将字符串包装在 { raw: 'str' } 对象中:

.sh 文件加载器

对于简单的 shell 脚本,你可以使用 Bun Shell 来代替 /bin/sh。将扩展名为 .sh 的文件传递给 bun:
script.sh
terminal
Bun Shell 脚本是跨平台的,因此可以在 Windows 上运行:
powershell

实现说明

Bun Shell 是一种使用 Rust 实现的小型编程语言,拥有手写的词法分析器、解析器和解释器。与 bash、zsh 及其他 Shell 不同,Bun Shell 会并发运行操作。

Bun Shell 的安全性

根据设计,Bun Shell 不会调用系统 shell,例如 /bin/sh。它是 Bash 的重新实现,运行在同一个 Bun 进程中。 解析命令参数时,Bun Shell 会将所有_插值变量_视为单个字面字符串。 这可以防止命令注入:
在这里,Bun Shell 会将 userInput 视为单个字符串,因此 ls 会尝试读取名为 my-file.txt; rm -rf / 的单个目录的内容。

安全注意事项

虽然 Bun Shell 默认会防止命令注入,但在某些情况下,你仍需自行负责安全性。 与 Bun.spawn 或 node:child_process.exec() API 类似,你可以有意执行一个会使用参数生成新 shell 的命令(例如 bash -c)。 此时,你交出了控制权,Bun 内置的保护机制不再适用,字符串将由新 shell 解释执行。

参数注入

Bun Shell 无法知晓外部命令如何解释其自身的命令行参数。攻击者可以提供目标程序会识别为自身选项或标志的输入,从而导致非预期行为。
建议:始终清理用户提供的输入,然后再将其作为参数传递给外部命令。 验证参数是应用程序的责任。

致谢

该 API 很大程度上受到 zx、dax 和 bnx 启发,感谢这些项目的作者。