You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调试Node.js中stdout的意外输出问题?

控制台输出异常缩进问题

相关代码如下:

console.log('A');
console.log('B');
console.log('C');

预期输出应为:

A
B
C

但实际输出却是:

A
 B
  C

这段代码位于一个包含其他逻辑的大型应用中。

我猜测是应用的其他部分向process.stdout写入了空白字符,但尝试捕获所有write调用后,并未找到问题根源:

const traces = [];

const originalStdout = process.stdout.write.bind(process.stdout);

process.stdout.write = (message) => {
    originalStdout(message);
    
    traces.push({
        message,
        stack: new Error().stack,
    });
};

const originalStderr = process.stderr.write.bind(process.stderr);

process.stderr.write = (message) => {
    originalStderr(message);
    
    traces.push({
        message,
        stack: new Error().stack,
    });
};

process.on('SIGINT', () => {
    console.error(traces);
});

生成的输出为:

A
 B
  C
   ^C[
  {
    message: 'A\n',
    stack: 'Error\n' +
      '    at process.stdout.write (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/bin/turbowatch.js:31:16)\n' +
      '    at console.value (node:internal/console/constructor:299:16)\n' +
      '    at console.log (node:internal/console/constructor:376:26)\n' +
      '    at flush (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/createSpawn.js:43:15)\n' +
      '    at output.noLeading (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/createSpawn.js:59:5)\n' +
      '    at Timeout.exec [as _onTimeout] (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/throttle-debounce@5.0.0/node_modules/throttle-debounce/cjs/index.js:85:16)\n' +
      '    at listOnTimeout (node:internal/timers:573:17)\n' +
      '    at process.processTimers (node:internal/timers:514:7)'
  },
  {
    message: 'B\n',
    stack: 'Error\n' +
      '    at process.stdout.write (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/bin/turbowatch.js:31:16)\n' +
      '    at console.value (node:internal/console/constructor:299:16)\n' +
      '    at console.log (node:internal/console/constructor:376:26)\n' +
      '    at flush (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/createSpawn.js:45:15)\n' +
      '    at output.noLeading (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/createSpawn.js:59:5)\n' +
      '    at Timeout.exec [as _onTimeout] (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/throttle-debounce@5.0.0/node_modules/throttle-debounce/cjs/index.js:85:16)\n' +
      '    at listOnTimeout (node:internal/timers:573:17)\n' +
      '    at process.processTimers (node:internal/timers:514:7)'
  },
  {
    message: 'C\n',
    stack: 'Error\n' +
      '    at process.stdout.write (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/bin/turbowatch.js:31:16)\n' +
      '    at console.value (node:internal/console/constructor:299:16)\n' +
      '    at console.log (node:internal/console/constructor:376:26)\n' +
      '    at flush (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/createSpawn.js:46:15)\n' +
      '    at output.noLeading (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/turbowatch@2.16.3/node_modules/turbowatch/dist/createSpawn.js:59:5)\n' +
      '    at Timeout.exec [as _onTimeout] (/Users/gajus/Developer/contra/gaia/node_modules/.pnpm/throttle-debounce@5.0.0/node_modules/throttle-debounce/cjs/index.js:85:16)\n' +
      '    at listOnTimeout (node:internal/timers:573:17)\n' +
      '    at process.processTimers (node:internal/timers:514:7)'
  }
]

为了验证,我尝试了多个Node.js版本和不同终端,但输出均一致。

更奇怪的是,执行以下代码时:

process.stdout.write('A');
process.stdout.write('B');
process.stdout.write('C');

输出为:

ABC

这符合预期——但结合之前console.log的表现,我原本以为会出现空白字符。

这种异常并非一直发生,应该是后台运行的某些程序造成的干扰。我通过在脚本顶部添加定时console.log验证了这一点:

setInterval(() => {
    console.log('|');
}, 10);

脚本输出如下:

|
|
|
|
|
|
|
|
 |
  |
   |
    |
     |
      |
       |
        |
         |
          |
           |
            |
             |
              |
               |
                |
                 |
                  |
                   |
                    |
                     |
|
|
|
|
|
|

看起来有程序在向stdout注入空白字符。但改用process.stdout.write执行相同逻辑时,却没有出现空白字符🤯:

setInterval(() => {
    process.stdout.write('|');
}, 10);

输出:

||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

更诡异的是,如果在这段代码中添加换行符,就又会出现异常行为:

setInterval(() => {
    process.stdout.write('|\n');
}, 10);

输出:

|
|
|
|
 |
  |
   |
    |
     |
      |
       |
        |
         |
          |
           |
            |
             |
              |
               |
                |
                 |
                  |
                   |
                    |
                     |
                      |
|
|
|
|
|
|
|

我还尝试重写stdout和stderr,确保只写入.\n:

const originalStdout = process.stdout.write.bind(process.stdout);

process.stdout.write = (message) => {
    originalStdout('.\n');
};

const originalStderr = process.stderr.write.bind(process.stderr);

process.stderr.write = (message) => {
    originalStderr('.\n')
};

结果依然出现相同的异常:

.
.
.
.
.
 .
  .
   .
    .
     .
      .
       .
        .
         .
          .
           .
            .
             .
              .
               .
                .
                 .
                  .
                   .
.
.
.
.
.

我认为有必要说明,该脚本的其他部分使用了child_process.spawn(),这应该和问题有关。


内容的提问来源于stack exchange,提问作者Gajus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:35:00