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.
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
...
...
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
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-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.
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 &")
Cant run Ruby script via gem ssh-net
The problem is in your ssh.exec!
call. Net::SSH
does not use a login shell to run your commands. A login shell is required for Bash to execute .bash_profile
.
Since your rbenv setup is in .bash_profile
, your exec!
call will be missing your full Ruby environment, and therefore running bundle
later in you restart
script will fail.
The solution should be to manually execute .bash_profile
, so that rbenv gets loaded:
output = ssh.exec!("source ~/.bash_profile; ...rest of commands...")
More information and other proposals here:
net-ssh and remote environment
Related Topics
Accessing the Child Instance in a Rabl Template
What Is the Equivalent to Rspec's 'It "Should …", Focus: True Do' in Minitest/Spec
How to Ssh Interactive Session
What's the Difference Between the Ruby Irb Prompt Modes
Detect Similar Sounding Words in Ruby
Ruby -- Capitalize First Letter of Every Sentence in a Paragraph
Routing Error No Route Matches [Get] "/Static_Pages/Home", Tutorial
How to Pass Content to Jekyll Default Converter After Custom Conversion
More Concise Version of Max/Min Without the Block
Rmagick Error After Installing Os X Mavericks
Ruby Ternary Operator Structure
Ruby or Rails Sort on Two/Multiple Date Fields
Unable to Delete File from Amazon S3 Using Ruby Script
Scraping a Site That Requires Login Username and Password on Two Separate Pages
Rails 3 and PDFkit. How to Specify Page Size
Using Ruby and Mechanize to Fill in a Remote Login Form Mystery