您可以将“脚本断路器”嵌入 UNKNOWN_CODE。就像是:
;setTimeout(function() { throw new Error("Execution time limit reached!") }, 2000);
所以,整个事情看起来像这样:
var UNKNOWN_CODE = "while(true){}";
var scriptBreaker = ';setTimeout(function() { throw new Error("Execution time limit reached!") }, 2000);';
var vm = require("vm");
var obj = {};
var ctx = vm.createContext(obj);
var script = vm.createScript(scriptBreaker + UNKNOWN_CODE);
try {
script.runInNewContext(ctx);
console.log("Finished");
}
catch (err) {
console.log("Timeout!");
// Handle Timeout Error...
}
更新:
经过更多测试后,我得出结论,可靠的方法是使用指向 Esailija 的过程。但是,我的做法有点不同。
在主应用程序中,我有这样的代码:
var cp = require('child_process');
function runUnsafeScript(script, callback) {
var worker = cp.fork('./script-runner', [script]);
worker.on('message', function(data) {
worker.kill();
callback(false, data);
});
worker.on('exit', function (code, signal) {
callback(new Error(code), false);
});
worker.on('error', function (err) {
callback(err, false);
});
setTimeout(function killOnTimeOut() {
worker.kill();
callback(new Error("Timeout"), false);
}, 5000);
}
在 script-runner.js 中,它如下所示:
var vm = require("vm");
var script = vm.createScript( process.argv[2] );
var obj = { sendResult:function (result) { process.send(result); process.exit(0); } };
var context = vm.createContext(obj);
script.runInNewContext(context);
process.on('uncaughtException', function(err) {
process.exit(1);
});
这种方法可以实现以下目标:
- 在有限的上下文中运行脚本
- 避免死循环和异常问题
- 同时运行许多(受硬件限制)不安全的脚本,这样它们就不会相互中断
- 将脚本执行结果传递给主应用程序进行进一步处理