Is there a way to have GNU Screen detect when it is being attached and to execute a shell script that I have whenever it is attached? The reason for this is that I want to keep my display variables correct for X11 forwarding, but I need to detect when screen reattached to a different computer to trigger my script.



You can run screen -S foo -X setenv DISPLAY "$DISPLAY"; screen -S foo -rd to change the environment of the screen process before attaching. This won't affect existing windows.

You can perhaps configure your shell to check for an updated DISPLAY (and any other relevant variable such as XAUTHORITY) each time they show a prompt. (This means you may have to press Enter once if the shell was sitting at a prompt when you attached the session.) Bash evaluates $PROMPT_COMMAND before displaying each prompt. Zsh runs the precmd function before displaying each prompt. For example, if you've put the desired environment assignments in a script ~/var/run/screen-12345.foo.env-update.sh (where 12345 is the pid of the screen process and foo is the session name), you can use something like (for zsh, untested; I don't think you'll be able to get away without forking in bash):

precmd () {
  local now=$SECONDS
  set ~/var/run/"screen-$STY.env-update.sh"(Nms-$(($now-$screen_env_time)))
  if [[ $# -ne 0 ]]; then
    . ~/var/run/"screen-$STY.env-update.sh"

Another thing you could do from $PROMPT_COMMAND or precmd, on some operating systems, is read the environment of the parent process (this assumes you have updated the environment of the screen process). For example, on Linux with zsh (do this only if running under screen):

precmd () {
  local record
  while read -r -d $'\0' record /proc/$PPID/environ; do
    case ${record%%=*} in
      DISPLAY|XAUHORITY) export $record;;

Technically, you can change the environment of another process, using a debugger. But there's a good chance that it'll crash that process, because the program's internal data structures won't match with the data kept by the kernel.

Note that none of these solutions will do any good if you run ssh inside a screen window.


What you eventually want can't be done. Even if you manage to get screen to run a script on connect, it still won't be able to change the environment of the child processes.

  • right now I have it exporting the environmental variable to a temp file. The temp file currently contains the value that I want. So once I connect I run: export DISPLAY=cat /tmp/screen_variable it's all good. I just want to automate that. – Sandro Oct 29 '10 at 2:30

I think Giles' solution is the most general one, but it has two drawbacks: (1) it doesn't work until after you have run a command, after the re-attach, and (2) the command is executed at every new command prompt. (What can I say, I hate wasting CPU cycles). There is an alternative, but it's also not perfect: When screen reattaches to a terminal of a different size than the previous window, screen sends the SIGWINCH signal to the shell, which you can trap:

trap some_function SIGWINCH

I've written a shell script (to be sourced along with .bashrc) which exploits this fact to handle rewriting the SSH_AUTH_SOCK and related variables when re-attaching a detached terminal. See the project here: https://gitlab.com/otheus.uibk/bashrc-ssh-agent . The script can be easily modified to also be integrated with the PROMPT_COMMAND.

Maybe we can update screen with an option to force SIGWINCH upon reattach? I am currently using 4.1.0 (shipped with RedHat 7) but current version is 4.6.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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