简体   繁体   English

有什么方法可以确定 nodejs 子进程是需要输入还是只是发送反馈?

[英]Is there any way to determine if a nodejs childprocess wants input or is just sending feedback?

I had a little freetime so I decided to rewrite all my bash scripts in JavaScript (NodeJS - ES6) with child processes.我有一点空闲时间,所以我决定用 JavaScript (NodeJS - ES6) 用子进程重写我所有的 bash 脚本。 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.但是有一个问题 - 您无法确定给定的data事件是反馈还是输入请求。 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 above example works totally fine.上面的例子完全正常。 But there are 2 things giving me an headache:但是有两件事让我头疼:

  1. Will ufw.stdin.write('y\\n');ufw.stdin.write('y\\n'); wait until it is needed and what happens if I have multiple inputs?等到需要它时,如果我有多个输入会发生什么? For example 'yes', 'yes', 'no'.例如“是”、“是”、“否”。 Do I have to write 3 lines of stdin.write() ?我必须写 3 行stdin.write()吗?

  2. Isn't the position where I use ufw.stdin.write('y\\n');是不是我用的位置ufw.stdin.write('y\\n'); a little confusing?有点混乱? I thought I need the input after my prompt made a request for input so I decided to change my code that my stdin.write() could run at the right time, makes sense right?我想在我的提示提出输入请求后我需要输入,所以我决定更改我的代码,让我的stdin.write()可以在正确的时间运行,对吗? However the only way to check when the 'right' time is on the stdout.on('data', callback) event.但是,检查“正确”时间何时在stdout.on('data', callback)事件上的唯一方法。 That makes thinks a little difficult, since I need to know if the prompt is aksing for user input or not...这让思考有点困难,因为我需要知道提示是否要求用户输入...

Here is my code which I think is totally wrong:这是我认为完全错误的代码:

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

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

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

// 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();
});

My major misunderstanding is when to use stdin for user input (automated) and where to place it in my code so it will be used at the right time, for example if I have multiple inputs for something like mysql_secure_installation .我的主要误解是何时将stdin用于用户输入(自动)以及将它放置在我的代码中的哪个位置,以便在正确的时间使用它,例如,如果我有多个输入,例如mysql_secure_installation

So I was wondering if it is possible and it seems not.所以我想知道是否有可能,但似乎没有。 I posted an issue for node which ended up beeing closed: https://github.com/nodejs/node/issues/16214我发布了一个最终被关闭的节点问题: https : //github.com/nodejs/node/issues/16214

 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.我认为您对管道 I/O 有错误的期望,因为它根本不是这样工作的。

Talking about expectations, check out expect.谈到期望,请查看期望。 There is probably a node.js port if you look around.如果你环顾四周,可能有一个 node.js 端口。

I'll close this out because it's not implementable as a feature, and as a question nodejs/help is the more appropriate place.我将关闭它,因为它不能作为功能实现,并且作为一个问题 nodejs/help 是更合适的地方。

So if anyone has the same problem as I had you can simply write multiple lines into stdin and use that as predefined values.因此,如果有人遇到与我相同的问题,您可以简单地将多行写入stdin并将其用作预定义值。 Keep in mind that will eventually break the stream if any input is broken or wrong in feature updates:请记住,如果功能更新中的任何输入损坏或错误,最终将中断流:

// new Spawn.
let spawn = require('child_process');
// new msqlsec process.
let msqlsec = spawn('mysql_secure_installation', ['']);
// Arguments as Array.
let inputArgs = ['password', 'n', 'y', 'y', 'y', 'y'];

// Set correct encodings for logging.
msqlsec.stdin.setEncoding('utf-8');
msqlsec.stdout.setEncoding('utf-8');
msqlsec.stderr.setEncoding('utf-8');

// Use defined input and write line for each of them.
for (let a = 0; a < inputArgs.length; a++) {
  msqlsec.stdin.write(inputArgs[a] + '\n');
}

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

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

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

For the sake of completeness if someone wants to fill the user input manually you can simply start the given process like this:为了完整起见,如果有人想手动填写用户输入,您可以简单地启动给定的过程,如下所示:

// new msqlsec process.
let msqlsec = spawn('mysql_secure_installation', [''], { stdio: 'inherit', shell: true });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM