ssh proxy script runs in ruby but not in jruby - ruby

I have a ruby script that uses the net::ssh gem.
Its a simple script to tunnel through a jump-off server to a destination box. The box is only visible to the jump-off server. Here is the script:
require 'net/ssh/proxy/command'
require "net/ssh"
class TestTunnel
def initialize
proxy = Net::SSH::Proxy::Command.new('ssh admin#10.10.10.10 nc %h %p 2>/dev/null')
p "proxy gotten"
Net::SSH.start("host1", "admin", :password => "admin", :proxy => proxy) do |ssh|
hostname = ssh.exec!("hostname")
p "In #{hostname}"
end
end
end
b=TestTunnel.new
The issue is the script runs in ruby but not in jruby. My framework runs off jruby so I need to use it with jruby.
My solution was to call a bash script from my jruby script to setup the tunnel and run commands there but I would rather have everything done within jruby.
Here are the errors I get:
~/src/main/ruby$ jruby --1.9 scripts/test_tunnel.rb
"proxy gotten"
IO::EAGAINWaitReadable: Resource temporarily unavailable - errno backtraces disabled; run with -Xerrno.backtrace=true to enable
And when I run in ruby:
~/src/main/ruby$ ruby scripts/test_tunnel.rb
"proxy gotten"
"In vz-int-api02\n"
~/src/main/ruby$
When I run with -Xerrno.backtrace=true I can see that jruby is 1.7.9 and I can see that its using ruby 1.9:
~/src/main/ruby$ jruby -Xerrno.backtrace=true --1.9 scripts/test_tunnel.rb
"proxy gotten"
IO::EAGAINWaitReadable: Resource temporarily unavailable -
read_nonblock at org/jruby/RubyIO.java:2856
recv at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/proxy/command.rb:75
fill at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/buffered_io.rb:65
next_packet at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/packet_stream.rb:88
poll_message at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:183
loop at org/jruby/RubyKernel.java:1519
poll_message at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:178
wait at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:215
loop at org/jruby/RubyKernel.java:1519
wait at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:213
initialize at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh/transport/session.rb:87
start at /usr/local/jruby-1.7.9/lib/ruby/gems/shared/gems/net-ssh-2.9.2/lib/net/ssh.rb:207
initialize at scripts/test_tunnel.rb:8
(root) at scripts/test_tunnel.rb:15
~/src/main/ruby$ jruby -Xerrno.backtrace=true --1.9 --version
jruby 1.7.9 (1.9.3p392) 2013-12-06 87b108a on Java HotSpot(TM) 64-Bit Server VM 1.8.0_72-b15 +indy [linux-amd64]
~/src/main/ruby$
Is there any way to get this to run in jruby like it does in ruby or is my solution to call a bash script from within jruby the only way to do this?
A

This sounds a lot like this bug in net-ssh that was fixed in net-ssh 3.0.2.
The commit message that closed that issue t was "Bugfix: proxy command was using nonblocking io api incorrectly causing rare IO::EAGAIN errors" which sounds like exactly what you are getting.

Related

Avoid display of backtrace when running Sinatra on an already taken port

