进程 I/O 的注意事项


process.stdoutprocess.stderr 在重要方面与其他 Node.js 流不同:

  1. 它们分别由 console.log()console.error() 内部使用。
  2. Writes may be synchronous depending on what the stream is connected to and whether the system is Windows or POSIX:
    • 文件:在 Windows 和 POSIX 上是同步的
    • TTY(终端): 在 Windows 上是异步的,在 POSIX 上是同步的
    • 管道(和套接字): 在 Windows 上是同步的,在 POSIX 上是异步的

这些行为部分是出于历史原因,因为更改它们会导致向后不兼容,但某些用户也期望它们。

同步写入避免了诸如使用 console.log()console.error() 写入的输出意外交错的问题,或者如果在异步写入完成之前调用 process.exit() 则根本不写入。 有关详细信息,请参阅 process.exit()

警告:同步写入会阻塞事件循环,直到写入完成。 在输出到文件的情况下,这几乎是瞬时的,但在高系统负载下,接收端没有读取管道,或者终端或文件系统缓慢,事件循环可能经常被阻塞并且时间长到足以对性能产生严重的负面影响。 这在写入交互式终端会话时可能不是问题,但在对流程输出流进行生产日志记录时要特别小心。

要检查流是否连接到 TTY 上下文,请检查 isTTY 属性。

例如:

$ node -p "Boolean(process.stdin.isTTY)"
true
$ echo "foo" | node -p "Boolean(process.stdin.isTTY)"
false
$ node -p "Boolean(process.stdout.isTTY)"
true
$ node -p "Boolean(process.stdout.isTTY)" | cat
false

有关更多信息,请参阅 TTY 文档。

process.stdout and process.stderr differ from other Node.js streams in important ways:

  1. They are used internally by console.log() and console.error(), respectively.
  2. Writes may be synchronous depending on what the stream is connected to and whether the system is Windows or POSIX:
    • Files: synchronous on Windows and POSIX
    • TTYs (Terminals): asynchronous on Windows, synchronous on POSIX
    • Pipes (and sockets): synchronous on Windows, asynchronous on POSIX

These behaviors are partly for historical reasons, as changing them would create backward incompatibility, but they are also expected by some users.

Synchronous writes avoid problems such as output written with console.log() or console.error() being unexpectedly interleaved, or not written at all if process.exit() is called before an asynchronous write completes. See process.exit() for more information.

Warning: Synchronous writes block the event loop until the write has completed. This can be near instantaneous in the case of output to a file, but under high system load, pipes that are not being read at the receiving end, or with slow terminals or file systems, its possible for the event loop to be blocked often enough and long enough to have severe negative performance impacts. This may not be a problem when writing to an interactive terminal session, but consider this particularly careful when doing production logging to the process output streams.

To check if a stream is connected to a TTY context, check the isTTY property.

For instance:

$ node -p "Boolean(process.stdin.isTTY)"
true
$ echo "foo" | node -p "Boolean(process.stdin.isTTY)"
false
$ node -p "Boolean(process.stdout.isTTY)"
true
$ node -p "Boolean(process.stdout.isTTY)" | cat
false

See the TTY documentation for more information.