preserve color when executing child_process.spawn

node.js

node.js Problem Overview


I'm trying to execute a windows command through cmd.exe in node.js using child_process.spawn. It executes correctly, but only displays in default text color. How do I preserver the color. Is it possible?

var spawn = require('child_process').spawn,
	cmd    = spawn('cmd', ['/s', '/c', 'C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild c:\\test.sln']);

cmd.stdout.on('data', function(data){
	process.stdout.write(data);
});

cmd.stderr.on('data', function(data){
	process.stderr.write(data);
});

cmd.on('exit', function(code){
	console.log(code);
});

When executing via node, the color is not preserved. Executing via node.js

When executing via cmd.exe directly, the color is present. (This is the expected behavior). How do I get this behvior when executing via node. When executing through cmd.exe

node.js Solutions


Solution 1 - node.js

There are new 'stdio' option for child_process.spawn(). Try following:

spawn("path to executable", ["params"], {stdio: "inherit"});

"Inherit" means [0, 1, 2] or [process.stdin, process.stdout, process.stderr].

Solution 2 - node.js

crossplatform solution that worked for me was to use both shell: true and stdio: 'inherit':

const spawn = require('child_process').spawn;

spawn('node', ['./child.js'], { shell: true, stdio: 'inherit' });

thanks @59naga https://github.com/nodejs/node/issues/2333

Solution 3 - node.js

If you are getting error:

> Cannot call method 'on' of null

Try this:

spawn("command", ["args"], { env : { FORCE_COLOR: true }});

works with mocha

Solution 4 - node.js

Try this instead:

var spawn = require('child_process').spawn
  , command = 'C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild c:\\test.sln'
  , cmd    = spawn('cmd', ['/s', '/c', command], { customFds: [0,1,2] });

cmd.on('exit', function(code){
    console.log(code);
});

Note that I'm not positive whether or not customFds works on Windows. I know that it's old deprecated functionality doesn't work, but when only passing [0,1,2] as the fd's, I think there is a special case for that.

I've been doing something similar here, but I've only ran that command on Unix machines. So let me know if that works on Windows.

Solution 5 - node.js

This doesn't fix the underlying issue (lack of a proper TTY stream) but it should help get around it.

If the sub-process you're running uses supports-color (https://www.npmjs.com/package/supports-color) like chalk, then you can set an environmental variable FORCE_COLOR to any value and it will skip the rest of the checks. This will allow you to continue to use pipes (and capture/modify the returned data) unlike the inherit fix.

There is also a node-pty (https://www.npmjs.com/package/node-pty) module that provides a .spawn with the ability to pass a pty (pseudo tty) that may be a more holistic answer. I haven't played with it yet, and I'm not sure if it's cross platform or not.

Solution 6 - node.js

If you want to either keep the color or add some notation for the output, you can try the code below:

var spawn = require('child_process').spawn,
var stream = require('stream');
cmd = spawn('cmd', ['/s', '/c', 'C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild c:\\test.sln'], { stdio: [process.stdin, process.stdout, 'pipe'] });
var customStream = new stream.Writable();
customStream._write = function (data, ...argv) {
        console.log('your notation');
        process.stderr._write(data, ...argv);
 };
cmd.stderr.pipe(customStream);

note that the code use es6

Solution 7 - node.js

I have tried many options above, and they did not work. For npm (and probably node) commands, this works:

const ps = _spawn('npm', ['outdated', '--color=always'], { stdio: 'pipe'});
ps.stdout.pipe(process.stdout);
// Then, you can also ps.stdout.on('data',...) for further processing

The trick is the --color=always (using Mac OSX with zsh). I did not need to do the FORCE_COLOR.

However, that does not work for all commands, for example ls does not seem to accept this argument.

Solution 8 - node.js

I was there too. Like said in the thread, there's no colored output because the command you're executing doesn't detect a TTY environment.
If you:

  • Don't want to inherit the child stdout
  • Don't know which command is going to be executed (then you don't know which of e.g --ansi or --colors can work)

Then you should spawn a PTY from node. You may use node-pty, but it is a hassle to install, and it doesn't support latest node versions. Instead, I suggest using this node package that I wrote.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionprabirView Question on Stackoverflow
Solution 1 - node.jsMitch SitinView Answer on Stackoverflow
Solution 2 - node.jsfredericrousView Answer on Stackoverflow
Solution 3 - node.jskonradlukaView Answer on Stackoverflow
Solution 4 - node.jsTooTallNateView Answer on Stackoverflow
Solution 5 - node.jsskarfaceView Answer on Stackoverflow
Solution 6 - node.jsgoumang2010View Answer on Stackoverflow
Solution 7 - node.jsJeremy ChoneView Answer on Stackoverflow
Solution 8 - node.jsCyriacBrView Answer on Stackoverflow