What is the proper way to prevent Sinatra from displaying the full backtrace, when it fails to properly run the server (for example, due to the port being already in use)?
This is a sample sinatra app:
# test.rb
require 'sinatra'
require 'bundler/inline'
gemfile do
gem 'sinatra'
gem 'puma'
end
set :bind, "0.0.0.0"
set :port, 3000
get '/' do
"hello"
end
Then, running it with ruby test.rb once, to occupy the port.
Then, running it again in another terminal window, and this full error backtrace is shown:
$ ruby test.rb
== Sinatra (v2.0.4) has taken the stage on 3000 for development with backup from Puma
Puma starting in single mode...
* Version 3.12.0 (ruby 2.5.0-p0), codename: Llamas in Pajamas
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://0.0.0.0:3000
== Someone is already performing on port 3000!
Traceback (most recent call last):
5: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/main.rb:26:in `block in <module:Sinatra>'
4: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1464:in `run!'
3: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1464:in `ensure in run!'
2: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1439:in `quit!'
1: from /store/gems/ruby-2.5.0/gems/puma-3.12.0/lib/puma/launcher.rb:147:in `stop'
/store/gems/ruby-2.5.0/gems/puma-3.12.0/lib/puma/single.rb:27:in `stop': undefined method `stop' for nil:NilClass (NoMethodError)
Traceback (most recent call last):
3: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1545:in `block in setup_traps'
2: from /store/gems/ruby-2.5.0/gems/sinatra-2.0.4/lib/sinatra/base.rb:1439:in `quit!'
1: from /store/gems/ruby-2.5.0/gems/puma-3.12.0/lib/puma/launcher.rb:147:in `stop'
/store/gems/ruby-2.5.0/gems/puma-3.12.0/lib/puma/single.rb:27:in `stop': undefined method `stop' for nil:NilClass (NoMethodError)
Since I am using it as an embedded server, I would like the output to simply and with the friendly error that Sinatra is already showing:
== Someone is already performing on port 3000!
and avoid showing the backtrace.
Ruby by default outputs error messages to the STDOUT. But if you're on *nix system you can do this:
ruby test.rb > /dev/null 2>&1
For windows you can probably do
ruby test.rb > NULL
windows powershell
ruby test.rb > $null
but for windows also see Is there a /dev/null on Windows?
But if you want programmatically suppress output when server is running this should work on *nix but not sure on windows
# test.rb
require 'sinatra'
require 'bundler/inline'
gemfile do
gem 'sinatra'
gem 'puma'
end
set :bind, "0.0.0.0"
set :port, 3000
get '/' do
"hello"
end
unless `ps aux | grep sinatra`.match('tcp://0.0.0.0:3000')
STDOUT.reopen('/dev/null', 'w')
STDERR.reopen('/dev/null', 'w')
end
See suppresing output to console with ruby
You can test to see if the port is in use by attempting to listen on the port before allowing Sinatra and Puma to take over. This isn't 100% effective because there's a race condition where you may open and close the port, but before Sinatra/Puma finish initializing some other process comes along and listens on the same port, but it should work for your use-case (which appears to be a cosmetic hack only).
Insert this code anywhere in test.rb:
require 'socket'
include Socket::Constants
begin
# Open and close the port
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.pack_sockaddr_in(3000, '0.0.0.0')
socket.bind(sockaddr)
socket.listen(1)
socket.close
rescue Errno::EADDRINUSE => error
# Traps the same error that is trapped by Sinatra and exits if raised
puts error.message
exit
end
Start the first one with ruby test.rb:
== Sinatra (v2.0.4) has taken the stage on 3000 for development with backup from Puma
Puma starting in single mode...
* Version 3.12.0 (ruby 2.6.0-p-1), codename: Llamas in Pajamas
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
Start the second one with ruby test.rb:
Address already in use - bind(2) for 0.0.0.0:3000
You can flesh out what you want printed to the console inside the rescue block.
This appears to be caused by an issue with Puma, that is fixed by this PR.

Process.detach cause sinatra-1.4.7 auto exit

here is my code:
class App < Sinatra::Base
get "/" do
pid =fork do
end
Process.detach(pid)
end
end
App.start!
when i curl localhost:4567, the server auto exit and the output is:
127.0.0.1 - - [13/Aug/2016:23:45:18 CST] "GET / HTTP/1.1" 200 0
- -> /
[2016-08-13 23:45:18] INFO WEBrick::HTTPServer#start done.
== Sinatra has ended his set (crowd applauds)
my environment is:
Linux Mint 17.3 Rosa
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
Why does Sinatra quit after just one request? I want it to keep running until I deliberately kill it.
It's not Process.detach that causes Sinatra to quit, but the fact that the forked process ends and runs its at_exit hooks, which shut down the server (though I'm not quite sure how that can leak from the child process to the parent).
There's a couple of simple ways to prevent this.
I prefer this set-and-forget solution:
configure do
disable :traps
end
The downside is that Ctrl-C causes a not-so-graceful exit.
Alternatively, add this to the beginning of any fork block:
settings.running_server = nil
The downside is that you need to remember to add this to all forked code.
You might also find someone suggesting at_exit { Process.exit! } in all fork blocks, but I think it's less reliable because other at_exit handlers could interfere with it.
Unfortunately, I don't see any configuration option in Sinatra that would fix forking and still allow graceful handling of Ctrl-C.

