IOError: закрытый поток в Ruby SFTP

Следующий код пытается получить список записей удаленного каталога через SFTP и Net::SFTP, но вызывает "закрытый поток" IOError, если каталог содержит большое количество файлов (~ 6000 файлов):

require 'net/ssh'
require 'net/sftp'
Net::SFTP.start('hostname', 'username', :password => 'password') do |sftp|
  # list the entries in a directory
  sftp.dir.foreach("/") do |entry|
    puts entry.longname
  end
end 

Как лучше всего этого избежать? Версии: net-sftp Gem: 2.0.5 и net-ssh Gem: 2.2.1, Ruby: 1.8.7. Полное сообщение об ошибке гласит:

IOError: closed stream
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/ruby_compat.rb:33:in `select'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/ruby_compat.rb:33:in `io_select'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/ruby_compat.rb:32:in `synchronize'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/ruby_compat.rb:32:in `io_select'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/packet_stream.rb:73:in `available_for_read?'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/packet_stream.rb:85:in `next_packet'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/session.rb:170:in `poll_message'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/session.rb:165:in `loop'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/session.rb:165:in `poll_message'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:451:in `dispatch_incoming_packets'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:213:in `preprocess'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:197:in `process'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `loop'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `loop_forever'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `loop'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:110:in `close'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-sftp-2.0.5/lib/net/sftp.rb:36:in `start'

person 0x4a6f4672    schedule 04.02.2013    source источник


Ответы (1)


Такое поведение может быть преднамеренным, если мы посмотрим на исходный код dir в net-sftp/lib/net/sftp/operations/dir.rb видим операцию закрытия:

def foreach(path)
  ..  
ensure
  sftp.close!(handle) if handle
end

Возможно, эта операция закрытия вызывает ошибку закрытого потока. Если это не указывает на ошибку, возможно, поймать исключение IOError. Также иногда помогает запуск цикла событий SSH:

begin   
  ..
  sftp.dir.foreach("/") do |entry|
    puts entry.longname
    # ...
    sftp.loop # Runs the SSH event loop 
  end
rescue IOError => Ex   
  puts "*** We are done: "+Ex.message 
end
person 0x4a6f4672    schedule 16.01.2014