# Ruby and \*NIX environment variables

**URL:** <https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822>\
**Category:** Ruby\
**Created:** [July 25, 2006, 7:28pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822 "2006-07-25T19:28:17Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 25, 2006, 7:28pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/1 "2006-07-25T19:28:17Z")

</div>

'allo,

Context: I’m replacing parts of an existing collection of shell scripts  
and bits of Perl with a unified Ruby system (this despite little to no  
understanding of either of the first two…). In one particular case, I  
have a script (values.sh) which contains instructions like

VARIABLE=VALUE

The results of which I would really like to be able to see from Ruby.  
I’m told that it’s setting environment variables and that the values  
are visible from the calling script because it invokes values.sh with a  
leading period, which causes them to share an environment - fair  
enough.

The question is this: if I call values.sh from within Ruby (with a  
leading period) will I be able to see the updated environment variables  
after it returns, or is this behaviour specific to when one shell  
script calls another? (They’re ksh scripts, if that information is  
helpful)

I’d test this myself, but I have no access to any \*NIX boxes until I’ve  
completed the design stage of this project… and my history is sadly  
Windowsy. ☹

Cheers

---

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 25, 2006, 7:40pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/2 "2006-07-25T19:40:51Z")

</div>

On Jul 25, 2006, at 1:25 PM, Ben Z. wrote:

> The question is this: if I call values.sh from within Ruby (with a  
> leading period) will I be able to see the updated environment  
> variables  
> after it returns, or is this behaviour specific to when one shell  
> script calls another? (They’re ksh scripts, if that information is  
> helpful)

The second one, fortunately or unfortunately as the case may be. .

 is the source command in ksh, it's equivalent to typing the contents of the shell script in the original file. Theres no why for a child process to affect it's parent's environment. OTOH if values.sh has simple value parts you may be able to parse the script with ruby to pull in the info.

---

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 25, 2006, 7:47pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/3 "2006-07-25T19:47:13Z")

</div>

On Wed, 26 Jul 2006, Logan C. wrote:

> is the source command in ksh, it’s equivalent to typing the contents of the  
> shell script in the original file. Theres no why for a child process to  
> affect it’s parent’s environment. OTOH if values.sh has simple value parts  
> you may be able to parse the script with ruby to pull in the info.

i do something like this

require ‘session’

bash = Session::Bash.new

stdout, stderr = bash.execute ‘ruby -r yaml -e" y ENV "’  
before = YAML.load stdout

stdout, stderr = bash.execute ‘. values.sh’

stdout, stderr = bash.execute ‘ruby -r yaml -e" y ENV "’  
after = YAML.load stdout

updated = after.to\_a - before.to\_a

updated.each{|k,v| ENV[k] = v}

which saves you having to parse the file and works even if it’s  
horrifically  
complicated…

-a

---

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 25, 2006, 8:12pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/4 "2006-07-25T20:12:05Z")

</div>

> i do something like this

[snip]

Thanks very much - I shall probably use that 😃

–  
Ben  
“Never worry about theory as long as the machinery does what it’s  
supposed to do.”

- Robert Heinlein

---

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 25, 2006, 8:44pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/5 "2006-07-25T20:44:10Z")

</div>

Erm, _puts on his newbie shirt_ I don’t seem to have the “session”  
package, maybe because this is one-click Ruby for Windows - is it  
included by default with the \*nix version, or do I need to get it from  
somewhere? If the latter, where? I assume  
[http://rubyforge.org/projects/session](http://rubyforge.org/projects/session) is the homepage, but there’s  
nothing there…

Cheers

–  
Ben

---

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 25, 2006, 9:03pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/6 "2006-07-25T21:03:15Z")

</div>

On Wed, 26 Jul 2006, Logan C. wrote:

> Very neat hack. Only thing I would change would be to do:
> 
> …  
> after = YAML.load stdout  
> ENV.update(after)

and a good change too!

-a

---

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 25, 2006, 8:34pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/7 "2006-07-25T20:34:21Z")

</div>

On Jul 25, 2006, at 1:45 PM, removed\_email\_address@domain.invalid wrote:

> > > helpful)

Very neat hack. Only thing I would change would be to do:

…  
after = YAML.load stdout  
ENV.update(after)

---

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 25, 2006, 10:59pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/8 "2006-07-25T22:59:18Z")

</div>

On Wed, 26 Jul 2006, Ben Z. wrote:

> –  
> Ben

it’s \*nix (or msys or cgywin) specific :

gem install -r session

you don’t need session btw. this’ll do it too:

```
 harp:~ > cat a.rb
 require 'yaml'
 require 'tempfile'

 def tmpfile txt = ''
   t = Tempfile.new rand.to_s
   t.write txt
   t.close
   t.path
 end

 values_sh = tmpfile %q(
   export KEY=VALUE
   export date=`date`
   export foo=bar
 )

 def propagate_env path
   cmds = <<-cmds
     echo __before__ ; ruby -r yaml -e' y ENV.to_hash '; echo 

```

**before**  
. #{ path }  
echo **after** ; ruby -r yaml -e’ y ENV.to\_hash '; echo  
**after**  
cmds

```
   stdout =
     IO.popen('sh', 'w+') do |sh|
       sh.write cmds
       sh.close_write
       sh.read
     end

   raise "env failure from <#{ path }>" unless $?.exitstatus == 0

   before = YAML.load 

```

%r/ **before** \s\*(._)\s_ **before** /mio.match(stdout)[1]  
after = YAML.load  
%r/ **after** \s\*(._)\s_ **after** /mio.match(stdout)[1]  
updated = {}  
after.each do |k,v|  
updated[k] = v if before[k].nil? or before[k] != after[k]  
end  
ENV.update updated  
updated  
end

```
 propagate_env values_sh

 p ENV['date']
 p ENV['foo']

 harp:~ > ruby a.rb
 "Tue Jul 25 14:57:06 MDT 2006"
 "bar"

```

regards.

-a

---

<div class="post-metadata">

**Author:** ![apocalympse](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/898d66/32.png) [@apocalympse](https://www.ruby-forum.com/u/apocalympse)\
**Post date:** [July 26, 2006, 9:40pm UTC](https://www.ruby-forum.com/t/ruby-and-nix-environment-variables/99822/9 "2006-07-26T21:40:13Z")

</div>

Well, I’ve bullied them into giving me access to a box, and got Ruby,  
RubyGems and session installed and apparently working - by reference to  
about three \*nix newbie tutorials, but still, it’s working 🙂

In the name of simplicity (my manager is unlikely to be happy with  
anything as complex-looking as the second code sample you gave me,  
which did work - thankyou!), I’d like to use your original example.

However, I’m getting the following error:

[root@pc2461 ~]# ruby ara.rb  
ara.rb:18: warning: default `to_a' will be obsolete ara.rb:18: warning: default`to\_a’ will be obsolete  
ara.rb:22:in `[]=’: can’t convert Object into String (TypeError)  
from ara.rb:22  
from ara.rb:22

I’ve tried playing around a bit but I can’t seem to get much more than  
that. Although “updated” ends up as an Array it only contains one value  
(which is just of type Object, and doesn’t correspond to any obvious  
objects like “nil”…). (I’ve wrapped the “real” .sh I want to capture  
variables from - it sets 8) Do you have any guesses as to why that’s  
happened?

Thanks so much for taking the time to help me with this!
