Ruby One liner | test remote host port - ruby

I'm trying below Perl command in Ruby
Perl
perl -MIO::Socket::INET -e 'until(new IO::Socket::INET("localhost:80")) { print "Waiting for network..\n"; sleep 1}'
How do I same thing in ruby ?
I have tried :
require 'socket'
until !( TCPSocket.new("localhost",80).close ) do
puts "Wait..."
sleep 1
end
I'm looking for one liner in Ruby.

The main difference is that Ruby will raise an error if it cannot establish the IO, so you need to rescue the error condition. It changes the flow somewhat, but is still very do-able:
loop { break if (TCPSocket.open("localhost",80) rescue nil); puts "Wait...."; sleep 1 }
As seen from other answer, it is possible to make a more literal conversion from the Perl version. Just use the Ruby expression (TCPSocket.open("localhost",80) rescue nil) to replace Perl's new IO::Socket::INET("localhost:80") so that Ruby's raise an error behaviour better matches Perl's return undef when cannot create the object.

This is similar:
require 'socket'
(puts "Waiting..."; sleep 1) until (TCPSocket.open("localhost",3000) rescue nil)
Full command line:
ruby -r socket -e '(puts "Waiting..."; sleep 1) until (TCPSocket.open("localhost",3000) rescue nil)'

Related

What's the difference between gets and readline?

As far as I know, both of them can read from the console.
I know gets can read from a file too, but I am interested in console-input.
Example:
a = readline.chomp
puts a
a = gets.chomp
puts a
This gives me the same output. So what's the difference for console-input?
From ruby-doc.org about Kernel#readline:
Equivalent to Kernel::gets, except readline raises EOFError at end of file.
gets returns nil at end of input.
You can see the difference easily:
echo -n "" | ruby -e "gets" # no error
echo -n "" | ruby -e "readline" # -e:1:in `readline': end of file reached (EOFError)

equivalent of backticks operator with ability to display output during execution

I'm looking for something equivalent of the backticks operator (``) with the capability to display output during shell command execution.
I saw a solution in another post:
(Running a command from Ruby displaying and capturing the output)
output = []
IO.popen("ruby -e '3.times{|i| p i; sleep 1}'").each do |line|
p line.chomp
output << line.chomp
end
p output
This solution doesn't fit my needs since $? remains nil after the shell command execution. The solution I'm looking for should also set $? (returning the value of $?.exitstatus in another way is also sufficient)
Thanks!
First, I'd recommend using one of the methods in Open3.
I use capture3 for one of my systems where we need to grab the output of STDOUT and STDERR of a lot of command-line applications.
If you need a piped sub-process, try popen3 or one of the other "pipeline" commands.
Here's some code to illustrate how to use popen2, which ignores the STDERR channel. If you want to track that also use popen3:
require 'open3'
output = []
exit_status = Open3.popen2(ENV, "ruby -e '3.times{|i| p i; sleep 1}'") { |stdin, stdout, thr|
stdin.close
stdout.each_line do |o|
o.chomp!
output << o
puts %Q(Read from pipe: "#{ o }")
end
thr.value
}
puts "Output array: #{ output.join(', ') }"
puts "Exit status: #{ exit_status }"
Running that outputs:
Read from pipe: "0"
Read from pipe: "1"
Read from pipe: "2"
Output array: 0, 1, 2
Exit status: pid 43413 exit 0
The example code shows one way to do it.
It's not necessary to use each_line, but that demonstrates how you can read line-by-line until the sub-process closes its STDOUT.
capture3 doesn't accept a block; It waits until the child has closed its output and exits, then it returns the content, which is great when you want a blocking process. popen2 and popen3 have blocking and non-blocking versions, but I show only the non-blocking version here to demonstrate how to read and output the content as it comes in from the sub-process.
Try following:
output = []
IO.popen("ruby -e '3.times{|i| p i; sleep 1 }'") do |f|
f.each do |line|
p line.chomp
output << line.chomp
end
end
p $?
prints
"0"
"1"
"2"
#<Process::Status: pid 2501 exit 0>
Using open3
require 'open3'
output = []
Open3.popen2("ruby -e '3.times{|i| p i; sleep 1}'") do |stdin,stdout,wait_thr|
stdout.each do |line|
p line.chomp
output << line.chomp
end
p wait_thr.value
end

what is a portable way in Ruby to check where STDIN will block if you attempt to read from it?

