I'd like to write a ruby script that then calls another ruby script. Example, I'd like to run the "test1.rb" from my script. The test1.rb has been simplified to just do this:
print "1"
Then get the result (-> 1).
I ask to help others to fix this problem, and they suggested the popen3 command:
require 'open3'
cmd = 'ruby "test1.rb"'
puts Dir.pwd
Open3.popen3(cmd) do |stdin, stdout|
var = stdout.read
puts var
end
However, the script send an error message:
X:/Ruby22-x64/lib/ruby/2.2.0/open3.rb:193:in `spawn': No such file or directory
- ruby "test1.rb" (Errno::ENOENT)
Please help me.
Related
My employer has Ruby 1.8.7 in the /usr/bin/ruby, and allows the usage of Ruby 2.4 only via SCL (sofoware collections).
Which means that when I run ruby, I need to use (from the RH6 shell) scl enablde ruby-24 'ruby foo.rb' when foo.rb
is the file name.
I want to enable the ruby call on the first execution line, i.e., instead of the Ruby code file looking like:
#!/usr/bin/ruby
puts "Hello world"
That the code will look
#!cmd
puts "Hello world"
Where the cmd is what calls via the scl and run the Ruby 2.4 for the puts command. I know that a wrapper file can be used. I want something in 1 file.
How about this:
#!/usr/bin/ruby
if RUBY_VERSION != "2.4.1"
exec "scl enable ruby-24; ruby __FILE__"
end
puts "Ruby Version: #{RUBY_VERSION}"
I have been trying to create a Ruby gem that simply exits my terminal whenever "x" is entered. Here is my main project file:
module SwissKnife
VERSION = '0.0.1'
class ConsoleUtility
def exit
`exit`
end
end
end
and my executable:
#!/usr/bin/env ruby
require 'swissknife'
util = SwissKnife::ConsoleUtility.new
util.exit
For some reason whenever I run this nothing appears to happen. I debugged it by adding in a simple puts 'Hello World!' in there, and it would print "Hello World!" but not exit. What am I doing wrong? Any help is greatly appreciated!
Backticks execute code in a new shell
exit isn't an executable that your shell runs, it's a special command understood by your shell - telling it to exit
So when you do
`exit`
it starts a shell which immediately exits. Not very useful. To exit the shell, you can instead kill Ruby's parent process.
Process.kill 'HUP', Process.ppid
I am trying to run a bash script (#command) that requires user input and I'm trying to feed that script input using the following code:
Open3.popen3(#command) do |stdin, stdout, stderr|
stdin.write("y")
stdout.gets
end
Here is an idea of the script:
exec sudo su -c "some command" $username
If anyone could tell me what I am doing wrong or has any suggestions on how to implement this a different way, that would be much appreciated.
Also, I can run the script like this:
#output = `#{#command}`
In this case, I can see the contents of the script output in the console I am running my app from. If there is anyway to feed input to that location that would work too.
Got my solution here:
How to fix hanging popen3 in Ruby?
Open3.popen3(#command) do |stdin, stdout, stderr|
stdin.puts "y\r\n"
stdout.each_line { |line| puts line }
stdin.close
end
out_err, status = Open3.capture2e(#command, :stdin_data => "y\r\n")
print out_err
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}
I have the following script:
#!/usr/bin/env ruby
require 'rubygems'
require 'net/ssh'
Net::SSH.start('host1', 'root', :password => "mypassword1") do |ssh|
stdout = ""
ssh.exec("cd /var/example/engines/")
ssh.exec!( "pwd" ) do |channel, stream, data|
stdout << data if stream == :stdout
end
puts stdout
ssh.loop
end
and i get /root, instead of /var/example/engines/
ssh.exec("cd /var/example/engines/; pwd")
That will execute the cd command, then the pwd command in the new directory.
I'm not a ruby guy, but I'm going to guess there are probably more elegant solutions.
In Net::SSH, #exec & #exec! are the same, e.g. they execute a command (with the exceptions that exec! blocks other calls until it's done). The key thing to remember is that Net::SSH essentially runs every command from the user's directory when using exec/exec!. So, in your code, you are running cd /some/path from the /root directory and then pwd - again from the /root directory.
The simplest way I know how to run multiple commands in sequence is to chain them together with && (as mentioned above by other posters). So, it would look something like this:
#!/usr/bin/env ruby
require 'rubygems'
require 'net/ssh'
Net::SSH.start('host1', 'root', :password => "mypassword1") do |ssh|
stdout = ""
ssh.exec!( "cd /var/example/engines/ && pwd" ) do |channel, stream, data|
stdout << data if stream == :stdout
end
puts stdout
ssh.loop
end
Unfortunately, the Net::SSH shell service was removed in version 2.
You can just give different commands separated by a new line. Something like:
#result = ssh.exec!("cd /var/example/engines/
pwd
")
puts #result
Its probably easier (and clearer) to pass the command to a variable, then pass the variable into exec. Same principle though.
see if there's something analogous to the file(utils?) cd block syntax, otherwise just run the command in the same subshell, e.g. ssh.exec "cd /var/example/engines/; pwd" ?
Im not a ruby programmer, but you could try to concatenate your commands with ; or &&
There used to have a shell service which allow stateful command like your trying to do in net/ssh v1 but it has been remove in v2. However there's a side project of the author of net/ssh that allows you to do that. Have a look here: http://github.com/jamis/net-ssh-shell
The current location of net-ssh-shell is changed.
What I decided to use though to call a random shell script is to scp a file to the remote machine and source it into shell. Basically doing this:
File.write(script_path, script_str)
gear.ssh.scp_to(script_path, File.dirname(script_path))
gear.ssh.exec(". script_path")