How to use 'ruby -e' to execute multiline program? - ruby

I want to execute program by 'ruby -e' but it executes program if it's in single line but it's not executing if it's multiple line and throws the error. For an example,
>ruby -e "puts 'rajagopalan'"
=>rajagopalan
but
>ruby -e "a=[1,2,3,4,5]
a.each do |i|
puts i
end
"
it throws the error that "a.each do |i|
The syntax of the command is incorrect.
"
Can someone guide me how to execute the mulitiline via ruby -e
I have attached image here

you can try here document in your shell command:
ruby <<END
a=[1,2,3,4,5]
a.each do |i|
puts i
end
END
Hope this helps....

Try this:
>ruby -e "a=[1,2,3,4,5]; a.each do |i| puts i; end"
Basic idea, use a semi-colon wherever a new-line would be needed.

This has nothing to do with Ruby. You need to read the manual of your terminal emulator and your shell and figure out how to escape newlines.
As can be seen in the error you posted, you get a shell prompt after the first line, so the shell clearly seems to think the command is finished. Ergo, the shell tries to interpret the Ruby commands as shell commands, which leads to the error.

Related

How to check for command return codes inside a ruby shell script?

I have a simple shell script written in ruby that runs some predefined commands and saves the output strings.
The script works well, but I need a way branch conditionally if the command fails. I've tried using the $? object but the script exits before it gets there.
#!/usr/bin/ruby
def run_command(cmd)
`#{cmd}`
if $?.success?
# continue as normal
else
# ignore this command and move on
end
end
run_command('ls')
run_command('not_a_command')
# Output:
# No such file or directory - not_a_command (Errno::ENOENT)...
I've tried $?.exitstatus or even just puts $? but it always exits before it gets there because the script is obviously running the command before hitting that line.
Is there a way to check if the command will run before actually running it in the script?
Hope that's clear, thanks for your time!
Use system (which returns true or false depending on exit code) instead of backticks (which return output string):
if system(cmd)
...
else
...
end
If you want it to run quietly without polluting your logs / output:
system(cmd, out: File::NULL, err: File::NULL)

Mix input/output with Ruby IO?

I am hoping to write a small method that can interact with a subprocess (bash in this case) and should be able to both write commands and have those commands print their outback back to my shell when running the Ruby file.
So far, I can do something similar with this code:
require 'io/console'
#shell = IO.popen('/bin/bash', 'w')
def run(command)
puts command
#shell.puts command
puts 'Done'
end
run 'var=3'
run 'echo $var'
run 'sleep 2'
run 'ls docs'
#shell.close
And then when I run this code all of the Ruby code is printed first, and only later does any of the shell code get printed:
var=3
Done
echo $var
Done
sleep 2
Done
ls docs
Done
3
<ls output>
I was trying to read some of the tests for io/console as I'm almost certain there exists a really straightforward way to interact with a subprocess like this and get the output inline with the commands being run:
https://github.com/ruby/io-console/blob/master/test/io/console/test_io_console.rb

How do I to run a command in Linux as a Ruby script?

Let's say I have some terminal commands like:
sudo mycommand1
mycommand2
#.....
What should I do run them via ruby script (not bash) in Ubuntu?
UPDATE:
I have a ruby script:
def my_method1()
#calculating something.....
end
def method2(var1, var2)
#how do I sudo mycommand1 and any other Lunix command from here?
end
def method3(var4)
#calculating something2....
end
You can do system, exec, or place the command in backticks.
exec("mycommand") will replace the current process so that's really only pratical at the end of your ruby script.
system("mycommand") will create a new process and return true if the command succeeded and nil otherwise.
If you need to use the output of your command in your Ruby script use backticks:
response = 'mycommand`
There are many questions on SO that answer this. However you can run a command in many ways using system, exec, (backticks), %x{} or using open3. I prefer to use open3 -
require 'open3'
log = File.new("#{your_log_dir}/script.log", "w+")
command = "ls -altr ${HOME}"
Open3.popen3(command) do |stdin, stdout, stderr|
log.puts "[OUTPUT]:\n#{stdout.read}\n"
unless (err = stderr.read).empty? then
log.puts "[ERROR]:\n#{err}\n"
end
end
If you want to know more about other options you can refer to Ruby, Difference between exec, system and %x() or Backticks for links to relevant documentation.
You can try these approaches:
%x[command]
Kernel.system"command"
run "command"
make some file.rb with:
#!/path/to/ruby
system %{sudo mycommand1}
system %{mycommand2}
and the chmod the file with exec permissions (e.g. 755)
It you need to pass variables between the two commands, run them together:
system %{sudo mycommand1; \
mycommand2}

Execute bash commands from a Rakefile

