如何在一个Node.js脚本中运行另一个Node.js脚本?

95

我有一个独立的Node脚本,名为compile.js。它位于小型Express应用程序的主文件夹中。

有时,我会从命令行运行compile.js脚本。在其他情况下,我希望它由Express应用程序执行。

这两个脚本都从package.json中加载配置数据。目前,compile.js没有导出任何方法。

什么是最好的方法来加载并执行这个文件呢?我已经查看了eval()vm.RunInNewContextrequire,但不确定哪种方式是正确的。

感谢您的帮助!


1
你考虑过 var exec = require('child_process').exec; exec('node <path>/compile.js', ...) 吗? - user1375096
您是否需要使用http://nodejs.org/api/process.html#process_process_execargv? - Phillip Kinkade
1
为什么不直接使用require()呢? - dandavis
@dandavis,“Compile.js目前没有导出任何方法。” - user1375096
@dandavis 我认为 require 可能会起作用,只是脚本中有一些异步操作。也许有一个带回调函数的 require 版本? - dylanized
Exec-sync看起来很有前途:http://davidwalsh.name/sync-exec - dylanized
3个回答

86
您可以使用子进程来运行脚本,并监听退出和错误事件,以了解进程何时完成或发生错误(在某些情况下,可能会导致退出事件未触发)。该方法的优点是适用于任何异步脚本,即使这些脚本并非专门设计为作为子进程运行,例如您想要调用的第三方脚本。示例:
var childProcess = require('child_process');

function runScript(scriptPath, callback) {

    // keep track of whether callback has been invoked to prevent multiple invocations
    var invoked = false;

    var process = childProcess.fork(scriptPath);

    // listen for errors as they may prevent the exit event from firing
    process.on('error', function (err) {
        if (invoked) return;
        invoked = true;
        callback(err);
    });

    // execute the callback once the process has finished running
    process.on('exit', function (code) {
        if (invoked) return;
        invoked = true;
        var err = code === 0 ? null : new Error('exit code ' + code);
        callback(err);
    });

}

// Now we can run a script and invoke a callback when complete, e.g.
runScript('./some-script.js', function (err) {
    if (err) throw err;
    console.log('finished running some-script.js');
});
请注意,如果在可能存在安全问题的环境中运行第三方脚本,则最好在沙盒虚拟机上下文中运行该脚本。

12
如果你想向调用的Node.js脚本添加参数: var process = childProcess.fork(scriptPath, ['arg1', 'arg2']); - Tyler Durden
4
如果您想同步运行简单的任务,您可以使用child_process.execFileSync(file[, args][, options])。请参阅https://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options。 - João Pimentel Ferreira
即使我在子进程上执行 process.exit(0)exit 事件也没有被触发。有什么想法吗? - João Pimentel Ferreira

24

将此行代码放置在 Node 应用程序的任何位置。

require('child_process').fork('some_code.js'); //change the path depending on where the file is.

在 some_code.js 文件中

console.log('calling form parent process');

3
终于有一个简单明了的答案了!谢谢! - Andor Németh

9

创建子进程可能很有用,参见http://nodejs.org/api/child_process.html

参考链接中的示例:

var cp = require('child_process');

var n = cp.fork(__dirname + '/sub.js');

n.on('message', function(m) {
  console.log('PARENT got message:', m);
});

n.send({ hello: 'world' });

现在,子进程的执行流程如下...还是从示例中来看:
process.on('message', function(m) {
  console.log('CHILD got message:', m);
});

process.send({ foo: 'bar' });

但对于简单的任务,我认为创建一个扩展了 events.EventEmitter 类的模块就可以了... http://nodejs.org/api/events.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接