Ruby and *NIX environment variables

'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. :frowning:

Cheers

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.

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

i do something like this

[snip]

Thanks very much - I shall probably use that :smiley:


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

  • Robert Heinlein

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 is the homepage, but there’s
nothing there…

Cheers


Ben

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

On Jul 25, 2006, at 1:45 PM, [email protected] wrote:

helpful)

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


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

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*(.)\sbefore/mio.match(stdout)[1]
after = YAML.load
%r/after\s*(.)\safter/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

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 :slight_smile:

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:

[[email protected] ~]# ruby ara.rb
ara.rb:18: warning: default to_a' will be obsolete ara.rb:18: warning: defaultto_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!

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs