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
?
那么如何在test.js中获得值“foo bar”呢?
I’ve read Unix and Node: Pipes and Streams but 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和Node: Pipes和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
? - 如何检测一个节点。js脚本正在通过一个shell管道运行,例如echo“foo bar”| ./test.js?
- If so, how to read out the piped value in Node.js?
- 如果是,如何在Node.js中读出管道值?
4 个解决方案
#1
20
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.0 because the example uses the stream2 API
注意:由于示例使用的是stream2 API,所以只使用节点>= 0.10.0
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
#2
38
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.isTTY
boolean:
快速、同步地检测管道内容是否被传递到节点中的当前脚本。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 isTTY
is not mentioned at all. Instead, it’s mentioned in the TTY documentation.
我以前没有找到它的原因是,我正在查看过程的文档,其中根本没有提到isTTY。相反,TTY文档中提到了它。
#3
1
If you need to pipe into nodejs using an inline --eval string in bash, cat
works too:
如果您需要在bash中使用内联的-eval字符串导入nodejs, cat也可以:
$ echo "Hello" | node -e "console.log(process.argv[1]+' pipe');" "$(cat)"
# "Hello pipe"
#4
1
You need to check stdout
(not stdin
like suggested elsewhere) like this:
你需要像这样检查stdout(不像其他地方建议的那样):
if (process.stdout.isTTY) {
// not piped
} else {
// piped
}
#1
20
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.0 because the example uses the stream2 API
注意:由于示例使用的是stream2 API,所以只使用节点>= 0.10.0
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
#2
38
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.isTTY
boolean:
快速、同步地检测管道内容是否被传递到节点中的当前脚本。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 isTTY
is not mentioned at all. Instead, it’s mentioned in the TTY documentation.
我以前没有找到它的原因是,我正在查看过程的文档,其中根本没有提到isTTY。相反,TTY文档中提到了它。
#3
1
If you need to pipe into nodejs using an inline --eval string in bash, cat
works too:
如果您需要在bash中使用内联的-eval字符串导入nodejs, cat也可以:
$ echo "Hello" | node -e "console.log(process.argv[1]+' pipe');" "$(cat)"
# "Hello pipe"
#4
1
You need to check stdout
(not stdin
like suggested elsewhere) like this:
你需要像这样检查stdout(不像其他地方建议的那样):
if (process.stdout.isTTY) {
// not piped
} else {
// piped
}