Edited at

Net::SCPでのハマりどころと解決方法

More than 3 years have passed since last update.


ハマりどころ1

ワイルドカード使えない。

require 'net/scp'

opt = {compression: true, password: scp_pass}
Net::SCP.upload!(scp_host, scp_user, '*.gz', scp_dir, opt) #can't use wildcard

これなら動く。

require 'file'

require 'net/scp'
files = Find.find(dir).select {|path| path if path =~ /^.*.gz$/}
opt = {compression: true, password: scp_pass}
Net::SCP.start(scp_host, scp_user, opt) do |scp|
files.each { |file| scp.upload!(file, "#{scp_file}/") }
end


ハマりどころ2

上でも動作するが、asyncにしたい。そういった時は次のコードを書くことになる。

require 'file'

require 'net/scp'
files = Find.find(dir).select {|path| path if path =~ /^.*.gz$/}
opt = {compression: true, password: scp_pass}
Net::SCP.start(scp_host, scp_user, opt) do |scp|
channels = files.map { |file| scp.upload(file, "#{scp_file}/")}
channels.each { |c| c.wait}
end

しかし、対象ファイルが大量だったりすると次のような謎のエラーが発生する。

rake aborted!

open failed (1)
/home/hoge/apps/vendor/bundle/ruby/2.1.0/gems/net-ssh-2.9.2/lib/net/ssh/connection/channel.rb:525:in `do_open_failed'
/home/hoge/apps/vendor/bundle/ruby/2.1.0/gems/net-ssh-2.9.2/lib/net/ssh/connection/session.rb:552:in `channel_open_failure'
/home/hoge/apps//vendor/bundle/ruby/2.1.0/gems/net-ssh-2.9.2/lib/net/ssh/connection/session.rb:466:in `dispatch_incoming_packets'
...

(たぶん)原因はc.waitの前に転送が終わってしまっているから、closeできないチャンネルが発生するため。

そこで次のように変更する。

require 'file'

require 'net/scp'
files = Find.find(dir).select {|path| path if path =~ /^.*.gz$/}
opt = {compression: true, password: scp_pass}
Net::SCP.start(scp_host, scp_user, opt) do |scp|
files.each { |file| scp.upload(file, "#{scp_file}/").wait }
end

意外にハマるので注意が必要である。