Ruby only executing the first line? - ruby

I'm writing a ruby script and found this strange behaviour.
Using ruby 2.4.2 [x86_64-darwin16]
Basically I'm trying to echo two separated messages and in my index.rb file I got:
exec("echo 'teste'")
exec("echo 'teste2'")
But when I run ruby ./index.rb
The output is:
teste
Why that's happening?
Shouldn't this be the output?
testeteste2

exec([env,] command... [,options])
Replaces the current process by running the given external command docs
It means that the first call to exec replaces your ruby program with echo, so the rest of the ruby program is not executed.
You can use backticks to run a command like you want:
`echo 'teste'`
`echo 'teste2'`

Related

How does this Ruby command line work? Seemingly running a CMD script with Ruby

I'm examining how ridk enable works in order to figure out how to hook it into Travis CI build logic. (The Ruby installation I'm studying is a RubyInstaller+Devkit installed locally; the commands are run from the "Start Command Prompt with Ruby" prompt.)
I've got stuck at a Ruby command line executed under the hood whose working is a mystery to me:
"C:\Ruby24-x64\bin\ruby" --disable-gems -x 'C:\Ruby24-x64\bin\ridk.cmd' enable
It seems to run a CMD script (?!) with Ruby -- which isn't supposed to be possible. Running it with -rtracer in place of --disable-gems shows that the execution somehow ends up jumping into C:/Ruby24-x64/lib/ruby/site_ruby/2.4.0/ruby_installer/runtime/ridk.rb.
Could someone explain to me how this command line works?
From man ruby:
-x[directory]
Tells Ruby that the script is embedded in a message. Leading garbage will be discarded until the first line that starts with #!
and contains the string, ruby
Any meaningful switches on that line
will be applied. The end of the script must be specified with either
EOF ^D ( control-D ^Z ( control-Z or the reserved word __END__ If the
directory name is specified, Ruby will switch to that directory before
executing script.
Which means the ridk.cmd has embedded ruby code.
The directory is optional, as indicated by both the square brackets around the name and the description. If provided, it should be directly after -x without any space, which effectively allows it to be an optional argument.

Ruby directly from command line

I know that I can run ruby code directly from the command line, like so:
ruby file.rb
But is there any way to run ruby code directly from the command line so that I don't have to save the file in the first place?
ruby -e 'puts("foobar :)"); puts(2 + 2)'
should print foobar :) and 4
The quick help invoked using ruby -h says:
$ ruby --help
Usage: ruby [switches] [--] [programfile] [arguments]
...
-e 'command' one line of script. Several -e's allowed. Omit [programfile]
...
#djaszczurowski's answer provides you an example.
Another, better, option is to use irb (the interactive Ruby interpreter). It displays a prompt and waits for you to enter Ruby code. Multiple lines of code can be entered; it is executed when the block is closed.
#ho-man's answer shows you how to use it.
If you have more code that you'll like to run you can use irb instead.
$ irb
2.4.1 :001 > puts (2+2)
4
=> nil

When specifying command-line arguments Ruby no longer waits for input using gets

When running a ruby script with command line arguments, the "gets" is no longer blocking, it doesn't work.
test.rb
#!/usr/bin/ruby
puts "should wait for input"
gets
puts "test"
and here is how I run it
$ ./test.rb test.rb
should wait for input
test
It didn't wait.
I'm running Ubuntu 16.04 desktop, and Ruby from repository ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]
What am I doing wrong?
In addition to STDIN.gets like others have recommended, you can use plain gets if you call ARGV.clear beforehand. The regular gets works as expected if there aren't command like arguments to the script, but if there are, then it will read them. It's not really clear why you're using ./test.rb test.rb, but the second filename is a command line argument.
More specifically, if regular gets is called when ARGV is populated, then the result will be the contents of the file.
max#max ~> echo "content" > test.txt
max#max ~> ruby -e "puts ARGV.inspect; puts gets" test.txt
["test.txt"]
content
Nevermind,
The "gets" actually takes the first line from the file I added in the cli arguments.
Very weird.

how to build wrapper script

Sort of an odd question, but: how would one go about creating a wrapper shell script that can be used in the #! line in other scripts.
wrap.sh
#!/bin/bash
set -e
echo "wrapper!"
exec ruby "$#"
test.rb
#!/usr/bin/env wrap.sh
puts RUBY_VERSION
puts "the ducks come from the trucks"
wrap.sh is in the path, and test.rb is marked as executable.
Now I do:
./test.rb
wrapper!
ruby: no Ruby script found in input (LoadError)
The goal is to execute the ruby script via the wrapper (The ruby version can be either local or comes from a traveling ruby install that is shipped along with the app).
As far as I can tell ruby is invoked, it's just unhappy with the #! in the test.rb and refuses to run the script. I cannot remove the #! because that's how the script is executed in the first place.
Any workarounds for this?
So, I cannot use rbenv/rvm/etc. There is more logic in the wrapper than this, but this is the gist of it.
Looks to me like the arguments are not being passed to Ruby in "$#". I don't think the bang-hash line is the problem.
I don't see anything in your script which actually passes the contents of test.rb to wrapper.sh, which is the bigger issue.
Perhaps the real problem can be solved by some other means? For example, is the problem you're trying to solve to run arbitrary commands prior to the invocation of any Ruby script from the command line? Perhaps it can be approached that way...
It looks like Ruby just checks that the hash-bang line contains "ruby": https://github.com/ruby/ruby/blob/v2_2_2/ruby.c#L1580 So basically having ruby somewhere in the #! line is all it takes.

executing shell command from ruby

This isn't working in ruby and I don't understand why?
#!/usr/bin/env ruby
exec "sort data.txt > data.sort"
data.txt is a comma sepparated file. Anyway.. If I try to execute that line in the shell it works without a problem.
When I try to run this script from my script, I get an empty file.
This isn't really an answer, but I wanted to share that your original usage of exec is actually working for me. This was how I set it up.
data.txt
"1,2,3,4,5,6,7,8"
sort.rb (I don't know what your sort did so I am just writing the same data out)
File.open(ARGV[0]){|f| puts f.read}
irb session
irb(main):001:0> exec "sort data.txt > data.sort"
When I ran this in irb, I did get a data.sort output file and it contained "1,2,3,4,5,6,7,8" as expected. I can run the same exec line through irb or from another ruby file, and I get the output file with data each time.
I am running Ruby 1.8.6 on a 32bit Windows XP system.
Have you tried
%x(sort data.txt > data.sort)

Resources