How do I execute a remote Ruby script file via SSH?

8.3k Views Asked by At

I have a Ruby file called "test.rb", and I uploaded it to the server via Net::SCP.

The contents of the file are:

puts "Hello, World"

How do I go about executing that file via Net::SSH and grab the STDOUT or STDERR?

This is the error I'm getting:

Bash: Ruby not found 

That's because Net::SSH won't load a login shell.

I've tried everything from Net::SSH::Shell to SSHkit and rye to solve the problem of executing the script and getting any STDOUT back.

How do I execute a script via Net::SSH when I don't have access to a login shell, and get any STDOUT or STDERR?

I'm using Ruby-2.1.0.

command = "ruby -e'print :hello'"
Net::SSH.start(server_connection.host, server_connection.ssh_username, port: server_connection.ssh_port, paranoid: false)  do |ssh|
  job.stdout  = ""
  job.stderr = ""
  ssh.exec! command do |channel, stream, data|
    job.stdout << data if stream == :stdout
    job.stderr << data if stream == :stderr
  end
  ssh.close
end
2

There are 2 best solutions below

0
On

This might help explain a bit:

require 'net/ssh'

# put commands to send to the remote Ruby here...
CMDs = [
  '-v',
]

print 'Enter your password: '
password = gets.chomp

Net::SSH.start('localhost', ENV['USER'], :password => password) do |ssh|

  remote_ruby = ssh.exec!('/usr/bin/which ruby').chomp
  puts 'Using remote Ruby: "%s"' % remote_ruby

  CMDs.each do |cmd|

    puts 'Sending: "%s"' % cmd

    stdout = ''
    ssh.exec!("#{ remote_ruby } #{ cmd }") do |channel, stream, data|
      stdout << data if stream == :stdout
    end

    puts 'Got: %s' % stdout
    puts
  end

end

Save that to a Ruby file. Turn on SSH access on your local machine, then run that script. It'll prompt for your password, then connect to the localhost and grab the path to the default Ruby. Then it'll loop through all commands in CMDs, executing them and returning their STDOUT.

For more options see the Net::SSH synopsis.

/usr/bin/which ruby

is a standard way to figure out which executable the system will use for a particular command. It searches the PATH and returns the path to that command. Usually that'll be /usr/bin/ruby for a *nix machine if Ruby was bundled with the OS or installed using yum or apt-get. If you installed it from source it might be in /usr/local/bin/ruby.

If you used RVM or rbenv or Homebrew, you'll have to sniff out their presence, and use whatever tricks their authors recommend. This code will hang for a bit, then raise an exception probably.

On my machine, running that code outputs:

Enter your password: some(secret)thang
Using remote Ruby: "/usr/bin/ruby"
Sending: "-v"
Got: ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]
3
On

Try this:

 ssh username@host "ruby -e'print :hello'"

This would execute Ruby on the host machine, and give you output the same way you can also run any other script on a remote machine.

require 'net/ssh'

host = "localhost"
username = "tuxdna"
password = "SOMEAWESOMEPASSWORDHERE"
command = "ruby -e'print :hello'"

class Job
  attr_accessor :stdout
  attr_accessor :stderr
end

job = Job.new

Net::SSH.start(host, username, password: password)  do |ssh|
  job.stdout  = ""
  job.stderr = ""
  ssh.exec! command do |channel, stream, data|
    job.stdout << data if stream == :stdout
    job.stderr << data if stream == :stderr
  end
  # ssh.close
end
p job

OUTPUT:

$ ruby myssh.rb
#<Job:0x00000002bed0a0 @stdout="hello", @stderr="">