我为用户提供了一种灵活的方式来使用JavaScript转换数据,在服务器端使用Node.js执行。有了这个设计,需要考虑3个问题:
安全性:我使用sandbox解决了安全问题,以避免使用本机Node.js库。
资源:我们可以使用v8选项--max_executable_size
轻松设置最大内存使用量。关于CPU使用情况,我会看到如何使用cpulimit
或renice
来管理它,现在并不重要。
时间:我需要限制脚本的执行时间,以避免它们作为hangry zombies运行。在这里,我卡住了。
我尝试过类似的事情:
node -e '
setTimeout(function() {
console.log("timeout");
process.exit;
}, 5000);
console.log("begin");
while (1);
'
但是这段代码只显示“开始”,似乎我的超时从未被调用过。 有什么想法吗?
答案 0 :(得分:7)
你可能想看看tripwire(https://github.com/tjanczuk/tripwire)。它是一个可以杀死失控节点脚本的模块,您可以设置超时。它是一个本机节点模块,因此这是一件需要考虑的事情,但它适用于Mac,Windows和Linux。
答案 1 :(得分:4)
不幸的是,如果您的用户可以启动阻止操作(例如while(1)
),则无法告知Node在一定时间后退出,因为阻止操作将阻止setTimeout
处理程序触发。确保用户启动的东西不会阻塞主循环,或者(这是非常坏主意)使用某种外部自动终止/超时来破坏Node进程。
基本上,您可以使用Node来限制非阻塞代码的执行时间,但Node的重点是阻止代码阻止所有内容。如果您的用户真的能够运行任意代码,我会考虑在更高级别运行您的进程管理器/超时杀手:例如,使用Node的exec工具生成具有终止超时的进程。
答案 2 :(得分:1)
节点built-in vm
module提供module.evaluate
,script.runInContext
以及其他一些方法,这些方法将在沙盒环境中运行代码,并使用timeout
选项指定最长时间(在ms)允许VM运行。
请注意,在Node.js中运行不受信任的代码充满了潜在的安全问题。甚至VM模块也明确说“ vm模块不是安全机制。不要用它来运行不受信任的代码。”(为什么不呢?Here is one reason why not:它看起来应该是无害的运行vm.runInNewContext("this.constructor.constructor('return process')().exit()")
但事实上它会导致Node终止。
您也可以考虑使用提供类似功能的Patrik Simek vm2,但声称“使用列入白名单的Node的内置模块运行不受信任的代码。安全!”文档中的一个例子:
const {VM} = require('vm2');
const vm = new VM({
timeout: 1000,
sandbox: {}
});
vm.run("process.exit()"); // throws ReferenceError: process is not defined