突然在我的staging和prod服务器上(不同但使用相同的VPS提供程序)我在使用我的ruby rails app时收到以下错误:
An Errno::ENOMEM occurred in projects#update:
Cannot allocate memory - identify -format %wx%h '/tmp/Lanscape_originalV220140520-32388-1alg9vz.png[0]'
vendor/bundle/ruby/1.9.1/gems/cocaine-0.3.0/lib/cocaine/command_line/runners/process_runner.rb:17:in `spawn’"
我该如何解决这个问题?
仅供参考我通过重启服务器暂时解决了这个问题
这是导致问题的项目更新文件:
class ProjectUpdatesController < ApplicationController
before_filter :get_project
def index
@project_updates = @project.project_updates
@project_update = ProjectUpdate.new
end
def show
@project_update = ProjectUpdate.find(params[:id])
end
def new
@project_update = ProjectUpdate.new
end
def edit
@project_update = ProjectUpdate.find(params[:id])
end
def create
@project_update = ProjectUpdate.new(params[:project_update])
@project_update.project = @project
return redirect_to :back, :alert => 'abc.' unless current_user.owner?(@project_update.project)
if @project_update.save
redirect_to project_project_updates_path(@project), :notice => 'abc.'
else
redirect_to project_project_updates_path(@project), :alert => 'abc.'
end
end
def update
@project_update = ProjectUpdate.find(params[:id])
return redirect_to :back, :notice => 'you cannot edit project update.' unless current_user.owner?(@project_update.project)
if @project_update.update_attributes(params[:project_update] )
redirect_to project_project_updates_path(@project), :notice => 'abc.'
else
redirect_to project_project_updates_path(@project), :alert => 'abcy.'
end
end
def destroy
@project_update = ProjectUpdate.find(params[:id])
return redirect_to :back, :alert => 'abc.' unless current_user.owner?(@project_update.project)
@project_update.destroy
respond_to do |format|
format.html { redirect_to project_project_updates_url(@project) }
format.json { head :no_content }
end
end
def get_project
@project = Project.find(params[:project_id])
end
def feed
@project = Project.find(params[:project_id])
@project_updates = @project.project_updates
respond_to do |format|
format.rss { render :layout => false }
end
end
end
答案 0 :(得分:2)
显然projects#update
会以某种方式触发对identify -format ...
的系统调用。宝石cocaine用于此目的。它在自述文件中说明如下:
https://github.com/thoughtbot/cocaine#posix-spawn
您可以通过安装posix-spawn gem来提高性能。在分叉命令行进程时,此gem可以保持您的应用程序堆不被复制。对于具有大堆的应用,增益可能很大。
我对此进行了测试并重现了错误。
#!/usr/bin/env ruby
require 'posix/spawn'
@arrays = []
def do_echos
begin
IO.popen('echo I am a child started with popen') { |io| puts io.read }
rescue Errno::ENOMEM => e
puts "IO.popen: #{e.message}"
end
begin
pid = Process.spawn('echo I am a child started with Process.spawn')
Process.wait(pid)
rescue Errno::ENOMEM => e
puts "Process.spawn: #{e.message}"
end
child = POSIX::Spawn::Child.new('echo', 'I am a child started with posix_spawn');
puts child.out
end
def fill_mem
begin
while true
@arrays << Array.new(10000000)
end
rescue NoMemoryError
puts "Allocated arrays until out of memory..."
end
end
do_echos
fill_mem
do_echos
输出:
我是一个从popen开始的孩子 我是一个从Process.spawn开始的孩子 我是一个刚开始使用posix_spawn的孩子 分配的数组直到内存不足...
开始的孩子
IO.popen:无法分配内存 - echo
Process.spawn:无法分配内存 - echo
我是一个以posix_spawn
总之,我建议您遵循可卡因的建议。
要包含posix-spawn,只需将其添加到Gemfile中,或者,如果您不使用bundler,请安装gem。