I would like to execute a number of bash commands from a Rakefile.
I have tried the following in my Rakefile
task :hello do
%{echo "World!"}
end
but upon executing rake hello there is no output?
How do I execute bash commands from a Rakefile?
NOTE:This is not a duplicate as it's specifically asking how to execute bash commands from a Rakefile.
I think the way rake wants this to happen is with: http://rubydoc.info/gems/rake/FileUtils#sh-instance_method
Example:
task :test do
sh "ls"
end
The built-in rake function sh takes care of the return value of the command (the task fails if the command has a return value other than 0) and in addition it also outputs the commands output.
There are several ways to execute shell commands in ruby. A simple one (and probably the most common) is to use backticks:
task :hello do
`echo "World!"`
end
Backticks have a nice effect where the standard output of the shell command becomes the return value. So, for example, you can get the output of ls by doing
shell_dir_listing = `ls`
But there are many other ways to call shell commands and they all have benefits/drawbacks and work differently. This article explains the choices in detail, but here's a quick summary possibilities:
stdout = %x{cmd} - Alternate syntax for backticks, behind the scenes
it's doing the same thing
exec(cmd) - Completely replace the running process with a new cmd process
success = system(cmd) - Run a subprocess and return true/false
on success/failure (based on cmd exit status)
IO#popen(cmd) { |io| } - Run a subprocess and connect stdout and
stderr to io
stdin, stdout, stderr = Open3.popen3(cmd) - Run a subprocess and
connect to all pipes (in, out, err)
Given that the consensus seems to prefer rake's #sh method, but OP explicitly requests bash, this answer may have some use.
This is relevant since Rake#sh uses the Kernel#system call to run shell commands. Ruby hardcodes that to /bin/sh, ignoring the user's configured shell or $SHELL in the environment.
Here's a workaround which invokes bash from /bin/sh, allowing you to still use the sh method:
task :hello_world do
sh <<-EOS.strip_heredoc, {verbose: false}
/bin/bash -xeu <<'BASH'
echo "Hello, world!"
BASH
EOS
end
class String
def strip_heredoc
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, ''.freeze)
end
end
#strip_heredoc is borrowed from rails:
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/string/strip.rb
You could probably get it by requiring active_support, or maybe it's autoloaded when you're in a rails project, but I was using this outside rails and so had to def it myself.
There are two heredocs, an outer one with the markers EOS and an inner one with the markers BASH.
The way this works is by feeding the inside heredoc between the BASH markers to bash's stdin. Note that it is running within the context of /bin/sh, so it's a posix heredoc, not a ruby one. Normally that requires the end marker to be in column 1, which isn't the case here because of the indenting.
However, because it's wrapped within a ruby heredoc, the strip_heredoc method applied there de-indents it, placing the entirety of the left side of the inner heredoc in column 1 prior to /bin/sh seeing it.
/bin/sh also would normally expand variables within the heredoc, which could interfere with the script. The single quotes around the start marker, 'BASH', tell /bin/sh not to expand anything inside the heredoc before it is passed to bash.
However /bin/sh does still apply escapes to the string before passing it to bash. That means backslash escapes have to be doubled to make it through /bin/sh to bash, i.e. \ becomes \\.
The bash options -xeu are optional.
The -eu arguments tell bash to run in strict mode, which stops execution upon any failure or reference to an undefined variable. This will return an error to rake, which will stop the rake task. Usually, this is what you want. The arguments can be dropped if you want normal bash behavior.
The -x option to bash and {verbose: false} argument to #sh work in concert so that rake only prints the bash commands which are actually executed. This is useful if your bash script isn't meant to run in its entirety, for example, if it has a test which allows it to exit gracefully early in the script.
Be careful to not set an exit code other than 0 if you don't want the rake task to fail. Usually, that means you don't want to use any || exit constructs without setting the exit code explicitly, i.e. || exit 0.
%{echo "World!"} defines a String. I expect you wanted %x{echo "World!"}.
%x{echo "World!"} executes the command and returns the output (stdout). You will not see the result. But you may do:
puts %x{echo "World!"}
There are more ways to call a system command:
Backticks: `
system( cmd )
popen
Open3#popen3
There are two ways:
sh " expr "
or
%x( expr )
Mind that ( expr ) can be { expr } , | expr | or ` expr `
The difference is, sh "expr" is a ruby method to execute something, and %x( expr ) is the ruby built-in method. The result and action are different. Here is an example
task :default do
value = sh "echo hello"
puts value
value = %x(echo world)
puts value
end
get:
hello # from sh "echo hello"
true # from puts value
world # from puts value
You can see that %x( expr ) will only do the shell expr but the stdout will not show in the screen. So, you'd better use%x( expr ) when you need the command result.
But if you just want to do a shell command, I recommend you use sh "expr". Because sh "irb" will make you go into the irb shell, while %x(irb) will dead.

ruby executing remote scripts in one line. (like installing rvm)

install rvm in one line example:
user$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
Now, say I have a ruby scripts like this at http://blah.com/helloworld.rb
puts "what's ur name?"
name = gets.chomp
puts "hello world from web, #{name}"
I would like to achieve this it in my shell without creating a temp file in one line or even better one command.
wget http://blah.com/helloworld.rb; ruby helloworld.rb; rm helloworld.rb
I have tried this, but user prompt will be ignored because of earlier pipe.
curl -s http://blah.com/helloworld.rb | ruby
What's the correct way to executing a remote ruby script? Thanks!
Like this:
ruby < <(curl -s http://blah.com/helloworld.rb)
Ruby evaluates ruby code similarly to how bash evaluates shell code
Another Ruby option based on Calibre install for shell scripts:
ruby -e "require 'open-uri'; system open('http:// or local file').read"
The same for Ruby scripts:
ruby -e "require 'open-uri'; eval open('http:// or local file').read"
Edited: Fixed missing quote and added Ruby script execution
From http://brew.sh/:
ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
In your Ruby code, you have to reopen stdin and tie it to the controlling terminal device /dev/tty!
rubyscript="$( cat <<-'EOF'
puts "what's ur name?"
name = gets.chomp
puts "hello world from web, #{name}"
EOF
)"
ruby <(echo '$stdin.reopen(File.open("/dev/tty", "r"))'; echo "$rubyscript")

Resources