1

In my .bash_profile I have:

if [ -f $(brew --prefix)/etc/bash_completion ]; then
  source $(brew --prefix)/etc/bash_completion
  GIT_PS1_SHOWDIRTYSTATE=1
  git_prompt='$(__git_ps1)'
fi
export PS1="\[\e[33m\]  \d \t \w$git_prompt\n\[\e[m\]\\$ "
export MYTESTVAR="hello world"

I have a Ruby script foo.rb that contains:

`source ~/.bash_profile`
puts `printenv`
puts `echo $PS1`
puts `echo $MYTESTVAR`

When I run ruby foo.rb the printenv command lists all environment variables, and the $MYTESTVAR line correctly returns hello world.

However, $PS1 does not show up. Why is this?

1 Answer 1

3

$MYTESTVAR line correctly returns hello world. $PS1 does not show up.

Indeed, you're right. Most variables work fine, but "PS1" in particular fails:

$ PS1=ps1 TEST1=test1 ruby -e 'puts `echo $PS1 and $TEST1`'
and test1

Why is this?

In Ruby, as you're probably aware, `somestring` executes somestring in a shell, as if you in C had opened a pipe to execl("/bin/sh", "-c", somestring, NULL).

On many systems, /bin/sh is provided by bash. Bash has this snippet in its initialization code:

  /* Execute the start-up scripts. */

  if (interactive_shell == 0)
    {
      unbind_variable ("PS1");
      unbind_variable ("PS2");
      interactive = 0;

In other words, it explicitly removes "PS1" and "PS2" because these variables are only intended for use with interactive shells.

On other systems where /bin/bash is provided by dash, as many modern Debian-based distros default to, you instead get the result you expected:

$ PS1=ps1 TEST1=test1 ruby -e 'puts `echo $PS1 $TEST1`'
ps1 and test1

The reason why your `source ~/.bash_profile` doesn't fix this is that each `backtick command` runs in a separate shell. Variables set in one is not reflected in the other.

If you just want the variable as exported by your shell, you should do what @anujm suggests and get it directly with ENV['PS1']. Not only is this easier and more robust, it's also a thousand times faster.

If you want the variable as set in your .bash_profile, regardless of how you ran your script, you can do both sourcing and printing in the same shell:

puts `bash -c 'source ~/.bash_profile; printf "%s" "$PS1"'`
Sign up to request clarification or add additional context in comments.

2 Comments

But it is more complicated than that because there five separate processes involved and each has its own environment.
I didn't catch that part. Updated.

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.