ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

PM2 与 stdin 交互式应用:使用 pm2 attach / pm2 send 向受管进程写入输入

PM2 与 stdin 交互式应用:使用 pm2 attach / pm2 send 向受管进程写入输入 运维CLI可观测性【免费下载链接】pm2Node.js/Typescript/Bun Production Process Manager with a built-in Load Balancer.项目地址https://gitcode.com/gh_mirrors/pm/pm2点击查看免费下载导读很多 CLI 工具、REPL 程序、聊天机器人或交互式服务在运行时依赖标准输入stdin接收用户指令。这类进程一旦交给 PM2 守护进程托管终端中的 stdin 便不再直接连通到子进程传统前台输入方式会失效。本文以仓库中的 examples/interact-via-stdin 示例为骨架完整讲解如何通过pm2 attach pm_id实时附加到进程的 stdin/stdout以及如何用pm2 send pm_id line一次性写入输入行并深入 PM2 源码说明其底层实现与使用限制。读完本文你将掌握托管 stdin 交互型 Node.js 应用、用命令向其发送指令、以及理解 PM2 附加机制的适用边界如 cluster 模式限制。场景定位为什么前台输入会失效PM2 通过 fork 或 cluster 模式把应用作为守护进程托管相关逻辑见 lib/God/ForkMode.js 与 lib/God/ClusterMode.js。应用不再直接挂在你的终端上因此直接向启动它的终端敲键盘无法把内容送进应用的 stdin。此时需要两条专用通道实时双向附加pm2 attach pm_id—— 将当前终端接到目标进程的 stdin 与 stdout既可以实时看到进程输出也可以逐行输入内容单向一次性写入pm2 send pm_id line—— 把一行文本直接写入进程的 stdin不建立持续会话。仓库 examples/interact-via-stdin/README.md 给出的核心流程只有两步$ pm2 start stdin.js $ pm2 attach 0下文将围绕这两条命令展开并补充它们对应的源码实现与测试验证。示例应用解读一个监听 stdin 的 Node.js 程序先看示例程序 examples/interact-via-stdin/stdin.js它利用 Node.js 内置的readline模块监听标准输入const readline require(readline); const rl readline.createInterface({ input: process.stdin, output: process.stdout }); rl.prompt(); rl.on(line, (data) { console.log(Received data); console.log(data); }); setInterval(() { //console.log(Yes); }, 2000);要点拆解readline.createInterface({ input: process.stdin, output: process.stdout })把进程的 stdin 作为输入源、stdout 作为输出目标rl.prompt()会在终端打印提示符默认提示用户可以输入rl.on(line, ...)在收到一行输入以换行符结束时触发回调这里打印Received data与原始内容setInterval仅用于保持事件循环活跃避免进程因无待处理事件而退出当前实现中回调被注释掉仅起保活作用。仓库测试中也有一份等价实现 test/fixtures/stdin/stdin.js它把回调写成console.log(Line %s received, line)用于 e2e 验证详见下文测试验证一节。该文件由 test/e2e/cli/attach.sh 引用位于测试夹具stdin/目录与示例代码互相印证。第一步启动 stdin 应用按 README 的说明在示例目录下执行$ pm2 start stdin.js执行后 PM2 会给该进程分配一个数字pm_id通常从 0 开始递增并返回进程列表。这一步的完整形态还可以追加日志重定向等参数例如测试脚本中的用法见 test/e2e/cli/attach.sh$ pm2 start stdin.js -o out-rel.log --merge-logs-o out-rel.log把该进程的 stdout 输出写入out-rel.log--merge-logs合并该应用所有实例此处单实例的日志文件。这样应用收到 stdin 输入后打印的内容会落入日志文件便于后续断言验证。第二步pm2 attach —— 实时附加 stdin/stdout启动完成后README 给出的交互方式是$ pm2 attach 0其中0是刚才启动进程的pm_id。执行后当前终端会被附加到该进程进程打印到 stdout 的内容会实时显示在终端你在终端输入的每一行会被写入该进程的 stdin。命令定义与参数命令在 lib/binaries/CLI.js 中定义commander.command(attach pm_id [command separator]) .description(attach stdin/stdout to application identified by pm_id)pm_id必填必须是进程的数字 ID不能用应用名称[command separator]可选参数作为写入 stdin 时每行末尾追加的分隔符默认是换行符\n。注意代码注释里明确标注了该命令 Not TTY ready即它不是一套完整的 TTY 终端仿真方案而是基于行line的附加会话——进程输出按行流式回显输入按行发送。此外 lib/binaries/CLI.js 第 93 行还提供了一个便捷选项--attachattach logging after your start/restart/stop/reload用于在start、restart、stop、reload之后自动附加日志查看与attach命令配合使用。实现原理读行 总线日志 写入 stdinpm2 attach的完整实现在 lib/API/Extra.js 的CLI.prototype.attach第 311–350 行可拆成三个并行的机制1. 参数校验。命令首先校验pm_idif (isNaN(pm_id)) { Common.printError(pm_id must be a process number (not a process name)); ... }也就是说pm2 attach my-app-name会直接报错必须使用pm2 list展示的进程编号。2. 实时回显 stdout。通过Client.launchBus启动 PM2 事件总线订阅log:*事件bus.on(log:*, function(type, packet) { if (packet.process.pm_id ! parseInt(pm_id)) return; process.stdout.write(packet.data); });只有packet.process.pm_id与目标pm_id匹配的日志包才会被写到当前终端因此附加时不会串台看到其他进程的输出。3. 按行写入 stdin。在当前终端上创建一个readline接口把用户的每一行输入交给sendLineToStdinvar rl readline.createInterface({ input: process.stdin, output: process.stdout }); rl.on(line, function(line) { that.sendLineToStdin(pm_id, line, separator, function() {}); });当用户关闭附加会话如 CtrlD 触发rl.on(close)时进程以成功状态退出 CLI。第三步pm2 send —— 一次性写入一行输入除了持续附加PM2 还提供单行发送命令。它在 lib/binaries/CLI.js 中定义为commander.command(send pm_id line) .description(send stdin to pm_id)用法示例来自测试脚本 test/e2e/cli/attach.sh$ pm2 send 0 LINEsend内部同样调用CLI.prototype.sendLineToStdinlib/API/Extra.js 第 285–305 行它把参数组装成一个数据包并通过远程调用发送给守护进程var packet { pm_id : pm_id, line : line (separator || \n) }; that.Client.executeRemote(sendLineToStdin, packet, function(err, res) { ... });注意这里会自动为行追加换行符除非显式传入自定义 separator这样目标应用用readline按行读取时能立即触发line事件。这与示例中rl.on(line, ...)的消费方式是匹配的。底层原理God.sendLineToStdin 与它的三重限制无论是attach还是send最终都汇聚到守护进程侧的同名方法God.sendLineToStdin实现在 lib/God/ActionMethods.js 第 652–680 行。它是理解该功能边界的关键God.sendLineToStdin function(packet, cb) { if (typeof(packet.pm_id) undefined || !packet.line) return cb(God.logAndGenerateError(pm_id or line field missing), {}); var pm_id packet.pm_id; var line packet.line; var proc God.clusters_db[pm_id]; if (!proc) return cb(God.logAndGenerateError(Process with ID pm_id unknown.), {}); if (proc.pm2_env.exec_mode cluster_mode) return cb(God.logAndGenerateError(Cannot send line to processes in cluster mode), {}); if (proc.pm2_env.status ! cst.ONLINE_STATUS proc.pm2_env.status ! cst.LAUNCHING_STATUS) return cb(God.logAndGenerateError(Process with ID pm_id offline.), {}); try { proc.stdin.write(line, function() { return cb(null, { pm_id : pm_id, line : line }); }); } catch(e) { return cb(God.logAndGenerateError(e), {}); } }从中可以提炼出三条硬性约束pm_id 必须存在且对应已注册进程进程从God.clusters_db[pm_id]中查找找不到会报 Process with ID ... unknown.。仅支持 fork 模式若进程exec_mode cluster_mode即用-i n启动的多实例 cluster 模式会直接返回 Cannot send line to processes in cluster mode。原因从架构上可以推断cluster 模式下存在多个工作进程实例多个 worker 共享/竞争同一 stdin 会引发语义混乱因此 PM2 选择直接禁止。若要使用 stdin 交互务必用默认的 fork 模式启动。进程必须处于可写入状态只有online或launching状态的进程才允许写入stopped、errored等状态会报 Process with ID ... offline.。只有通过上述校验后才会真正执行proc.stdin.write(line, callback)把输入行写入目标进程的 stdin 管道。这解释了为什么示例 README 里要求先pm2 start stdin.js进程必须在线再pm2 attach 0。测试验证attach 场景的 e2e 测试仓库为 stdin 交互提供了完整的端到端测试 test/e2e/cli/attach.sh它直接验证了pm2 send路径cd $file_path/stdin $pm2 start stdin.js -o out-rel.log --merge-logs out-rel.log # Send LINE\n to stdin application $pm2 send 0 LINE cat out-rel.log grep LINE out-rel.log sleep 2 spec Should have reveived line流程为用重定向日志启动 stdin 夹具应用 → 清空日志 → 用pm2 send 0 LINE写入一行 → 在日志文件中 grep 出LINE字样从而断言应用确实从 stdin 收到了该行。该测试由 test/e2e.sh 第 30 行纳入 e2e 测试矩阵。把这一流程套用到交互式调试中即先pm2 start再用pm2 send或pm2 attach喂入指令最后到应用日志里检查响应。实战要点与注意事项pm_id 是数字attach/send均不接受进程名称可通过pm2 list查看目标进程的 IDpm2 attach的校验逻辑在 lib/API/Extra.js 中明确要求数字。fork 模式前提想与 stdin 交互应用必须以 fork 模式启动默认cluster 模式会被God.sendLineToStdin拒绝。行结束符send默认在行尾补\nattach支持通过第二个参数指定自定义 separator适配按其他分隔符解析输入的应用。保持进程存活示例程序用setInterval维持事件循环避免应用因输入暂时为空而退出自己的交互程序也应保证事件循环不提前结束。日志回显附加会话把目标进程的 stdout 实时写到当前终端若同时配置了-o out.log输出也会进入日志文件方便事后回溯。以上内容以 examples/interact-via-stdin/README.md 为骨架结合 examples/interact-via-stdin/stdin.js、lib/binaries/CLI.js、lib/API/Extra.js、lib/God/ActionMethods.js 与 test/e2e/cli/attach.sh 展开。至此你已能完整落地托管 stdin 交互型应用 → 实时附加 → 单行投喂 → 日志验证的整套工作流。赞分享运维CLI可观测性【免费下载链接】pm2Node.js/Typescript/Bun Production Process Manager with a built-in Load Balancer.项目地址https://gitcode.com/gh_mirrors/pm/pm2点击查看免费下载相关推荐N_m3u8DL-RE 快速上手流媒体下载实战指南N_m3u8DL RE 快速上手流媒体下载实战指南 流媒体最让人头疼的不是播放而是页面上那条链接其实只是 m3u8、MPD 这类播放列表文件存下网页也拿CLI音视频PM2 Installer 使用教程PM2 Installer 使用教程 项目介绍 PM2 Installer 是一个用于自动化安装 PM2 作为服务的开源项目特别适用于 Windows 环境PM2 WebUI安装与使用教程PM2 WebUI安装与使用教程 1. 项目介绍 PM2 WebUI是一个强大的Web界面工具为Node.js应用的开发者提供了一个与PM2 Plus相匹敌的上一篇Wot Design Uni 终极指南打造跨平台移动应用的完整解决方案下一篇PyTorch微分方程求解终极指南torchdiffeq完整解析与实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表