node.js 将标准输出重定向到文件 nodejs
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32719923/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Redirecting stdout to file nodejs
提问by Supervision
I've created:
我创建了:
var access = fs.createWriteStream('/var/log/node/api.access.log', { flags: 'w' });
Then piped:
然后管道:
process.stdout.pipe(access);
Then tried:
然后尝试:
console.log("test");
And nothing has appeared in /var/log/node/api.access.log. However this way is working:
/var/log/node/api.access.log 中没有出现任何内容。但是这种方式是有效的:
process.stdout.pipe(access).write('test');
Could someone explain what am I doing wrong ?
有人可以解释我做错了什么吗?
回答by Anatol - user3173842
I solved this problem the following way:
我通过以下方式解决了这个问题:
var access = fs.createWriteStream('/var/log/node/api.access.log');
process.stdout.write = process.stderr.write = access.write.bind(access);
Of course you can also separate stdout and stderr if you want.
当然,如果需要,您也可以将 stdout 和 stderr 分开。
I also would strongly recommend to handle uncaught exceptions:
我也强烈建议处理未捕获的异常:
process.on('uncaughtException', function(err) {
console.error((err && err.stack) ? err.stack : err);
});
This will cover the following situations:
这将涵盖以下情况:
- process.stdout.write
- process.stderr.write
- console.log
- console.dir
- console.error
- someStream.pipe(process.stdout);
- throw new Error('Crash');
- throw 'never do this';
- throw undefined;
- process.stdout.write
- 进程.stderr.write
- 控制台日志
- 控制台目录
- 控制台错误
- someStream.pipe(process.stdout);
- throw new Error('崩溃');
- 抛出“永远不要这样做”;
- 抛出未定义;
回答by richardpringle
Checkout console.Console, the parent class of the normal console.
Checkout console.Console,父类正常console。
var myLogFileStream = fs.createWriteStream(pathToMyLogFile);
var myConsole = new console.Console(myLogFileStream, myLogFileStream);
You can then you use myConsole.log, myConsole.error, myConsole.dir, etc. and write directly to your file.
然后您可以使用myConsole.log、myConsole.error、myConsole.dir等并直接写入您的文件。
You can also monkey patchprocess.stdout.writeas follows:
您还可以按如下方式进行猴子补丁process.stdout.write:
var fn = process.stdout.write;
function write() {
fn.apply(process.stdout, arguments);
myLogFileStream.write.apply(myLogFileStream, arguments);
}
process.stdout.write = write;
there are also other options for overwriting console._stdoutdepending on the motivation for logging the stdoutto a file.
console._stdout根据记录stdout到文件的动机,还有其他覆盖选项。
回答by MIchael Odumosu
@user3173842 for the reply on I solved this problem the following way:
@user3173842 的回复我通过以下方式解决了这个问题:
var access = fs.createWriteStream('/var/log/node/api.access.log');
process.stdout.write = process.stderr.write = access.write.bind(access);
you do understand that process.stdoutcontinues after process.on('exit')and therefore the fs.WriteStreamcloses after with process.stdout, according to
https://github.com/nodejs/node/issues/7606
根据https://github.com/nodejs/node/issues/7606,
您确实了解process.stdout在之后继续process.on('exit'),因此在fs.WriteStream之后关闭process.stdout
so now the question remains, if the developer desired to have the fs.Writestream.write()return to its normal functionality and when fs.Writestream.endis called the writestream closes. How would the developer go about doing this I did
所以现在问题仍然存在,如果开发人员希望fs.Writestream.write()恢复其正常功能以及何时fs.Writestream.end调用 writestream 关闭。开发人员将如何进行我所做的
a_l = asyncify_listener
p_std_stream_m is a process stream manager object
p_std_stream_m.std_info.p_stdout_write = process.stdout.write
process.stdout.write = w_stream.write.bind(w_stream)
process.once('beforeExit', a_l( p_std_stream_m.handler,process.stdout,w_stream ) )
where in the 'beforeExit' event listener I did
process.stdout.write = p_std_stream_m.std_info.p_stdout_write
w_stream.end()
It works and you use the once method because the process.stdoutseems to do a lot of work
at this time.
Is this good practice, would you do this or what would you do in this situation
anyone can feel free to reply.
它有效并且您使用 once 方法,因为此时process.stdout似乎做了很多工作。这是一个好的做法,你会这样做,或者在这种情况下你会做什么,任何人都可以随时回复。
回答by Magus
process.stdoutis a Writable. pipeis a method of Readable(Cf StreamAPI documentation : https://nodejs.org/api/stream.html
process.stdout是可写的。pipe是一种方法Readable(参见 StreamAPI 文档:https://nodejs.org/api/stream.html
You can see the documentation of process.stdouthere : https://nodejs.org/api/process.html#process_process_stdout
您可以在process.stdout此处查看文档:https: //nodejs.org/api/process.html#process_process_stdout
It's surprising that you can do process.stdout.pipe(...);without any error. But i suppose this call just do nothing. Except returning a new Writable stream binded to stdout (or maybe it returns process.stdoutitself. There's no specification for that in the documentation).
令人惊讶的是,您可以毫无错误地进行操作process.stdout.pipe(...);。但我想这个电话什么都不做。除了返回绑定到 stdout 的新 Writable 流(或者它可能返回process.stdout自身。文档中没有具体说明)。
If you want to redirect stdout to a file, you have many solutions :
如果要将标准输出重定向到文件,您有很多解决方案:
- Just use your command line to do that. Windows style :
node myfile.js > api.access.log. - Replace the console object by your own object. And you can rewrite console methods.
- I'm not sure, but it may be possible to replace
process.stdoutwith your own stream (and you can do whatever you want with this)
- 只需使用您的命令行即可。窗户风格:
node myfile.js > api.access.log。 - 用您自己的对象替换控制台对象。您可以重写控制台方法。
- 我不确定,但可以
process.stdout用你自己的流替换(你可以用它做任何你想做的事)
回答by Nikita Kurtin
Originally based on @Anatol-user3173842 answer
最初基于@Anatol-user3173842 答案
But in my case I needed to hook the stdout & stderr and also write into a file.
但就我而言,我需要挂钩 stdout 和 stderr 并写入文件。
So for those who need to keep the normal stdout behaviour in addition to writing into the file. Use the following.
所以对于那些除了写入文件之外还需要保持正常标准输出行为的人。使用以下内容。
For non-errors:
对于非错误:
// stdout logging hook
const stdoutWrite0 = process.stdout.write;
process.stdout.write = (args) => { // On stdout write
CustomLogger.writeToLogFile('log', args); // Write to local log file
args = Array.isArray(args) ? args : [args]; // Pass only as array to prevent internal TypeError for arguments
return stdoutWrite0.apply(process.stdout, args);
};
For errors:
对于错误:
// stderr logging hook
const stderrWrite0 = process.stderr.write;
process.stderr.write = (args) => { // On stderr write
CustomLogger.writeToLogFile('error', args); // Write to local error file
args = Array.isArray(args) ? args : [args]; // Pass only as array to prevent internal TypeError for arguments
return stderrWrite0.apply(process.stderr, args);
};
// uncaught exceptions
process.on('uncaughtException', (err) => {
CustomLogger.writeToLogFile('error', ((err && err.stack) ? err.stack : err));
});
Here is the CustomLoggercode, where I also separate the log files by date:
这是CustomLogger代码,我还按日期分隔日志文件:
export class CustomLogger {
static LOGS_DIR = 'location-of-my-log-files';
private static logDailyName(prefix: string): string {
const date = new Date().toLocaleDateString().replace(/\//g, '_');
return `${CustomLogger.LOGS_DIR}/${prefix}_${date}.log`;
}
private static writeToLogFile(prefix, originalMsg) {
const timestamp = Date.now();
const fileName = this.logDailyName(prefix);
const logMsg = prepareForLogFile(originalMsg);
fs.appendFileSync(fileName, `${timestamp}\t${logMsg}\n\n`);
return originalMsg;
}
}

