New tmux session only sources .zshrc, and doesn't pick up the $PATH defined in .profile
Solution 1
The behavior you describe is the expected one. Environment variables are defined in .profile
, which is read when you log in. Starting a new tmux session does not log you in. Tmux does start a login shell by default, but you've turned this off in the configuration, so the tmux windows just inherit the outside environment.
If you put source .profile
in your .zshrc
, this overrides whatever environment the shell is running in. This means that you can't run a shell inside a different environment from your default one, e.g. to try something with a different PATH
.
Just remove source .profile
from .zshrc
. You'll have your default environment, set at login time, in all shells.
If your login shell is zsh, note that it reads .zprofile
at login time, not .profile
. This is different from bash, which reads .profile
if there is no .bash_profile
. Zsh works differently because its syntax is different from sh, so it can't read .profile
directly. If you want to have a .profile
that works under sh for GUI logins and to also use the same file for text mode logins, and you have zsh set as your login shell, then use the following line as your ~/.zprofile
:
emulate sh -c 'source ~/.profile'
If tmux is configured to run a login shell, then all tmux windows will override the surrounding environment instead of inheriting it. This means that if you define new variables outside of tmux, you'll still have them in the tmux session, but if you change the values of variables that are already defined then your changes will be lost inside tmux. All in all, tmux's default behavior doesn't make much sense. Avoiding this is the point of the set-option -g default-command $SHELL
line in ~/.tmux.conf
.
If you use tmux as a way to do a “fresh login”, you may prefer to have each window run in a fresh environment. If so, then you should probably clean up your environment with something like
set-option -g default-command env -i USER="$USER" LOGNAME="$LOGNAME" $SHELL
And remember that if your login shell is zsh then it reads .zprofile
, not .profile
.
Solution 2
You should remove your the set-option -g default-shell $SHELL
from .tmux.conf
; it's not necessary, because tmux
will use the SHELL
envvar by default.
This is what the manpage says:
default-shell path Specify the default shell. This is used as the login shell for new windows when the default-command option is set to empty, and must be the full path of the exe- cutable. When started tmux tries to set a default value from the first suitable of the SHELL environment vari- able, the shell returned by getpwuid(3), or /bin/sh. This option should be configured when tmux is used as a login shell.
tmux
will start a login shell (ie a shell that is sourcing ~/.profile
or ~/.zprofile
-- and ~/.zlogout
or ~/.bash_logout
before exiting) by default:
default-command shell-command Set the command used for new windows (if not specified when the window is created) to shell-command, which may be any sh(1) command. The default is an empty string, which instructs tmux to create a login shell using the value of the default-shell option.
See here for a discussion about this behavior -- which is quite surprising and different from that of screen
.
So, if you want tmux
to start a non-login shell using your default shell, put the following in your ~/.tmux.conf
:
set -g default-command $SHELL
and if you want it to run a login shell with another shell than your default one:
set -g default-command "/alternative/sh -l"
xji
Updated on September 18, 2022Comments
-
xji over 1 year
After reading multiple questions on this topic I still feel lost. I read suggestions that one should set the environment variables including
$PATH
in.profile
instead of specifically in.bashrc
or.zshrc
, and this is what I did.My default shell is
zsh
and I have setset-option -g default-shell $SHELL
intmux.conf
.However, now whenever I launch tmux sessions, it apparently doesn't pick up any modification to
$PATH
and only sources.zshrc
. My current workaround is to addsource ~/.profile
at the end of.zshrc
, which I don't think is the right thing to do.This post indicates that tmux/screen usually runs as subshells instead of login shells, and thus don't necessarily source
.profile
. However, another post claimed that if you can runlogout
in the shell, it is a login shell, which I was indeed able to. Many posts also claimed thattmux
should look for.bash_profile
plus.profile
, but would overlook.bashrc
, which is apparently not what happened in my case of the zsh equivalent.What is the best practice to use tmux with zsh and have it properly pick up environment variables, after all?
-
mosvy over 5 years
-
Gilles 'SO- stop being evil' over 5 yearsYes, that's a problem with tmux: it starts a login shell when it has no business to do so. The point of
set-option -g default-shell $SHELL
is precisely to avoid this. But with or without this option, it still inherits the environment variables that were set at login time (unless overridden by the tmux or shell initialization). -
Gilles 'SO- stop being evil' over 5 years@mosvy I don't see any statement in my answer that is not true. It was incomplete because I'd forgotten about this tmux behavior, but either way, it still runs an environment that's derived from the login-time environment.
-
mosvy over 5 years"Starting a new tmux session does not start a login shell: you're already logged in." -- that's not true, unless you want to redefine "login shell" to something else than the usual definition: "A login shell is one whose first character of argument zero is a
-
, or one started with the--login
option." -
mosvy over 5 yearsa) modern desktop environments can no longer be trusted to pass everything from
~/.profile
to subprocesses b) the OP didn't indicate that they logged out and then in from their session in order to test changes to~/.profile
. And, as you mentioned,zsh
may not source~/.profile
, but only~/.zprofile
-- that may cause another bout of confusion depending on wheretmux
was started from. -
xji over 5 yearsThanks. Apparently I didn't know the difference between
.zprofile
and.profile
and that caused my confusion.