【问题标题】:preserve color when executing child_process.spawn执行 child_process.spawn 时保留颜色
【发布时间】:2011-10-11 12:08:59
【问题描述】:

我正在尝试使用 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 执行时,颜色是存在的。 (这是预期的行为)。通过节点执行时如何获得这种行为。

【问题讨论】:

  • +1 用于简单、可执行的示例,以及解释现在和以后的漂亮屏幕截图。不错!

标签: node.js


【解决方案1】:

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

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

“继承”表示 [0, 1, 2] 或 [process.stdin, process.stdout, process.stderr]。

【讨论】:

  • +1 很好的解决方案,不使用已弃用的功能。在我看来,这绝对是成功的答案。
  • 效果很好!注意:像spawnedThing.stdout.onspawnedThing.stderr.on 这样的事件函数将不再存在,因为它从其父级继承了写入流。当我收到此错误消息时,我花了一点时间才意识到这一点:Cannot call method 'on' of null
  • 我有一个与 Chris 提到的有关的问题 - 我想在每一行输出中添加一些自定义文本,所以我需要“on”功能,但既然它们现在已经消失了,我该如何保留原始输出颜色并为输出的每一行添加一些内容?
  • 在 Windows 下也适用于我。
  • 对于那些有Cannot call method 'on' of null 错误的人...当您将stdio 设置为继承时,您可以在父进程中使用process.stdout.on,因为子进程从中继承stdio。
【解决方案2】:

对我有用的跨平台解决方案是同时使用 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

【讨论】:

  • 这行得通,但你怎么知道哪个日志来自哪个子进程?使用inherit 将使子进程日志的行为类似于父进程日志。
  • 我的目标是在日志到达控制台时显示它们。就像我们在詹金斯构建控制台中看到的那样。就我而言,我不在乎区分哪个日志来自何处。使用我使用的解决方案是唯一适合我需要的解决方案。顺便说一句,我推荐的正确记录日志的解决方案是 bunyan。温斯顿也很棒,但班扬更轻
  • 太棒了,正是我需要的!
【解决方案3】:

如果遇到错误:

无法调用 null 的“on”方法

试试这个:

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

适用于摩卡

【讨论】:

  • 如果你收到错误“spawn node ENOENT”,这个变体对我有用:process.env.FORCE_COLOR = true; spawn("command", ["args"], { env: process.env });
  • 谢谢@konradluka。我需要在我的代码中设置stdio: ['pipe', 'pipe', 'pipe'],所以添加FORCE_COLOR env var 对我有用!
  • 你是传奇
  • 这是为我解决问题的唯一答案,谢谢!
【解决方案4】:

试试这个:

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 传递时,我认为这是一种特殊情况。

我一直在做something similar here,但我只在 Unix 机器上运行过该命令。所以让我知道这是否适用于 Windows。

【讨论】:

  • 由于customFds 已被弃用,有没有办法在Unix 机器上不使用customFds 来做到这一点?
  • @JPrichardson 不幸的是,如果没有已弃用的customFds,就没有其他方法可以做到这一点。我不相信它会很快消失,尤其是对于这个用例。
  • 作为旁注@prabir,我假设您正在尝试为节点编译本机插件。你绝对应该结帐node-gyp 并使用它,它会让生活更轻松:)
  • 附带说明,任何真正想要此功能的人都应该对此表示赞同:github.com/joyent/node/issues/2754
  • 这对我在 ubuntu bash 下仅使用 ls 不起作用
【解决方案5】:

这并不能解决根本问题(缺少适当的 TTY 流),但应该有助于解决这个问题。

如果您正在运行的子进程使用支持颜色 (https://www.npmjs.com/package/supports-color),例如粉笔,那么您可以将环境变量 FORCE_COLOR 设置为任何值,它将跳过其余的检查。这将允许您继续使用管道(并捕获/修改返回的数据),这与 inherit 修复不同。

还有一个 node-pty (https://www.npmjs.com/package/node-pty) 模块,它为 .spawn 提供了传递 pty(伪 tty)的能力,这可能是一个更全面的答案。还没玩过,不知道是不是跨平台的。

【讨论】:

  • 我可以确认这是可行的,并且可以保留颜色,同时能够捕获和修改stdout。顺便说一句,我只需将环境变量传递给spawn 选项env,就可以轻松设置环境变量!
  • 不知何故我错过了一些东西。我试过这个,但是当我这样做时: process.env.FORCE_COLOR = 'true'; const proc = execa('npm', ['outdated'], { cwd: dir, stdout: 'pipe', reject: false, env: process.env }); proc.stdout?.pipe(process.stdout);颜色不起作用,但如果我输入标准输出:process.stdout(并删除.pipe),颜色会显示。我一定是错过了什么。
【解决方案6】:

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

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

注意代码使用的是es6

【讨论】:

  • 不能为我解决问题。
【解决方案7】:

我在上面尝试了很多选项,但它们都不起作用。对于 npm(也可能是节点)命令,这是可行的:

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 的 Mac OSX)。我不需要做 FORCE_COLOR。

但是,这不适用于所有命令,例如 ls 似乎不接受此参数。

【讨论】:

    【解决方案8】:

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

    • 不想继承子标准输出
    • 不知道将要执行哪个命令(然后您不知道 --ansi 或 --colors 中的哪一个可以工作)

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

    【讨论】:

    • 当链接到您自己的网站或内容(或您附属的内容)时,您must disclose your affiliation in the answer 以免被视为垃圾邮件。根据 Stack Exchange 政策,在您的用户名中包含与 URL 相同的文本或在您的个人资料中提及它不被视为充分披露。此外,这是您最近第三个链接到包裹的答案,即使披露也接近过度自我推销。
    • 知道了。我试图尽可能多地曝光,让其他人知道存在解决方案,这样他们就不会像我一样绝望。但从现在开始我会小心的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 1970-01-01
    • 1970-01-01
    • 2013-09-20
    • 1970-01-01
    • 2017-01-07
    相关资源
    最近更新 更多