How to source a shell script and execute its functions in ruby - ruby

I'm new to ruby . I'm trying to source my shell script in ruby and execute functions in sourced shell script.
below is my shell script /tmp/test.sh
#!/bin/bash
function hello {
echo "hello, this script is being called from ruby"
}
below is my ruby script test.rb
#!/usr/bin/ruby
system("source /tmp/test.sh")
puts $?.exitstatus
system("hello")
puts $?.exitstatus
output using system
[root#localhost ~]# ruby test.rb
127
127
I even tried the back tick approach, but i got below error
code :
#!/usr/bin/ruby
status=`source /root/test.sh`
puts status
status2=`hello`
puts status2
error:
ruby test.rb
test.rb:3:in ``': No such file or directory - source (Errno::ENOENT)
from test.rb:3:in `<main>'
can anyone tell what is wrong in my code.

You can use session gem, or write a solution yourself.
script.sh:
#!/bin/bash
function hello() {
echo "Hello, World!"
}
Ruby file:
IO.popen('bash', 'r+') do |sh|
sh.puts 'source script.sh'
sh.puts 'hello'
sh.close_write
puts sh.gets
end
# => Hello, World!

Related

Ruby frozen string literal pragma order caused error

Given a file with Ruby 2.3.0p0:
#!/usr/bin/env ruby
# frozen_string_literal: true
# Exit cleanly from an early interrupt
Signal.trap("INT") { abort }
This is fine.
# frozen_string_literal: true
#!/usr/bin/env ruby
# Exit cleanly from an early interrupt
Signal.trap("INT") { abort }
will result in error:
syntax error near unexpected token `"INT"'
`Signal.trap("INT") { abort }'
Why?
A shebang has to appear on the file's initial line.
A file test.rb containing:
#!/usr/bin/env ruby
# foo bar
puts "hello from #{RbConfig.ruby}"
will be run via Ruby:
$ ./test.rb
hello from /.../ruby-2.3.0/bin/ruby
But if test.rb contains: (1st and 2nd line swapped)
# foo bar
#!/usr/bin/env ruby
echo "hello from $SHELL"
it will be run as an ordinary shell script:
$ ./test.rb
hello from /.../bin/zsh
Therefore, the error you are getting is no Ruby error, it's from your shell.

How do i run Ruby script from command line ?

I've a file, which I can run from command line using:
ruby filename.rb
Which outputs:
12345
A different script containing:
def hi()
puts "hello"
end
does not return anything when I run it from the command-line.
How do I run this from the command line?
Add puts hi("John") to the bottom of the method:
def hi(name)
puts "hello"
end
puts hi("John")
Where "John" is whatever name you want it to be.
Then just run it as usual, ruby yourfilename.rb
Try putting this in filename.rb:
def hi()
puts "hello"
end
hi
Then run your code in the command line: with ruby filename.rb

Run def in ruby program

I'm a beginner in programming and wrote this little program:
Test.rb:
# encoding: utf-8
require 'open-uri'
require 'nokogiri'
def parse_file
doc = Nokogiri::XML(File.open("test.xml"))
parse_xml(doc)
end
def parse_xml(doc)
doc.root.elements.each do |node|
parse_tracks(node)
end
end
def parse_tracks(node)
if node.node_name.eql? 'kapitel'
puts 'New Kapitel'
end
end
I know how to execute this code:
ruby test.rb
But how can I call the def parse_file?
Simply add whatever you want to the end of your file. Ruby scripts are simply scripts, they are being interpreted:
…
end
parse_file # ⇐ HERE YOU GO
You can either call the method at the end of your test.rb file:
def parse_file
# ...
end
parse_file
And run it with
$ ruby test.rb
Or leave the file as it is, require it as a library and call the method manually:
$ ruby -r test.rb -e "parse_file"
Rather than hard-coding your file path, you can pass it as an argument when calling your script. Arguments can be accessed via the ARGV array:
def parse_file(file)
doc = Nokogiri::XML(File.open(file))
parse_xml(doc)
end
parse_file(ARGV.first)
Now you can run it with:
$ ruby test.rb test.xml
Another option is to make the script executable. Add a shebang as the first line of you file:
#!/usr/bin/env ruby
And set the execute flag:
$ chmod +x test.rb
Now you can run it with:
$ ./test.rb test.xml
just add
parse_file
in the end of your ruby file

Checking if a Ruby program was executed or imported via require

How do you check if a Ruby file was imported via "require" or "load" and not simply executed from the command line?
For example:
Contents of foo.rb:
puts "Hello"
Contents of bar.rb
require 'foo'
Output:
$ ./foo.rb
Hello
$ ./bar.rb
Hello
Basically, I'd like calling bar.rb to not execute the puts call.
Change foo.rb to read:
if __FILE__ == $0
puts "Hello"
end
That checks __FILE__ - the name of the current ruby file - against $0 - the name of the script which is running.
if __FILE__ != $0 #if the file is not the main script which is running
quit #then quit
end
Put this on top of all code in foo.rb
For better readability you can also use $PROGRAM_NAME
if __FILE__ == $PROGRAM_NAME
puts "Executed via CLI #{__FILE__}"
else
puts 'Referred'
end
More info: What does __FILE__ == $PROGRAM_NAME mean in ruby?

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