用日志消息退出node.js脚本的正确方法是什么?

我有一个node.js脚本,使用WriteStream执行一些日志logging到文件。 在某些事件中,我想停止脚本的执行,即警告在此之后立即login并退出。 asynchronousNode.js不允许我们这样做直截了当,如:

#!/usr/local/bin/node var fs = require('fs'); var stream = fs.createWriteStream('delme.log', { flags: 'a' }); stream.write('Something bad happened\n'); process.exit(1); 

这个脚本并没有向delme.log追加消息,而是对该文件不做任何处理。 处理“退出”事件和冲洗不起作用。 在退出之前写入最后一条日志消息的唯一方法是在setTimeout()包装process.exit(1) setTimeout()

 #!/usr/local/bin/node var fs = require('fs'); var stream = fs.createWriteStream('delme.log', { flags: 'a' }); stream.write('Something bad happened\n'); setTimeout(function(){ process.exit(1); }, 30); 

然而在这种forms下,它不会立即停止脚本的执行,脚本将在发生严重事件后运行一段时间。 所以我想知道是否有其他方式退出脚本与日志消息?

既然你想阻止,而且已经在使用stream,你可能会想要自己处理写作。

 var data = new Buffer('Something bad happened\n'); fs.writeSync(stream.fd, data, 0, data.length, stream.pos); process.exit(); 

改进。

 var fs = require('fs'); var stream = fs.createWriteStream('delme.log', {flags: 'a'}); // Gracefully close log process.on('uncaughtException', function () { stream.write('\n'); // Make sure drain event will fire (queue may be empty!) stream.on('drain', function() { process.exit(1); }); }); // Any code goes here... stream.write('Something bad happened\n'); throw new Error(SOMETHING_BAD); 

try-catch块的工作原理是丑陋的。 尽pipe如此,信贷去@nab,我只是对它进行了美化。

要在退出之前将所有日志消息刷新到文件,可能需要将脚本执行包装在try-catch块中。 一旦发生了不好的事情,它就会被logging下来,并引发一个exception,这个exception将被外部try从中asynchronous取出:

 #!/usr/local/bin/node var fs = require('fs'); var stream = fs.createWriteStream('delme.log', { flags: 'a' }); var SOMETHING_BAD = 'Die now'; try { // Any code goes here... if (somethingIsBad) { stream.write('Something bad happened\n'); throw new Error(SOMETHING_BAD); } } catch (e) { if (e.message === SOMETHING_BAD) { stream.on('drain', function () { process.exit(1); }); } else { throw e; } } 

我会主张在这个事件中写信给stderr,比如微不足道的例子

 console.error(util.inspect(exception)); 

然后让监督*进程处理日志持久性。 从我现在的理解,你不必担心标准输出和stderr在节点退出之前没有刷新(虽然我在0.2.x版本中看到了有问题的相反行为)。

(*)监督的过程中,从supervisord,上帝,monit,永远,pswatch等select…

这也提供了一个干净的path来使用PaaS提供商,如Heroku和dotcloud等…让基础设施pipe理日志logging

我认为这是正确的方法:

 process.on('exit', function (){ // You need to use a synchronous, blocking function, here. // Not streams or even console.log, which are non-blocking. console.error('Something bad happened\n'); });