I am trying to use the Net::SSH library to login and manage a host that supports ssh. It is a piece of telecom equipment and so speaks TL1. I seem to be able to log in successfully, but when I try to ssh.exec something, it aborts saying it could not execute command. Here is my simple code:
require 'net/ssh'
Net::SSH.start('10.204.121.192', 'password', :password => "password") do |ssh|
ssh.exec("INH-MSG-ALL;")
end
If i point the same code at a Linux server and provide a command such as "ls -l /", it works fine. What I am wondering is, can I use this ssh library? Do I need to use another command instead of exec?
This is the error output:
/usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:322:in `block (2 levels) in exec': could not execute command: "INH-MSG-ALL;" (RuntimeError)
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/channel.rb:597:in `call'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/channel.rb:597:in `do_failure'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:586:in `channel_failure'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:456:in `dispatch_incoming_packets'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:213:in `preprocess'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:197:in `process'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `block in loop'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `loop'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `loop'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:110:in `close'
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/net-ssh-2.2.1/lib/net/ssh.rb:194:in `start'
from ssh_test.rb:3:in `<main>'
I assume it works fine when you login in the shell manually.
To understand what is the difference when you connect through net/ssh collect output of env command in both cases and compare.
That most probably you'll see a difference that will lead you to a solution or at least will give you dirty trick.
UPDATE. (Not working)
Net::SSH.start('10.204.121.192', 'password', :password => "password") do |ssh|
ssh.open_channel do |channel|
channel.on_data do |ch, data|
puts "got data: #{data.inspect}"
end
channel.send_data("INH-MSG-ALL;\n")
end
end
UPDATE2. (Working)
Net::SSH.start('10.204.121.192', 'password', :password => "password") do |ssh|
ssh.open_channel do |channel|
channel.send_channel_request "shell"
channel.on_data do |ch, data|
puts "got data: #{data.inspect}"
end
channel.send_data("INH-MSG-ALL;\n")
end
end
Thanks forker for your updates),
One more thing,
from your code how to make this
puts "got data: #{data.inspect}"
to output data for each command sent to the shell ?
Does this code wait for each command to complete?
Thanks.
Related
My current network setup is like this:
LocalMachine <---SSH---> Server <---Telnet---> Router.
I am trying to connect to the Router from LocalMachine via Server (direct connection is not possible, Server acts as sort of proxy). Ruby's net/ssh gem is used for the ssh connection to the Server.
require 'net/ssh'
#hostname = "10.16.96.40"
#username = "server_username"
#password = "server_password"
Net::SSH::start(#hostname, #username, :password => #password) do |session|
session.open_channel do |channel|
channel.send_channel_request "shell" do |ch, success|
if success
puts "user shell started successfully"
else
puts "could not start user shell"
end
end
channel.send_data("telnet 192.168.11.201\n")
channel.send_data("router_username\n")
channel.send_data("router_password\n")
channel.send_data("sh ip int brief\n")
channel.on_data do |ch, data|
print data
end
end
session.loop
end
The script gets connected to the router. It gets the printout. But then the session hangs when expected it to be closed.
When I stop script execution manually with Ctrl+C I get the following message:
^C/usr/local/lib/ruby/gems/2.2.0/gems/net-ssh-3.2.0/lib/net/ssh/ruby_compat.rb:25:in `select': Interrupt
from /usr/local/lib/ruby/gems/2.2.0/gems/net-ssh-3.2.0/lib/net/ssh/ruby_compat.rb:25:in `io_select'
from /usr/local/lib/ruby/gems/2.2.0/gems/net-ssh-3.2.0/lib/net/ssh/connection/session.rb:210:in `process'
from /usr/local/lib/ruby/gems/2.2.0/gems/net-ssh-3.2.0/lib/net/ssh/connection/session.rb:170:in `block in loop'
from /usr/local/lib/ruby/gems/2.2.0/gems/net-ssh-3.2.0/lib/net/ssh/connection/session.rb:170:in `loop'
from /usr/local/lib/ruby/gems/2.2.0/gems/net-ssh-3.2.0/lib/net/ssh/connection/session.rb:170:in `loop'
from 25_net_ssh_channel_shell.rb:33:in `block in <main>'
from /usr/local/lib/ruby/gems/2.2.0/gems/net-ssh-3.2.0/lib/net/ssh.rb:240:in `start'
from 25_net_ssh_channel_shell.rb:9:in `<main>'
Any idea how to close the channel/session and get rid of the blinking cursor?
I call the method send_csr1 from the method send_crs with this line of code:
send_csr1(pipe.read,#username,#password)
The problem is that normally the next line of code would be executed:
pipe.close_write
But somehow it wont what results in that the cmd is never closed. When i close it manually i get the error:
in `read': Interrupt
from stack.rb:49:in `block in send_csr'
from stack.rb:45:in `popen'
from stack.rb:45:in `send_csr'
from stack.rb:88:in `block in <main>'
from stack.rb:87:in `each'
from stack.rb:87:in `<main>'
My question is what do i have to change in my code, that ruby surley closes the cmd?
My full code:
def send_csr
IO.popen('cmd', 'r+') do |pipe|
pipe.puts('cd C:/OpenSSL/bin')
pipe.puts('openssl.exe')
pipe.puts("req -config c:/OpenSSL/openssl.cnf -in #{#csr}")
send_csr1(pipe.read,#username,#password)
pipe.close_write
end
end
def send_csr1(text,user,password)
#conn.basic_auth(user,password)
#res = #conn.get do |request|
request.url "csr"
request.headers['Content-Type'] = 'text/plain'
request.body = "#{text}"
end
end
The following code tries to list the entries of a remote directory via SFTP and Net::SFTP, but it causes an "closed stream" IOError if the directory contains a large number of files (~ 6000 files):
require 'net/ssh'
require 'net/sftp'
Net::SFTP.start('hostname', 'username', :password => 'password') do |sftp|
# list the entries in a directory
sftp.dir.foreach("/") do |entry|
puts entry.longname
end
end
What is the best way to avoid it? Versions are net-sftp Gem: 2.0.5 and net-ssh Gem: 2.2.1, Ruby: 1.8.7. The full error message reads:
IOError: closed stream
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/ruby_compat.rb:33:in `select'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/ruby_compat.rb:33:in `io_select'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/ruby_compat.rb:32:in `synchronize'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/ruby_compat.rb:32:in `io_select'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/packet_stream.rb:73:in `available_for_read?'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/packet_stream.rb:85:in `next_packet'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/session.rb:170:in `poll_message'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/session.rb:165:in `loop'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/transport/session.rb:165:in `poll_message'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:451:in `dispatch_incoming_packets'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:213:in `preprocess'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:197:in `process'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `loop'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `loop_forever'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:161:in `loop'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-ssh-2.2.1/lib/net/ssh/connection/session.rb:110:in `close'
from ~/.rvm/gems/ruby-1.8.7-p330/gems/net-sftp-2.0.5/lib/net/sftp.rb:36:in `start'
The behavior could be deliberate, if we take a look at the dir source code in net-sftp/lib/net/sftp/operations/dir.rb, we see a close operation:
def foreach(path)
..
ensure
sftp.close!(handle) if handle
end
It is possible that this close operation causes the closed stream error. If it does not indicate a bug, it is possible the catch the IOError exception. It also seems to help to run the SSH event loop occasionally:
begin
..
sftp.dir.foreach("/") do |entry|
puts entry.longname
# ...
sftp.loop # Runs the SSH event loop
end
rescue IOError => Ex
puts "*** We are done: "+Ex.message
end
Every time I call my rake task it say:
[2012-07-12 15:50:01] ERROR IOError: An existing connection was forcibly closed by the remote host
C:/jruby-1.3.1/lib/ruby/1.8/webrick/httpresponse.rb:324:in `_write_data'
C:/jruby-1.3.1/lib/ruby/1.8/webrick/httpresponse.rb:180:in `send_header'
C:/jruby-1.3.1/lib/ruby/1.8/webrick/httpresponse.rb:103:in `send_response'
C:/jruby-1.3.1/lib/ruby/1.8/webrick/httpserver.rb:79:in `run'
C:/jruby-1.3.1/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
C:/jruby-1.3.1/lib/ruby/1.8/webrick/server.rb:162:in `start'
[2012-07-12 15:50:29] ERROR IOError: An existing connection was forcibly closed by the remote host
C:/jruby-1.3.1/lib/ruby/1.8/webrick/httpserver.rb:55:in `run'
C:/jruby-1.3.1/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
C:/jruby-1.3.1/lib/ruby/1.8/webrick/server.rb:162:in `start'
I have tryed different options thinking that it could be the call to the rake task but apparently isn't, also I have tryed with Mongrel and WEBRick in case that it could be the server.
I'm using Jruby 1.3.1
The task it's not been executed.
This is part of my code:
application_controller.rb
def call_rake(task, options = {})
options[:rails_env] ||= Rails.env
args = options.map { |n, v| "#{n.to_s.upcase}='#{v}'" }
system "C:/jruby-1.3.1/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake #{task} #{args.join(' ')} start"
end
forbidden_file.rake
desc "Process CSV file"
task :process_file => :environment do
forbidden_file = ForbiddenFile.find(ENV["csv"])
forbidden_file.upload_file
end
Controller
...
call_rake :process_file, :csv => params[:files]
redirect_to forbidden_files_url
...
It's working now, I just removed the word start from the command.
system "rake #{task} #{args.join(' ')}"
I am trying to run some functional test on a small server I have created. I am running Ruby 1.9.2 and RSpec 2.2.1 on Mac OS X 10.6. I have verified that the server works correctly and is not causing the problems I am experiencing. In my spec, I am attempting to spawn of a process to start the server, run some examples, and then kill the process running the server. Here is the code for my spec:
describe "Server" do
describe "methods" do
let(:put) { "put foobar beans 5\nhowdy" }
before(:all) do
#pid = spawn("bin/server")
end
before(:each) do
#sock = TCPSocket.new "127.0.0.1", 3000
end
after(:each) do
#sock.close
end
after(:all) do
Process.kill("HUP", #pid)
end
it "should be valid for a valid put method" do
#sock.send(put, 0).should == put.length
response = #sock.recv(1000)
response.should == "OK\n"
end
#more examples . . .
end
end
When I run the spec, it appears that the before(:all) and after(:all) blocks are run and the server processes is killed before the examples are run, because I get the following output:
F
Failures:
1) Server methods should be valid for a valid put method
Failure/Error: #sock = TCPSocket.new "127.0.0.1", 3000
Connection refused - connect(2)
# ./spec/server_spec.rb:11:in `initialize'
# ./spec/server_spec.rb:11:in `new'
# ./spec/server_spec.rb:11:in `block (3 levels) in <top (required)>'
When I comment out the call to Process.kill, the server is started and the tests are run, but the server remains running, which means I have to go manually kill it.
It seems like I am misunderstanding what the after(:all) method is supposed to do, because it is not being run in the order I thought it would. Why is this happening? What do I need to do so that my specs
Are you sure the server is ready to accept connections? Maybe something like this would help:
before(:each) do
3.times do
begin
#sock = TCPSocket.new "127.0.0.1", 2000
break
rescue
sleep 1
end
end
raise "could not open connection" unless #sock
end