Create a ruby pseudo terminal (PTY) and invoke an interactive command (SFTP)

Purpose

I needed to upload files on a SFTP server programmatically and automatically in a RoR Enviroment. SFTP ruby library wrapper are very limited (I only found this one actually) and is in maintenance (not more maintained) and I had some troubles uploading large files.

Anyway I decided to come back to use the old SFTP Command Line Interface who is perfectly working.

Unlucky this one is an Interactive CLI.

The trick is to use a Ruby Pseudo Terminal (PTY) , listen to the console input for some patterns and write in the console output according this pattern as a real user would do.

Here is a code snippet who doing the job and working perfectly.

Code

RUBY
require 'pty'
require 'expect'

PTY.spawn('sftp [email protected]:/uploads') do |input, output|

  # Say yes to SSH fingerprint
  input.expect(/fingerprint/, 2) do |r|

    output.puts "yes" if !r.nil?

    # Enter SFTP password
    input.expect(/password/, 2) do |r|

      output.puts 'your_sftp_password' if !r.nil?

      input.expect(/sftp/) do

        # List folders and files in `/uploads`
        output.puts 'ls'

        # Check if folder named `foo` exist
        input.expect(/foo/, 1) do |result|

          is_folder_exist = result.nil? ? false : true
          # Create `foo` folder if does'nt exist
          output.puts "mkdir foo" if !is_folder_exist
          # Change directory to `foo`
          output.puts "cd foo"
          # Upload `/path/to/local/foo.txt` in `foo` folder as `foo.txt`
          output.puts "put /path/to/local/foo.txt foo.txt"
          # Exit SFTP
          output.puts "exit"

        end

      end

    end

  end

end
Click to expand and view more

Gist

Available here . Please feel free to improve it !

More…

Quentin Rousseau

Quentin Rousseau

CTO & Co-founder at Rootly (YC S21)

San Francisco, CA

Former Instacart SRE. Rock climber & wine enthusiast.

Start searching

Enter keywords to search articles

↑↓
ESC
⌘K Shortcut