Desperate help needed with SSH

Hi you Ruby Guru’s

I have a small problem thats driving me crazy. I am trying to connect to
multiple ssh servers (1 at a time), run a number of commands and capture
the output to a unique file for each server.

My code looks like this :

– snip –

require ‘rubygems’
require ‘net/ssh’

hosts = [‘10.0.255.1’ , ‘10.0.255.2’ , ‘10.0.255.3’]

instructions = [
‘sh version’,
‘sh cdp ne’
]

hosts.each do |host|
Net::SSH.start(host, ‘user’, :password => ‘password’) do |ssh|

fn = File.open("output\/#{host}.txt", 'w')
instructions.each do |command|
  fn.puts "|--------\[#{command}\]--------------------------"
  fn.puts ssh.exec!(command)
end
fn.close

end
end

– snip –

When I run this I get the following error :

Net::SSH::ChannelOpenFailed: (4)

If I remove the instructions.each loop and run only a single command.
Life
is good and it all works. If I add a second ssh.exec! or the loop, the
error returns.

It appears that the ssh.exec! closes the connection. How do I keep it
open
to allow me to run a second command?

Alan.

On 13.05.2009, at 11:05, [email protected] wrote:

]
These instructions looks strange for me. Are you sure that these run
on all hosts?

Try to use other instructions that should work like
[“echo foo”, “sh -c ‘echo bar’”]

Maybe your instructions kill the shell environment by calling exec
or something similar.

hosts.each do |host|
Net::SSH.start(host, ‘user’, :password => ‘password’) do |ssh|
File.open(“output/#{host}.txt”, ‘w’) do |fn|

instructions.each do |command|
fn.puts “|--------[#{command}]--------------------------”
fn.puts ssh.exec!(command)
end
end

end
end

– snip –

This part should be ok, but you can improve your code and use a block
for File.open().

File.open(“output/#{host}.txt”, ‘w’) do |fn|

end # fn.close not needed, because the block end close the file
already.

When I run this I get the following error :

Net::SSH::ChannelOpenFailed: (4)

If I remove the instructions.each loop and run only a single
command. Life
is good and it all works. If I add a second ssh.exec! or the loop, the
error returns.

Calling ssh.exec!() twice in a session is not a problem.

irb> Net::SSH.start(host, user, :password => passwd) do |ssh|
irb> [‘sh -c “echo foo”’, ‘echo bar’].each do |command|
irb> puts ssh.exec!(command)
irb> end
irb> end
foo
bar

hth. regards, Sandor
Szücs

Hi Sandor

Thanks for the reply.

The host I am connecting to is a Cisco Router. The commands definitely
work on a manual SSH session from my terminal

The first command always works.
I get the channel failure when trying to run the second command.
I tried swapping the two commands around, but I get the same failure.

I used the following code to talk to my mac:

require ‘rubygems’
require ‘net/ssh’

Net::SSH.start(‘127.0.0.1’, ‘user’, :password => ‘password’) do |ssh|
ssh.exec “ls -al”
ssh.exec “pwd”
ssh.exec “ps -axe”
ssh.loop
end

Which worked great. I then changed the IP address and replaced the
commands with router commands:

require ‘rubygems’
require ‘net/ssh’

Net::SSH.start(‘10.0.255.1’, ‘name’, :password => ‘password’) do |ssh|
ssh.exec “sh ver”
ssh.exec “cdp ne”
ssh.loop
end

And it fails at the second ssh.exec, so I’m guessing this is related
to the Cisco SSH Server.

Alan.

On 17 May 2009, at 12:26 AM, Sandor Szücs wrote:

unknown wrote:

I have a small problem thats driving me crazy. I am trying to connect to
multiple ssh servers (1 at a time), run a number of commands and capture
the output to a unique file for each server.

Try using Net::SSH::Telnet (which is something I wrote to talk to
routers). It hides the Net::SSH API behind a simple Net::Telnet one, and
as a side benefit, you can write code which connects transparently using
either telnet or ssh.

Alternatively, looking at the Net::SSH::Telnet code may show you how to
drive Net::SSH successfully.

HTH,

Brian.

On 18.05.2009, at 19:23, Alan Claughan wrote:

And it fails at the second ssh.exec, so I’m guessing this is related
to the Cisco SSH Server.

Ack.
Maybe there are options that you can set on the router to let the
channel open?

regards, Sandor
Szücs