盒子
盒子

基于进程对象process将日志、错误写入不同文件

process同样是一个全局对象,它提供了对标准流的访问接口。而process.stdoutprocess.stderr都是可写流,要将process.stdoutprocess.stderr中的数据写入不同的文件,首先需要将其转换为一个可读流双工流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const fs = require('fs');
const stream = require('stream');
const rawStdout = process.stdout;
const rawStderr = process.stderr;
// 创建一个PassThrough流
const newStdout = new stream.PassThrough();
const newStderr = new stream.PassThrough();
// 重新定义 process.stdout 的Getter
process.__defineGetter__('stdout',function(){
// 原样返回 PassThrough
return newStdout;
});
// 重新定义 process.stderr 的Getter
process.__defineGetter__('stderr',function(){
// 原样返回 PassThrough
return newStderr;
});
// 将 process.stdout 中的数据写入 stdout.log 文件
newStdout.pipe(fs.createWriteStream('./stdout.log'));
// 将 process.stderr 中的数据写入 stderr.log 文件
newStderr.pipe(fs.createWriteStream('./stderr.log'));
console.log('向 stdout 中写入数据');
console.error('向 stderr 中写入数据');

按这个来可以实现一个基础版的日志,不过fs.createWriteStream方法最好用追加的模式newStdout.pipe(fs.createWriteStream('./stdout.log',{'flags':'a'}));这样子每次重启就不会把之前的日志覆盖掉了。按目前的代码,可以很好的工作。

然后当我的程序在express中跑的时候,会发现console.log输入的内容直接在控制台中打印?而对应的日志文件stdout.log为空,怎么运行不了了?我的日志呢?

追查原因,发现是代码引入了consolidate(多模版引擎共存v0.14.1)模块引入问题,继续追查,发现是consolidate中引入的bluebird模版的问题,继续追查,发现是bluebird.js引入的promise.js的问题,继续追查,发现是promise.js引入的debuggability.js的问题。debugger半天,代码终于停留在了让我感觉毛骨悚然的地方,代码第802行:

1
typeof console !== "undefined" && typeof console.warn !== "undefined"

细看一下,不就是判断console是否为undefined吗?接着校验console.warn是否为undefined吗?怎么回事?

先看看代码正常的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var fs = require('fs');
var stream_mao = require('stream');
var rawStdout = process.stdout;
var rawStderr = process.stderr;
// 创建一个PassThrough流
var newStdout = new stream_mao.PassThrough();
var newStderr = new stream_mao.PassThrough();
// 重新定义 process.stdout 的Getter
process.__defineGetter__('stdout',function(){
// 原样返回 PassThrough
return newStdout;
});
// 重新定义 process.stderr 的Getter
process.__defineGetter__('stderr',function(){
// 原样返回 PassThrough
return newStderr;
});
// 将 process.stdout 中的数据写入 stdout.log 文件
newStdout.pipe(fs.createWriteStream( process.cwd() + '/stdout.log',{'flags':'a'}));
// 将 process.stderr 中的数据写入 stderr.log 文件
newStderr.pipe(fs.createWriteStream(process.cwd() + '/stderr.log',{'flags':'a'}));
console.log('向 stdout 中写入数据');
console.error('向 stderr 中写入数据');

控制台测试:

process_stdout_success控制台打印

日志写入成功。

接着看看添加那句逻辑运算符代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var fs = require('fs');
var stream_mao = require('stream');
var rawStdout = process.stdout;
var rawStderr = process.stderr;
// 创建一个PassThrough流
var newStdout = new stream_mao.PassThrough();
var newStderr = new stream_mao.PassThrough();
// 就添加了这行代码,其他不变
typeof console !== "undefined" && typeof console.warn !== "undefined";
// 重新定义 process.stdout 的Getter
process.__defineGetter__('stdout',function(){
// 原样返回 PassThrough
return newStdout;
});
// 重新定义 process.stderr 的Getter
process.__defineGetter__('stderr',function(){
// 原样返回 PassThrough
return newStderr;
});
// 将 process.stdout 中的数据写入 stdout.log 文件
newStdout.pipe(fs.createWriteStream( process.cwd() + '/stdout.log',{'flags':'a'}));
// 将 process.stderr 中的数据写入 stderr.log 文件
newStderr.pipe(fs.createWriteStream(process.cwd() + '/stderr.log',{'flags':'a'}));
console.log('向 stdout 中写入数据');
console.error('向 stderr 中写入数据');

控制台测试:

process_stdout_error控制台打印

也就是日志文件没写入。

我就在第8行加了这句诡异的代码,我的世界就崩溃了。。。

我的node版本是:v0.12.7,应该是系统问题,不是引入的第三方模块的问题,有解决方案的可以共享

支持一下
扫一扫,支持lcoder