Atualizando variáveis ​​de ambiente da sessão da tela para refletir o novo login gráfico?


20

Eu uso o linux e gosto de fazer todo o meu trabalho de linha de comando em uma única sessão de tela, para que eu possa reiniciar meu login gráfico e outros sem perder meus terminais. No entanto, quando eu saio e volto à minha sessão gráfica, isso altera todas as minhas variáveis ​​de ambiente da sessão, como sessões DBus. Isso significa que, após o login novamente, minha sessão de tela agora tem as variáveis ​​de ambiente antigas (e incorretas). Portanto, agora, quando tento iniciar programas gráficos a partir da minha sessão de tela, na melhor das hipóteses, eles emitem um aviso sobre a impossibilidade de conexão com o barramento de sessão. Na pior das hipóteses, eles não conseguem iniciar completamente.

Então, o que estou procurando é uma maneira de modificar variáveis ​​de ambiente em uma instância de tela em execução, para que todas as janelas de tela criadas posteriormente herdem as novas variáveis ​​de ambiente. Existe uma maneira de fazer isso?


3
Aha! Eu só folheou toda a manpage tela para encontrar este: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

Pode-se invocar o setenv usando a opção -X para a tela. Infelizmente, ele funciona apenas em todas as cascas subseqüentemente bifurcadas, não na casca atual.
Boris Bukh

Observe que o byobu agora incorpora uma solução para isso tanto para a tela quanto para o tmux.
Ryan C. Thompson

Respostas:


8

Você não pode iniciar um script de shell a partir da screensessão, pois herdaria o ambiente antigo. No entanto, você pode fazer um esforço para colocar as novas variáveis ​​de ambiente na sessão de tela antiga. Você pode preencher esse quinto ao iniciar sua sessão gráfica.

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

Inicie esse script em segundo plano no login (ele será encerrado somente quando todas as variáveis ​​forem lidas nele).

Agora você pode ler a partir do fifo, por exemplo, adicione esta função ao seu .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
}

para que você possa na sua screensessão antiga

update_session

você não precisaria fazer isso uma vez por janela na sessão em execução para modificar o shell principal da janela?
quack quixote

Bom, como o ~ quack diz, você precisa atualizar cada shell independentemente.
dmckee

Certo, você precisa fazer isso em cada shell screen. O AFAIK screennão expõe soquetes ou similares para se comunicar com as sessões em execução a partir do exterior.
Benjamin Bannier

@dmckee mas é claro que cada nova screen sessão já tem as variáveis de ambiente recentes
Benjamin Bannier

Decidi aceitar apenas esta resposta por enquanto. Se algum dia eu realmente implementar isso, atualizarei. Mas, por enquanto, basta apenas ter uma sensação confusa de saber que é teoricamente possível.
Ryan C. Thompson

2

Eu implementei um script para fazer isso. Você pode obtê-lo aqui: https://github.com/DarwinAwardWinner/screen-sendenv

Depois de colocar screen-sendenv.pyno seu $PATH, você pode usar o seguinte trecho no seu .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
}

Para usá-lo, basta executar screen_pushenvantes de executar screen -rpara reconectar à sua sessão de tela. Depois de se conectar screen -r, você pode atualizar o ambiente em seus shells existentes com screen_pullenv. As funções tmux realizam o mesmo para o tmux, outro multiplexador de terminal semelhante à tela.


Uau Ryan, isso é muito código. O que havia de errado com a resposta previamente aceita (pelo menos foi inspiradora)?
Benjamin Bannier

11
Bem, eu descobri que a tela (e também o tmux) tem um comando "setenv" que define uma variável de ambiente para a própria tela, não o shell na janela atual da tela. Portanto, isso significa que, depois de usar meu script, todas as janelas recém-criadas nessa sessão de tela obterão automaticamente o novo ambiente, sem a necessidade de executar o script de atualização em cada uma delas. Obviamente, um script de atualização ainda pode ser útil para atualizar os shells existentes, mas você deve reescrevê-lo para não ler em um FIFO, mas para consultar os próprios valores na sessão screen / tmux.
Ryan C. Thompson

Você pode ver como inserir variáveis ​​no shell atual da sessão screen / tmux aqui , nas funções screen_updatee tmux_update. Atualizarei minha resposta com uma versão independente do byobu.
Ryan C. Thompson

11
De qualquer forma, para responder diretamente à sua pergunta sobre o que estava errado, sua resposta não responde completamente à pergunta, mas responde a uma pergunta relacionada. Você mostra como atualizar variáveis ​​de ambiente dentro de um shell em execução em uma sessão de tela, mas não como atualizar variáveis ​​de ambiente na própria sessão de tela (de modo que as janelas criadas recentemente herdam os novos valores). Eu aceitei isso no momento porque ainda era uma boa solução, mas eu sempre tinha a intenção de , eventualmente, implementar uma verdadeira resposta para a minha pergunta como pediu . Então, nada pessoal.
Ryan C. Thompson

Hey Ryan, obrigado por responder. Agora que você mencionou setenv, vejo como isso é melhor. Não era óbvio no código ao qual você vinculou. Obrigado novamente!
Benjamin Bannier

2

Você pode chamar o setenvcomando para alterar as variáveis ​​de ambiente no processo de tela interativamente, usando: Ctrl- A+ :setenv(Observe o :caractere para inserir um comando de tela.) Você será solicitado a fornecer o nome e o valor da variável de ambiente.

Observe que (conforme outras respostas / comentários) isso afeta o processo de tela (principal) e, portanto, as sessões de tela recém-criadas, mas não a sessão de tela atual nem as sessões de tela existentes.

Você pode especificar o nome e o valor da variável de ambiente ao mesmo tempo, se desejar: Ctrl- A+ :setenv DISPLAY :100. Irá definir o DISPLAY para ": 100" para novas sessões de tela.

Para remover uma variável de ambiente, você pode usar 'unsetenv' - por exemplo, Ctrl- A+:unsetenv DISPLAY


0

Esta é provavelmente uma solução mais simples (você decide). A parte importante é o alias que chama a savedisplayfunção toda vez que o screencomando é executado. Os comandos não são executados automaticamente, portanto, podem ser inseridos em ~/.bashrcvez de algo muito especializado ~/.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'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.