Shell Out from Ruby While Setting an Environment Variable

Shell out from ruby while setting an environment variable

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

system accepts any arguments that Process.spawn accepts.

Ruby: pass environment variable to sudo script?

you need sudo -E

$ irb
>> system({'MYVAR' => "42"}, "sudo wrapper.sh")
=> true
>> system({'MYVAR' => "42"}, "wrapper.sh")
42
=> true
>> system({'MYVAR' => "42"}, "sudo -E wrapper.sh")
42
=> true
>>

Source shell script into environment within a ruby script

The reason this isn't working for you is b/c ruby runs its system commands in separate shells. So when one system command finishes, the shell that had sourced your file closes, and any environment variables set in that shell are forgotten.

If you don't know the name of the sourced file until runtime, then Roboprog's answer is a good approach. However, if you know the name of the sourced file ahead of time, you can do a quick hack with the hashbang line.

% echo sourcer.rb
#!/usr/bin/env ruby
exec "csh -c 'source #{ARGV[0]} && /usr/bin/env ruby #{ARGV[1]}'"
% echo my-script.rb
#!/usr/bin/env ruby sourcer.rb /path/to/file/I/want/to/source.csh
puts "HAPPYTIMES = #{ENV['HAPPYTIMES']}"
% ./my-script.rb
HAPPYTIMES = True

All of these will only help you use the set enviroment variables in your ruby script, not set them in your shell (since they're forgotten as soon as the ruby process completes). For that, you're stuck with the source command.

Passing an environment variable to a shell script from Fastlane

Expanding From Within The Immediate Shell

Assuming that sh, here, is a fastlane command that invokes a shell command with the given argument as script text:

# as a fastlane directive
sh './decrypt.sh "$ENCRYPTION_P12"'

Note that if this were being literally invoked as a command line for /bin/sh, it would need a -c argument:

# in other contexts
sh -c './decrypt.sh "$ENCRYPTION_P12"'

Note that this absolutely depends on ENCRYPTION_P12 being an environment variable -- that is, exported to the environment by the system by which it was set.


Expanding from Within The Invoked Script

That said, if it is an environment variable, you have a better option: Just use it.

That is, inside decrypt.sh, you can refer to "$ENCRYPTION_P12" without needing to set it explicitly, as the shell implicitly imports all environment variables as shell variables -- and they're passed down to child processes without any explicit actions needed.


Things to Avoid: Shell Injection Attacks

Finally, an aside: The dangerous way to do this would have been something like:

# INSECURE: DO NOT DO THIS
sh "./decrypt.sh #{ENV['ENCRYPTION_P12']}"

or

# STILL INSECURE
sh "./decrypt.sh \"#{ENV['ENCRYPTION_P12'}\""

or

# STILL INSECURE
sh "./decrypt.sh '#{ENV['ENCRYPTION_P12'}'"

...thereby substituting the value into your generated string at the Ruby level. This is dangerous, however, as that string is parsed as code -- meaning that contents of ENCRYPTION_P12 could then be leveraged in shell attacks.

For instance, consider the case (given below in bash syntax):

# this will make any of the above do Very Evil Things
ENCRYPTION_P12=$'$(rm -rf ~)\'$(rm -rf ~)\''

...for which both rms will execute if directly substituted into generated shell script (as opposed to expanded during parameter expansion -- '${foo}' -- which takes place after the expansion phases which make this dangerous have already passed).

How do I save changes to the system ENV from Ruby (NOT COMMAND SHELL)?

Unfortunately you cannot have a process directly save an environment setting, however you can check out this:

Persisting an environment variable through Ruby

To see how to take advantage of saving the values in registry and making it eventually make it to the environment variables.

Exporting an Environment Variable in Ruby

Simple answer: You can't.

Longer answer: You can't, unless the operating environment provides hooks to do so. Most do not. The best you can usually do is print out the assignments you want done and have the parent execute them.

Ruby, which exception is best to handle unset environment variables?

Could use ENV.fetch('FOO') which then raises a KeyError if not found.



Related Topics



Leave a reply



Submit