Bash + Node.js + stdin/stdout 重定向:错误 "not a tty"
Bash + Node.js + stdin/stdout redirection: error "not a tty"
此问题可能是 Windows 特有的。我没有在 Linux 或 Mac.
上测试过它
我使用:
- Windows 7 64 位
- Node.js 8.1.3
- Git for Windows 2.8.1,包括 GNU bash,版本 4.3.42(5)-release
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
二进制文件本身而不是别名。有一些方法可以实现这一点:
包装在 shell 脚本中,该脚本将直接调用 node
,因为非交互式 shell 不获取 aliases.sh
文件。查看其他答案(sh
和 bash
都有效)
呼叫
env node my-cli.js > foo.txt
或
command node my-cli.js > foo.txt
env
在默认环境下运行命令,效果同上述方法;而 command
是 bash
shell 内置的,用于绕过别名。
- 点赞
\node my-cli.js > foo.txt
或
'node' my-cli.js > foo.txt
或
"node" my-cli.js > foo.txt
反斜杠和引号是明确绕过别名的结构。
- 调用方式
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
不是别名,因此它可以按照您希望的方式工作。
此问题可能是 Windows 特有的。我没有在 Linux 或 Mac.
上测试过它我使用:
- Windows 7 64 位
- Node.js 8.1.3
- Git for Windows 2.8.1,包括 GNU bash,版本 4.3.42(5)-release
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
二进制文件本身而不是别名。有一些方法可以实现这一点:
包装在 shell 脚本中,该脚本将直接调用
node
,因为非交互式 shell 不获取aliases.sh
文件。查看其他答案(sh
和bash
都有效)呼叫
env node my-cli.js > foo.txt
或
command node my-cli.js > foo.txt
env
在默认环境下运行命令,效果同上述方法;而 command
是 bash
shell 内置的,用于绕过别名。
- 点赞
\node my-cli.js > foo.txt
或
'node' my-cli.js > foo.txt
或
"node" my-cli.js > foo.txt
反斜杠和引号是明确绕过别名的结构。
- 调用方式
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
不是别名,因此它可以按照您希望的方式工作。