Gnu Screen:附加时执行命令

Gnu Screen:附加时执行命令

有没有办法让 GNU Screen 检测何时连接并在连接时执行我拥有的 shell 脚本?这样做的原因是我想保持显示变量正确以进行 X11 转发,但我需要检测屏幕何时重新连接到另一台计算机以触发我的脚本。

谢谢。

答案1

您可以在附加之前运行screen -S foo -X setenv DISPLAY "$DISPLAY"; screen -S foo -rd以更改进程的环境screen。这不会影响现有窗口。

您或许可以将 shell 配置为在每次显示提示时检查更新DISPLAY(以及任何其他相关变量,例如)。(这意味着,如果 shell 在连接会话时处于提示符下,则可能必须按一次。)Bash在显示每个提示之前进行评估。Zsh 在显示每个提示之前运行该函数。例如,如果您已将所需的环境分配放在脚本中(其中 12345 是屏幕进程的 pid,是会话名称),则可以使用类似(对于 zsh,未经测试;我认为您无法在 bash 中不使用分叉):XAUTHORITYEnter$PROMPT_COMMANDprecmd~/var/run/screen-12345.foo.env-update.shfoo

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

在某些操作系统上,您可以从$PROMPT_COMMAND或执行的另一件事precmd是读取父进程的环境(这假设您已经更新了 screen 进程的环境)。例如,在 Linux 上使用 zsh(仅在 screen 下运行时执行此操作):

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

从技术上讲,你可以使用调试器来改变另一个进程的环境。但很有可能会导致该进程崩溃,因为该程序的内部数据结构与内核保存的数据不匹配。

请注意,如果您在屏幕窗口内运行 ssh,这些解决方案都无济于事。

答案2

您最终想要的无法实现。即使您设法让 screen 在 connect 上运行脚本,它仍然无法更改子进程的环境。

答案3

我认为 Giles 的解决方案是最通用的,但它有两个缺点:(1)它只有在您运行命令之后,重新连接之后才有效,并且(2)该命令在每个新的命令提示符下执行。(我能说什么呢,我讨厌浪费 CPU 周期)。还有一种替代方法,但它也不完美:当screen重新连接到与前一个窗口大小不同的终端时,screenSIGWINCH信号发送到 shell,您可以捕获该信号:

trap some_function SIGWINCH

我编写了一个 shell 脚本(与 .bashrc 一起提供),利用这一事实来处理在重新连接分离的终端时重写 SSH_AUTH_SOCK 和相关变量。在此处查看项目:https://gitlab.com/otheus.uibk/bashrc-ssh-agent。该脚本可以轻松修改,以便与 PROMPT_COMMAND 集成。

也许我们可以更新screen一个选项,在重新连接时强制使用 SIGWINCH?我目前正在使用 4.1.0(随 RedHat 7 一起提供),但当前版本是 4.6。

相关内容