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

时间:2012-02-08 10:10:50

标签: node.js

我有一个node.js脚本,它使用WriteStream对文件进行一些日志记录。在某些事件上,我想停止执行脚本,即警告记录并在此之后立即退出。 asyncronious node.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附加消息。处理'退出'事件和刷新不起作用。到目前为止,在退出之前写入最后一条日志消息的唯一方法是将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);

但是在这种形式下,它不会立即停止脚本执行,并且在关键事件发生后脚本将运行一段时间。所以我想知道是否有其他方法可以通过日志消息退出脚本?

5 个答案:

答案 0 :(得分:12)

由于你想要阻止,并且已经在使用流,你可能想要自己处理写作。

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

答案 1 :(得分:3)

要在退出之前将所有日志消息刷新到文件,可能需要在try-catch块中包装脚本执行。一旦发生了坏事,它就会被记录并抛出一个异常,这个异常将被外部try捕获,从中可以安全地异步退出:

#!/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;
  }
}

答案 2 :(得分:3)

<强>改进。

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块工作但很难看。学分仍然是@nab,我只是美化了它。

答案 3 :(得分:1)

我主张在这个事件中写给stderr - 例如琐碎的例子

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

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

(*)对于监督过程,请选择supervisord,god,monit,forever,pswatch等......

这也为使用Heroku和dotcloud等PaaS提供商提供了一条干净的道路......让基础设施管理日志记录

答案 4 :(得分:1)

我认为这是正确的方法:

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');
});