Ошибка Ruby Net::SFTP при использовании session.exec

Я получаю неожиданное поведение от Net::SFTP в Ruby (ruby 1.9.3p194).

Вариант №1 не работает. Он запускает блок SFTP и использует session.exec! для запуска команды оболочки.

Net::SFTP.start(...) do |sftp|
  sftp.session.exec! "mkdir -p ..."  # Fails here.
  sftp.upload!(...)
end

Вариант №2 работает успешно. Он запускает блок SSH и использует sftp.upload! для копирования файла.

Net::SSH.start(...)  do |ssh|
  ssh.exec! "mkdir -p ..."
  ssh.sftp.upload!(...)
end

Любые идеи или объяснения будут оценены.

Вот трассировка стека из варианта №1:

can't add a new key into hash during iteration

net-ssh-2.6.3/lib/net/ssh/connection/session.rb:296:in `[]='
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:296:in `open_channel'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:320:in `exec'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:354:in `exec!'
dor-services-3.20.0/lib/dor/services/digital_stacks_service.rb:28:in `block in transfer_to_document_store'
net-sftp-2.0.5/lib/net/sftp/session.rb:939:in `call'
net-sftp-2.0.5/lib/net/sftp/session.rb:939:in `block in do_version'
net-sftp-2.0.5/lib/net/sftp/session.rb:939:in `each'
net-sftp-2.0.5/lib/net/sftp/session.rb:939:in `do_version'
net-sftp-2.0.5/lib/net/sftp/session.rb:909:in `when_channel_polled'
net-ssh-2.6.3/lib/net/ssh/connection/channel.rb:311:in `call'
net-ssh-2.6.3/lib/net/ssh/connection/channel.rb:311:in `process'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:214:in `block in preprocess'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:214:in `each'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:214:in `preprocess'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:197:in `process'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:161:in `block in loop'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:161:in `loop'
net-ssh-2.6.3/lib/net/ssh/connection/session.rb:161:in `loop'
net-sftp-2.0.5/lib/net/sftp/session.rb:802:in `loop'
net-sftp-2.0.5/lib/net/sftp/session.rb:787:in `connect!'
net-sftp-2.0.5/lib/net/sftp.rb:32:in `start'

person FMc    schedule 23.01.2013    source источник
comment
Почему вы используете вспомогательную оболочку для mkdir, когда Net::SFTP поддерживает mkdir(...) и mkdir!(...)?   -  person the Tin Man    schedule 24.01.2013
comment
@theTinMan Я задавался тем же вопросом, когда впервые увидел код. После некоторых экспериментов я понял, что mkdir!(...) не делает того, что делает mkdir -p — создает промежуточные каталоги, если они не существуют. В любом случае, Вариант №1 должен работать... но это не так.   -  person FMc    schedule 24.01.2013
comment
Правильно, он не делает промежуточные каталоги, которые будет делать -p, но это будет простой шаг.   -  person the Tin Man    schedule 24.01.2013


Ответы (1)


Вот код, который я написал для решения этой проблемы:

def mkdir_p(sftp, path)
  memo = "/"
  # [0..-2] to skip the filename
  path.split("/")[0..-2].each do |dir|
    next if dir.empty?
    if sftp.dir.entries(memo).map { |entry| entry.name }.include?(dir)
      memo += "/#{dir}"
    else
      memo += "/#{dir}"
      puts "Creating the following directory: #{memo}"
      sftp.mkdir!(memo)
    end
  end
end
person Powers    schedule 23.09.2014