Skip to main content

How to make Net::SSH work with Jruby on Windows

Net::SFTP works like a charm in Jruby on Linux. However, when I tested my application in Windows, I ran into a fail "to load -- dl/import ssh" error and then into "IOError (The system cannot find the path specified)". To work around the errors, I had to make some changes to the Net::SSH code to make it work. There are 2 files you need to change gems\net-ssh-2.0.4\lib\net\ssh\known_hosts.rb and gems\net-ssh-2.0.4\lib\net\ssh\authentication\pageant.rb.

For known_hosts.rb change the add(host, key) method located at the end of file to read like this:

# Tries to append an entry to the current source file for the given host
    # and key. If it is unable to (because the file is not writable, for
    # instance), an exception will be raised.
    def add(host, key)
      begin #jpt
        File.open(source, "a") do |file|
          blob = [Net::SSH::Buffer.from(:key, key).to_s].pack("m*").gsub(/\s/, "")
          file.puts "#{host} #{key.ssh_type} #{blob}"
        end
      rescue
#Note that I am just ignoring the error
        puts $!.to_s #just print error msg and goes into its merry way
      end
    end

For pageant.rb just clear everything so it looks something like this:

#require 'dl/import'
#require 'dl/struct'

require 'net/ssh/errors'

module Net; module SSH; module Authentication

  # This module encapsulates the implementation of a socket factory that
  # uses the PuTTY "pageant" utility to obtain information about SSH
  # identities.
  #
  # This code is a slightly modified version of the original implementation
  # by Guillaume Marçais (guillaume.marcais@free.fr). It is used and
  # relicensed by permission.
  module Pageant

    # From Putty pageant.c
    AGENT_MAX_MSGLEN = 8192
    AGENT_COPYDATA_ID = 0x804e50ba
    
    # The definition of the Windows methods and data structures used in
    # communicating with the pageant process.
    module Win
    end

    # This is the pseudo-socket implementation that mimics the interface of
    # a socket, translating each request into a Windows messaging call to
    # the pageant daemon. This allows pageant support to be implemented
    # simply by replacing the socket factory used by the Agent class.
    class Socket

    end

  end

end; end; end

Comments

A couple questions...

Has a bug report been filed with the Net::SSH developers?

Does one need putty installed?

Your blog is the only article I can find explaining this, and I'm still a bit confused, as there are oodles of Windows users out there that could potentially be using these gems.

Thanks!

-Tres
Juan Pablo said…
I just filed the bug today. Thanks for suggesting that.

I did have Putty installed on my system when running my program. But since the pageant.rb is getting completed replaced in the code shown, I don't think you really need Putty.
Anonymous said…
Thanks for the quick response.

I assumed it was using PuTTY and installed the pageant service with no luck.

So if it replaces putty, did you simply remove old un-needed code?

Making these changes does successfully suppress the dl/import error, however a new one arises on my station "The system cannot find the path specified", which looks surprisingly similar to your
IOError.

I am using NetBeans 6.5 with JRuby 1.1.3 (Built-in). I've tried JRuby 1.1.4 with same results.

"net-ssh" is version 2.0.4, and "jruby-openssl" is version 0.3.

Thanks for any assistance.

-Tres
Juan Pablo said…
Yeah, I simply removed the PuTTY code that required dl to work. It was more of a trial and error to see which part of the code was needed :)

Did you do the change to known_hosts.rb? (the "add(host, key)" method located at the end of file) Maybe that will take away your file error.

You can paste your stack trace here if it the above does not work.
Juan,

Yes, I've made both of the changes specified.

Here's is (what i would consider) the stack trace using the Ruby debug flag. It is at the bottom of the post.

http://fatbuttlarry.blogspot.com/2008/10/ruby-trying-it-again.html

-Tres
Thanks Juan. I'll try removing and adding these modules again.

-Tres
I started from scratch only to realize that the error message I was getting is not causing failure.

Seems to be working. I'll just ignore the error message for now. Thanks for your help.

http://fatbuttlarry.blogspot.com/2008/10/ruby-for-dummies-nine-steps-for.html

-Tres
magix Yu said…
For modifying the known_hosts.rb, there is a better solution for this(i think ^_^).

Add te following to ssh.rb(the entry of the net-ssh) to override the File.expand_path

class File
class << self
alias_method :expand_path2, :expand_path
end
end

class File
def File.expand_path(source)
source = File.expand_path2(source)
if (ENV['OS'] =~ /win/i) #RUBY_PLATFORM can not be use in current Jruby. you alway get 'java'
source.gsub!(/\//, '\\')
end
return source
end
end

Popular posts from this blog

Powershell script for converting JPG to TIFF

The following Powershell script will convert a batch of JPEG files to TIFF format: #This Code is released under MIT license [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") $files_folder = 'C:\path-where-your-jpg-files-are\' $pdfs = get-childitem $files_folder -recurse | where {$_.Extension -match "jpg"} foreach($pdf in $pdfs) { $picture = [System.Drawing.Bitmap]::FromFile( $pdf.FullName ) $tiff = $pdf.FullName.replace('.PDF','').replace('.pdf','').replace('.jpg','').replace('.JPG','') + '.tiff' $picture.Save($tiff) }

Power Automate: SFTP action "Test connection failed"

When I added an SFTP create file action to my Power Automate flow ( https://flow.microsoft.com ) , I got the following error in the action step, within the designer: "Test connection failed" To troubleshoot the Power Automate connection, I had to: go the Power Automate portal then "Data"->"Connections"  the sftp connection was there, I clicked on the ellipsis, and entered the connection info It turns out, that screen provides more details about the connection error. In my case, it was complaining that "SSH host key finger-print xxx format is not supported. It must be in 'MD5' format". I had provided the sha fingerprint that WinScp shows. Instead, I needed to use the MD5 version of the fingerprint. To get that, I had to run in command line (I was in a folder that had openssh in it): ssh -o FingerprintHash=md5 mysftpsite.com To get the fingerprint in MD5 format. I took the string (without the "MD5:" part of the string) and put

Alert if file missing using Powershell

The following Powershell script can be used to send an email alert when a file is missing from a folder or it is the same file from a previous check: $path_mask = "yourfile_*.txt" $previous_file_store = "lastfileread.txt" $script_name = "File Check" ###### Functions ########## Function EMailLog($subject, $message) {    $emailTo = "juanito@yourserver.com"    $emailFrom = "alert@yourserver.com"    $smtpserver="smtp.yourserver.com"       $smtp=new-object Net.Mail.SmtpClient($smtpServer)    $smtp.Send($emailFrom, $emailTo, $subject, $message) } Try {    #get files that match the mask    $curr_file = dir $path_mask |  select name    if ($curr_file.count -gt 0)    {        #file found        #check if the file is different from the previous file read        $previous_file = Get-Content $previous_file_store        $curr_file_name = $curr_file.Item(0).Name        if ($