-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't encourage users to break their system zsh #426
Conversation
For years, OS X has mistakently invoked `path_helper` in `/etc/zshenv` (affecting all zsh runtimes, even non-interactive shells such as scripts) instead of from `/etc/zprofile` where it should have been because it needs to only run once for a login shell. This frustrated a lot of users since `path_helper` would unexpectedly reorder their PATH by putting system paths first during nested invocations of zsh. Many have disabled their `path_helper` because they believed it to be the culprit. Instead, what they should have done is fixed the OS X configuration bug and renamed their `/etc/zshenv` to `/etc/zprofile`. Recently, El Capitan shipped and users of zsh rejoiced because it has finally fixed its faulty zsh configuration: the `path_helper` is now correctly invoked from `/etc/zprofile`. This was a deliberate change on Apple's part and is a BUG FIX, NOT A REGRESSION. However, now this project suggests the opposite: revert the El Capitan fix and move `/etc/zprofile` to `/etc/zshenv`. This is unwise since it teleports us to the olden days of broken zsh configuration. Please don't instruct users to break their system. This reverts commit 15de0bc.
cc: @thoughtbot/shell |
@mislav, these changes and your documentation make sense to me. Given that moving path configuration to |
- Don't add `git/safe/../bin` to `$PATH`, on boot `chruby` add it's gems to the `$PATH` on reading a `.ruby-version` file. - Remove `/sbin` and `/usr/sbin` from `$PATH` - they are already in there. See thoughtbot/dotfiles#426
Moving PATH configuration to But if we fix BTW here is how the warning messages from this PR look like: |
This is, unfortunately, a complex issue that doesn't seem to have an obvious answer. There is a recommendation to set the
The user manual has some confusing instructions about
Many systems, such as Arch Linux, recommend configuring the path in
Configuring the I'm not sure what the correct solution is here given the weird and unfortunate history of |
zsh's own sample
Now, as for your pushback:
Can you be specific about which terminal emulators you speak of? Both Terminal.app and iTerm are configured to start shells in login mode by default, be it bash or zsh. Although this is not the standard in Linux distributions, it seems to be the standard on OS X. In fact, the sole reason how bash (the default shell) gets its system path is that it consults
Both tmux, vim, and any other program that you start from your shell will inherit the current environment. They don't need to additionally set PATH within their process because they already have correct PATH. When you issue shell commands within vim, they will be executed with the correct PATH environment that vim already inherited. Do you have any specific example of how my approach could backfire? Because I have one example with how setting PATH in
|
Another example of how putting user config in I realize this is specific to rbenv, but it's just an example of how encouraging people to do their config in |
This ensures the version managers (rbenv, nodenv, dinghy, etc.) continue to work on OS X 10.11 “El Capitan.” The issue was that in OS X 10.11, the invocation of `path_helper` was moved from /etc/zshenv to /etc/zprofile in the system ZSH config, which meant that our local ~/.zshenv ran before the main system paths were set, which meant that it couldn’t find the installations of rbenv et al., so they were never initialised. Thoughtbot is encouraging a different change, to actually move those system configs around (thoughtbot/dotfiles@15de0bc), but I’d rather leave them where they are, especially when its debatable as to whether ~/.zshenv is the right place to do this kind of setup (see thoughtbot/dotfiles#426 for an ongoing discussion about this). The fix at this point is just to move all of this setup to the top of ~/.zshrc.
It seems like zsh contains conflicting information, then? It recommends setting
We had issues specifically with tmux (this may only have occurred for users who were also using We've gone back and forth on this a number of times (as OS X has with Given that:
I'm wondering if the benefit we gain by configuring any We currently change
@geoffharcourt @gylaz @croaky any thoughts on eliminating this issue forever by splitting out the |
I'm 👍 with any approach that this project takes as long as it doesn't suggest |
I noticed problems with Homebrew when the /usr/local/sbin directory wasn't in the path, so we'll probably want to make sure that's added, but we can do that in I use the |
When
For users that want their shell to source |
@mislav, thanks very much for all the research and the contribution. I made a few small comments around the |
Making tweaks such as setting EDITOR or changing PATH only makes sense for interactive shells, e.g. those that open in your Terminal window or when you log in to a server. Non-interactive shells (such as those started by running `zsh myscript.zsh` or any executable with `zsh` shebang) should instead inherit those values from the environment. Furthermore, changing PATH in `~/.zshenv` is not advised since stock OS X `/etc/zprofile` will reoder PATH by means of `path_helper`, so it's better to make any additional PATH manipulation in `~/.zprofile` or `~/.zshrc`.
`.zshenv` is executed for all zsh programs, even those run from executables and not as an interactive shell, and furthermore due to OS X's use of `path_helper` in `/etc/zprofile` which runs after that, it's not a good place to configure additional PATH entries. From zsh(1) man page: > As /etc/zshenv is run for all instances of zsh, it is important that > it be kept as small as possible. So `.zshenv` is generally considered advanced usage and is not recommended that people drop their casual login shell config in here. Because of people's historical misuse of `.zshenv`, stop documenting it in the README and suggest that people do their PATH and other configuration in `.zshrc`.
Warn people who might have PATH and similar configuration in their `~/.zshenv.local` that they should upgrade to `~/.zshrc.local` since that's a much better phase for such configuration. This is for backwards compatibility with people's personal configurations from pre-El Capitan days. The generic `.zshenv` file from zsh distribution[1] advises: > .zshenv is sourced on ALL invocations of the shell, unless the -f > option is set. It should NOT normally contain commands to set the > command search path, or other common environment variables unless you > really know what you're doing. E.g. running `PATH=/custom/path gdb program` > sources this file (when gdb runs the program via $SHELL), so you want > to be sure not to override a custom environment in such cases. Note > also that .zshenv should not contain commands that produce output or > assume the shell is attached to a tty. [1]: http://sourceforge.net/p/zsh/code/ci/master/tree/StartupFiles/zshenv
If `/etc/zshenv` that calls `path_helper` is found on the system, assume OS X version pre-El Capitan and suggest that this file gets renamed to `zprofile` so that it only gets sourced on login shells and doesn't mess up PATH order on nested invocation of zsh.
This is so it doesn't run every time when zsh starts in interactive mode, but just once per `rcup`.
@geoffharcourt Changes made. I've moved broken OS X |
rcup(1) seems like the only thing we can assume here. |
This is to avoid outputting ANSI escape codes to scripts and log files.
Added a change so warning messages are colorized only if stderr is attached to a tty (default mode). If redirected to a log file, for instance, ANSI escape codes won't be used. |
I think only running that check in rcup(1) is a good idea. Whenever I have a problem with the shell on either of my machines my first move is to run rcup(1) before diagnosing further. |
@geoffharcourt Anything else I could do for you? @jferris If this gets merged, it might be worth reverting thoughtbot/laptop@50c3e22. |
@mislav on new OS X installs, it's located at The laptop script is designed to be run on a new laptop, so I don't think we have to worry about older versions of OS X there. |
@mislav I'm just waiting a little bit longer for any internal reports from people trying out the branch. The prior changes were made quickly in an attempt to resolve users' problems with El Capitan after upgrading, and I want to be more patient and deliberate making a significant change here. I expect to merge this in this week. I very much appreciate your work here, just being cautious before we seesaw back from the prior recommendation. |
Thanks for the feedback! |
* Add back missing EDITOR and VISUAL variables: these aliases were lost when reconciling changes from #426's changes to `zshrc`. * Move aliases setup to occur after loading other config, as some of our aliases depend on environment variables having been set, so alias loading must come last after we've sourced `zsh/configs`. * Move autocompletion for `g` function from the function definition to to `zsh/completions/_g` * Move `PATH` setup to `zsh/configs/post` to ensure it happens after other configuration that might alter the `PATH`
* Add back missing EDITOR and VISUAL variables: these aliases were lost when reconciling changes from #426's changes to `zshrc`. * Move aliases setup to occur after loading other config, as some of our aliases depend on environment variables having been set, so alias loading must come last after we've sourced `zsh/configs`. * Move autocompletion for `g` function from the function definition to to `zsh/completions/_g` * Move `PATH` setup to `zsh/configs/post` to ensure it happens after other configuration that might alter the `PATH`
* Add back missing EDITOR and VISUAL variables: these aliases were lost when reconciling changes from #426's changes to `zshrc`. * Move aliases setup to occur after loading other config, as some of our aliases depend on environment variables having been set, so alias loading must come last after we've sourced `zsh/configs`. * Move autocompletion for `g` function from the function definition to to `zsh/completions/_g` * Move `PATH` setup to `zsh/configs/post` to ensure it happens after other configuration that might alter the `PATH`
See thoughtbot/dotfiles#426 for more details on why this change should be made.
This is the recommended location for setting the zsh path (https://sf.net/p/zsh/code/ci/master/tree/StartupFiles/zshenv), and problems arise with macOS El Capitan and later when set in zshenv. This problem is discussed in thoughtbot/dotfiles#426 and rbenv/rbenv#781. This also allows reverting a previous commit (08d13a0) that disabled global zsh config files.
This reverts 15de0bc, which I find to be harmful advice. El Capitan finally fixed
/etc/zshenv
to be called/etc/zprofile
, and now you're suggesting to users to undo that fix without understanding of what they were doing?El Capitan's
/etc/zprofile
callspath_helper
, which is a OS X utility to initialize the system PATH. This is meant to run for login shells before any user PATH configuration. Therefore,/etc/zprofile
is the perfect place to call it.If
/etc/zshenv
calledpath_helper
, like it did in older versions of OS X, then it would reorder PATH on all subsequent invocations of zsh, such as nested shells (e.g. runningzsh
from bash) or executables withzsh
in their shebang. This was a bug, and resulted in failed commands and much confusion to users, who thought thatpath_helper
is the main culprit and some used sudo to disable this utility, further messing up their system.After reverting the offending documentation addition, my approach to solving problem (as implemented in this PR) is as follows:
/etc/zshenv
(OS X versions pre-El Capitan) and suggest the user renames them tozprofile
..zshenv
configuration (runs too early) to.zshrc
where it runs only once for interactive shells, and after system PATH is now set up..zshenv
. Instead, most typical user tweaks for their environment need to be in.zshrc
, such as PATH edits..zshenv.local
for backwards compatibility, but issue a warning on stderr when its configuration changes PATH, and suggest to user that it gets moved to.zshrc.local
.Please observe more information for each of my commits from their commit messages.
The benefits of this approach:
sudo
to make harmful changes to the system, except for fixing a OS X bug. El Capitan users don't have to fix anything..zshenv
, thus speeding up non-interactive zsh executables..zshrc
as it should be used: to host configuration for interactive shells.~/.zshenv
) to the preferred long-term approach.References #307, #421, closes #423
Note that this probably "breaks" Alfred workflows again as pointed out in #289. However, Alfred purposely doesn't start shells in login mode so that they're isolated from user's terminal environment. Alfred's own documentation states that workflows should not depend on any particular setup in the user's environment. If someone makes private workflows for themselves and needs to use rbenv version switching, they should setup rbenv within the workflow.
Further reading:
path_helper
on OS X is incorrect sorin-ionescu/prezto#381/cc @geoffharcourt @ventsislaf @reshleman