Saturday, July 15, 2006

A short Net::SFTP tutorial and freezing gems

FTP itself is not very secure, since it sends a user's login and password over cleartext. So while Net::FTP in Ruby is pretty handy, I'm hoping to wean off of it soon.

That's when, after poking around for a couple minutes that Net::SFTP exists under the Net::SSH project. Huzzah! Yet, shared hosts don't have the ability for you to just install anything though. So it was then I found:

gem list --remote net-sftp
gem install net-sftp

So that way, I can install it as a gem on shared hosts. Also, I had forgotten how to freeze gems in rails. After lots of futile searching, I did come across a more automatic way. I didn't like the way it copied everything in the ./lib, because ./lib is suppose to be for in-house libraries, and ./vendor is for 3rd party libraries. I'd like to keep them separate.

So I remembered there was a manual way to do it....Ends up is that all you have to do is copy your gems into the vendor directory. use:

gem unpack gem_name

And it'll copy the gem into the current directory for you. However, in order to be able to include it as if it were a library, you'll need to change the environment.rb file found in your config directory in your application root directory.

Under the do |config| block, you'll see "config.load_paths". Uncomment that line and add the various gems in the vendor directory. Note that you don't put commas inbetween every path.

config.load_paths += %W(#{RAILS_ROOT}/vendor/needle-1.3.0/lib/
#{RAILS_ROOT}/vendor/net-ssh-1.0.9/lib/ )

So now, you'll be able to do "require "net/sftp" even if the gem isn't installed.
So how do you use the Net::SSH and Net::SFTP libraries? Just looking at the APIs, I thought I could piece it together, but it's not as simple as it sounds. It took a bit of poking around to find this manual for Net::SSH. There is no manual for Net::SFTP--only a Net::SFTP FAQ. And after looking at the manuals and FAQs, it is as simple as it looks. I wonder why I didn't get it...

Here's a little tutorial on how to start an SFTP session.

require 'net/sftp'

Net::SFTP.start(host, user, password) do |sftp|
sftp.put_file "/path/to/local.file", "/path/to/remote.file"

Albeit the SFTP library is complicated and kinda hard to use, the coolest thing that I found out about is that you can do is actually upload a file from memory. I wasn't able to figure out how to do this with the native Net::FTP library in Ruby.

require 'net/sftp'

data = "This is the contents of my file"

Net::SFTP.start(host, user, password) do |sftp|
sftp.open_handle("/path/to/remote.file", "w") do |file_handle|
contents = sftp.write(file_handle, data)
puts contents.code

I don't know exactly how this is done, but my naive guess is that since you already have an SSH session open through SFTP, you're able to perform native commands outside of the FTP protocol? Either way, it's just what I needed, so I wouldn't have to create local copies, upload them, and then delete them.

1 comment:

  1. This comment has been removed by a blog administrator.