Перенаправление stdout в файл nodejs

Я создал:

var access = fs.createWriteStream('/var/log/node/api.access.log', { flags: 'w' });

Затем передается по каналу:

process.stdout.pipe(access);

Затем попытался:

console.log("test");

И ничего не появилось в /var/log/ node/api.access.log. Однако этот способ работает:

process.stdout.pipe(access).write('test');

Может кто-нибудь объяснить, что я делаю неправильно?

Ответ 1

Я решил эту проблему следующим образом:

var access = fs.createWriteStream('/var/log/node/api.access.log');
process.stdout.write = process.stderr.write = access.write.bind(access);

Конечно, вы можете также разделить stdout и stderr, если хотите.

Я также настоятельно рекомендую обрабатывать исключенные снимки:

process.on('uncaughtException', function(err) {
  console.error((err && err.stack) ? err.stack : err);
});

Это будет охватывать следующие ситуации:

  • process.stdout.write
  • process.stderr.write
  • console.log
  • console.dir
  • console.error
  • someStream.pipe(process.stdout);
  • сбросить новую ошибку ('Crash');
  • throw "никогда не делайте этого";
  • throw undefined;

Ответ 2

Оформить заказ console.Console, родительский класс нормального console.

var myLogFileStream = fs.createWriteStream(pathToMyLogFile);

var myConsole = new console.Console(myLogFileStream, myLogFileStream);

Затем вы можете использовать myConsole.log, myConsole.error, myConsole.dir и т.д. и записывать непосредственно в свой файл.

Вы также можете патч обезьяны process.stdout.write следующим образом:

var fn = process.stdout.write;

function write() {
  fn.apply(process.stdout, arguments);
  myLogFileStream.write.apply(myLogFileStream, arguments);
}

process.stdout.write = write;

есть также другие варианты перезаписывания console._stdout в зависимости от мотивации записи stdout в файл.

Ответ 3

process.stdout является записываемым. pipe - это метод Readable (документация Cf StreamAPI: https://nodejs.org/api/stream.html

Вы можете увидеть документацию process.stdout здесь: https://nodejs.org/api/process.html#process_process_stdout

Удивительно, что вы можете сделать process.stdout.pipe(...); без ошибок. Но я полагаю, что этот призыв просто ничего не делает. За исключением возврата нового потока Writable, связанного с stdout (или, возможно, он возвращает process.stdout сам. В документации нет спецификации).

Если вы хотите перенаправить stdout в файл, у вас есть много решений:

  • Просто используйте свою командную строку для этого. Стиль Windows: node myfile.js > api.access.log.
  • Заменить объект консоли вашим собственным объектом. И вы можете переписать консольные методы.
  • Я не уверен, но может быть возможно заменить process.stdout на собственный поток (и вы можете делать все, что хотите, с этим)

Ответ 4

@user3173842 для ответа на я решил эту проблему следующим образом:

var access = fs.createWriteStream('/var/log/node/api.access.log');
process.stdout.write = process.stderr.write = access.write.bind(access);

вы понимаете, что process.stdout продолжается после process.on('exit') и поэтому fs.WriteStream закрывается после process.stdout соответствии с https://github.com/nodejs/node/issues/7606

поэтому теперь остается вопрос: если разработчик хотел, чтобы fs.Writestream.write() вернулся к своей нормальной функциональности, и когда fs.Writestream.end, сценарий закрывается. Как бы разработчик сделал это, я сделал

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()

Это работает, и вы используете метод process.stdout потому что process.stdout кажется, делает много работы в это время. Является ли это хорошей практикой, сделаете ли вы это или что бы вы сделали в этой ситуации, любой может ответить.