views:

1245

answers:

4

If I'm writing a shell script and I want to "source" some external (c-)shell scripts to set up my environment, I can just make calls like this:

source /file/I/want/to/source.csh

I want to replace a shell script that does this with a ruby script. Can I do a similar thing in the ruby script?

Update:

Just tried it with test_script.csh:

#!/bin/csh

setenv HAPPYTIMES True

...and test_script.rb:

#!/usr/bin/env ruby
system "~/test_script.csh"
system "echo $HAPPYTIMES"

Sadly, no HAPPYTIMES as of yet.

A: 

This looks like C shell?

You can, but not with source. You need to use eval instead, and the ruby script would need to kick out csh statements.

So this:

eval `/path/to/ruby-script`

Would basically execute ruby-script and then execute (in the shell process) the output of the script.

What you can't do is set the environment using native ruby methods: any changes would be lost when the ruby interpreter exits.

Chris J
Hmmm, ok. I'm trying to ask how to do this given that the script which sets up the environment is a shell (not ruby) script. So, how about this? \`eval /path/to/csh-script\`
Charlie
Ah -before you clarified, I read it backwards: I thoughgt you wanted to source a ruby script rather than a shell script.In that case there's not much you can do I suspect. When you execute a process, it spawns a copy of the environment and any changes made by that process to the environment are not copied back to the parent process.Hence the hack to basically right a ruby-script that returns a shell-script. Effectively, the only route you have then is to execute the shell script, have that kick out key:value pairs to STDOUT, catch that and post-process within your script to set the env.
Chris J
A: 
system 'source /file/I/want/to/source.sh'

Not sure that this will do what you want though. It will execute the source command in a subshell. Try it and see it it does what you're after.

Henry
I tried this and it does not appear to do what I'm after. I'm trying to get the environment variables set by the shell script into the environment the ruby script is running in.
Charlie
environment changes in a child process do not affect the parent
glenn jackman
I thought that might be the case. Sorry for wasting your time.
Henry
+1  A: 

You are going to have to write a function to run something like the following, and capture the output ("backtick" operation):

/bin/csh -e '. my_script ; env'

Loop on each line, match against something like

/^(\w+)=(.*)$/

Then use the first match capture as the var name, and the second capture as the var value.

(yes, I'm hedging on the fact that I know Perl way better than Ruby, but the approach would be the same)

Roboprog
Actually, what I did capture ALL environment variables after running the script.IFF the assignments in the "script" have no interpolated values, only string literals, you could get what you want be merely reading the file, rather than having to run it on a pipe (backtick).
Roboprog
A: 

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.

rampion
I'm guessing the only reason this works in, say, csh, is that you're using the same shell instance to interpret the script you're sourcing. So you couldn't source a .csh file from a bash script any more than you could source it from a ruby script...
Charlie