Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if a Node.js script is running through a shell pipe?

Tags:

bash

node.js

pipe

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.

Let’s say I enter:

echo "foo bar" | ./test.js 

Then how can I get the value "foo bar" in test.js?

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.

TL;DR My question is two-fold:

  1. How to detect if a Node.js script is running through a shell pipe, e.g. echo "foo bar" | ./test.js?
  2. If so, how to read out the piped value in Node.js?
like image 368
Mathias Bynens Avatar asked Mar 17 '13 21:03

Mathias Bynens


People also ask

How do I run a shell script in node js?

Node. js can run shell commands by using the standard child_process module. If we use the exec() function, our command will run and its output will be available to us in a callback. If we use the spawn() module, its output will be available via event listeners.

What does pipe do in node js?

pipe() method in a Readable Stream is used to attach a Writable stream to the readable stream so that it consequently switches into flowing mode and then pushes all the data that it has to the attached Writable.

Is node js a shell?

Node. js ships with a Read-Eval-Print Loop, also known as a REPL. It is the Node. js interactive shell; any valid JavaScript which can be written in a script can be passed to the REPL.


2 Answers

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:

$ 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.

like image 112
Mathias Bynens Avatar answered Sep 21 '22 01:09

Mathias Bynens


Pipes are made to handle small inputs like "foo bar" but also huge files.

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.

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

note: use only node >= 0.10.0 because the example uses the 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 
like image 32
Jerome WAGNER Avatar answered Sep 21 '22 01:09

Jerome WAGNER