Unable to connect to postgresQL with Ruby

I've searched in the archive but could not find an answer to my dilemma. I'm coding in Ruby and using watir webdriver framework on my local Mac Yosemite and want to connect to postgres database on a linux box.
I have the required ruby gems installed on my local Mac
* LOCAL GEMS *
dbd-pg (0.3.9)
pg (0.18.4)
dbi (0.4.5, 0.4.4)
I am using the following code.
require 'rubygems'
require 'pg'
require 'dbd/pg'
require 'dbi'
conn = PGconn.connect("10.0.xx.xx","5432",'','',"mydbname","dbuser", "")
res = conn.exec('select * from priorities_map;')
puts res.getvalue(0,0)
conn.close if conn
On running this
I a getting these errors
.initialize': Could not connect to server: Connection refused (PG::ConnectionBad)
Is the server running on host "10.0.xx.xx" and accepting
TCP/IP connections on port 5432?
If I use the code
dbh = DBI.connect("dbi:pg:mydbname:ipaddress", "user", "")
row = dbh.exec('select * from etr_priorities_map;')
puts row.getvalue(0,0)
dbh.disconnect if dbh
I get the error
block in load_driver': Unable to load driver 'pg' (underlying error: wrong constant name pg) (DBI::InterfaceError) from System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/monitor.rb:211:in `mon_synchronize'
I am new to Ruby. How can I resolve these issues?
The first error, as #Doon said in the comments, comes from the TCP connection and usually means your database is not listening on the network. Most PostgreSQL packages come with a default configuration that only allows local connections, but you can enable connections over the network in the server configuration via the listen_addresses setting. I installed PostgreSQL through Homebrew on my Mac, and my config is at /usr/local/var/postgres/postgresql.conf, but if you installed it some other way the path may be different.
The second error is happening because the "driver" part of the connection string is case-sensitive, and the DBD driver for Postgres is named Pg, not pg. Try this:
dbh = DBI.connect("dbi:Pg:mydbname:ipaddress", "user", "")
Also, unless you have your heart set on using Ruby/DBI, you might want to consider using a more-recently maintained library. Ruby-DBI is very well-written and tested, but it hasn't seen a release since 2010, and Ruby itself has changed pretty significantly in the interim.
If you do want to consider alternatives, I use Sequel for mostly everything, and I highly recommend it, especially for Postgres development, but both DataMapper and ActiveRecord have a large userbase as well.

Issues trying to bootstrap Chef for windows client with knife-windows

