ruby-on-railssshnet-ssh

Errno::ENOTTY Inappropriate ioctl for device when connecting to a remote server through Net::SSH on SuSe (with Ruby on Rails 5.2.4)


My Ruby on Rails application remotely starts some scripts on a distant SuSe server (SUSE Linux Enterprise Server 15 SP2). It relies on the net-ssh gem which is declared in the Gemfile: gem 'net-ssh'.

The script is triggerd remotely through the following block:

    Net::SSH.start(remote_host, remote_user, password: remote_password) do |ssh|
      feed_back = ssh.exec!("#{event.statement}")
    end

This works as expected as long as long as the Rails server runs on Windows Server 2016, which is my DEV environment. But when I deploy to the Validation environment, which is SUSE Linux Enterprise Server 15 SP2, I get this error message:

Errno::ENOTTY in myController#myMethod 
Inappropriate ioctl for device

On another hand, issuing the SSH request through the command line - from SUSE to SUSE - works as expected too. Reading around I did not find a relevant parameter for the Net::SSH module to solve this.

Your suggestions are welcome!


Solution

  • I finally found out that the message refers to the operating mode of SSH: it requires a sort of terminal emulation - so called pty - wrapped into a SSH chanel.

    So I implemented it this way:

    Net::SSH.start(remote_host, remote_user, password: remote_password) do |session|
      session.open_channel do |channel|
        channel.request_pty do |ch, success|
          raise "Error requesting pty" unless success
          puts "------------ pty successfully obtained"
        end
    
        channel.exec "#{@task.statement}" do |ch, success|
          abort "could not execute command" unless success
    
          channel.on_data do |ch, data|
            puts "------------ got stdout: #{data}"
            @task.update_attribute(:return_value, data)
          end
    
          channel.on_extended_data do |ch, type, data|
            puts "------------ got stderr: #{data}"
          end
    
          channel.on_close do |ch|
            puts "------------ channel is closing!"
          end
    
        end
      end
    
      ### Wait until the session closes
      session.loop
    end
    

    This solved my issue.

    Note: The answer proposed above was only a part of the solution. The same error occured again with this source code when deploying to the production server.

    The issue appears to be the password to the SSH target: I retyped it by hand instead of doing the usual copy/paste from MS Excel, and the SSH connection is now successful!

    As the error raised is not a simple "connection refused", I suspect that the password string had a specific character encoding, or an unexpected ending character.

    As the first proposed solution provides a working example, I leave it there.