I want to write a script, to be packaged into a gem, which will modify its parameters and then exec a new ruby process with the modified params. In other words, something similar to a shell script which modifies its params and then does an exec $SHELL $*. In order to do this, I need a robust way of discovering the path of the ruby executable which is executing the current script. I also need to get the full parameters passed to the current process - both the Ruby parameters and the script arguments.
The Rake source code does it like this:
RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']).
sub(/.*\s.*/m, '"\&"')
If you want to check on linux: read files:
/proc/PID/exe
/proc/PID/cmdline
Other useful info can be found in /proc/PID dir
For the script parameters, of course, use ARGV.
File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
Related
I'm using Ruby on Linux.
I'd like to test for the existence of a command on the Linux system.
I'd like to not get back the output of the command that I'm testing for.
I'd also like to not get back any output that results from the shell being unable to find the command.
I want to avoid using shell redirection from within the command that I send to the shell. So something like system("foo > /dev/null") would be unsuitable.
I'm ok with using redirection if there is a way to do it from Ruby.
The simplest thing would be just to use system. Let's say you're looking for ls.
irb(main):005:0> system("which ls")
/bin/ls
=> true
If that's off the table, you could peek into the directories in ENV["PATH"] for the executable you're looking for. ENV["PATH"].split(":") would give you an array of directory names to check for the desired command. If you find a file with the right name, you may want to ensure it's an executable.
I want to avoid using shell redirection from within the command that I
send to the shell. So something like system("foo > /dev/null") would
be unsuitable. I'm ok with using redirection if there is a way to do it from Ruby.
system("exec which cmd", out: "/dev/null")
puts "Command is available." if ($?).success?
The exec is to explicitly avoid unnecessary forking in the shell.
As a sidenote type -P can be used instead of which, but it relies on Bash and may have surprising effects if script is ported to an environment with a different default shell.
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.
Writing a shell script to switch between ruby versions because currently my rvm setup requires me to write 2-3 lines to switch ruby versions, and im constantly doing this because im writing a ruby app which requires 2.2.1 and latex documents which requires ruby 1.9.1. My current code probably looks more like pseudocode, so please help me to get it to run. Here's the code:
#!/bin/sh
/bin/bash --login
rvm list // this is an external shell command
echo -n Use which one? >
read text
rvm use $text // this is an external shell command
That script is problematic since it will run bash as a login shell and then refuse to run any of those other lines until you exit it.
You probably don't need a shell script for what you're trying to do, just have two aliases set up in your profile:
alias rlist='rvm list'
alias ruse='rvm use'
Then you can enter rlist if you want a list of them, or ruse 2.2.1 (for example) to select one.
Alternatively, as Walter A points out in a comment, you could also hard-code the possibilities assuming you don't want it too dynamic:
alias rbapp='rvm use 2.2.1'
alias rbltx='rvm use 1.9.1'
This has the added advantage of allowing you to do more things at the end if needed:
alias rbltx='rvm use 1.9.1; echo Using Latex ruby'
something that's not normally possible with aliases needing parameters.
I have a groovy script and I need to call a ruby script.
I would like to pass arguments to Ruby script and would like to capture the output from Ruby script to use it in Groovy Script. Can somebody suggest how I can do this? I tried Process.execute(). It works for other dos commands but not for cmd /c ruby test.rb.
Since a ruby file isn't a batch file you don't need to use cmd to execute it. You could do
Process.execute("ruby.exe test.rb")
Assuming ruby.exe is on your path. Another option depending on your requirements may be to use JRuby which will allow you to run ruby code on the JVm and integrate nicely with Groovy.
I'm trying to change the directory of the shell I start the ruby script form via the ruby script itself...
My point is to build a little program to manage favorites directories and easily change among them.
Here's what I did
#!/usr/bin/ruby
Dir.chdir("/Users/luca/mydir")
and than tried executing it in many ways...
my_script (this doesn't change the directory)
. my_script (this is interpreted as bash)
. $(ruby my_script) (this is interpreted as bash too!)
any idea?
Cannot be done. Child processes cannot modify their parents environment (including the current working directory of the parent). The . (also known as source) trick only works with shell scripts because you are telling the shell to run that code in the current process (rather than spawning a subprocess to run it). Just for fun try putting exit in a file you run this way (spoiler: you will get logged out).
If you wish to have the illusion of this working you need to create shell functions that call your Ruby script and have the shell function do the actual cd. Since the functions run in the current process, they can change the directory. For instance, given this ruby script (named temp.rb):
#!/usr/bin/ruby
print "/tmp";
You could write this BASH function (in, say, you ~/.profile):
function gotmp {
cd $(~/bin/temp.rb)
}
And then you could say gotmp at the commandline and have the directory be changed.
#!/usr/bin/env ruby
`../your_script`
Like this?
Or start your script in the directory you want it to do something.
Maybe I don't get your question. Provide some more details.