我通过 Homebrew 使用 Mac OS X、iTerm2、zsh 和 Tmux。当我在 iTerm2 中启动终端会话时,全局 PATH 变量看起来仍然很好。但是当我打开一个 Tmux 会话时,PATH 变量会使用它已经包含的相同路径进行扩展。我将在我的 .zshrc 中放置一个问题解决代码片段,但我仍然对 PATH 变量被填充两次的原因感兴趣。
3 回答
发生这种情况是因为您的 .zshrc 会针对每个新的 zsh 进程进行评估。因此,当您启动 iTerm2 时,它会评估您对 $PATH 的更改,然后当您启动 tmux 时,它会获取修改后的 $PATH 并将其传递给其中的新 zsh 实例,并且新的 zsh 进程再次评估 .zshrc 制作再次更改。
有几种方法可以防止这种情况。
$TMUX
首先,为了特别防止它发生在 tmux 内部的 shell 中,如果设置了 $TMUX,您可以跳过这些更改:
if [[ -z $TMUX ]]; then
PATH="$PATH:/foo"
fi
zprofile
另一种选择是将 .zshrc 的那部分移动到 .zprofile 文件中。此文件仅由登录 shell 评估。但是,默认情况下 tmux 会启动新的 shell 作为登录 shell,因此您还需要通过在 tmux 配置中添加以下内容来防止 tmux 这样做:
set -g default-command /bin/zsh
您可能需要在那里调整 zsh 的路径。这将阻止 tmux 将 zsh 进程作为登录 shell 启动,因此 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