【问题标题】:Getting error "Cannot allocate memory" for Rails为 Rails 获取错误“无法分配内存”
【发布时间】:2013-12-19 20:25:36
【问题描述】:

在我的项目中,有一个脚本可以返回我必须在表格中显示的产品列表。

为了存储我使用IO.popen的脚本的输入:

@device_list = []
IO.popen("device list").each do |device|
  @device_list << device
end

device list 是给我产品列表的命令。

我将@device_list 数组返回到我的视图,以便通过迭代来显示。

运行时出现错误:

Errno::ENOMEM (Cannot allocate memory):
for IO.popen

我在另一个脚本 device status 上只返回 true 和 false,但我得到了同样的错误:

def check_status(device_id)        
    @stat = system("status device_id")
    if @stat == true
         "sold"
    else
         "not sold"
    end
  end

我该怎么办?

【问题讨论】:

  • 每当我看到 Rails 运行 shell 命令时,我都想知道权限问题。您确定用户 Rails 以有权运行脚本的身份运行吗?你可以从rails console 运行它吗?您可以从您的应用程序运行其他 shell 命令(例如ls)吗?我意识到错误将您指向记忆,但也许它只是在这里变得混乱。
  • 你的机器内存不足吗?
  • @np_ 当我从rails console 运行这些命令时,它们运行良好。

标签: ruby-on-rails ruby ruby-1.8


【解决方案1】:

您的device list 输出似乎太大了。

"Cannot allocate memory (Errno::ENOMEM)" 是一个描述问题的有用链接。

限制device list的输出并检查。然后就可以知道是不是内存问题了。

【讨论】:

  • 好的,我已经查看了该线程。但我有另一个脚本命令 device status,它只返回 truefalse 但我得到了同样的错误。
【解决方案2】:

IO.popenKernel#system 在内存方面都可能是昂贵的操作,因为它们都依赖于 fork(2)。 Fork(2) 是一个 Unix 系统调用,它创建一个子进程来克隆父进程的内存和资源。这意味着,如果您的父进程使用 500mb 内存,那么您的子进程也将使用 500mb 内存。每次您执行Kernel#systemIO.popen 时,您的应用程序的内存使用量都会增加运行Rails 应用程序所需的内存量。

如果您的开发机器的 RAM 比生产服务器多,或者如果您的生产服务器产生更多的输出,您可以做两件事:

  1. 增加生产服务器的内存。
  2. 使用Resque 之类的东西进行一些内存管理。

您可以使用 Resque 将这些操作作为作业排队。然后 Resque 将生成“workers”/子进程以从队列中获取工作,处理它然后退出。 Resque 仍然分叉,但重要的是,worker 在完成任务后退出,从而释放内存。每次工作人员执行一项工作时,内存都会出现峰值,但它会在每次完成后回到您应用的基线内存。

您可能必须同时执行上述两个选项,并寻找其他方法来最大程度地减少应用程序的内存使用量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2017-12-07
    • 2016-04-17
    • 1970-01-01
    • 2020-01-14
    • 2018-06-23
    • 2012-09-08
    相关资源
    最近更新 更多