Node.js CLI 与 readline:交互脚本与 REPL
很多人只把 Node 当 服务端运行时;其实 工具链、脚手架、运维脚本 也大量用 Node 写 CLI。
这一篇围绕 命令行入口 展开,想讲清楚几件事:process.argv与参数约定、readline适合什么交互、以及 REPL 在调试里扮演什么角色。
从 process.argv 到「像样的 CLI」
process.argv 是一个字符串数组:
- 前两项通常是 node 路径 和 脚本路径;
- 真正业务参数从 下标 2 起。
手写解析很快会乱,工程上常见:
minimist/yargs/commander等库做 子命令、选项、默认值;--之后 透传给子进程的规则要 文档化。
习惯:
- 退出码:成功 0,用法错误 1 或其它约定,和 CI 联动;
- stderr 打错误,stdout 打出给机器或管道用的结果,方便 shell 组合。
stdin / stdout / stderr:管道与 TTY
process.stdin 可读,stdout / stderr 可写。
要点:
- 判断 是否 TTY(
process.stdin.isTTY):交互式 CLI 和 管道喂数据 是两条路径; - 大输入 用 流式读,不要
readFileSync(0)一把梭 unless 场景明确。
和 Stream 篇一致:字节流 进,按行或按协议 切。
readline:问答式、逐行日志处理
readline.createInterface({ input, output }) 常用于:
- 密码工具、迁移向导:一问一答;
input接文件流或 stdin,逐行 处理日志、CSV。
特点:
- 按行 舒服,二进制协议 不适合;
- 关闭时要
rl.close(),避免 句柄挂住进程(配合unref或显式exit)。
复杂 全屏 TUI(表格、快捷键)会换 blessed、ink 等库,readline 只管 简单文本交互。
REPL:node 不加脚本时
node 直接进入 REPL:交互执行 JS,适合:
- 试一小段 API;
- 看模块导出(
require('fs')); - 临时算个数。
局限:
- 和项目里的 tsconfig / 路径别名 不一致时要 用
node -r或先编译; - 有副作用的模块 不要随便
require试。
repl 模块 也可嵌进自有工具里做 小控制台,属于进阶用法。
shebang 与可执行文件:#!/usr/bin/env node
发布 CLI 包时常在入口文件第一行:
#!/usr/bin/env node(Unix);package.json里bin字段映射到该文件。
Windows 下 npm 会生成 cmd 包装,具体行为以 npm 文档 为准。
小结:CLI 也是「产品」
- 参数与退出码 是可组合性的一部分;
- stdin/stdout 语义 分清,方便脚本串联;
readline覆盖 问答与按行;复杂 UI 另选栈;- REPL 适合 快试,不等于 替代测试。
把 CLI 写稳,和 包管理、生产运行 两篇一起看,工具发布与运维体验会连成一条线。