I am having some problems trying to bootstrap a windows node for Chef. This node was initially able to be partially bootstrapped, it was getting through most of the process but however, failing near the end - on the windows client itself I can see a number of expected files under C:\Chef
However since upgrading my Ruby and Knife-Windows to remedy the original issue - I am now not able to bootstrap at all, I get the error below:
chefadmin#AUK-CHEFMGT1:~$ knife bootstrap windows winrm 10.28.154.61 -x chefadmin -P xxxxxx
/opt/chefdk/embedded/lib/ruby/gems/2.1.0/gems/chef-12.5.1/lib/chef/mixin/path_sanity.rb:25:
warning: Insecure world writable dir /usr/local/bin in PATH, mode 040777
Waiting for remote response before bootstrap.10.28.154.61 .
10.28.154.61 Response received.
Remote node responded after 0.01 minutes.
Bootstrapping Chef on 10.28.154.61
ERROR: RuntimeError: Knife-Windows < 1.0 does not support validatorless bootstraps
I've tried a few different versions of knife-windows, initially 1.1.1, and most recently the pre-release version of 1.0.0 rc1, however, they are all giving me this error.
I am not sure why this is a problem, as the validation.pem does exist on the windows client in C:\Chef\
In case it matters, here is my knife.rb config file:
chefadmin#AUK-CHEFMGT1:~$
GNU nano 2.2.6 File: /home/chefadmin/chef-repo/.chef/knife.rb
current_dir = File.dirname(__FILE__)
log_level :info
log_location STDOUT
node_name "chefadmin"
client_key "#{current_dir}/ChefRSA.pem"
validation_client_name "company"
validation_key "#{current_dir}/companyvalidator"
chef_server_url "https://10.28.253.101/organizations/company"
syntax_check_cache_path "#{ENV['HOME']}/.chef/syntaxcache"
cookbook_path ["#{current_dir}/../cookbooks"]
"#{current_dir}/companyvalidator" Does that file exist? Usually that would be something ending in .pem. If that path isn't a thing, it would fall back to new-style bootstrapping which I don't think works on Windows yet.

Ruby Net-SFTP Unresponsive

I'm trying to upload a file to a SFTP site using Net::SFTP.
The problem is the Ruby process never returns. It's frozen, stuck, never-ending... I have to Ctrl-C to make it stop.
I can connect to the ftp server in the command line using sftp.
I've tried this code on Linux (Ubuntu) and Snow Leopard and it does the same thing.
Installed the latest version of Net::SSH and Net::SFTP.
From gem list net:
net-sftp (2.0.5)
net-ssh (2.1.4)
Different combinations of hash arguments (see code below)
Tried to call Net::SFTP.start instead of creating a SSH session first.
Server responds with "SFTP protocol version 3" when I login using a command line tool and ask for the version.
I'm running Ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10.7.0]
Debug output from :verbose (last couple of lines):
D, [2011-07-29T17:30:52.692192 #19399] DEBUG -- tcpsocket[80c06478]: read 36 bytes
D, [2011-07-29T17:30:52.692609 #19399] DEBUG -- tcpsocket[80c06478]: received packet nr 7 type 99 len 12
I, [2011-07-29T17:30:52.692751 #19399] INFO -- net.ssh.connection.session[80bd5da0]: channel_success: 0
D, [2011-07-29T17:30:52.692817 #19399] DEBUG -- net.sftp.session[80bd5c24]: sftp subsystem successfully started
D, [2011-07-29T17:30:52.693625 #19399] DEBUG -- tcpsocket[80c06478]: queueing packet nr 8 type 94 len 28
D, [2011-07-29T17:30:52.693834 #19399] DEBUG -- tcpsocket[80c06478]: sent 52 bytes
Sample code:
require 'rubygems'
require 'net/sftp'
FTP = "someftpsite"
FTP_USER_NAME = "user"
FTP_PASSWORD = "password"
hash = {:password => FTP_PASSWORD, :verbose => :debug, :keys=>[""],:auth_methods => ["password"], :timeout => 5, :port=>22}
begin
Net::SSH.start(FTP,FTP_USER_NAME, hash) do |test|
test.sftp.upload!("localfile","remotefile")
end
rescue Exception => err
puts "error:#{err.inspect}"
end
Edit: 8/22/2011
This seems to be related to the interactiveness of the SFTP server. I solved this by creating a shell script using expect and shelling out from Ruby to run the file. The shell script is created at run time. This seems really hackish, but it's the only way I've been able to make it work using Ruby. If anyone else has a suggestion, I would love to find a better way to do this.
You could use public/private key authentication instead. http://net-ssh.rubyforge.org/ssh/v1/chapter-2.html#s2

Resources