【问题标题】:How to set a maximum execution time of a script with node.js?如何使用 node.js 设置脚本的最大执行时间?
【发布时间】:2013-03-02 16:15:45
【问题描述】:

我为我的用户提供了一种使用 JavaScript 转换数据的灵活方法,在服务器端使用 Node.js 执行。采用这种设计,需要考虑 3 个问题:

  • 安全性:我使用sandbox 解决了安全问题,以避免使用本机 Node.js 库。

  • 资源:我们可以使用 v8 选项 --max_executable_size 轻松设置最大内存使用量。关于CPU使用率,我看看怎么用cpulimit或者renice来管理,现在无所谓了。

  • 时间:我需要限制脚本的执行时间,以避免它们像僵尸一样运行。我在这里卡住了。

我试过类似的东西:

 node -e '
    setTimeout(function() {
       console.log("timeout");
       process.exit;
    }, 5000);
    console.log("begin");
    while (1);
 '

但是这段代码只显示“开始”,似乎我的超时从未被调用。 有什么想法吗?

【问题讨论】:

  • 这些是你的脚本吗?或者您是否试图限制任意代码的执行?您是否尝试为整个应用程序设置时间限制?还是里面的一大段代码?
  • 我想限制其中一段代码的执行。
  • 你的“while(1);”正在阻止执行,删除它,你会看到开始和超时。
  • 我的用户可能会使用这个while(1)。我在一个不好的用例中选择了我的例子,需要限制的用例:-)。
  • 为什么你也不能使用沙盒模块呢?如果您查看source code,您可以看到您可以为子进程提供超时选项

标签: node.js execution-time


【解决方案1】:

Node 的 built-in vm module 提供 module.evaluatescript.runInContext 和其他几种方法,它们将在沙盒环境中运行代码,并采用 timeout 选项来指定允许 VM 运行的最长时间(以毫秒为单位)为。

请注意,在 Node.js 中运行不受信任的代码会充满潜在的安全问题。甚至VM模块都明确表示“vm模块不是安全机制。不要使用它来运行不受信任的代码。”(为什么不呢?Here is one reason why not:看起来运行起来应该是无害的vm.runInNewContext("this.constructor.constructor('return process')().exit()") 但实际上它会导致 Node 终止。

您也可以考虑使用Patrik Simekvm2,它提供了类似的功能,但声称“使用列入白名单的 Node 的内置模块运行不受信任的代码。安全!”文档中的一个示例:

const {VM} = require('vm2');

const vm = new VM({
    timeout: 1000,
    sandbox: {}
});

vm.run("process.exit()"); // throws ReferenceError: process is not defined

【讨论】:

    【解决方案2】:

    您可能想查看tripwire (https://github.com/tjanczuk/tripwire)。它是一个可以杀死失控节点脚本的模块,您可以设置超时。它是一个本地节点模块,因此需要考虑一件事,但它适用于 Mac、Windows 和 Linux。

    【讨论】:

    • 我的问题现在有点老了,但你的回答看起来很有趣。
    • @AlainTiemblo 哈哈,我现在明白了。这是我团队中刚刚发现这个的人传给我的。现在任何搜索的人都可以使用它。 :p
    • 是的,这就是“死灵法师”徽章存在的原因 :-) 一些新的答案可以更好地适应旧问题。感谢分享。
    【解决方案3】:

    不幸的是,如果您的用户可以启动阻塞操作(如 while(1)),则无法告诉 Node 在一定时间后退出,因为阻塞操作会阻止 setTimeout 处理程序触发。要么确保用户启动的东西不会阻塞主循环,要么(这是一个非常坏主意)使用某种外部自动终止/超时来破坏节点进程。

    基本上,您可以使用 Node 来限制非阻塞代码的执行时间,但 Node 的全部意义在于阻塞代码会阻塞一切。如果您的用户确实能够运行任意代码,我会考虑在更高级别运行您的进程管理器/超时杀手:例如,使用 Node 的 exec 工具生成具有终止超时的进程。

    【讨论】:

    • 啊,好吧,在这种情况下,我将在node 命令之前使用timeout 5s,这也会杀死我的进程。无论如何,谢谢。
    • 如果你走这条路,请确保无论你的 Node 进程正在做什么,a) 如果它在操作过程中中止,它不会破坏事情,并且 b) 不会离开系统上未释放的资源(当某些程序发送 kill -9 时会发生这种情况)。
    • 实际上,sandbox I use 执行您所说的操作(我看到一些 execs 和 sigkills 在超时后由父进程管理)。第一次没有看到它,因为所有示例都使用默认值......无论如何都很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多