6

I'm trying to run some third party bash scripts from within my ruby program.

Before I can run them they require me to source a file. On the command line it all works fine but within Ruby it doesn't work. I've found out that system commands will open a new child shell process and any sourcing will be done in that and can't be seen from the parent shell process running the Ruby script. When the system call ends, the child shell is also killed.

How do i get round this problem?

5 Answers 5

8

Do this:

$ source whatever.sh
$ set > variables.txt

And then in Ruby:

File.readlines("variables.txt").each do |line|
  values = line.split("=")
  ENV[values[0]] = values[1]
end

After you've ran this, your environment should be good to go.

Sign up to request clarification or add additional context in comments.

4 Comments

Ill try this. So does this means the script can alter the enviroment variables of its containing shell process and therefore any further child processes created via system calls with inherit?
No, but any process executed from the Ruby script will inherit the script's variables.
The above works for a single thread and I do the below. But a question I have how do I use a merged COPY of the environment with IO.popen ? somehow it doesn't seem to work. with "system" I can do: # ... create new "path" here subEnv = Hash.new; subEnv.merge!(ENV); # copy old environment subEnv['PATH'] = path; # set new values in copy system(subEnv, commandLine);
If you have a value with a = this won't work (e.g. URL=http://google.com?q=foo). split takes a second argument which limits the splitting. Instead do: key, value = line.split "=", 2; ENV[key] = value
2

I'm not sure if I understand your question correctly. Do you try to source a shell script before running another one? In this case the answer is simple:

#!/bin/env ruby
system "source <path_to_source_file> && <command>"

If the source file contains variables which your command should use you have to export them. It is also possible to set environment variables within your Ruby script by using ENV['<name_of_var>'] = <value>.


Update: Jan 26, 2010 - 15:10

You can use IO.popen to open a new shell:

IO.popen("/bin/bash", "w") do |shell|
  shell.puts "source <path_to_source_file>"
  shell.puts "<command>"
end

7 Comments

I don't think that Executing with system will help, because the vars will be set only for the shell process that gets spawned to execute that command.
i cant even get system "source .bashrc" to work in my user directory. It complains command not found. Are you sure source can be used like you posted?
It worked for me. I tried this on OSX 10.6. Is shell of the user who executes the script set to /bin/bash? (I also updated my answer.)
thanks for your reply. Ive been googling this and cant figure out why i cant source .bashrc inside the script. how do i check if the shell is set to /bin/bash?
The shell varibale $SHELL stores the login shell of the user. I think this should work in this particular case. But remember it's the users login shell, so running something like /bin/sh -c "echo $SHELL" from a bash shell still prints /bin/bash.
|
2

This is horrible, but..

env = %x{. /some/shell/script/which/setups/your/env && env}
env.split("\n").each do |line|
  key, value = line.split("=", 2)
  ENV[key] ||= value unless value.nil? or value.empty?
end

1 Comment

This grabs all exported variables. It works, but that seems like poor behavior.
0

I did this because I didn't want to have to write a file or mix up my ruby code with this stuff:

#!/usr/bin/env bash
eval $(echo "$(cat .env) $1" | tr '\n' ' ')

I put this in ~/bin/run_with_env.sh and then for example I can run:

% run_with_env.sh "rails console"

Comments

0

Modifying ENV works only for a single thread and I do the below instead. But a question I have how do I use a merged COPY of the environment with IO.popen ? somehow it doesn't seem to work.

with "system" I can do:

# ... create new "path" here

    subEnv = Hash.new;
    subEnv.merge!(ENV); # copy old environment
    subEnv['PATH'] = path; # set new values in copy

    system(subEnv, commandLine);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.