I would like to find out if there is a portable way to check in a Ruby script whether it will block if it attempts to read from STDIN. The following is an approach that works for Unix (and Cygwin) but not native Win32. (It is based on a Perl approach I learned long ago.)
$ cat read-stdin.rb
#! /usr/bin/ruby
# test of reading from STDIN
require 'fcntl'
# Trace info on input objects
$stdout.sync=TRUE if $DEBUG # make sure standard output and error synchronized
$stderr.print "ARGV=#{ARGV}\n" if $DEBUG
$stderr.print "ARGF=#{ARGF}\n" if $DEBUG
# See if input available, showing usage statement if not
blocking_stdin = FALSE
if (defined? Fcntl::F_GETFL) then
$stderr.print "F_GETFL=#{Fcntl::F_GETFL} O_RDWR=#{Fcntl::O_RDWR}\n" if $DEBUG
flags = STDIN.fcntl(Fcntl::F_GETFL, 0)
$stderr.print "flags=#{flags}\n" if $DEBUG
blocking_stdin = TRUE if ((flags & Fcntl::O_RDWR) == Fcntl::O_RDWR)
$stderr.print "blocking_stdin=#{blocking_stdin}\n" if $DEBUG
end
if (blocking_stdin && (ARGV.length == 0)) then
$stderr.print "usage: #{$0} [-]\n"
Process.exit
end
# Read input and output it
$stderr.print "Input:\n" if $DEBUG
input_text = ARGF.read()
$stderr.print "Output:\n" if $DEBUG
print "#{input_text}\n"
Here is the interaction without debugging:
$ grep -v DEBUG read-stdin.rb >| /tmp/simple-read-stdin.rb
$ echo hey | ruby /tmp/simple-read-stdin.rb
hey
$ ruby /tmp/simple-read-stdin.rb
usage: /tmp/simple-read-stdin.rb [-]
Here is the interaction with debugging:
$ echo hey | ruby -d read-stdin.rb
ARGV=
ARGF=ARGF
F_GETFL=3 O_RDWR=2
flags=65536
blocking_stdin=false
Input:
Output:
hey
$ ruby -d read-stdin.rb
ARGV=
ARGF=ARGF
F_GETFL=3 O_RDWR=2
flags=98306
blocking_stdin=true
usage: read-stdin.rb [-]
I don't know if it is universally portable and I also don't know if it is considered a good idea (blocking isn't such a bad concept) but there is a non-blocking read method in IO. You can use it like this:
chunk = nil
begin
chunk = STDIN.read_nonblock(4096)
rescue Errno::EAGAIN
# Handle the case if it would block
chunk = 'nothing there...'
end
Though, I think it's quite disappointing it doesn't work without specifying a buffer size like IO#read does it, but working around this by using a loop should be quite easy.

Ruby system call get information about command failure

Say I have a simple command line interpreter like this:
while true
print '> '
cmd = gets.chomp
break if cmd =~ /^(exit|quit)/
system(cmd) || puts('Command not found or invalid.')
end
I would like to, instead of the "Command not found or invalid." message get an actual error message, like one you would get from bash. How would I do this?
well, if it's unix-like system you could actually append 2>&1 to your command:
system(cmd + ' 2>&1 ')
which would redirect your stderr to stdout
another way is using %x[...] :
irb(main):027:0> def hello
irb(main):029:2* %x[hello]
irb(main):030:2> rescue Exception => e
irb(main):031:2> puts e.message
irb(main):033:1> end
=> nil
irb(main):034:0> hello
No such file or directory - hello
=> nil
irb(main):035:0>
meaning, you can rescue the command execution and return the exception message

How can a Ruby script detect that it is running in irb?

I have a Ruby script that defines a class. I would like the script to execute the statement
BoolParser.generate :file_base=>'bool_parser'
only when the script is invoked as an executable, not when it is require'd from irb (or passed on the command line via -r). What can I wrap around the statement above to prevent it from executing whenever my Ruby file is loaded?
The condition $0 == __FILE__ ...
!/usr/bin/ruby1.8
class BoolParser
def self.generate(args)
p ['BoolParser.generate', args]
end
end
if $0 == __FILE__
BoolParser.generate(:file_base=>__FILE__)
end
... is true when the script is run from the command line...
$ /tmp/foo.rb
["BoolParser.generate", {:file_base=>"/tmp/foo.rb"}]
... but false when the file is required or loaded by another ruby script.
$ irb1.8
irb(main):001:0> require '/tmp/foo'
=> true
irb(main):002:0>
use $0
in irb the value of $0 is "irb"
in your file is "/path/to/file"
an explanation here

Resources