Errno::EEXIST 使用 CKEditor 上传图片时出错

Errno::EEXIST error during image upload using CKEditor

当我尝试从我的 rails 3.2 应用程序在 CKEditor 中上传文件时出现此错误。

我已经使用 capistrano 进行部署,但现在卡在了这个错误。

它适用于我的本地和 UAT 环境,但不适用于生产环境。

之前我遇到了访问被拒绝的问题,我修复了这个问题,现在我收到以下错误:

An Errno::EEXIST occurred in pictures#create_pic:

  File exists @ dir_s_mkdir - /var/www/web_cc_cap1/releases/20161230073928/public/system
  /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/fileutils.rb:247:in `mkdir'

deploy.rb

# config valid only for current version of Capistrano
lock '3.6.1'

set :application, 'web_app'
set :repo_url, 'sample.git'

# set :rvm_ruby_string, "2.1.0@capistrano"
# set :rvm_ruby_version, "2.1.0"
# set :rvm_type, :system

# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
# Default deploy_to directory is /var/www/my_app_name

set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
set :log_level, :debug

# set :nginx_roles, :web
# default_run_options[:pty] = true
set :pty, true

set :resque_verbose, false

我从错误通知邮件中得到的完整回溯:

-------------------------------
Backtrace:
-------------------------------

  /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/fileutils.rb:247:in `mkdir'
  /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/fileutils.rb:247:in `fu_mkdir'
  /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/fileutils.rb:224:in `block (2 levels) in mkdir_p'
  /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/fileutils.rb:222:in `reverse_each'
  /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/fileutils.rb:222:in `block in mkdir_p'
  /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/fileutils.rb:208:in `each'
  /usr/local/rvm/rubies/ruby-2.1.0/lib/ruby/2.1.0/fileutils.rb:208:in `mkdir_p'
  carrierwave (0.9.0) lib/carrierwave/sanitized_file.rb:290:in `mkdir!'
  carrierwave (0.9.0) lib/carrierwave/sanitized_file.rb:209:in `copy_to'
  carrierwave (0.9.0) lib/carrierwave/storage/file.rb:34:in `store!'
  carrierwave (0.9.0) lib/carrierwave/uploader/store.rb:59:in `block in store!'
  carrierwave (0.9.0) lib/carrierwave/uploader/callbacks.rb:17:in `with_callbacks'
  carrierwave (0.9.0) lib/carrierwave/uploader/store.rb:58:in `store!'
  carrierwave (0.9.0) lib/carrierwave/mount.rb:371:in `store!'
  carrierwave (0.9.0) lib/carrierwave/mount.rb:223:in `store_data!'
  activesupport (3.2.14) lib/active_support/callbacks.rb:427:in `_run__1373012483211490398__save__252829260382173436__callbacks'
  activesupport (3.2.14) lib/active_support/callbacks.rb:405:in `__run_callback'
  activesupport (3.2.14) lib/active_support/callbacks.rb:385:in `_run_save_callbacks'
  activesupport (3.2.14) lib/active_support/callbacks.rb:81:in `run_callbacks'
  activerecord (3.2.14) lib/active_record/callbacks.rb:264:in `create_or_update'
  activerecord (3.2.14) lib/active_record/persistence.rb:84:in `save'
  activerecord (3.2.14) lib/active_record/validations.rb:50:in `save'
  activerecord (3.2.14) lib/active_record/attribute_methods/dirty.rb:22:in `save'
  activerecord (3.2.14) lib/active_record/transactions.rb:259:in `block (2 levels) in save'
  activerecord (3.2.14) lib/active_record/transactions.rb:313:in `block in with_transaction_returning_status'
  activerecord (3.2.14) lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
  activerecord (3.2.14) lib/active_record/transactions.rb:208:in `transaction'
  activerecord (3.2.14) lib/active_record/transactions.rb:311:in `with_transaction_returning_status'
  activerecord (3.2.14) lib/active_record/transactions.rb:259:in `block in save'
  activerecord (3.2.14) lib/active_record/transactions.rb:270:in `rollback_active_record_state!'
  activerecord (3.2.14) lib/active_record/transactions.rb:258:in `save'
  active_scaffold (3.3.3) lib/active_scaffold/extensions/unsaved_record.rb:15:in `save_with_unsaved_flag'
  app/controllers/application_controller.rb:707:in `respond_with_asset'
  app/controllers/pictures_controller.rb:17:in `create_pic'
  actionpack (3.2.14) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
  actionpack (3.2.14) lib/abstract_controller/base.rb:167:in `process_action'
  actionpack (3.2.14) lib/action_controller/metal/rendering.rb:10:in `process_action'
  actionpack (3.2.14) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
  activesupport (3.2.14) lib/active_support/callbacks.rb:557:in `_run__1719685529573174046__process_action__303294515139870162__callbacks'
  activesupport (3.2.14) lib/active_support/callbacks.rb:405:in `__run_callback'
  activesupport (3.2.14) lib/active_support/callbacks.rb:385:in `_run_process_action_callbacks'
  activesupport (3.2.14) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (3.2.14) lib/abstract_controller/callbacks.rb:17:in `process_action'
  actionpack (3.2.14) lib/action_controller/metal/rescue.rb:29:in `process_action'
  actionpack (3.2.14) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
  activesupport (3.2.14) lib/active_support/notifications.rb:123:in `block in instrument'
  activesupport (3.2.14) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  activesupport (3.2.14) lib/active_support/notifications.rb:123:in `instrument'
  actionpack (3.2.14) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
  actionpack (3.2.14) lib/action_controller/metal/params_wrapper.rb:207:in `process_action'
  activerecord (3.2.14) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (3.2.14) lib/abstract_controller/base.rb:121:in `process'
  actionpack (3.2.14) lib/abstract_controller/rendering.rb:45:in `process'
  actionpack (3.2.14) lib/action_controller/metal.rb:203:in `dispatch'
  actionpack (3.2.14) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
  actionpack (3.2.14) lib/action_controller/metal.rb:246:in `block in action'
  actionpack (3.2.14) lib/action_dispatch/routing/route_set.rb:73:in `call'
  actionpack (3.2.14) lib/action_dispatch/routing/route_set.rb:73:in `dispatch'
  actionpack (3.2.14) lib/action_dispatch/routing/route_set.rb:36:in `call'
  journey (1.0.4) lib/journey/router.rb:68:in `block in call'
  journey (1.0.4) lib/journey/router.rb:56:in `each'
  journey (1.0.4) lib/journey/router.rb:56:in `call'
  actionpack (3.2.14) lib/action_dispatch/routing/route_set.rb:608:in `call'
  exception_notification (4.0.1) lib/exception_notification/rack.rb:28:in `call'
  rack (1.4.5) lib/rack/deflater.rb:13:in `call'
  warden (1.2.3) lib/warden/manager.rb:35:in `block in call'
  warden (1.2.3) lib/warden/manager.rb:34:in `catch'
  warden (1.2.3) lib/warden/manager.rb:34:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
  rack (1.4.5) lib/rack/etag.rb:23:in `call'
  rack (1.4.5) lib/rack/conditionalget.rb:35:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/head.rb:14:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/flash.rb:242:in `call'
  rack (1.4.5) lib/rack/session/abstract/id.rb:210:in `context'
  rack (1.4.5) lib/rack/session/abstract/id.rb:205:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/cookies.rb:341:in `call'
  activerecord (3.2.14) lib/active_record/query_cache.rb:64:in `call'
  activerecord (3.2.14) lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
  activesupport (3.2.14) lib/active_support/callbacks.rb:405:in `_run__904569922375962105__call__252829260382173436__callbacks'
  activesupport (3.2.14) lib/active_support/callbacks.rb:405:in `__run_callback'
  activesupport (3.2.14) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
  activesupport (3.2.14) lib/active_support/callbacks.rb:81:in `run_callbacks'
  actionpack (3.2.14) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  rack (1.4.5) lib/rack/sendfile.rb:102:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
  railties (3.2.14) lib/rails/rack/logger.rb:32:in `call_app'
  railties (3.2.14) lib/rails/rack/logger.rb:16:in `block in call'
  activesupport (3.2.14) lib/active_support/tagged_logging.rb:22:in `tagged'
  railties (3.2.14) lib/rails/rack/logger.rb:16:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/request_id.rb:22:in `call'
  rack (1.4.5) lib/rack/methodoverride.rb:21:in `call'
  rack (1.4.5) lib/rack/runtime.rb:17:in `call'
  activesupport (3.2.14) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
  rack (1.4.5) lib/rack/lock.rb:15:in `call'
  actionpack (3.2.14) lib/action_dispatch/middleware/static.rb:63:in `call'
  rack-ssl (1.3.3) lib/rack/ssl.rb:27:in `call'
  rack-cache (1.2) lib/rack/cache/context.rb:136:in `forward'
  rack-cache (1.2) lib/rack/cache/context.rb:143:in `pass'
  rack-cache (1.2) lib/rack/cache/context.rb:155:in `invalidate'
  rack-cache (1.2) lib/rack/cache/context.rb:71:in `call!'
  rack-cache (1.2) lib/rack/cache/context.rb:51:in `call'
  railties (3.2.14) lib/rails/engine.rb:484:in `call'
  railties (3.2.14) lib/rails/application.rb:231:in `call'
  railties (3.2.14) lib/rails/railtie/configurable.rb:30:in `method_missing'
  /usr/local/rvm/gems/ruby-2.1.0/gems/passenger-5.0.10/lib/phusion_passenger/rack/thread_handler_extension.rb:94:in `process_request'
  /usr/local/rvm/gems/ruby-2.1.0/gems/passenger-5.0.10/lib/phusion_passenger/request_handler/thread_handler.rb:157:in `accept_and_process_next_request'
  /usr/local/rvm/gems/ruby-2.1.0/gems/passenger-5.0.10/lib/phusion_passenger/request_handler/thread_handler.rb:110:in `main_loop'
  /usr/local/rvm/gems/ruby-2.1.0/gems/passenger-5.0.10/lib/phusion_passenger/request_handler.rb:414:in `block (3 levels) in start_threads'
  /usr/local/rvm/gems/ruby-2.1.0/gems/passenger-5.0.10/lib/phusion_passenger/utils.rb:111:in `block in create_thread_and_abort_on_exception'

pictures_controller.rb

class PicturesController < ApplicationController
  respond_to :html, :json
  layout 'ckeditor/application'
  before_filter :login_required
  before_filter :find_asset, :only => [:destroy]
  before_filter :ckeditor_authorize!  
  before_filter :authorize_resource

  def create_pic
    @picture = Ckeditor.picture_model.new
      respond_with_asset(@picture)
  end
end

application_controller.rb

  def respond_with_asset(asset)

      file = params[:CKEditor].blank? ? params[:qqfile] : params[:upload]
      asset.data = Ckeditor::Http.normalize_param(file, request)
      callback = ckeditor_before_create_asset(asset)

      if callback && asset.save
        body = params[:CKEditor].blank? ? asset.to_json(:only=>[:id, :type]) : %Q"<script type='text/javascript'>
          window.parent.CKEDITOR.tools.callFunction(#{params[:CKEditorFuncNum]}, '#{config.relative_url_root}#{Ckeditor::Utils.escape_single_quotes(asset.url_content)}');
        </script>"

        render :text => body
      else
        render :nothing => true
      end
  end

更新:我写的S3挂载秘籍

desc "Mounting S3 for the first time"
    task :mounting_s3 do
        on main_server, in: :sequence, wait: 5 do |host|
            as 'www-data' do
                within "#{code_folder_path}/current" do
                    code_folder = "#{code_folder_path}/current"
                    path = "#{code_folder_path}/current/public/system"
                    unmount_path = "#{code_folder_path}/shared/public/system"

                    # check first if public/system exists
                    puts "** Checking if public/system folder exists on #{host}"
                    puts "** testing if it is there #{test("[ -d #{path} ]")}"
                    if test("[ -d #{path} ]")
                        puts "** public/system folder exists.."
                        puts "** Checking if S3 is mounted"
                        result = capture "cd #{code_folder} && mountpoint public/system" , raise_on_non_zero_exit: false
                        puts "result #{result}"
                        if  result.match('is a mountpoint') != nil
                            puts "** S3 is mounted at #{path} on #{host}"
                        elsif result.match('is not a mountpoint') != nil
                            puts "** #{path} is not a mountpoint on #{host}"
                            execute! "cd #{code_folder} && sudo su - www-data -s /bin/bash -c 's3fs cc-s-p #{path}'"
                        end 
                    else
                        puts "** public/system folder does not exists.."
                        puts "** Mounting S3"
                        execute! "cd #{code_folder} && sudo su - www-data -s /bin/bash -c 's3fs cc-s-p #{path}'"
                    end 
                end
            end
        end 
    end

end

我该如何解决这个问题,这个错误是什么意思?

最明显的解决方案是允许网络服务器根据需要生成 public/system 目录。在 deploy.rb 中删除它:

set :linked_dirs, fetch(:linked_dirs, []).push(
  %w|log tmp/pids tmp/cache tmp/sockets vendor/bundle|
)

现在服务器应该在第一次访问时以适当的权限自行创建此目录。在您当前的情况下,此目录是由部署脚本创建的,即 运行 [我想] 不是作为网络服务器用户。


如果此目录不为空,但您仍想部署它,只需指示 capistranochown 将其归网络服务器用户所有。

作为最后的手段,可以将权限设置为 777,但我坚决认为这是解决问题的最糟糕方法。

我已经解决了这个问题,我注意到其他一些用户对 /etc 文件夹中的 s3fs-passwd 文件有权限。通过执行 chown deploy:deploy s3fs-passwd 授予部署用户访问该文件的权限,并且 /public/system 开始显示正确的文件权限而不是 ?? ????? 并且上传现在工作正常。

在我的例子中,我遇到了同样的错误,原因是 public/system 是一个符号链接(我正在迁移)。我可以通过使用 bind mount 而不是符号链接来欺骗 rails 不会失败:

mount --bind /orig/public/system /your/public/system

希望对大家有所帮助。