I have a script at /venv/bin/activate that sets some environment variables. I’m looking for a way to start zsh, have it source this script, and then continue with a normal interactive session. When I exit this session, the session I return to should not know about any of the environment changes that activate made. How can I invoke zsh like this?

(This is pretty much the same question as this one, except that I’m using zsh instead of bash.)


If the activate script only sets environment variables, you can read it in one shell, then execute a new, interactive zsh instance.

sh -c '. /venv/bin/activate; exec zsh -i'

The wrapper shell sh can be replaced by any shell that is able to parse /venv/bin/activate, including zsh if the activate script is compatible with it.

In addition to environment variables, the interactive zsh instance will inherit the process ID and a few other process settings such as resource limits (ulimit …) and ignored signals (trap '' …). On the other hand, settings of the shell itself are not preserved: shell variables (var=… if var is not exported), shell options (set -… or shopt …), key bindings, alias and function definitions, etc.

Obviously this won't work if your .zshrc overrides environment variables set by the activate script. That's one of the reasons .*shrc files should not set environment variables.

  • This is a good solution as long as you don’t need to return to the original shell afterward (and as long as the effects of activate fall into only the categories you mentioned). – bdesham Sep 6 '19 at 20:45
  • @bdesham Yes, I meant that you should run that as a separate shell script but I can see that it isn't clear, I'll clarify. – Gilles 'SO- stop being evil' Sep 6 '19 at 20:56
  • Oh, even better. Thanks for clarifying. – bdesham Sep 6 '19 at 21:40
  • This doesn't work with modern zsh (nb it works if the final shell command is sh or bash, for example) – jmetz Mar 12 at 16:17
  • @jmetz What doesn't work? It certainly works with Python virtual environments, and I don't see what recent changes in zsh could break similar scripts from other communities. The only thing I can see that would break it is if you do something weird in your .zshrc like overriding PATH. In which case, don't do this. – Gilles 'SO- stop being evil' Mar 12 at 17:34


Create a (possibly temporary) directory at, say, /venv_startup that contains two files, .zshenv and .zshrc. The .zshenv file consists of

source ~/.zshenv
source /venv/bin/activate

while .zshrc says

source ~/.zshrc

Now, invoke zsh via

ZDOTDIR=/venv_startup zsh

This says to zsh, “instead of starting out by sourcing the .zshenv and .zshrc files in $HOME, source the files of those names in /venv_startup instead.” Since the versions in /venv_startup source the ones in $HOME anyway, the net effect is that the shell will run

source /venv/bin/activate

in between executing your zshenv and your zshrc. After that, it will be a normal interactive session.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.