Lately there has been some talking in Ruby-Talk on how to send files using scp. Some people are doing just fine by calling scp with a pre-shared password, but I don’t like that approach and it doesn’t work for my purpose, so I did a bit of experimentation and found this code works:

require 'net/ssh'
require 'net/sftp'

class SSHAgent
 def initialize
    @agent_env = Hash.new
    agenthandle = IO.popen("/usr/bin/ssh-agent -s", "r")
    agenthandle.each_line do |line|
     if line.index("echo") == nil
         line = line.slice(0..(line.index(';')-1))
         key, value = line.chomp.split(/=/)
         puts "Key = #{key}, Value = #{value}"
         @agent_env[key] = value
     end
    end
 end
 def [](key)
    return @agent_env[key]
 end
end

agent = SSHAgent.new
ENV["SSH_AUTH_SOCK"] = agent["SSH_AUTH_SOCK"]
ENV["SSH_AGENT_PID"] = agent["SSH_AGENT_PID"]
system("/usr/bin/ssh-add")

Net::SSH.start( '192.168.1.12',
        :username=>'pgquiles',
        :compression_level=>0,
        :compression=>'none'
       ) do |session|
                 session.sftp.connect do |sftp|
             sftp.put_file("bigvideo.avi", "bigvideo.avi")
            end
end

I was using a passwordless private key for this experiment. Should you want to use a password-protected private key, you might want to set the DISPLAY and SSH_ASKPASS environment variables or use a smartcard reader and the ‘-s reader’ parameter.

The SSHAgent class comes from a public paste (I don’t know who its author is or the license that code is under).

Lastly, there is an undesired behaviour in Net::SFTP: when you use the put_file method it loads the whole file in memory, therefore you need loads of memory if you want to send big files. I’ve tried a naive fix (iterating writes) but it didn’t work (it complains about “no such file”, I think it’s a channels-related issue). Jamis Buck, the author of Net::SFTP, told me he currently has no time to fix this issue. In case you feel brave enough, the offending method starts in line 202 in

net-sftp-1.1.0/lib/net/sftp/session.rb.

One Thought on “A solution for public-keyed SFTP and Ruby

  1. I always spent my half an hour to read this website’s articles every day along with a cup of coffee.

Leave a Reply

Your email address will not be published. Required fields are marked *

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Post Navigation