我通过 Homebrew 使用 Mac OS X、iTerm2、zsh 和 Tmux。当我在 iTerm2 中启动终端会话时,全局 PATH 变量看起来仍然很好。但是,当我打开 Tmux 会话时,PATH 变量将使用其已包含的相同路径进行扩展。我将在我的 .zshrc 中放置一个解决问题的代码片段,但我仍然对 PATH 变量被填满两次的原因感兴趣。
发生这种情况是因为您的 .zshrc 会针对每个新的 zsh 进程进行评估。 因此,当您启动 iTerm2 时,它会评估对 $PATH 的更改,然后当您启动 tmux 时,它会获取修改后的 $PATH 并将其传递到其中的 zsh 的新实例,并且新的 zsh 进程再次评估 .zshrc再次改变。
有多种方法可以防止这种情况发生。
首先,为了专门防止 tmux 内的 shell 发生这种情况,如果设置了 $TMUX,您可以跳过进行这些更改:
if [[ -z $TMUX ]]; then
PATH="$PATH:/foo"
fi
另一种选择是将 .zshrc 的该部分移动到 .zprofile 文件中。 该文件仅由登录 shell 评估。 但是,默认情况下 tmux 会启动新的 shell 作为登录 shell,因此您还需要通过将以下内容添加到您的 tmux 配置中来防止 tmux 这样做:
set -g default-command /bin/zsh
您可能需要调整那里的 zsh 路径。 这将阻止 tmux 作为登录 shell 启动 zsh 进程,因此 tmux 内部的 zsh 不会查看 .zprofile。
与您链接到的用于防止添加重复项的代码片段类似的另一个选项是将路径修改更改为:
typeset -aU path
path=( $path /foo )
这是有效的,因为 zsh 自动将 $path 变量设置为镜像 $PATH 内容的数组。 排版的 -U 选项会修改该变量,以便条目是唯一的。
我发现这个 GitHub 线程非常有用。 此评论的解决方案对我有用:
# /etc/zshenv
if [ -x /usr/libexec/path_helper ]; then
PATH="" # Add this line
eval `/usr/libexec/path_helper -s`
fi
通过这样做,您必须将 PATH 修改放入
~/.zshrc
而不是 ~/.zprofile
。我也从线程中尝试了这个解决方案,但对我不起作用。
我的解决方案:
第1步:
在 .bashrc 或 .zshrc 中
ExtraPath="/foo/bar:$HOME/bin" # your customized path here, /foo/bar and $HOME/bin for instance
if ! [[ "$PATH" =~ "$ExtraPath" ]] ; then PATH="$ExtraPath:$PATH" ; fi # if the PATH does not contain your customized path, then insert yours, else do nothing.
第2步:
在~/.tmux.conf中,添加
set -g default-command "${SHELL}"
在这种情况下,tmux 不会获取 /etc/profile 的源代码,因此它不会弄乱你的 PATH
在 .zshrc 的开头添加以下内容:
# Check if TMUX is set and exit if true
if [[ -n "$TMUX" ]]; then
return
fi
如果通过 tmux 运行,它只会返回。 其他方法对我不起作用。 具体来说,在我附加到 PATH 的每个地方添加一个保护条件是很乏味的,并且对于我调用外部脚本(也修改了路径)的地方(rbenv、npm 等),它失败了。