Node: Please implement a feature where one can check if stdout wants input.

Created on 15 Oct 2017  路  7Comments  路  Source: nodejs/node

I had a little freetime so I decided to rewrite all my bash scripts in JavaScript (NodeJS - ES6) with child processes. Everything went smoothly until I wanted to automate user input.

Yes, you can do automate the user input. But there is one Problem - you can't determine if the given data event is a feedback or a request for input. At least I can't find a way to do it.

So basically you can do this:

// new Spawn.
let spawn = require('child_process');
// new ufw process.
let ufw = spawn('ufw', ['enable']);

// Use defined input.
ufw.stdin.setEncoding('utf-8');
ufw.stdout.pipe(process.stdout);
ufw.stdin.write('y\n');

// Event Standard Out.
ufw.stdout.on('data', (data) => {
  console.log(data.toString('utf8'));
});

// Event Standard Error.
ufw.stderr.on('data', (err) => {
  // Logerror.
  console.log(err);
});

// When job is finished (with or without error) it ends up here.
ufw.on('close', (code) => {
  // Check if there were errors.
  if (code !== 0) console.log('Exited with code: ' + code.toString());
  // End input stream.
  ufw.stdin.end();
});

The given example only works if there is one guaranteed input. But what about multiple inputs? And how can I tell my code to use the right input on the right time?

I don't think that nodejs has a built in feature which will tell me "Ok, now I need input!". Because the only way to get a non error feedback is through:

 // Event Standard Out.
process.stdout.on('data', (data) => {
   // Feedback.
   console.log(data);
});
question wrong repo

Most helpful comment

So there must be a kind of event where the started process is telling node to wait for input.

No, not really. Node.js communicates with child processes through pipes and those work like buffered channels or a mail drop: A sends at its leisure, B receives when it's ready or waits if nothing is available yet. If A sends but B is not ready yet, the operating system holds it in storage.

In other words, you cannot in general know when the other side is ready to receive data, at least not in a portable way (and for non-portable solutions you have to look outside node.js core.)

All 7 comments

IIUC what you are requesting is basically readline? Check out this example.

No, readline will create an option to have user input. I am asking for a way to determine if the current process is waiting for an input. A good example would be the use of child process spawn to start a mysql_secure_installation. The first sdtout data event will return a text. The second one will ask for the root password, then again a text and so on. That is where I want to have the option to fill predefined values like stored in an array ['password', 'n', 'y', 'y', 'y', 'y'].

How am I supposed to figure out that the started process wants input through stdin?
And how can I pass a sequence of inputs like stated above as an array for example?

I am asking for a way to determine if the current process is waiting for an input.

There isn't one. I think you have wrong expectations about pipe I/O because that's simply not how it works.

Talking about expectations, check out expect. There is probably a node.js port if you look around.

I'll close this out because it's not implementable as a feature, and as a question nodejs/help is the more appropriate place.

@bnoordhuis:

I'll close this out because it's not implementable as a feature, and as a question nodejs/help is the more appropriate place.

I understand that, I just want to point out that if you start a mysql_secure_installation through spawn like this:
let msqlsec = spawn('mysql_secure_installation', [''], { stdio: 'inherit', shell: true });
Then you are indeed able to fill in the desired inputs (manually) because the process is asking for it and waits for it. So there must be a kind of event where the started process is telling node to wait for input.

It is just not clear yet to me, I will figure it out. You can keep this closed if you still think it is not implementable.

So there must be a kind of event where the started process is telling node to wait for input.

No, not really. Node.js communicates with child processes through pipes and those work like buffered channels or a mail drop: A sends at its leisure, B receives when it's ready or waits if nothing is available yet. If A sends but B is not ready yet, the operating system holds it in storage.

In other words, you cannot in general know when the other side is ready to receive data, at least not in a portable way (and for non-portable solutions you have to look outside node.js core.)

Thank you for your explanation, that made things clearer to me.

So, How the terminal tools know the input event should be triggered?

Was this page helpful?
0 / 5 - 0 ratings