Bash + Node.js + stdin/stdout 重定向:错误 "not a tty"

Bash + Node.js + stdin/stdout redirection: error "not a tty"

此问题可能是 Windows 特有的。我没有在 Linux 或 Mac.

上测试过它

我使用:

node my-cli.js > foo.txt: 错误 output is not a tty

node my-cli.js < foo.txt: 错误 input is not a tty.

创建文件my-cli:

#!/bin/sh

node "path/to/my-cli.js" "$@"
exit $?

致电./my-cli > foo.txt./my-cli < foo.txt

这也适用于参数:./my-cli --answer 42 > foo.txt

sh -c 'node my-cli.js' > foo.txt 适合我

发生这种情况是因为 Git for Windows 在默认设置下将获取此文件 /etc/profile.d/aliases.sh,这将执行 alias node="winpty node.exe",这是与 [=12] 交互使用所必需的=](以及其他程序,如 python,...)。因此,当您调用 node xxx <yyy >zzz 时,您的 shell 实际上是在后台调用 winpty node xxx

winpty works by starting the winpty-agent.exe process with a new, hidden console window, which bridges between the console API and terminal input/output escape codes. It polls the hidden console's screen buffer for changes and generates a corresponding stream of output.

,但副作用是 stdin 和 stdout 不被识别为 tty 的。

因此,当管道或重定向时,您可能希望调用 node 二进制文件本身而不是别名。有一些方法可以实现这一点:

  1. 包装在 shell 脚本中,该脚本将直接调用 node,因为非交互式 shell 不获取 aliases.sh 文件。查看其他答案(shbash 都有效)

  2. 呼叫
    env node my-cli.js > foo.txt
    command node my-cli.js > foo.txt

env在默认环境下运行命令,效果同上述方法;而 commandbash shell 内置的,用于绕过别名。

  1. 点赞
    \node my-cli.js > foo.txt
    'node' my-cli.js > foo.txt
    "node" my-cli.js > foo.txt

反斜杠和引号是明确绕过别名的结构。

  1. 调用方式
    node.exe my-cli.js > foo.txt
    /full/path/to/node my-cli.js > foo.txt
    relative/path/to/node my-cli.js > foo.txt

别名是 node,不是 node.exe 也不是 path/to/node,它仍然指向实际的二进制文件。

扩展这些解决方案的一种方法是编写一个包装脚本来检测 piping/redirection(这本身就是一个全新的挑战 tbh),它将决定是否使用 winpty

由于我 2022 年来到这里,在 GitBash 中遇到了同样的问题,其他答案之一为我指出了最简单的解决方案。

因为您已经在输入

node my-cli.js > foo.txt

您需要做的就是将 node 更改为 node.exe 并保持其他一切不变。

node.exe my-cli.js > foo.txt

上面的别名答案让我尝试了这个。 node 是别名,但 node.exe 不是别名,因此它可以按照您希望的方式工作。