When using the master branch version of rbenv, tmux no longer respects rbenv. For example I have global ruby setup to 2.0.0-p0 and when I run rbenv version it correctly reports 2.0.0-p0, it is also correctly reported when I run ruby --version. Now in the same session I start a new tmux session using tmux new. Now when I run rbenv version it still correctly reports 2.0.0-p0, however when I run ruby --version it now reports 1.8.7. When I run which ruby it shows me /usr/bin/ruby instead of the ruby shim.
I forgot to mention that everything works as expected on v0.4.0.
Your problem is due to $PATH ordering. You could have shared your PATH with us, but you don't have to now because I know exactly what happened.
Your PATH in your regular terminal session is something like:
rbenv shims : rbenv bin : system paths
By entering tmux, you spawned a nested interactive subshell. That means that your .bashrc or .zshrc get sourced again, and the same paths get added to the already prepared PATH. You finish up with something like:
rbenv bin : system paths : rbenv shims : rbenv bin : system paths
The master branch of rbenv avoids adding shims to the PATH twice. So you finished with ruby from system paths (/usr/bin/ruby) having precedence over rbenv's shims (~/.rbenv/shims/ruby).
The solution is to configure your shell initialization file (e.g. .bashrc) to not repeat the PATH setup if it's already there. I solve that by running my PATH through a small executable that strips out the duplicates.
@mislav maybe I am missing it, but I cannot figure out quite where your checking the PATH for duplicates in that file you linked to. Could you add something to the README for ZSH and BASH users?
It's handled by a command I call in the end of the above linked file
I'm not able to get your solution working as it puts the rbenv shims and bin paths at the end of the PATH. At this point /usr/bin/ruby takes over.
As you can see the shims get properly added in the non-tmux version, but adding the consolidation code moves them to the end anyway.
rbenv.sh (bash_profile include)
export PATH="$HOME/.rbenv/bin:$PATH"
echo $PATH
eval "$(rbenv init -)"
echo $PATH
export PATH="$(consolidate-path)"
echo $PATH
output from tmux new tab
/Users/code/.rbenv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/code/.rbenv/shims:/Users/code/.rbenv/bin
/Users/code/.rbenv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/code/.rbenv/shims:/Users/code/.rbenv/bin
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/code/.rbenv/bin:/Users/code/.rbenv/shims
output from new iterm window
/Users/code/.rbenv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
/Users/code/.rbenv/shims:/Users/code/.rbenv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/code/.rbenv/shims:/Users/code/.rbenv/bin
@jgeiger Strange; it looks like as though you have something in /etc/zshenv or ~/.zshenv?
The default shell is bash but I checked the files you suggested. Right now my workaround is to just remove the check to see if shims has already been added. Once I do that, everything works file (with the issue of having rbenv shims,bin in the path twice)
~/.zshenv is empty
box:etc $ cat zshenv
# system-wide environment settings for zsh(1)
if [ -x /usr/libexec/path_helper ]; then
eval `/usr/libexec/path_helper -s`
fi
box:etc $ /usr/libexec/path_helper -s
PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/code/.rbenv/shims:/Users/code/.rbenv/bin"; export PATH;
@jgeiger As I suspected, there is your problem: you have a /etc/zshenv calling out to path_helper. This is not your fault, but a bug that ships with OS X. Rename that file to zprofile:
sudo mv /etc/zshenv /etc/zprofile
I tried this and it didn't seem to help. I'm running into an issue where the rbenv bin,shims always end up at the end up the path. The box I'm working on may be re-imaged in the near future so for now I'll just fix it in the rbenv init script by removing the check to see if shims already exists.
Thanks.
It seems like tmux will always call the profile for your shell, not just the rc (I'm using bash, and it's definitely calling /etc/profile, which also has a call to path_helper).
What I'm doing to fix it is changing /etc/profile to this:
if [[ -z $TMUX ]] && [ -x /usr/libexec/path_helper ]; then
eval `/usr/libexec/path_helper -s`
fi
instead of
if [ -x /usr/libexec/path_helper ]; then
eval `/usr/libexec/path_helper -s`
fi
tmux doesn't call the profile for any shell by itself. Your shell does, because with tmux, interactive shells get nested and that can lead to the above problems.
Reopening this because it's getting people tripped up
After a couple of hours of tinkering, the optimal way to solve this (without disabling path_helper entirely) is to make the following patch to /etc/zshenv:
--- /etc/zshenv.orig
+++ /etc/zshenv
@@ -1,4 +1,5 @@
# system-wide environment settings for zsh(1)
if [ -x /usr/libexec/path_helper ]; then
+ PATH=""
eval `/usr/libexec/path_helper -s`
fi
The underlying problem is that all your shell configuration files are loaded twice when you create a tmux session/window. So the following happens:
1) /etc/zshenv is loaded, which runs /usr/libexec/path_helper, which sets your PATH variable.
2) Your own configuration scripts, which load rbenv, which puts the shims directory at the front of your PATH.
3) You run tmux.
4) path_helper runs again, putting stuff before your shims directory.
5) Your configuration scripts run again, and rbenv sees that the shims directory already exists in your PATH, and does nothing.
This patch ensures that your shell configuration is loaded starting from a blank path. This has two benefits:
1) You won't end up with duplicate paths and an even messier PATH variable.
2) At step 5, rbenv will see that the shims directory doesn't exist in your PATH yet, and load it properly.
@markprzepiora's solution worked for me
I ran into the same problem with tmux & rbenv this morning, @tonyarkles solution worked for me as a bash user.
@markprzepiora the problem with your solution (versus what @mislav recommends: moving /etc/zshenv to /etc/zprofile) is that any modifications to $PATH in ~/.zprofile will be wiped out when starting a sub-shell or running a script.
I'm running tmux + bash in ITerm 2 (Mac OS X 10.9), and @tonyarkles solution worked for me.
I'm running tmux + bash in ITerm 2 (Mac OS X 10.9) and @tonyarkles solution worked for me as well. But after a boot or shell rebooting.
//best
_EDIT: Don't do this. It sorts alphabetically, which you probably don't want._
Running tmux + bash on OS X 10.9 with this in my ~/.profile:
PATH=`echo $PATH | tr ':' '\n' | sort | uniq | tr '\n' ':'`
via http://linuxg.net/oneliners-for-removing-the-duplicates-in-your-path/
@audionerd I would not advise using this method, since it uses sort and therefore arranges items in your PATH alphabetically, which is never what I want (I want manual control of ordering of items in my PATH)
@mislav Thanks, good point.
I think I found a fix that works now. I'm running bash, and I wanted a solution that worked only for my current user (no messing with /etc/profile), so I ended up with a ~/.bash_profile which looks like this:
if [ -f /etc/profile ]; then
PATH=""
source /etc/profile
fi
. ~/.profile
. ~/.bashrc
Now my $PATH is the same with or without tmux.
Override path_helper by calling it again. The PATH is cleared first and then rebuilt. The result is far less duplication of directories. rbenv is also setup here. /etc/zshenv:
# Mac OS X uses path_helper to preload PATH, clear it out first
if [ -x /usr/libexec/path_helper ]; then
PATH=''
eval `/usr/libexec/path_helper -s`
fi
# if rbenv is present, configure it for use
if which rbenv &> /dev/null; then
# Put the rbenv entry at the front of the line
export PATH="$HOME/.rbenv/bin:$PATH"
# enable shims and auto-completion
eval "$(rbenv init -)"
fi
@audionerd @Serta Thanks for the explanations. I am using the example from @Serta above with tmux and rbenv and things are working as expected. P.S. Hi Eric! :)
I'm really having problems with this. I can't use your consolidate-path script, because I'm not using zsh.
Why does Rbenv not add the .rbenv/shims/ directory to the $PATH if it already exists? If it did, then everything would be duplicated, and everything would be fine. This way only .rbenv/shims/ isn't duplicated, and then shell gets to system Ruby.
Your problem is not rbenv. Your problem is other parts of the system (that includes user scripts) reordering and duplicating PATH entries in a way it breaks your environment.
consolidate-path is a unix executable which can be invoked from bash, zsh, ksh, fish, Ruby, Python, or any other program or shell, as long as you have zsh installed somewhere on the system. You don't actually have to run zsh as your interactive shell.
I already went with @markprzepiora's solution. But thanks for the info, I didn't know that I can run it anyways.
Other parts of system don't reorder my PATH entries, they just duplicate them. But what is the bright side of rbenv not duplicating its shims? Why is it in the code base?
rbenv doesn't duplicate the shims directory since it goes against the practice of duplicating PATH entries, in case shims is already in PATH. Crazy as it may sound, rbenv actually _doesn't_ believe that the way to fight the duplication problem is with more duplication.
Hi all. Ive had duplicate path entries for quite some time now. Running OSX 10.7, zsh, rbenv, tmux. I've tried solutions from some comments here and the only solution that worked for me was putting this inside .zprofile.
# ~/.zprofile
if [ -f /etc/profile ]; then
PATH=""
source /etc/profile
fi
Whereas /etc/profile I've never touched. The contents are:
if [ -x /usr/libexec/path_helper ]; then
eval `/usr/libexec/path_helper -s`
fi
if [ "${BASH-no}" != "no" ]; then
[ -r /etc/bashrc ] && . /etc/bashrc
fi
I too simply can't get this to work.
I've tried @mislav's solution using his consolidate-path script and then having these two exports at the end of my .zshenv:
export PATH
export PATH="$(consolidate-path)"
which results in the terminal session freezing upon sourcing (I can force cancel whatever sourcing process is happening by sending ctrl-c). This happens when spawning a new terminal or when launching tmux.
Was anybody on linux using zsh able to solve this?
tmux -V
tmux 1.8
tmux show environment -g
RBENV_DIR=/home/jottr
RBENV_HOOK_PATH=:/home/jottr/.rbenv/rbenv.d:/usr/local/etc/rbenv.d:/etc/rbenv.d:/usr/lib/rbenv/hooks:/home/jottr/.rbenv/plugins/rbenv-binstubs/etc/rbenv.d:/home/jottr/.rbenv/plugins/rbenv-gem-rehash/etc/rbenv.d
RBENV_ROOT=/home/jottr/.rbenv
RBENV_SHELL=zsh
RBENV_VERSION=1.9.3-p484
running consolidate path got this error everytime was opening my terminal:
/etc/zshenv:3: fork failed: resource temporarily unavailable
/Users/fernandes/.zshenv:89: fork failed: resource temporarily unavailable
maybe its a zsh config or something like that, but solved putting @mislav consolidate-path inline on my ~/.zshenv
export PATH
typeset -a paths result
paths=($path)
while [[ ${#paths} -gt 0 ]]; do
p="${paths[1]}"
shift paths
[[ -z ${paths[(r)$p]} ]] && result+="$p"
done
export PATH=${(j+:+)result}
if someone knows the fix for resource temporarily unavailable please tell, if someone has the same problem, this workaround worked
thank you guys, thanks @mislav for the solution
Most helpful comment
After a couple of hours of tinkering, the optimal way to solve this (without disabling
path_helperentirely) is to make the following patch to/etc/zshenv:The underlying problem is that all your shell configuration files are loaded twice when you create a tmux session/window. So the following happens:
1)
/etc/zshenvis loaded, which runs/usr/libexec/path_helper, which sets your PATH variable.2) Your own configuration scripts, which load rbenv, which puts the shims directory at the front of your PATH.
3) You run tmux.
4)
path_helperruns again, putting stuff before your shims directory.5) Your configuration scripts run again, and rbenv sees that the shims directory already exists in your PATH, and does nothing.
This patch ensures that your shell configuration is loaded starting from a blank path. This has two benefits:
1) You won't end up with duplicate paths and an even messier PATH variable.
2) At step 5, rbenv will see that the shims directory doesn't exist in your PATH yet, and load it properly.