Environment Variables and GNU Screen
I am an avid user of GNU screen. However, one problem I’ve run into lately in Ubuntu involves the interaction of persistent screen sessions and less-than-persistent X sessions. I’ve found that after starting a new X session, new environment variables are set (such as DISPLAY, SSH_AGENT_PID, and SSH_AUTH_SOCK). This causes an incosistency between my X session’s variables and those that exist in my persistent screen session. This post discusses my solution to this issue.
I’m currently running the currently unreleased Ubuntu Jaunty on virtually all of my machines. At times, such as when resuming my notebook, I find that my X session has died. This is not that much of an inconvenience for me—I do most of my work within a screen session that exists as long as the machine stays running, regardless of what X decides to do. However, services such as ssh-agent must be restarted when creating a new X session and along with this restart comes a new set values for SSH_AGENT_PID and SSH_AUTH_SOCK. In addition, it is possible that DISPLAY may change as well.
While these variables have changed, the screen sessions values have not been updated. So when I re-attach to the running screen session and attempt to use ssh, I find that rather than using the running ssh-agent process to cache my passphrase, I am prompted in my terminal to enter the passphrase. If I were able to use the updated environment variables I could use the ssh-agent process and all would be fine.
As I normally do, I googled for this issue and ran across this solution to the problem. Rather than reiterate the details presented in this post, I simply show the two zsh functions I’ve written, as they differ sightly from the afore mentioned post:
grabvars() { VARS="SSH_AGENT_PID SSH_AUTH_SOCK DISPLAY" #For each variable in $VARS for x in $(echo $VARS) ; do eval echo $x=\$$x | sed 's/=/="/ s/$/"/ s/^/export /' done 1>$VARSLOC } sourcevars() { if [[ -f $VARSLOC ]]; then source $VARSLOC fi }
Note that VARSLOC names the file that the export statements should be written to.
How do I use these two functions? sourcevars is called every time a new shell is created (I’ve simply added a call to this function in ~/.zshrc). grabvars is only called when I create or attach to a screen session, so I’ve aliased ‘screen’ to be ‘grabvars; screen’. So now when I first login and create a new terminal, this terminal has the updated environment vars. I do a ‘screen -DR session_name’ to attach, which then calls grabvars, the correct values are written to VARSLOC, and my screen session is attached. If I create a new window in my screen session, the correct variables are now set. If I want the updated variables in an exsiting window, I simply call ‘sourcevars’.

Hey, thanks for the solution. This was bugging me (my X sessions don’t last long because I have numerous users on this computer, but I want my screen(1) sessions to last as close to forever as possible).
Here’s a slightly more compact version that uses more zsh powerz:
grabvars()
{
for x in SSH_AGENT_PID SSH_AUTH_SOCK DISPLAY; do
echo “export $x=’${(P)x:q}’”
done >$VARSLOC
}
sourcevars()
{
[ -f $VARSLOC ] && source $VARSLOC
}
The differences are:
1) I inlined the variable names inside the loop. I didn’t need the temporary “$VARS” variable, but if I did I would use an array (“VARS=(SSH_AGENT_PID SSH_AUTH_SOCK DISPLAY)”) instead of a string so I could save the “$(echo …)” part.
2) I used a single echo—no point in creating then parsing the string again. Zsh’s smart (P) Expansion Flag does exactly what we want.
3) Just for completeness I threw in the ‘q’ Parameter Expansion flag so that it would escape a theoretical space/quote/etc.
4) No need to say “1>”, since 1 is STDOUT, and that’s the default for “>”.
5) Used the more idiomatic “[ -f ... ] && ____” form.
Just some thoughts—Really I’m only tinkering for the fun of it. The overall solution is a smart one, and I wasn’t thinking of it on my own.
Thank you.
-rjk
Thanks for the improvements! I actually don’t rely on this nearly as much as I used to (I recently switched to a Mac). However, I’m still rocking zsh and have the version I posted in my .zshrc. I’ll update my config. Thanks again!