Ruby Net-Ssh Calling Bash Script with Interactive Prompts

ruby net-ssh calling bash script with interactive prompts

managed to fix this by using the channel function, here's the method I use now

def connect(host,command)

require 'rubygems'
require 'net/ssh'

user = LocalConfig::SSH_DETAILS[:user]
pass = LocalConfig::SSH_DETAILS[:pass

o = ""
Net::SSH.start(host, user, :password => pass, :paranoid => false, :auth_methods => ['password'], :timeout => 30 )do |ssh |
channel = ssh.open_channel do |ch|
ch.exec(command) do |ch2, success|
ch2.send_data "myUserName\n"
ch2.send_data "mPassWord\n"

ch.on_data do |ch2, data|
o += data
end
end
end
channel.wait
return o.to_s
end
end

Ruby net/ssh is not running bash commands in background

You need to redirect both stdout and stderr somewhere else than the terminal, otherwise exec! will hang waiting for process output.

This is the simplest solution I found:

ssh.exec!("sleep 600 &> /dev/null &")

&> redirects both stdin and stderr at the same time.
If you want to redirect the output for logging, you can do so separately if you like:

ssh.exec!("command 2> error.log > output.log &")

ruby net-ssh login shell

Net-SSH is too low level to simply provide this up front (the way it is now, anyways). You can check out Net-SSH-Shell which builds upon Net-SSH to add login shell functionality: https://github.com/mitchellh/net-ssh-shell

The implementation is solid and works, however I found its not too useful since you can't specifically extract things like stderr or exit status because the commands run in a sub-shell, so you can only get stdout. The net-ssh-shell library uses some hacks to get the exit status.

I've needed a "login shell" for my own Ruby projects and to do this I've generally executed things directly into the shell using the following code:

def execute_in_shell!(commands, shell="bash")
channel = session.open_channel do |ch|
ch.exec("#{shell} -l") do |ch2, success|
# Set the terminal type
ch2.send_data "export TERM=vt100\n"

# Output each command as if they were entered on the command line
[commands].flatten.each do |command|
ch2.send_data "#{command}\n"
end

# Remember to exit or we'll hang!
ch2.send_data "exit\n"

# Configure to listen to ch2 data so you can grab stdout
end
end

# Wait for everything to complete
channel.wait
end

With this solution you still don't get exit status or stderr of commands run into the login shell, but at least the commands are executed in that context.

I hope this helps.

Ruby Net-SSH-Shell get standard out from execute! method

Have you tried doing it this way?

Net::SSH.start('host','user') do |ssh|
ssh.shell do |bash|
process = bash.execute! 'ls'
process.on_output do |a, b|
# a is the process itself, b is the output
p [a, b]
end
end
end

You can have a look at the definition of Net::SSH::Process here: https://github.com/mitchellh/net-ssh-shell/blob/master/lib/net/ssh/shell/process.rb

EDIT

I think the problem lies with the ! in execute! because the following works fine for me:

require 'net/ssh'
require 'net/ssh/shell'

Net::SSH.start('students.iitmandi.ac.in', 'k_vikhyat') do |ssh|
ssh.shell do |bash|
process = bash.execute 'whoami'
process.on_output do |a, b|
p b
end
bash.wait!
bash.execute! 'exit'
end
end

I am not sure why this is the case, because it looks like execute! creates a process, runs wait! and then returns the process.

Interactive SSH session using Net::SSH or creating a STDIN Socket

Sockets are really nothing more than file descriptors, and since STDIN is a file descriptor too, it doesn't hurt to try.

What you want however, is to put the TTY into raw mode first to get interactivity.

This code seems to work fine:

begin
system('stty cbreak -echo')

Net::SSH.start(...) do |session|
session.open_channel do |...|
...
session.listen_to(STDIN) { |stdin|
input = stdin.readpartial(1024)
channel.send_data(input) unless input.empty?
}
end.wait
end
ensure
system('stty sane')
end

Using Net::SSH to login to shell and get stateful output

Net::SSH has been updated a few days ago, and using the first example of the README on the first page of the project did exactly what you wanted to do :

require 'net/ssh'

Net::SSH.start('my_server', 'my_user') do |ssh|
output = ssh.exec!("ls")
puts output
end

#=>
# 20130402_083136_DSCF0923.jpg
# 20160715_113357_DSC_6050.jpg
# 20160715_121646_DSC_2.jpg
...
...


Related Topics



Leave a reply



Submit