mislav
mislav

Reputation: 15209

Shell out from ruby while setting an environment variable

I need to shell out to a process while setting an environment variable for it. I tried this one-liner:

system "RBENV_VERSION=system ruby extconf.rb"

This syntax works in shell script but not from ruby. (Update: turns out this syntax works from ruby after all, but I failed to see its effect due to my particular use-case.)

So I'm doing this:

rbenv_version = ENV['RBENV_VERSION']
ENV['RBENV_VERSION'] = 'system'
begin
  system "ruby extconf.rb"
ensure
  ENV['RBENV_VERSION'] = rbenv_version
end

I'm forced to such a long expression because I don't want to override the environment variable permanently if it already had a value.

Anything shorter that comes to your mind?

Upvotes: 23

Views: 11555

Answers (5)

rtomayko
rtomayko

Reputation: 1136

Ruby 1.9 includes Process::spawn which allows an environ hash to be provided.

Process::spawn is also the foundation for system, exec, popen, etc.
You can pass an environment to each.

Under Ruby 1.8, you may want to consider the POSIX::Spawn library,
which provides the same interfaces

Upvotes: 7

Avdi
Avdi

Reputation: 18418

system({"MYVAR" => "42"}, "echo $MYVAR")

system accepts any arguments that Process.spawn accepts.

Upvotes: 76

Shai
Shai

Reputation: 1509

Actually that worked for me.

shai@comp ~ » irb                                                                                                                                     
1.9.3p0 :001 > system %{SHAIGUITAR=exists ruby -e 'puts ENV["SHAIGUITAR"]'}
exists
 => true 

But if it doesn't, maybe you can try prepending "env" to whatever variable you need. E.g.

system(%{env SHAIGUITAR=exists ruby bla.rb})

Upvotes: 3

Phrogz
Phrogz

Reputation: 303224

Using your same approach, but wrapped up as a block method that temporarily modifies the environment (like the block form of Dir.chdir):

def with_environment(variables={})
  if block_given?
    old_values = variables.map{ |k,v| [k,ENV[k]] }
    begin
       variables.each{ |k,v| ENV[k] = v }
       result = yield
    ensure
      old_values.each{ |k,v| ENV[k] = v }
    end
    result
  else
    variables.each{ |k,v| ENV[k] = v }
  end
end

with_environment 'RBENV_VERSION'=>'system' do
  `ruby extconf.rb`
end

Upvotes: 4

AndrewVos
AndrewVos

Reputation: 1295

This may work?

system <<-CMD
export VARNAME=123
other_command
CMD

Upvotes: 2

Related Questions