如何调试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
相关产品推荐
相关产品推荐

