Search code examples
environment-variablestmux

Why does tmux new-session propagate the value of PATH to the new session?


When running tmux new-session, a new tmux session is created, and depending on whether a server exists or not, the following happens:

  • if there's no server running, a new one gets created, and the session inherits the whole environment because it ends up in the global server environment
  • if there's already a server running, the session inherits the global environment of the server, plus a list of specific overrides that are set from the environment of the shell that called the tmux new-session command

The list of specific overrides for the second case can be defined using the update-environment option, which defaults to ["DISPLAY", "KRB5CCNAME", "SSH_ASKPASS", "SSH_AUTH_SOCK", "SSH_AGENT_PID", "SSH_CONNECTION", "WINDOWID", "XAUTHORITY"]

However, it seems that PATH is an exception, as it doesn't appear in the list above, but nevertheless gets propagated into the new session.

What's the reason of this behavior?

What I tried is export PATH=$PATH:/hello FOO=bar and then tmux new-session: the session had PATH containing :/hello at the end, but FOO wasn't set. The expected behavior would have been to have PATH set as the same value of the tmux global environment (which can be printed with tmux show-environment -g), rather than having the local override :/hello. FOO was not set, and that was the expected behavior.


Solution

  • According to comments in source code the behavior is intentional:

        /*
         * Then the PATH environment variable. The session one is replaced from
         * the client if there is one because otherwise running "tmux new
         * myprogram" wouldn't work if myprogram isn't in the session's path.
         */
        if (c != NULL && c->session == NULL) { /* only unattached clients */
            ee = environ_find(c->environ, "PATH");
            if (ee != NULL)
                environ_set(child, "PATH", 0, "%s", ee->value);
        }
        if (environ_find(child, "PATH") == NULL)
            environ_set(child, "PATH", 0, "%s", _PATH_DEFPATH);
    

    It makes sense to me since PATH is so essential and many other programs depend on it to work properly. If you need to pass other env vars you can use new-session -e FOO=bar ...