NodeJS 执行child_process.spawn时保留颜色

g52tjvyc  于 2023-01-08  发布在  Node.js
关注(0)|答案(9)|浏览(215)

我正在尝试使用child_process. spawn通过node.js中的cmd.exe执行一个windows命令。它可以正确执行,但只显示默认的文本颜色。我如何保留颜色。可以吗?

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

通过节点执行时,颜色不保留。

直接通过cmd.exe执行时,颜色显示。(这是预期行为)。通过node.

执行时如何获得此行为

pdsfdshx

pdsfdshx1#

child_process.spawn()有新的'stdio'选项。请尝试以下操作:

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

“继承”表示[0、1、2]或[进程.标准输入、进程.标准输出、进程.标准错误]。

42fyovps

42fyovps2#

对我有效的跨平台解决方案是同时使用shell: truestdio: 'inherit'

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

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

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

qyzbxkaa

qyzbxkaa3#

如果出现错误:
无法调用null的方法"on
试试这个:

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

与摩卡咖啡一起使用

1cosmwyk

1cosmwyk4#

试试这个:

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

请注意,我不确定customFds是否能在Windows上工作,我知道它的旧功能不起作用,但当只将[0,1,2]作为fd传递时,我认为这是一种特殊情况。
我在这里也做过类似的事情,但是我只在Unix机器上运行过这个命令,所以请告诉我这个命令在Windows上是否有效。

oknwwptz

oknwwptz5#

这并不能解决根本问题(缺乏适当的TTY流),但它应该有助于解决这个问题。
如果你正在运行的子进程使用supports-color(https://www.npmjs.com/package/supports-color),比如chalk,那么你可以设置一个环境变量FORCE_COLOR为任意值,它将跳过剩下的检查。这将允许你继续使用管道(并捕获/修改返回的数据),这与inherit修复不同。
还有一个node-pty(https://www.npmjs.com/package/node-pty)模块,它为.spawn提供了传递pty(伪tty)的能力,这可能是一个更全面的答案,我还没有尝试过它,我不确定它是否跨平台。

zsbz8rwp

zsbz8rwp6#

我已经尝试了上面的许多选项,它们都不起作用。对于npm(可能还有node)命令,这是有效的:

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

诀窍是--color=always(使用带有zsh的MacOSX)。我不需要做FORCE_COLOR。
然而,这并不适用于所有命令,例如ls似乎不接受此参数。

ldioqlga

ldioqlga7#

如果你想保留颜色或者为输出添加一些符号,你可以尝试下面的代码:

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

91zkwejq8#

我也在那里。就像在线程中说的,没有彩色输出,因为您正在执行的命令没有检测到TTY环境。
如果您:

  • 不想继承子级stdout
  • 不知道要执行哪个命令(那么你就不知道--ansi或--colors中的哪一个可以工作)

然后你应该从节点生成一个PTY,你可以使用node-pty,但是它安装起来很麻烦,而且它不支持最新的节点版本,相反,我建议使用我写的this node package

evrscar2

evrscar29#

为了保留stdout/stderr流中的颜色,不要直接生成应用程序,而是使用unbuffer工具(在linux上,您可能需要运行apt install expect

let app = "command to run";
let args = ["--array", "--of", "--arguments"];
var child = cp.spawn("unbuffer", [app, ...args], {cwd:tempPath()});

child.stdout.on('data', function (data) {
  process.stdout.write('stdout: ' + data);
});

child.stderr.on('data', function (data) {
  process.stdout.write('stderr: ' + data);
});

child.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

相关问题