如何读取并操作NestJS应用的stdout,过滤指定的knexjs日志提示?
解决方法
方案1:直接从Knex层面关闭警告(更推荐)
你不需要拦截stdout,直接在Knex初始化配置中添加参数即可关闭该特定警告,修改你的Knex连接配置:
import { Knex } from 'knex'; const knexConfig: Knex.Config = { client: 'sqlite3', connection: { filename: './你的数据库文件路径.sqlite3' }, useNullAsDefault: true, // 添加以下配置即可关闭returning相关的sqlite警告 suppressReturningWarning: true };
如果你是用@nestjs/knex模块,直接将上述配置传入KnexModule.forRoot()的参数即可。
方案2:全局拦截stdout做内容过滤
如果确实需要自定义读取、过滤stdout的所有输出,正确的做法是重写process.stdout.write方法,而不是添加data事件监听器:
- 代码必须放在项目入口文件
main.ts的最顶部,早于所有模块、Service的初始化逻辑:
// 先保存原始的stdout写入方法 const originalWrite = process.stdout.write.bind(process.stdout); // 重写写入方法 process.stdout.write = (chunk: any, encoding?: BufferEncoding | ((err?: Error) => void), callback?: (err?: Error) => void) => { if (typeof chunk === 'string') { // 匹配需要过滤的警告内容 if (chunk.includes('.returning() is not supported by sqlite3 and will not have any effect.')) { // 匹配成功直接跳过输出 return true; } } // 其余内容正常输出 return originalWrite(chunk, encoding as BufferEncoding, callback); }; // 后面才是Nest初始化的原有逻辑 async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); } bootstrap();
原代码失效原因说明
process.stdout是可写流,默认不会触发data事件,只有在管道转发场景下才会触发,所以你添加的data监听器根本不会执行。- 你在监听器内部调用了
console.log,而console.log本身会调用process.stdout.write,会形成死循环导致日志输出卡死,所以会出现没有任何消息输出的问题。 - 拦截逻辑如果放在Service内部,加载时机晚于Knex初始化的过程,Knex启动阶段的警告已经输出,无法拦截。
内容的提问来源于stack exchange,提问作者Makuna
相关产品推荐
相关产品推荐

