更新屏幕会话环境变量以反映新的图形登录?


20

我使用linux,并且我希望在一个屏幕会话中完成所有命令行工作,以便可以重新启动图形登录等而不会丢失终端。但是,当我注销并返回图形会话时,这会更改所有会话环境变量,例如DBus会话。这意味着,再次登录后,我的屏幕会话现在具有旧的(和错误的)环境变量。因此,现在当我尝试从屏幕会话中启动图形程序时,充其量它们会发出有关无法连接到会话总线的警告。最糟糕的是,它们无法完全启动。

因此,我正在寻找一种在正在运行的屏幕实例中修改环境变量的方法,以便所有随后创建的屏幕窗口都将继承新的环境变量。有没有办法做到这一点?


3
啊哈!我只是翻阅了整个屏幕的联机帮助页来找到它: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 C. Thompson

可以使用-X切换到屏幕来调用setenv。,,它仅适用于所有随后的分叉Shell,不适用于当前Shell。
鲍里斯·布赫

请注意,byobu现在为屏幕和tmux合并了解决方案。
瑞安·汤普森

Answers:


8

您无法从screen会话中启动Shell脚本,因为它将继承旧环境。但是,您可以使用fifo将新的环境变量添加到旧的屏幕会话中。您可以在开始图形会话时填充该fifo。

#!/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

登录时在后台启动该脚本(仅当从中读取所有变量时,该脚本才会终止)。

现在您可以阅读fifo了,例如,将此功能添加到您的 .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
}

这样您就可以在旧screen会话中

update_session

您是否不需要在运行的会话中为每个窗口执行一次此操作来修改窗口的主外壳?
quack quixote 2010年

很好,尽管正如〜quack所说,您确实需要独立更新每个shell。
dmckee'2

正确,您需要在中的每个shell中执行此操作screen。AFAIK screen没有暴露任何套接字或类似的东西来与外部运行的会话进行通信。
本杰明·班尼尔

@dmckee,但是当然每个 screen会话都已经具有最近的环境变量
Benjamin Bannier 2010年

我决定暂时只接受这个答案。如果我能够真正实现这一目标,我将进行更新。但是就目前而言,仅仅知道理论上是可能的就足以产生模糊的感觉。
瑞安·汤普森

2

我已经实现了一个脚本来做到这一点。您可以在这里获取它:https : //github.com/DarwinAwardWinner/screen-sendenv

把后screen-sendenv.py进入你的$PATH,你可以用下面的代码片段在你的.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
}

要使用它,只需screen_pushenv在运行screen -r以重新连接到屏幕会话之前先运行。然后,在附加后screen -r,可以使用来更新现有外壳中的环境screen_pullenv。tmux功能可以完成tmux的相同功能,tmux是类似于屏幕的另一个终端多路复用器。


哇,瑞恩,很多代码。先前接受的答案出了什么问题(至少在鼓舞人心)?
本杰明·班尼尔

1
好吧,我发现屏幕(还有tmux)都有一个“ setenv”命令,该命令为屏幕本身而不是当前屏幕窗口中的外壳设置环境变量。因此,这意味着您使用我的脚本后,该屏幕会话中所有新创建的窗口将自动获取新环境,而不必在每个窗口中都运行更新脚本。当然,更新脚本对于更新现有shell仍然有用,但是您必须重写它,而不是从FIFO中读取,而是向screen / tmux会话本身查询新值。
瑞安·汤普森

您可以在和函数中从此处查看如何从screen / tmux会话将变量拉入当前外壳。我将使用与byobu无关的版本来更新我的答案。screen_updatetmux_update
瑞安·汤普森

1
无论如何,要直接回答有关问题的问题,您的答案并不能完全回答问题,而是可以回答相关问题。您将展示如何更新在屏幕会话中运行的外壳程序内的环境变量,而不是如何在屏幕会话本身中更新环境变量(例如,新产生的窗口继承新值)。当时我接受了它,因为它仍然是一个很好的解决方案,但是我一直打算最终实现对所问问题的真正答案。因此,没有什么私人的。
瑞安·汤普森

嘿,瑞安,谢谢回答。既然您提到了,setenv我就知道这会更好。从链接到的代码来看,这不是很明显。再次感谢!
本杰明·班尼尔

2

您可以使用以下setenv命令来调用该命令以交互方式在屏幕处理中更改环境变量:Ctrl- A+ :setenv(请注意:输入屏幕命令的字符。)将提示您输入环境变量的名称和值。

请注意(根据其他答案/评论),这会影响(父)屏幕处理并因此影响新创建的屏幕会话,但不影响您当前的屏幕会话或任何现有的屏幕会话。

如果需要,可以同时指定环境变量的名称和值:Ctrl- A+ :setenv DISPLAY :100。将新屏幕会话的DISPLAY设置为“:100”。

要删除环境变量,可以使用'unsetenv'-例如Ctrl- A+:unsetenv DISPLAY


0

这可能是一个更简单的解决方案(您决定)。重要的部分是savedisplay每次screen运行命令时都会调用函数的别名。这些命令不会自动运行,因此可以~/.bashrc代替类似的非常专门的命令来放置~/.ssh/rc

savedisplay() {
    # Write latest bash display to a file, This is used to 
    # update running bash sessions for a "screen -r"
    echo "export DISPLAY=$DISPLAY" > ~/.XDISPLAY
    echo "export XAUTHORITY=$XAUTHORITY" >> ~/.XDISPLAY
    # This will only update the environment for new windows
    screen -X setenv DISPLAY $DISPLAY
    screen -X setenv XAUTHORITY $XAUTHORITY
}

# run this to update env variable in a running session
updatedisplay() {
    source ~/.XDISPLAY 
}

alias screen='savedisplay && screen'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.