在本文中,我们将了解 Google 的 zx 库提供了什么,以及我们如何使用它来使用 Node.js 编写 shell 脚本。然后,我们将通过构建一个命令行工具来学习如何使用 zx 的功能,该工具可以帮助我们修复新的 Node.js 项目引导配置。
编写 Shell 脚本:问题
创建一个 shell 脚本——一个由诸如 Bash 或 zsh 之类的 shell 执行的脚本——可以是自动化重复任务的好方法。Node.js 似乎是编写 shell 脚本的理想选择,因为它为我们提供了许多核心模块,并允许我们导入我们选择的任何库。它还使我们能够访问 JavaScript 提供的语言特性和内置函数。
但是,如果您尝试编写一个在 Node.js 下运行的 shell 脚本,您可能会发现它并不像您希望的那样流畅。您需要为子进程编写特殊处理,注意转义命令行参数,然后最终弄乱stdout(标准输出)和stderr(标准错误)。它不是特别直观,并且会使用 shell 脚本非常尴尬。
Bash shell 脚本语言是编写 shell 脚本的流行选择。无需编写代码来处理子进程,并且它具有用于处理stdout和stderr. 但是用 Bash 编写 shell 脚本也不是那么容易。语法可能很混乱,难以实现逻辑,或处理诸如提示用户输入之类的事情。
Google 的 zx库有助于使用 Node.js 高效且愉快地编写 shell 脚本。
跟随要求
跟随本文有一些要求:
- 理想情况下,您应该熟悉 JavaScript 和 Node.js 的基础知识。
- 您需要能够在终端中轻松运行命令。
- 您需要安装Node.js >= v14.13.1。
本文中的所有代码都可以在 GitHub 上找到。
Google 的 zx 是如何工作的?
Google 的 zx 提供了封装子进程的创建以及处理stdout这些stderr进程的函数。我们将使用的主要函数是$函数。这是它的一个例子:
import { $ } from "zx";
await $`ls`;
这是执行该代码的输出:
$ ls
bootstrap-tool
hello-world
node_modules
package.json
README.md
typescript
上面示例中的 JavaScript 语法可能看起来有点古怪。它使用一种称为标记模板文字的语言功能。它在功能上与写作相同await $("ls")。
Google 的 zx 提供了其他几个实用函数来简化 shell 脚本编写,例如:
- cd(). 这允许我们更改当前的工作目录。
- question(). 这是 Node.js readline模块的包装器。它可以直接提示用户输入。
除了 zx 提供的实用功能外,它还为我们提供了几个流行的库,例如:
- 粉笔。这个库允许我们为脚本的输出添加颜色。
- 极简主义。解析命令行参数的库。然后将它们暴露在argv物体下。
- 取。Fetch API的流行 Node.js 实现。我们可以使用它来发出 HTTP 请求。
- fs-额外。一个库存,它公开了 Node.js 核心fs 模块,以及许多其他方法,可以更轻松地使用文件系统。
现在我们知道 zx 给了我们什么,让我们用它创建我们的第一个 shell 脚本。
使用 Google 的 zx 的 Hello World
首先,让我们创建一个新的项目:
mkdir zx-shell-scripts
cd zx-shell-scripts
npm init --yes
然后我们可以安装zx库:
npm install --save-dev zx
注意:zx文档建议使用 npm 全局安装库。通过将其安装为我们项目的本地依赖项,我们可以确保始终安装 zx,并控制我们的 shell 脚本使用的版本。
顶层await
为了await在 Node.js中使用顶层——在函数await之外async——我们需要在支持顶层的ECMAScript (ES) 模块await中编写代码。"type": "module"我们可以通过添加我们的 来表明一个项目中的所有模块都是 ES 模块package.json,或者我们可以将单个脚本的文件扩展名设置为.mjs. 我们将为.mjs本文中的示例使用文件扩展名。
运行命令并捕获其输出
让我们创建一个名为hello-world.mjs. 我们将添加一个shebang 行,它告诉操作系统 (OS)内核使用程序运行脚本node:
#! /usr/bin/env node
现在我们将添加一些使用 zx 运行命令的代码。
在下面的代码中,我们正在运行一个命令来执行ls程序。该ls程序将列出当前工作目录(脚本所在的目录)中的文件。我们将捕获命令进程的标准输出,将其存储在变量中,然后将其记录到终端:
// hello-world.mjs
import { $ } from "zx";
const output = (await $`ls`).stdout;
console.log(output);
注意:zx文档建议放入/usr/bin/env zx我们脚本的 shebang 行,但我们正在使用它/usr/bin/env node。这是因为我们已经安装zx为项目的本地依赖项。然后我们显式地从包中导入我们想要使用的函数和对象zx。这有助于明确我们脚本中使用的依赖项来自何处。
然后我们将使用chmod使脚本可执行:
chmod u+x hello-world.mjs
让我们运行我们的脚本:
./hello-world.mjs
我们现在应该看到以下输出:
$ ls
hello-world.mjs
node_modules
package.json
package-lock.json
README.md
hello-world.mjs
node_modules
package.json
package-lock.json
READ