Skip to content

Instantly share code, notes, and snippets.

@pbrisbin
Created October 27, 2014 18:55
Show Gist options
  • Save pbrisbin/45654dc74787c18e858c to your computer and use it in GitHub Desktop.
Save pbrisbin/45654dc74787c18e858c to your computer and use it in GitHub Desktop.
ZSH startup file headaches

Default behavior dictates the following order for ZSH startup files:

  • /etc/zshenv
  • ~/.zshenv
  • /etc/zprofile (if login shell)
  • ~/.zprofile (if login shell)
  • /etc/zshrc (if interactive)
  • ~/.zshrc (if interactive)
  • /etc/zlogin (if login shell)
  • ~/.zlogin (if login shell)

Notes:

  • zshenv is the place to set environment variables
  • zshrc is the place for aliases, functions etc

Setting environment variables in zshenv means that they'll be present for non-interactive uses (think cron commands). This is what you want.

At least Debian/Gentoo/Arch ship an /etc/zprofile which sets (not adds to, sets) a value for $PATH. Because this file is sourced after ~/.zshenv, any value you may have set there is overridden.

Possible solutions:

  • Move the system /etc/zprofile to /etc/zshenv
  • Set your path in ~/.zprofile, not ~/.zshenv

Neither are great.

Moving /etc/zprofile to /etc/zshenv means whatever commands are there are now invoked for every shell (rather than once at login). This is wasteful, there's no need to (re)set your locale in every shell every time.

Setting environment variables in zprofile means they'll be set once (on login) and inherited by all shells invoked directly or indirectly. This mostly works. The variables won't be present for (e.g.) cron commands and any exports must be duplicated in your crontab.

References:

Copy link

ghost commented Apr 7, 2023

So far, the best method I've found is to set my path in .zshenv and source .zshenv from .zshrc if environment variables were changed in an undesired way.

@dluciv
Copy link

dluciv commented Jun 13, 2023

macOS has a similar issue - in /etc/zprofile it reorders the existing PATH

My ugly solution for Mac OS was:

  1. In .zshenv link PATH to an array of unique items: typeset -U path.
  2. Create path_prepend=( ~/.local/bin ...) and prepend it to path: path=($path_prepend $path).
    • Under Mac OS I strictly needed my entries in the beginning of a $PATH, because its Automator only executes .zshenv on program start and applies no more settings. Sic.
  3. Later, in .zprofile, repeat path=($path_prepend $path), which ended with good condition of $PATH because of typeset -U.

Quite dirty, but works nicely.

@snOm3ad
Copy link

snOm3ad commented Nov 14, 2023

Notes:

  • zshenv is the place to set environment variables

https://www.zsh.org/mla/users/2003/msg00512.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment