如何在node.js中处理stdout

时间:2014-04-17 21:22:55

标签: node.js bash stdout std stdin

我尝试自动执行每次在服务器上测试应用和网站时经历的流程。我目前正在nodejitsu上运行。当我测试了一些东西并且它在我的本地机器上工作时,我接下来要做的就是......

  1. 打开我的package.json文件
  2. 删除域字段,并将名称和子域更改为暂存。 (更改版本号也可能有意义)
  3. 然后我jitsu deploy
  4. 确认任何提示(例如批准增加版本号)
  5. 应用程序启动后,我会查看我的应用程序如何在服务器上运行,进行更改等等
  6. 在我完成之后,我的应用程序准备好了,我在package.json文件中撤消了我的更改。我想自动化这个过程。我想到了一个很小的node.js文件。到目前为止......

    /*
     * Use this file to deploy an app to the staging server on nodejitsu
     */
    var bash = require('child_process').spawn('bash');
    var colors = require('colors');
    var fs = require('fs');
    
    // stdout setup
    bash.stdout.on('data', function (data) {
      console.log('stdout: ' + data);
    });
    bash.stdout.on('error', function (err) {
      console.log('stdout error: '.red, err);
    });
    
    // on bash exit
    bash.on('exit', function (code) {
      console.log('Exiting... ', code);
    });
    
    // grab package.json
    var package = '';
    fs.readFile('package.json', {encoding: 'utf-8'}, function (err, data) { // grab the package.json file contents
      if (err) throw err;
      package = JSON.parse(data);
      fs.rename('package.json', 'rename-me-before-deploying.json'); // rename the package.json file
      package.name = 'stajing'; // alter json
      package.subdomain = 'stajing'; // alter json
      package.domains = []; // alter json
      fs.writeFile('package.json', JSON.stringify(package, null, 2), function(err) { // write the new package to package.json
        if (err) throw err;
        bash.stdin.write('jitsu deploy\n'); // Deploy to staging app on nodejitsu.
        setTimeout(function () { // this needs to be replaced
          bash.stdin.write('yes\n');
        }, 5000);
        console.log("All done : )");
        // bash.stdin.end(); // close out
      });
    });
    

    我这里有几个问题。我非常确定我需要知道完成它,是当nodejitsu提示我增加版本号prompt: Is this ok?: (yes)时触发的事件,以便我可以确认,如果发生这种情况,以及触发的事件整个过程完成后,我可以将更改恢复到我的package.json文件,将我的应用程序部署到暂存环境,我的文件基本上不受影响。

1 个答案:

答案 0 :(得分:2)

我未设置此处运行jitsu deploy。但是,这里有一些代码说明了如何处理提示:

var command = require('child_process').spawn('./command.js');
require('colors');

var stdout = "";
var prompt_re = /Is it okay \(yes\)\?.*?$/m;
command.stdout.on('data', function (data) {
    console.log("stdout data: ".green + data);
    stdout += data;
    if (prompt_re.test(stdout)) {
        command.stdin.write("yes\n");
        // Flush the current buffer.
        stdout = "";
    }
});

command.stdout.on('error', function (err) {
    console.log('stdout error: '.red, err);
});

var exit_msg = 'Exited with code... ';
command.on('exit', function (code) {
    if (code != 0) {
        console.log(exit_msg.red, code);
        process.exit(1); // Or whatever you want to handle errors.
    }

    console.log(exit_msg.green, code);
    // The code you want to execute once your command is done goes here.
});

一些解释:

  1. 上面的代码将从command.stdout获取的数据缓存为存储在stdout变量中的字符串,并针对 进行测试,因为如果有' sa很多输出并不能保证提示会在单个data事件中到达。 (例如,它可能包含一堆数据+字符串Is it,然后下一个data事件可能包含提示的其余部分。)

  2. 正则表达式prompt_re包含'。*?$'因为我用来模拟获取提示的命令使用转义码来表示颜色,我不能打扰与输出的确切代码匹配。

  3. 此代码假定在输出提示后该命令将立即停止并等待。这似乎是一个安全的假设。

  4. 它还假定提示文本不能显示为不是提示的内容。这是否安全取决于您的具体情况。

  5. 我用来模拟正在运行的命令的./command.js文件是:

    #!/usr/bin/env node
    
    var prompt = require("prompt");
    
    function ask(cb) {
        prompt.get(["Is it okay (yes)?"], function (err, result) {
            console.log("asked");
            cb();
        });
    }
    
    setTimeout(function () {
        ask(function () {
            setTimeout(function () {
                ask(function () { process.exit(0); });
            }, 1000);
        });
    }, 5000);
    

    等待5秒,提示一次,等待1秒,再次提示并退出。