TMUX setting environment variables for sessions

Viewed 39427

I work in a situation where I have multiple projects and within each are many scripts that make use of environment variables set to values specific to that project.

What i'd like to do is use a separate tmux session for each project and set the variables so that they are set for all windows in that session.

I tried to use the set-environment option which works using the -g option but then sets the variable for all sessions connected to that server.

Without the -g option I see its set when using show-environment but can't access the variable in the shell.

Has anyone come up with a way of fixing this?

Using tmux 1.8 and tcsh

7 Answers

Version 3.2 of tmux will support a -e option for the new-session command for altering the local environment directly.

In the mean time, you can use this to run a new tmux session with a particular environment available and up to date (or one of the other solutions mentioned):

tmux new-session 'export MY_VAR=value; exec bash'

The problem with tmux is that when you first run it, the tmux server is created and it inherits the environment that is available at this time of creation. This is called the global environment. When you run tmux again and create a new session, the tmux server still holds its copy of the environment. But this copy is the "old" environment that the server learned about when it was created, i.e. the global environment.

About the tmux commands that work with the tmux environment:

  • set update-environment MY_VAR: this will tell tmux to take the MY_VAR variable from the global environment and make it a session environment, i.e. a local environment (listed by the show-environment command). Then, the session will be able to change the value of this variable without affecting the global environment.
  • set-environment MY_VAR value: This will create (or change) a variable in the local environment of the session.
  • set-environment -g MY_VAR value: This will create (or change) a variable in the global environment.

Also, note that when you run tmux and tmux calls bash (or another shell), bash will have a copy of the server's (global) environment. Even if you change an environment variable before calling tmux, creating a new session will be oblivious of the changes. If you add a tmux command in a conf file and run tmux e.g. with tmux source-file tmux-session.conf, any variable you mention in the conf will be evaluated in the context of the global environments the tmux server knows about and not the in the context from where you run the tmux command. So, in order to make a new session see the new value of the variable, you have to call tmux in a way that passes the new value of the env variable directly to it. This is what the solutions here try to do. This is also what the new -e option will allow you to do.

I approached this a little differently, assuming I had separate initialization scripts for each environment.

Using tmux v3.0a.

The spec:

  1. When I invoke tmux I want it to load up a specific environment for that session.
  2. For each window within the tmux session I want that same environment session replicated.
  3. I also want to be able to invoke subsequent tmux sessions with different environments and each window invocation should load that environment. (just like the first session) And subsequent sessions should not interfere with prior sessions.
  4. I have shell scripts to initialize each of my environments.

So how can I associate a shell script with a session and have all window invocations use that shell script?

Simple Solution:

Found a simple solution here: How to start two tmux sessions with different environments?

With my original solution I ran into an issue with the tmux global environment. When I ran multiple sessions, whichever one ran first set the global environment. Then I would need to close other tmux sessions before I ran new sessions.

A better solution is to set up a separate tmux server for each environment.

Use the -L flag to tmux from within a shell that already has the environment defined you want.

Shell environment A: tmux -L environA

Shell environment B: tmux -L environB

Name your environments any way you want. Set up some aliases for each environment? Or you can test environment variables to determine which tmux server you want to use. Each tmux named server will keep its environment separate.

Then there is no need to set bash startup files, etc. as I had described in my original solution.

Example

In my case I'm starting a tmux session per project within a bash script and I needed to activate a relevant virtual environment for that session, including any newly opened tabs. To do so, I added the following virtual environment activation code to the ~/.bashrc:

if [ -n "$VIRTUAL_ENV" ]; then
    source $VIRTUAL_ENV/bin/activate;
fi

However if I need to set foo environment for Session_1 and bar environment for Session_2, the VIRTUAL_ENV variable is globally set to bar after creating Session_2, so any newly opened tabs in Session_1 erroneously ends up in bar environment.

Solution

original HOWTO (commit).

  1. Add the following in your ~/.profile (or ~/.bashrc):
# For Tmux VirtualEnv support
tmux_get_var(){
    local key=$1
    [[ -n "$TMUX" ]] && tmux showenv | awk -F= -v key="$key" '$1==key {print $2}'
}

# activate the virtual environment if it is declared
venv=$(tmux_get_var "VIRTUAL_ENV")
if [ -n "$venv" ]; then
    source $venv/bin/activate;
fi
  1. Set the VIRTUAL_ENV variable for the target session:
tmux setenv -t ${SESSION_NAME} 'VIRTUAL_ENV' /path/to/virtualenv/

Setting it for current session is quite easy: Ctr-b: to open tmux command prompt and enter setenv FOO foo. This will not apply for existing windows -- but there you can use export $(tmux show-env FOO).

For new sessions this pattern might be useful:

  1. tmux new -s session
  2. Ctr-b : set-env FOO foo -- set FOO=foo for the session
  3. Ctr-b c -- create new, second window ($FOO is set here)
  4. Ctr-b l -- go to old, first window
  5. exit the first window
  6. all windows now have FOO=foo

Tested with Tmux 1.8.

Related