简体   繁体   English

Node.js - child_process.exec和输出重定向

[英]Node.js - child_process.exec and output redirection

I'm trying to write a file templating script using Node.js. 我正在尝试使用Node.js编写文件模板脚本。 I have a JSON file called template.json which stores template information. 我有一个名为template.json的JSON文件,它存储模板信息。 The idea behind my script is that, if I type something like: 我的脚本背后的想法是,如果我输入类似的东西:

tmpl.js java Joe

it will do the following: 它将执行以下操作:

  1. Call touch Joe.java 打电话给touch Joe.java
  2. Read template.json to get the template for Java files 阅读template.json以获取Java文件的模板
  3. Use its information to replace all the placeholders with Joe 使用其信息用Joe替换所有占位符
  4. Write the result to Joe.java 将结果写入Joe.java
  5. Execute emacsclient Joe.java 执行emacsclient Joe.java

Now, I wrote this script as follows: 现在,我写了这个脚本如下:

#!/usr/local/bin/node --harmony

var templates = require('./config/template.json'),
    args = process.argv;

if (args.length < 4) {
    console.log("Not enough arguments!");
} 
else {
    var type = args[2],
        name = args[3];
    if (type in templates) {
        var tmpl = templates[type],
            contents = make_output(tmpl["format"],name),
            file_name = name + tmpl["extension"],
            command = "touch " + file_name + " && echo -e '" + contents +
            "' &> " + file_name + " && emacsclient " + file_name;
        invoke(command);
    }
    else {
        console.log("No template for %s", type);
    }
}


//Helpers

//Invokes comm with args in the terminal, returns all output
//Does not play nice with command redirection
function invoke(comm) {
    var exec = require('child_process').exec,
    child = exec(comm,
             function (error, stdout, stderr) {
                         if (error !== null) {
                 console.log(stderr);
                 }
             });
}

//If template is a format string, processes it with x as the
//replacement. Otherwise, just evaluates.
//Limited to one replacement at most.
function make_output(template, x) {
    if(/.*\%s.*/i.test(template)) {
        var util = require('util');
        return util.format(template,x);
    }
    else {
        return template;
    }
}

Basically, the command it ends up building is something like: 基本上,它最终建立的命令是这样的:

touch Joe.java && echo -e `bunch of template stuffs` &> Joe.java && emacsclient Joe.java

Now, the problem I am getting is that the above command relies on output redirection, which my invoke command doesn't deal with very well - specifically, everything executes, but I get an empty file! 现在,我得到的问题是上面的命令依赖于输出重定向,我的invoke命令没有很好地处理 - 具体来说,一切都执行,但我得到一个空文件! Is there a way I can change either invoke or what I'm constructing to be invoked to avoid this problem? 有没有一种方法,我可以改变任何invoke ,否则我什么构造调用,以避免这个问题?

The issue is that Node's child_process.exec starts sh but you are using features that are peculiar to bash . 问题是Node的child_process.exec启动了sh但你使用的是bash特有的功能。 The &> is interpreted as & > in sh (two operators: a control operator and a redirection operator) and echo -e will use sh 's builtin implementation of echo , which does not understand -e . &>被解释为& >sh (两个运算符:控制操作员和一个操作者重定向)和echo -e将使用sh的内置执行echo ,其不理解-e

It would probably be possible to work around the issues above but using the shell like you do is fragile. 它可能可以解决上面的问题,但像你一样使用shell是脆弱的。 For instance if your template contains single quotes ( ' ), these quotes may interfere with the single quotes you use in your command. 例如,如果您的模板包含单引号( ' ),则这些引号可能会干扰您在命令中使用的单引号。 A more robust way to do it would be to change the main part of your code to use fs.writeFileSync rather than using shell commands to write to your file: 更强大的方法是更改​​代码的主要部分以使用fs.writeFileSync而不是使用shell命令写入文件:

var templates = require('./config/template.json'),
    fs = require("fs"),
    args = process.argv;

if (args.length < 4) {
    console.log("Not enough arguments!");
}
else {
    var type = args[2],
        name = args[3];
    if (type in templates) {
        var tmpl = templates[type],
            contents = make_output(tmpl["format"],name),
            file_name = name + tmpl["extension"],
            command = "emacsclient " + file_name;

        fs.writeFileSync(file_name, contents);

        invoke(command);
    }
    else {
        console.log("No template for %s", type);
    }
}

You'd also want to modify make_output to perform the transformations that echo -e would have done for you. 您还需要修改make_output以执行echo -e为您完成的转换。

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

相关问题 在node.js child_process.exec上显示进度? - Show progress on node.js child_process.exec? 在将child_process.exec用于Node.js时,为什么输出从STDERR而不是STDOUT发出? - Why does output come out from STDERR and not STDOUT when using child_process.exec for Node.js? 在 node.js 中,如何使用 child_process.exec 使所有事情都可以异步发生? - In node.js, how to use child_process.exec so all can happen asynchronously? / bin / sh:1:节点:在child_process.exec中找不到 - /bin/sh: 1: node: not found with child_process.exec 如何使用 Bluebird 保证 Node 的 child_process.exec 和 child_process.execFile 函数? - How to promisify Node's child_process.exec and child_process.execFile functions with Bluebird? 获得&#39;child_process.exec&#39;的SUDO特权 - Gaining SUDO privileges for 'child_process.exec' NodeJS:child_process.exec 不执行函数 - NodeJS: child_process.exec not executing function Node.js的stdout child_process exec被缩短了 - Stdout of Node.js child_process exec is cut short 使用节点child_process.exec执行top命令时,如何解决错误? - How to resolve the error while executing top command using node child_process.exec? child_process.exec 尝试在一些奇怪的情况下启动节点(而不是 shell 命令) - child_process.exec tries to launch node (instead of shell command) in some odd circumstances
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM