为什么这个FTP块读取操作抛出EOFError?

时间:2015-11-23 13:31:42

标签: ruby-on-rails ruby-on-rails-4 ftp readline

有人可以解释为什么这个块读取操作会抛出EOFError吗?我看到它的方式,它只会在完全读取文件时结束块。我错过了什么?我该如何解决?非常感谢。

注意:我应该提到它有时运行正常,而在其他情况下它会抛出EOFError。在同一位置的同一个文件中......

    Net::FTP.open(host=ftp.address, user='********', passwd='********') do |ftp|
      ftp.passive = true
      files = ftp.nlst('*')
      s3 = Aws::S3::Resource.new(region: 'us-east-1')
      files.each do |file|
        ftp.getbinaryfile(file, file, 65536) # Copies file to /tmp
        UpdateVfile.loader(@company, file) # Process file from /tmp
        s3_file = file + Time.zone.now.strftime("-%Y-%m-%dT%H-%M.xls")
        obj = s3.bucket('mydatafeed').object(s3_file) # Build object in S3 bucket
        data = ''
        ftp.getbinaryfile(file, nil, 65536) do |block|  <== EOFError thrown here!
          data << block
        end
        obj.put(body: data) # Write it to S3
        ftp.delete(file) # Delete the file from FTP
      end
    end

堆栈追踪:

An EOFError occurred in background at 2015.11.23 :

  end of file reached
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:1112:in `readline'

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

  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:1112:in `readline'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:289:in `getline'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:300:in `getmultiline'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:318:in `getresp'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:351:in `block in sendcmd'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/monitor.rb:211:in `mon_synchronize'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:349:in `sendcmd'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:394:in `makepasv'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:406:in `transfercmd'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:490:in `block (2 levels) in retrbinary'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:199:in `with_binary'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:488:in `block in retrbinary'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/monitor.rb:211:in `mon_synchronize'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:487:in `retrbinary'
  /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/net/ftp.rb:620:in `getbinaryfile'
  /app/lib/tasks/updates_vfile.rake:40:in `block (6 levels) in <top (required)>'

FTP debug_mode OUTPUT:

put: TYPE A
get: 200 Command TYPE okay.
put: PASV
get: 227 Entering Passive Mode (75,101,155,12,5,165)
put: NLST *
get: 150 File status okay; about to open data connection.
get: 226 Closing data connection.
put: TYPE I
get: 200 Command TYPE okay.
put: PASV
get: 227 Entering Passive Mode (75,101,155,12,5,163)
put: RETR <filename redacted>
get: 150 File status okay; about to open data connection.
get: 226 Transfer complete.
...output from update processing
put: PASV
rake aborted!
EOFError: end of file reached

1 个答案:

答案 0 :(得分:1)

问题原来是FTP空闲超时。因为UpdateVfile.loader是一个长期运行的任务,所以我将FTP单独放置太长时间,并且它使用EOFError来摧毁它。显然,超时错误会比这样一个让我比没有诊断信息更糟糕的不起眼的失败好得多。

如果装载机很短,那就有用了。对于更激烈的更新,它花了太长时间。当我更改源以尝试诊断并解决问题时,EOFError移动到ftp.delete命令,这对我来说更没意义。

我发现了一些暗示这个问题的讨论。结果,我在调用加载器之前改变了我的进程以处理所有FTP工作。这可靠地工作。否则,我要么必须定期发送保持活动,要么找到修改超时期限的方法。两者似乎都不容易实现。

如果有人能向我解释为什么FTP会发出EOFError而不是超时错误,我会感到高兴。这是不对的,会在诊断上导致任何人完全走错方向。谢谢......