Skip to content

Instantly share code, notes, and snippets.

@pguillory
Created December 5, 2010 23:51
Show Gist options
  • Save pguillory/729616 to your computer and use it in GitHub Desktop.
Save pguillory/729616 to your computer and use it in GitHub Desktop.
Hooking into Node.js stdout
var util = require('util')
function hook_stdout(callback) {
var old_write = process.stdout.write
process.stdout.write = (function(write) {
return function(string, encoding, fd) {
write.apply(process.stdout, arguments)
callback(string, encoding, fd)
}
})(process.stdout.write)
return function() {
process.stdout.write = old_write
}
}
console.log('a')
console.log('b')
var unhook = hook_stdout(function(string, encoding, fd) {
util.debug('stdout: ' + util.inspect(string))
})
console.log('c')
console.log('d')
unhook()
console.log('e')
console.log('f')
@dmarcelino
Copy link

Thanks @pguillory, I've used it on debug-logger

@wthit56
Copy link

wthit56 commented Oct 12, 2015

Genius! In my implementation, I created a new object to add my changes to:

var stdout = process.stdout;
var shadow = process.stdout = Object.create(process.stdout);
shadow.original = stdout;
shadow.write = function() {
    // stdout.original.write.apply(stdout, arguments); // not shown
    result.stdout += data;
};

(Which didn't work. Ignore me. ;P)

@jkuri
Copy link

jkuri commented Jan 28, 2016

Thanks for this.

@karlpokus
Copy link

FYI. Commenting out this line mutes the log too.

@reliasn
Copy link

reliasn commented Dec 14, 2016

This implementation redirects both stdout and stderr to a log file:

var log_file = require('fs').createWriteStream(__dirname + '/log.txt', {flags : 'w'})

function hook_stream(stream, callback) {
  var old_write = stream.write

  stream.write = (function(write) {
    return function(string, encoding, fd) {
      write.apply(stream, arguments)  // comments this line if you don't want output in the console
      callback(string, encoding, fd)
    }
  })(stream.write)

  return function() {
    stream.write = old_write
  }
}

console.log('a')
console.error('b')

var unhook_stdout = hook_stream(process.stdout, function(string, encoding, fd) {
  log_file.write(string, encoding)
})

var unhook_stderr = hook_stream(process.stderr, function(string, encoding, fd) {
  log_file.write(string, encoding)
})

console.log('c')
console.error('d')

unhook_stdout()
unhook_stderr()

console.log('e')
console.error('f')

It should print in the console

a
b
c
d
e
f

and in the log file:

c
d

@dherault
Copy link

dherault commented Jun 10, 2019

This one works with AWS Lambda:

function hookStdout(callback) {
  const boundProcessStdout = process.stdout.write.bind(process.stdout)
  const boundProcessStderr = process.stderr.write.bind(process.stderr)

  process.stdout.write = (string, encoding, fd) => {
    boundProcessStdout(string, encoding, fd)
    callback(string, encoding, fd, false)
  }

  process.stderr.write = (string, encoding, fd) => {
    boundProcessStderr(string, encoding, fd)
    callback(string, encoding, fd, true)
  }

  return () => {
    process.stdout.write = boundProcessStdout
    process.stderr.write = boundProcessStderr
  }
}

@MaiTrinh
Copy link

MaiTrinh commented Nov 3, 2020

thanks for this.

@nexensys
Copy link

Thank you so much for this! I'm trying to make an advanced CLI for a nextjs app, but webpack uses stdout and messes up all of the formatting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment