Project

General

Profile

Actions

Feature #6648

open

Provide a standard API for retrieving all command-line flags passed to Ruby

Added by headius (Charles Nutter) almost 12 years ago. Updated about 18 hours ago.

Status:
Assigned
Target version:
-
[ruby-core:45867]

Description

Currently there are no standard mechanisms to get the flags passed to the currently running Ruby implementation. The available mechanisms are not ideal:

  • Scanning globals and hoping they have not been tweaked to new settings
  • Using external wrappers to launch Ruby
  • ???

Inability to get the full set of command-line flags, including flags passed to the VM itself (and probably VM-specific) makes it impossible to launch subprocess Ruby instances with the same settings.

A real world example of this is "((%bundle exec%))" when called with a command line that sets various flags, a la ((%jruby -Xsome.vm.setting --1.9 -S bundle exec%)). None of these flags can propagate to the subprocess, so odd behaviors result. The only option is to put the flags into an env var (((|JRUBY_OPTS|)) or ((|RUBYOPT|))) but this breaks the flow of calling a simple command line.

JRuby provides mechanisms to get all its command line options, but they require calling Java APIs from Ruby's API set. Rubinius provides its own API for accessing comand-line options, but I do not know if it includes VM-level flags as well as standard Ruby flags.

I know there is a (({RubyVM})) namespace in the 2.0 line. If that namespace is intended to be general-purpose for VM-level features, it would be a good host for this API. Something like...

  class << RubyVM
    def vm_args; end # returns array of command line args *not* passed to the target script

    def script; end # returns the script being executed...though this overlaps with $0

    def script_args; end # returns args passed to the script...though this overlaps with ARGV, but that is perhaps warranted since ARGV can be modified (i.e. you probably want the original args)
  end

Related issues 1 (0 open1 closed)

Is duplicate of Ruby master - Feature #4046: Saving C's **argv and cwd allows Ruby programs to reliably restart themselvesFeedbackActions

Updated by headius (Charles Nutter) almost 12 years ago

Oops, this should be a feature request.

Actions #2

Updated by nobu (Nobuyoshi Nakada) almost 12 years ago

  • Tracker changed from Bug to Feature

I'm positive to the feature, but RubyVM wouldn't be right place.
It is CRuby specific and unexpected to be in other implementations.

Updated by nobu (Nobuyoshi Nakada) almost 12 years ago

  • Description updated (diff)
Actions #4

Updated by headius (Charles Nutter) over 11 years ago

ARGV is a special class; perhaps ARGV could have the methods?

Updated by headius (Charles Nutter) over 11 years ago

I was mistaken...it is ARGF, not ARGV that is a special class. ARGV is a normal array.

Another option: ENV, which is a special Hash-like class. ENV.vm_args, ENV.script, and ENV.script_args aren't bad.

Updated by headius (Charles Nutter) over 11 years ago

Ping...we'd still like to have this to be able to build a unifying benchmark tool, which needs to be able to report the actual command-line arguments passed to the runtime. Current tricks are too ugly (parsing ps output, for example), and this would not be difficult to add.

I'm leaning toward ENV having a few special methods for this, but I'm open to other ideas.

Updated by mame (Yusuke Endoh) over 11 years ago

  • Status changed from Open to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)
  • Target version set to 2.6

I'm sorry that matz didn't noticed this.

--
Yusuke Endoh

Actions #8

Updated by naruse (Yui NARUSE) over 6 years ago

  • Target version deleted (2.6)
Actions #9

Updated by hsbt (Hiroshi SHIBATA) 21 days ago

  • Description updated (diff)

Updated by Dan0042 (Daniel DeLorme) 5 days ago · Edited

I'd like to revive this proposal.

The OP mentions calling a subcommand with the same options/flags as the current interpreter, and that's a fine use case. As for me I'm also interested in re-executing the current script while keeping ruby options/flags.

Some time ago I tried writing a rbenv alternative based on the idea of adding "-r versionchecker" to RUBYOPT and then re-executing the current script with a different interpreter if we find a .ruby-version file that specifies a different version. No bash, no shims! But it was not to be; the lack of this proposed API made it infeasible. In particular if ruby is executed with the -e argument it appears impossible to get back the value.

I imagine this feature would also be very useful for web servers that need to re-execute upon receiving USR2. Currently they need to have all their options in RUBYOPT.

Since the path to the current interpreter is already in RbConfig.ruby I would suggest RbConfig.ruby_args for this API.

Then we could have a copy of the original $0 in RbConfig.script and a copy of the original ARGV in RbConfig.script_args, and to re-execute we can do

exec(RbConfig.ruby, *RbConfig.ruby_args, *RbConfig.script, *RbConfig.script_args)

Extra features I'd like, if possible:

  1. if ruby is invoked with -e argument(s), $0 is "-e" but RbConfig.script should be an array of the arguments:
ruby -e 'p 42' -e 'p RbConfig.script'
42
["-e", "42", "-e", "p RbConfig.script"]
  1. if ruby is invoked with script on stdin, $0 is "-" but RbConfig.script should be an array with "-e":
echo 'p RbConfig.script' | ruby
["-e", "p RbConfig.script"]

If either of those extra features are impossible/undesirable, RbConfig.script should be false so that exec/system fails with TypeError rather than executing random things.

Updated by Eregon (Benoit Daloze) 5 days ago · Edited

I fully agree with the proposal of @Dan0042 (Daniel DeLorme).
This is also needed for MSpec, which currently works around the lack of it by requiring to pass any ruby option through -T-option (which is awkward and error-prone), it would be much nicer if we could have RbConfig.ruby_args.

In fact MSpec is also forced to create an extra process due to the lack of this API (which is a noticeable overhead, even more so on Ruby implementations with a slower startup than CRuby), because that's currently the only way to ensure the main process specs and subprocesses created by specs have the same VM options.
We cannot know if the initial process from the mspec executable has the same ruby options as the options passed through -T (typically not), hence the extra process.

Updated by kddnewton (Kevin Newton) about 18 hours ago

As another note, this would be useful within CRuby itself. Right now there are lots of tests that run assert_in_out_err, which in turn calls EnvUtil.invoke_ruby. EnvUtil.invoke_ruby does not pass along some command-line options like RJIT, YJIT, Prism, etc. So there appear to be some tests that are being run in the CRuby CI that aren't testing what they should be testing.

Actions

Also available in: Atom PDF

Like1
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like1Like0Like0