Detectando a sessão do X em um script bash (.bashrc etc.)

16

Recentemente eu coloquei xset b offno meu .bashrc. Agora eu estou irritado com o erro que aparece quando eu faço logon via tty ou via ssh, ou seja, fora da sessão X.

A primeira coisa que me veio à mente foi [[ -z "$SOME_VAR" ]] && xset b off(bem, acontece que a variável de teste sendo definida versus vazia) é uma pergunta diferente). Mas qual SOME_VAR é o correto?

Então, diferenciei a setsaída de tty e a saída de urxvt setpara ver quais variáveis ​​são definidas em X e ausentes em tty. Como esperado, havia muitas diferenças (listando apenas as que me pareciam relevantes):

  • DESKTOP_SESSION
  • DISPLAY
  • GDMSESSION
  • SESSION_MANAGER
  • WINDOWID
  • WINDOWPATH
  • XAUTHORITY
  • XDG_SESSION_COOKIE
  • XDG_CONFIG_DIRS
  • XDG_DATA_DIRS
  • XDG_MENU_PREFIX

Qual é o mais correto e universal para testar, a fim de detectar se estou em uma sessão X ou não? Algo que funcionaria em tantas distros, plataformas e ambientes de desktop quanto possível?

Ou existe uma maneira ainda melhor do que testar variáveis ​​de ambiente?

Alois Mahdal
fonte

Respostas:

8

Uma maneira simples e eficaz de testar se o servidor de exibição está disponível e válido é testá-lo xhost. Você não pode sempre confiar na verificação de um valor na DISPLAYvariável, pois ela pode ser definida com um valor inválido.

if xhost >& /dev/null ; then echo "Display exists"
else echo "Display invalid" ; fi

O motivo para fazer isso é porque eu executo vários scripts no meu usuário crontabque operam no visor quando ele existe, mas funcionam de maneira diferente quando não. No topo da minha crontab, defino a DISPLAYvariável como :0mesmo que ela ainda não exista. Os scripts crontabque começam com @rebootiniciarão independentemente de você ter uma exibição ou não. Isso permitirá que você detecte dinamicamente quando sua exibição entra e sai no mesmo script.

NOTA: O >&único funciona em bash> = 4. Caso contrário, use> /dev/null 2>&1

cmevoli
fonte
Bom, testado também com ssh -X; funciona bem!
Alois Mahdal
13

Eu acho que a verificação DISPLAYseria a melhor abordagem.

  • Ele lida com logins remotos (por exemplo, ssh -X).
  • Está disponível na maioria das plataformas, se não em todas.
  • É independente do gerenciador de janelas / DE.
Renan
fonte
2
Eu também aceitaria DISPLAYou simplesmente suprimiria a mensagem de erro em geral. Dê um /dev/nullpouco de amor de vez em quando.
Frostschutz
3
@frostschutz Não, estou tentando executar apenas parte relevante do script. Suprimir mensagens de erro não dá nenhum passo nessa direção. De fato, isso pode levar a sérias confusões na solução de problemas de outras coisas que podem potencialmente quebrar.
Alois Mahdal
11
Comecei a usar essa abordagem logo após a resposta, e funcionava perfeitamente com sshs simples até agora, quando comecei a fazer ssh -X--- poder usar o Vim sobre ssh para que o conteúdo selecionado pelo modo visual chegue à área de transferência local X, para a qual você não precisa do xserver no lado do servidor. Portanto, o DISPLAY é definido da mesma maneira que simplesmente permite o encaminhamento, mesmo que xserver e xset não estejam presentes.
Alois Mahdal
Isso seria então:if [[ $DISPLAY ]]; then … fi
Serge Stroobandt 16/10
11
Sua DISPLAYvariável pode apontar para uma exibição que realmente não possui um servidor X em execução (por exemplo, quando é codificado em um script ou o servidor X foi desligado após a definição da variável).
n.st 16/05/19
6

