Google 出品的 zx:把 Bash 脚本写成 JavaScript,我再也不想回去了

lxiol
📝
Content could not be extracted

原文链接:https://mp.weixin.qq.com/s/LveNHweDAL_4K0WPf0uG9Q

每个程序员都写过 Bash 脚本。

部署、备份、批量处理、CI/CD 流水线——这些场景离不开 Shell。

但 Bash 写起来有多痛苦,只有写过的人知道。

变量不加引号就炸。数组操作反人类。字符串处理全靠 sed 和 awk。错误处理基本靠 set -e 碰运气。想并行执行?先学一遍 xargs -P。

Google 的工程师们显然也被折磨够了。

所以他们造了 zx——用 JavaScript 写 Shell 脚本的工具。

45K Star,Apache-2.0 协议,2021 年开源至今持续更新到 8.8 版本。

一句话:让你用 JavaScript 的全部能力,调用任何 Shell 命令。

看个最简单的例子:

1
2
3
4
5
6
`#!/usr/bin/env zx

const branch = await $`git branch --show-current`
await $`git pull origin ${branch}`
const count = await $`git log --oneline --since="7 days ago" | wc -l`
console.log(`分支: ${branch}, 7天提交: ${count}次`)`

$template literal`` 就是执行 Shell 命令。

返回值是 ProcessPromise,await 后拿到完整输出。

管道、重定向,跟 Bash 一模一样。但你拥有了 JavaScript 的全部武器库。

六个让你立刻想用的特性

1. 变量自动转义——再也不用背引号规则

1
2
`const name = 'foo & bar; rm -rf /'
await $`mkdir /tmp/${name}``

这段代码不会删掉你的硬盘。

${} 里的变量会自动转义,特殊字符被安全处理。

在 Bash 里,同样的场景你需要 "${name}",外层双引号,内层可能还要转义。稍有疏忽就是安全漏洞。

2. Promise.all 并行——Bash 做不到的优雅

1
2
3
4
5
`await Promise.all([
  $`npm run build`,
  $`npm run lint`,
  $`npm test`,
])`

三行代码,三个任务同时跑。

Bash 要并行?要么 &wait,要么 xargs -P,写出来的代码像天书。

3. 内置 fetch——不用再装 curl

1
2
3
`const resp = await fetch('https://api.github.com/repos/google/zx')
const data = await resp.json()
console.log(`Star: ${data.stargazers_count}`)`

zx 直接内置了 fetch API。

HTTP 请求、JSON 解析,原生支持。不用在 Bash 里拼 curl 参数再用 jq 解析了。

4. 管道操作——比 Bash 更强

1
2
3
`const result = await $`echo "hello world"`
  .pipe($`tr '[a-z]' '[A-Z]'`)
  .pipe($`awk '{print $1}'`)`

pipe() 方法可以链式调用,还支持管道到文件、到 Writable Stream。

甚至可以在进程结束后再 pipe——zx 会缓冲所有数据,保证顺序正确。这在 Bash 里根本做不到。

5. 输出直接解析为 JS 对象

1
2
3
`const lines = await $`ls -la`.lines()
const json = await $`cat config.json`.json()
const buf = await $`cat image.png`.buffer()`

.lines() 返回数组,.json() 自动解析,.buffer() 拿到二进制数据。

Bash 里你要 readarrayjq、还有各种奇怪的重定向。

6. Markdown 即脚本——可执行的技术文档

1
2
3
4
5
6
7
8
9
10
11
12
`# 部署脚本

\`\`\`bash
npm run build
\`\`\`

检查构建结果:

\`\`\`javascript
const size = await $`du -sh dist/`
console.log(`构建产物: ${size}`)
\`\`\``

zx deploy.md 直接运行。

把脚本写进 Markdown 文档,既是一份可读的操作手册,也是一个可执行的脚本。

为什么 AI 写脚本了还需要 zx

Claude、GPT 都能写 Shell 脚本,但 AI 生成的 Bash 代码有一个致命问题:看起来正确,实则暗藏杀机。

引号嵌套错一层、变量没加双引号、特殊字符没转义——这些 bug 测试时不出现,上了生产才炸。

zx 的自动转义消灭了整类引号问题。AI 写 zx 不需要判断”这里加不加引号”——因为根本不需要加。

审查也更省心。try/catch 划定风险边界,Promise.all 明确并行范围,const/let 变量有清晰作用域。Bash 脚本十几行管道拼一起,$1 $2 $! 满天飞,一眼看不出哪行有风险。

简单说:更少代码,更不易出错,更容易审查。

上手只需要 30 秒

1
2
3
4
5
6
7
8
9
10
11
12
13
`# 安装
npm install zx

# 写个脚本(用 .mjs 后缀是为了支持顶层 await)
cat > hello.mjs << 'EOF'
#!/usr/bin/env zx
await $`echo "Hello from zx!"`
const pkg = await $`cat package.json`.json()
console.log(`项目: ${pkg.name}`)
EOF

# 运行
npx zx hello.mjs`

支持 Node.js 12+、Bun、Deno,也支持 .ts 文件直接运行。

它适合什么场景

CI/CD 流水线——GitHub Actions 里跑 zx 脚本,比写 Bash 清爽十倍。

运维自动化——批量部署、日志分析、健康检查,配合 JavaScript 的数据处理能力如虎添翼。

开发工具脚本——项目脚手架、代码生成器、本地开发环境初始化。

可执行文档——把操作手册写成 Markdown,团队成员 zx deploy.md 直接跑。

不适合什么

高频调用、对性能要求极致的场景,原生 Bash 还是更快。

纯运维团队不熟悉 JavaScript 的,学习成本不低。

简单的两三行命令,直接 Bash 就好,不需要引入 zx。

最后

zx 不是要消灭 Bash。

简单的命令行操作,Bash 永远是最快的选择。

但当脚本超过 20 行,需要处理 JSON、需要并行、需要 HTTP 请求、需要错误恢复——

zx 给了你一个体面的退路。

用你写了多年的 JavaScript,写那些 Bash 写得让人崩溃的脚本。

项目地址: https://github.com/google/zx

文档: https://google.github.io/zx/

许可证: Apache-2.0

Star: 45K+(2026年4月数据)


💬 本文评论区已开启,但暂无读者留言。

本文转载自微信公众号,如有侵权请联系删除。

  • 标题: Google 出品的 zx:把 Bash 脚本写成 JavaScript,我再也不想回去了
  • 作者: lxiol
  • 创建于 : 2026-04-29 20:17:44
  • 更新于 : 2026-05-12 16:52:54
  • 链接: https://blog.lxiol.cn/2026/04/29/Google-出品的-zx把-Bash-脚本写成-JavaScript我再也不想回去了/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。