bash 如何检测 Node.js 脚本是否正在通过 shell 管道运行?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15466383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to detect if a Node.js script is running through a shell pipe?
提问by Mathias Bynens
My question is similar to this one: How to detect if my shell script is running through a pipe?. The difference is that the shell script I'm working on is written in Node.js.
我的问题与此类似:如何检测我的 shell 脚本是否正在通过管道运行?. 不同之处在于我正在处理的 shell 脚本是用 Node.js 编写的。
Let's say I enter:
假设我输入:
echo "foo bar" | ./test.js
Then how can I get the value "foo bar"in test.js?
然后,我怎么能得到的价值"foo bar"的test.js?
I've read Unix and Node: Pipes and Streamsbut that only seems to offer an asynchronous solution (unless I'm mistaken). I'm looking for a synchronous solution. Also, with this technique, it doesn't seem very straightforward to detect if the script is being piped or not.
我读过Unix and Node: Pipes and Streams但这似乎只提供了一个异步解决方案(除非我弄错了)。我正在寻找同步解决方案。此外,使用这种技术,检测脚本是否被管道传输似乎不是很简单。
TL;DR My question is two-fold:
TL; DR 我的问题有两个:
- How to detect if a Node.js script is running through a shell pipe, e.g.
echo "foo bar" | ./test.js? - If so, how to read out the piped value in Node.js?
- 如何检测 Node.js 脚本是否正在通过 shell 管道运行,例如
echo "foo bar" | ./test.js? - 如果是这样,如何在 Node.js 中读出管道值?
采纳答案by Jerome WAGNER
Pipes are made to handle small inputs like "foo bar" but also huge files.
管道用于处理像“foo bar”这样的小输入以及大文件。
The stream API makes sure that you can start handling data without waiting for the huge file to be totally piped through (this is better for speed & memory). The way it does this is by giving you chunks of data.
流 API 确保您可以开始处理数据而无需等待大文件完全通过管道(这对速度和内存更好)。它这样做的方式是为您提供大量数据。
There is no synchronous API for pipes. If you really want to have the whole piped input in your hands before doing something, you can use
管道没有同步 API。如果您真的想在做某事之前将整个管道输入掌握在手中,您可以使用
note: use only node >= 0.10.0because the example uses the stream2 API
注意:仅使用node >= 0.10.0因为示例使用了 stream2 API
var data = '';
function withPipe(data) {
console.log('content was piped');
console.log(data.trim());
}
function withoutPipe() {
console.log('no content was piped');
}
var self = process.stdin;
self.on('readable', function() {
var chunk = this.read();
if (chunk === null) {
withoutPipe();
} else {
data += chunk;
}
});
self.on('end', function() {
withPipe(data);
});
test with
测试
echo "foo bar" | node test.js
and
和
node test.js
回答by Mathias Bynens
I just found out a simpler answer to part of my question.
我刚刚为我的部分问题找到了一个更简单的答案。
To quickly and synchronously detect if piped content is being passed to the current script in Node.js, use the process.stdin.isTTYboolean:
要快速同步地检测管道内容是否正在传递给 Node.js 中的当前脚本,请使用process.stdin.isTTY布尔值:
$ node -p -e 'process.stdin.isTTY'
true
$ echo 'foo' | node -p -e 'process.stdin.isTTY'
undefined
So, in a script, you could do something like this:
因此,在脚本中,您可以执行以下操作:
if (process.stdin.isTTY) {
// handle shell arguments
} else {
// handle piped content (see Jerome's answer)
}
The reason I didn't find this before is because I was looking at the documentation for process, where isTTYis not mentioned at all. Instead, it's mentioned in the TTY documentation.
我之前没有找到这个的原因是因为我正在查看 的文档process,isTTY根本没有提到哪里。相反,它在TTY 文档中提到。
回答by Chet
It turns out that process.stdin.isTTYis not reliable because you can spawn a child process that is not a TTY.
事实证明这process.stdin.isTTY是不可靠的,因为您可以生成一个不是 TTY 的子进程。
I found a better solution hereusing file descriptors.
You can test to see if your program with piped in or out with these functions:
您可以测试您的程序是否使用这些函数输入或输出:
function pipedIn(cb) {
fs.fstat(0, function(err, stats) {
if (err) {
cb(err)
} else {
cb(null, stats.isFIFO())
}
})
}
function pipedOut(cb) {
fs.fstat(1, function(err, stats) {
if (err) {
cb(err)
} else {
cb(null, stats.isFIFO())
}
})
}
pipedIn((err, x) => console.log("in", x))
pipedOut((err, x) => console.log("out", x))
Here's some tests demonstrating that it works.
这里有一些测试证明它有效。
??? node pipes.js
in false
out false
??? node pipes.js | cat -
in false
out true
??? echo 'hello' | node pipes.js | cat -
in true
out true
??? echo 'hello' | node pipes.js
in true
out false
??? node -p -e "let x = require('child_process').exec(\"node pipes.js\", (err, res) => console.log(res))"
undefined
in false
out false
??? node -p -e "let x = require('child_process').exec(\"echo 'hello' | node pipes.js\", (err, res) => console.log(res))"
undefined
in true
out false
??? node -p -e "let x = require('child_process').exec(\"echo 'hello' | node pipes.js | cat -\", (err, res) => console.log(res))"
undefined
in true
out true
??? node -p -e "let x = require('child_process').exec(\"node pipes.js | cat -\", (err, res) => console.log(res))"
undefined
in false
out true
回答by Erik Lundmark
If you need to pipe into nodejs using an inline --evalstring in bash, catworks too:
如果您需要在 bash 中使用内联 --eval字符串通过管道输入 nodejs ,cat也可以:
$ echo "Hello" | node -e "console.log(process.argv[1]+' pipe');" "$(cat)"
# "Hello pipe"
回答by nikolay
You need to check stdout(not stdinlike suggested elsewhere) like this:
您需要像这样检查stdout(stdin不像其他地方建议的那样):
if (process.stdout.isTTY) {
// not piped
} else {
// piped
}