Eu normalmente uso a TERMvariável para testar o X nos meus scripts.

TERMgeralmente é definido como linuxTTY e xtermX.
Eu uso a palavra "geralmente" aqui, pois aplicativos como GNU Screen e TMux parecem mexer com a TERMvariável.

darnir
fonte
tente echo $TERMdescobrir a configuração rica em seu mashine em diferentes consoles. Eu uso [ $TERM == "linux" ] && echo do some stuffno Ubuntu
rubo77
3

Isso deve funcionar perfeitamente bem:

[ ! -t 0 ] && xset b off                                  

http://tldp.org/LDP/abs/html/fto.html

-t

    file (descriptor) is associated with a terminal device

    This test option may be used to check whether the stdin [ -t 0 ] 
    or stdout [ -t 1 ] in a given script is a terminal.

Portanto, quando isso é avaliado como false ( [ ! -t 0 ]), estamos em um ambiente de GUI.

terdon
fonte
Com isso, obtenho o mesmo resultado no X e no console, ou seja, [ -t 0 ]e [ -t 1 ]ambos são verdadeiros.
Emanuel Berg
Estranho, ele funciona para mim quando sshing em um host remoto.
terdon
[ -t 0 ]funciona bem no console no Ubuntu (usando CTRL ALT F1)
rubo77
0

Existem várias maneiras de fazer isso.

No bash, tente

function xruns {
    if [[ `pstree -As $$ | grep xinit | wc -l` == 1 ]]; then
        echo "You are in X."
    else
        echo "You are not in X."
    fi
}

Ou, no zsh, tente

#!/usr/bin/zsh

CURRENT_VT=`tty`

if [[ ${CURRENT_VT[6]} == "p" ]];        # or `${CURRENT_VT:5:1}` in bash
then
   # X stuff
else 
   # non-X stuff      
fi
Emanuel Berg
fonte
Ponto em questão, mas você testa seu código antes de postar? O primeiro possui um erro de sintaxe e, na verdade, não detecta se estamos na sessão do X, o que ocorrerá echo 1se o X estiver em execução e você fizer login via tty1-6 ou ssh. O outro sempre faz "coisas não-X" - acho que isso ${CURRENT_VT[6]}significa 6ª linha do que 6ª char.
Alois Mahdal
@AloisMahdal: Aha, minhas coisas não funcionam no bash (eu uso o zsh). Não pensei nisso. Bem, você pode experimentá-lo no zsh (tipo zsh) e possivelmente fazer algumas modificações, se quiser, para fazê-lo funcionar no bash.
Emanuel Berg
@AloisMahdal: OK, eu mudei. Quanto ao "logon via tty1-6", por acaso, é isso que eu faço, e então uso a segunda solução (acima) e defino uma variável. Confira isso .zshrc e procure export VT. Eu uso a variável para armazenar em que Linux VT / console / tty eu estou (para o prompt zsh), mas no X, apenas a defino como "X" (embora não seja um VT). Mas isso é detalhes, você pode trabalhar da maneira que quiser no bash usando o mesmo princípio.
Emanuel Berg
Eu adicionei a versão bash da condição ao segundo exemplo. No entanto, acho que o primeiro ainda está errado. Talvez ter ps imprimindo apenas ancestrais ajudaria. Não tenho certeza se é possível, no entanto.
Alois Mahdal
@AloisMahdal: Confira a edição. Faz isso por mim, incluindo as coisas tty.
Emanuel Berg
0

if [[ $DISPLAY ]]

No mesmo computador, $DISPLAYretornará, por exemplo, 0:0em um emulador de terminal, mas nada em um terminal real. Isso pode ser facilmente testado com CtrlAltF1versus CtrlAltF7.

Uma bashcondição baseada $DISPLAYseria da seguinte maneira:

if [[ $DISPLAY ]]; then 
  
fi
Serge Stroobandt
fonte