Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I use linux, and I like to do all my command-line work within a single screen session, so that I can restart my graphical login and such without losing my terminals. However, when I log out and back into my graphical session, this changes all my session environment variables, such as DBus sessions. This means that after logging in again, my screen session now has the old (and wrong) environment variables. So now when I try to start graphical programs from my screen session, at best they emit a warning about not being able to connect to the session bus. At worst, they fail to start completely.

So, what I'm looking for is a way to modify environment variables in a running instance of screen, so that all subsequently-created screen windows will inherit the new environment variables. Is there a way to do this?

share|improve this question
2  
Aha! I just paged through the whole screen manpage to find this: setenv [var [string]] Set the environment variable var to value string. If only var is specified, the user will be prompted to enter a value. If no parameters are specified, the user will be prompted for both variable and value. The environment is inherited by all subsequently forked shells. –  Ryan Thompson Feb 9 '10 at 17:09
    
One can invoke setenv using -X switch to screen. Alas, it works only on all subsequently forked shells, not on the current shell. –  Boris Bukh Dec 7 '11 at 20:28
    
Note that byobu now incorporates a solution for this for both screen and tmux. –  Ryan Thompson Dec 15 at 22:28

2 Answers 2

You cannot start a shell script from the screen session since it would inherit the old environment. You can however us a fifo to get the new environment variables into the old screen session. You can fill that fifo when you start your graphical session.

#!/bin/bash
FIFO=/tmp/your_variables
[ -e $FIFO ] && cat $FIFO > /dev/null || mkfifo $FIFO

# save number of variables that follow
NVARS=2
echo $NVARS > $FIFO
echo ENV1=sth1 > $FIFO
echo ENV2=sth2 > $FIFO

Start that script in the background on login (it will only terminate when all variables are read from it).

Now you can read from the fifo, e.g. add this function to your .bashrc

update_session() {
  FIFO=/tmp/your_variables

  NVAR=$(cat $FIFO)
  for i in $(seq $NVAR); do
    export $(cat $FIFO)
  done
  #delete the pipe, or it will not work next time 
  rm $FIFO
}

so that you can in your old screen session

update_session
share|improve this answer
    
wouldn't you need to do this once per window in the running session to modify the window's main shell? –  quack quixote Feb 7 '10 at 22:22
    
Nice, though as ~quack says, you do need to update each shell independently. –  dmckee Feb 7 '10 at 22:28
    
Right, you need to do that in each shell in screen. AFAIK screen exposes no sockets or similar to communicate with running sessions from the outside. –  Benjamin Bannier Feb 8 '10 at 0:19
    
@dmckee but of course every new screen session already has the recent environment variables –  Benjamin Bannier Feb 8 '10 at 0:30
    
I've decided to just accept this answer for now. If I ever get around to actually implementing this, I'll update. But for now, it's enough just to have warm fuzzy feeling of knowing that it's theoretically possible. –  Ryan Thompson Mar 18 '10 at 18:07
up vote 2 down vote accepted

I have implemented a script to do this. You can get it here: https://github.com/DarwinAwardWinner/screen-sendenv

After putting screen-sendenv.py into your $PATH, you can use the following snippet in your .bashrc:

VARS_TO_UPDATE="DISPLAY DBUS_SESSION_BUS_ADDRESS SESSION_MANAGER GPG_AGENT_INFO"
screen_pushenv () {
  screen-sendenv.py -t screen $VARS_TO_UPDATE
}
tmux_pushenv () {
  screen-sendenv.py -t tmux $VARS_TO_UPDATE
}
screen_pullenv () {
  tempfile=$(mktemp -q) && {
    for var in $VARS_TO_UPDATE; do
      screen sh -c "echo export $var=\$$var >> \"$tempfile\""
    done
    . "$tempfile"
    rm -f "$tempfile"
  }
}
tmux_pullenv () {
  for var in $VARS_TO_UPDATE; do
    expr="$(tmux showenv | grep "^$var=")"
    if [ -n "$expr" ]; then
      export "$expr"
    fi
  done
}

To use it, just run screen_pushenv before you run screen -r to reattach to your screen session. Then, after attaching with screen -r, you can update the environment in your existing shells with screen_pullenv. The tmux functions accomplish the same thing for tmux, another terminal multiplexer similar to screen.

share|improve this answer
    
Wow Ryan, that is a lot of code. What was wrong with the previously accepted answer (it was inspiring at least)? –  Benjamin Bannier Jan 15 '12 at 17:34
    
Well, I discovered that screen (and also tmux) have a "setenv" command that sets an environment variable for screen itself, not the shell in the current window of screen. So that means that after you use my script, all newly-created windows in that screen session will automatically get the new environment, without having to run the update script in every one of them. Of course, an update script could still be useful for updating existing shells, but you have to rewrite it not to read from a FIFO, but to query the screen/tmux session itself for the new values. –  Ryan Thompson Jan 15 '12 at 20:22
    
You can see how to pull variables into the current shell from the screen/tmux session here, in the screen_update and tmux_update functions. I'll update my answer with a byobu-independent version of these. –  Ryan Thompson Jan 15 '12 at 20:25
1  
Anyway, to directly answer your question about what was wrong, your answer doesn't quite answer the question, but rather answers a related question. You show how to update environment variables inside a shell running inside a screen session, but not how to update environment variables in the screen session itself (such that newly-spawned windows inherit the new values). I accepted it at the time because it was still a good solution, but I had always intended to eventually implement a real answer to my question as asked. So, nothing personal. –  Ryan Thompson Jan 15 '12 at 20:43
    
Hey Ryan, thanks for answering. Now that you mentioned setenv I see how this is better. It wasn't obvious from the code you linked to. Thanks again! –  Benjamin Bannier Jan 15 '12 at 21:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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