• 173

nodejs中如何知道子进程正在等待输入,并向其输入数据

比如npm login命令需要依次输入usernamepasswordemail

我启动一个子进程执行npm login我该如何知道子进程正在等待输入,并向其输入内容呢?

阅读 1.5k
评论
    2 个回答

    是在控制台输入么,用readline,代码如下

    // login.js
    const readline = require('readline')
    
    function createInput(msg) {
      const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
      })
      return new Promise(function(resolve, reject) {
        rl.question(`请输入${msg}: `, data => {
          rl.close()
          resolve(data)
        })
      })
    }
    
    Promise.resolve()
      .then(() => {
        return createInput('用户名').then(username => ({ username }))
      })
      .then(userInfo => {
        return createInput('密码').then(password => ({
          ...userInfo,
          password,
        }))
      })
      .then(userInfo => {
        return createInput('邮箱').then(email => ({
          ...userInfo,
          email,
        }))
      })
      .then(userInfo => {
        console.log(userInfo)
      })

    补充

    那可以用进程通讯,下面是简单的实现,你可以看看后面的参考文章,详细研究下node的进程间通讯
    我是用node来实现的,如果发送端是别的语言的话,你需要找找相应语言是怎么实现进程通讯的

    // login.js
    const userInfo = {}
    const codes = ['username', 'password', 'email']
    let currIndex = 0
    
    function get({ code, data }) {
      const currentCode = codes[currIndex]
      if (code === currentCode) {
        userInfo[code] = data
        const nextCode = codes[++currIndex]
        if (nextCode) {
          send(nextCode, `请给我 ${currentCode}`)
        } else {
          send('done', userInfo)
        }
      } else {
        send(currentCode, `请给我 ${currentCode}`)
      }
    }
    function send(code, message) {
      process.send({ code, message })
    }
    process.on('message', msg => {
      get(msg)
    })
    
    send(codes[currIndex], `请给我 ${codes[currIndex]}`)
    // send-login.js
    const { spawn } = require('child_process')
    const child = spawn('node', ['login.js'], { stdio: [null, null, null, 'ipc'] })
    const userInfo = {
      username: 'root',
      password: '123456',
      email: 'admin@root.com',
    }
    child.on('message', msg => {
      const { code } = msg
    
      if (code === 'done') {
        child.kill()
        console.log(msg.message)
      } else {
        child.send({ code, data: userInfo[code] })
      }
    })

    参考

      • 1
      • 新人请关照

      不知道你解决木有, 我也是今天刚解决的,共享一下。
      参考大佬的文章 在Node.js中如何将数据以stdin的方式传递进由spawn产生的子进程?

      
      const fs = require('fs');
      
      const { spawn } = require('child_process');
      
      var subProcess = spawn('cnpm.cmd', ['login'], { cmd: __dirname });
      subProcess.on('error', function() {
          console.log('error');
          console.log(arguments);
      });
      subProcess.on('close', code => {
          if (code != 0) {
              console.log(`子进程退出码:${code}`);
          } else {
              console.log('登录成功');
          }
          process.stdin.end();
      });
      subProcess.stdin.on('end', () => {
          process.stdout.write('end');
      });
      
      subProcess.stdout.on('data', onData);
      subProcess.stderr.on('data', onData);
      function onData(data) {
          process.stdout.write('# ' + data);
          process.stdin.on('data', input => {
              input = input.toString().trim();
              subProcess.stdin.write(input + '\n');
          });
      }
        撰写回答

        登录后参与交流、获取后续更新提醒