Reputation: 15209
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
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
Reputation: 18418
system({"MYVAR" => "42"}, "echo $MYVAR")
system
accepts any arguments that Process.spawn
accepts.
Upvotes: 76
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
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
Reputation: 1295
This may work?
system <<-CMD
export VARNAME=123
other_command
CMD
Upvotes: 2