'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
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 
–
Ben
“Never worry about theory as long as the machinery does what it’s
supposed to do.”
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 
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: 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!