Wykrywanie sesji X w skrypcie bash (.bashrc itp.)

16

Ostatnio umieściłem xset b offna swoim .bashrc. Teraz denerwuje mnie błąd, który pojawia się, gdy loguję się przez tty lub ssh, tj. Poza sesją X.

Pierwszą rzeczą, jaka przyszła mi do głowy, było [[ -z "$SOME_VAR" ]] && xset b off(cóż, okazuje się, że ustawienie zmiennej testowej vs. bycie pustym to inne pytanie). Ale który SOME_VAR jest poprawny?

Więc różnicowałem setdane wyjściowe tty i dane wyjściowe urxvt, setaby zobaczyć, które zmienne są ustawione w X, a których brakuje w tty. Zgodnie z oczekiwaniami było całkiem sporo różnic (wymieniając tylko te, które wydawały mi się istotne):

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

Który z nich jest najbardziej poprawny i uniwersalny do przetestowania w celu wykrycia, czy jestem w sesji X, czy nie? Coś, co działałoby na wielu dystrybucjach, platformach i środowiskach desktopowych, jak to możliwe?

Czy jest jeszcze lepszy sposób niż testowanie zmiennych środowiskowych?

Alois Mahdal
źródło

Odpowiedzi:

8

Prostym i skutecznym sposobem sprawdzenia, czy serwer wyświetlania jest dostępny i prawidłowy, jest przetestowanie go xhost . Nie zawsze można polegać na sprawdzeniu wartości w DISPLAYzmiennej, ponieważ można ją ustawić z niepoprawną wartością.

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

Powodem tego jest to, że uruchamiam w skrypcie kilka skryptów, crontabktóre działają na ekranie, gdy istnieje, ale działają inaczej, gdy nie są. Na górze crontabustawiam DISPLAYzmienną na, :0nawet jeśli jeszcze nie istnieje. Skrypty crontabzaczynające się od @rebootzaczynają się bez względu na to, czy masz wyświetlacz, czy nie. Umożliwi to dynamiczne wykrywanie, kiedy ekran pojawia się i przechodzi w ramach tego samego skryptu.

UWAGA: >&działa tylko w bash> = 4. W przeciwnym razie użyj> /dev/null 2>&1

cmevoli
źródło
Ładne, przetestowane również z ssh -X; działa w porządku!
Alois Mahdal
13

Myślę, że sprawdzanie DISPLAYbyłoby najlepszym podejściem.

  • Obsługuje zdalne logowanie (np. Ssh -X).
  • Jest dostępny na większości - jeśli nie na wszystkich - platformach.
  • Jest niezależny od menedżera okien / DE.
Renan
źródło
2
Postanowiłbym też DISPLAYpo prostu ogólnie usunąć komunikat o błędzie. /dev/nullOd czasu do czasu daj trochę miłości.
frostschutz
3
@frostschutz Nie, próbuję uruchomić tylko odpowiednią część skryptu. Pomijanie komunikatów o błędach nie czyni żadnego kroku w tym kierunku. W rzeczywistości może to prowadzić do poważnych nieporozumień podczas rozwiązywania innych problemów , które mogą się zepsuć.
Alois Mahdal
1
Zacząłem używać tego podejścia wkrótce po odpowiedzi, i działało ono idealnie z prostymi sshs do tej pory, kiedy zacząłem robić ssh -X--- możliwość używania Vima przez ssh, aby zawartość wybrana przez tryb wizualny trafiła do lokalnego schowka X, dla którego nie potrzebujesz Xserver po stronie serwera. Tak więc DISPLAY zostaje ustawiony tak samo, jak proste włączenie przekazywania, nawet jeśli xserver i xset nie są obecne.
Alois Mahdal
To byłoby wtedy:if [[ $DISPLAY ]]; then … fi
Serge Stroobandt
1
Twoja DISPLAYzmienna może wskazywać na ekran, który tak naprawdę nie ma uruchomionego serwera X (na przykład, gdy jest on zakodowany na stałe w skrypcie lub serwer X został zamknięty po ustawieniu zmiennej).
n
6

Zwykle używam TERMzmiennej do testowania X w moich skryptach.

TERMjest zwykle ustawiony linuxna TTY i xtermX.
Używam tutaj słowa „zwykle”, ponieważ aplikacje takie jak GNU Screen i TMux wydają się zadzierać ze TERMZmienną.

darnir
źródło
spróbuj echo $TERMznaleźć bogate ustawienia na swoim komputerze w różnych konsolach. Używam [ $TERM == "linux" ] && echo do some stuffna Ubuntu
rubo77
3

Powinno to działać idealnie dobrze:

[ ! -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.

Tak więc, kiedy to zmienia się na false ( [ ! -t 0 ]), jesteśmy w środowisku GUI.

terdon
źródło
Dzięki temu otrzymuję ten sam wynik zarówno w X, jak i w konsoli, a mianowicie [ -t 0 ]i [ -t 1 ]oba są prawdziwe.
Emanuel Berg
Dziwne, działa dla mnie, gdy sshing do zdalnego hosta.
terdon
[ -t 0 ]działa dobrze na konsoli w Ubuntu (używając CTRL ALT F1)
rubo77
0

Można to zrobić na wiele sposobów.

W bash spróbuj

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

Lub, w Zsh, spróbuj

#!/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
źródło
Punkt wzięty, ale czy testujesz swój kod przed opublikowaniem? Pierwszy z nich ma błąd składniowy i nie wykrywa, czy jesteśmy w sesji X, więc zrobi to, echo 1jeśli X jest uruchomiony i logujesz się przez tty1-6 lub ssh. Drugi zawsze robi rzeczy inne niż X - myślę, że ${CURRENT_VT[6]}oznacza to raczej szóstą linię niż szósty znak.
Alois Mahdal
@AloisMahdal: Aha, moje rzeczy nie działają w bash (używam zsh). Nie myślałem o tym. Cóż, możesz spróbować w zsh (type zsh) i ewentualnie wprowadzić pewne modyfikacje, jeśli ci się spodoba, aby działał w bash.
Emanuel Berg
@AloisMahdal: OK, zmieniłem to. Jeśli chodzi o „logowanie przez tty1-6”, tak się dzieje, to właśnie robię, a następnie używam drugiego rozwiązania (powyżej) i ustawiam zmienną. Sprawdź to .zshrc i wyszukaj export VT. Używam tej zmiennej do przechowywania tego, w czym jestem Linux VT / console / tty (dla zachęty zsh), ale w X po prostu ustawiłem ją na „X” (chociaż nie VT). Ale to są szczegóły, możesz to wypracować w dowolny sposób, używając tej samej zasady.
Emanuel Berg
Dodałem wersję warunkową warunku do drugiego przykładu. Myślę jednak, że pierwszy jest nadal błędny. Może pomogłoby posiadanie ps print tylko przodków . Nie jestem jednak pewien, czy to możliwe.
Alois Mahdal
@AloisMahdal: Sprawdź edycję. To wszystko dla mnie, w tym tty.
Emanuel Berg
0

if [[ $DISPLAY ]]

Na tym samym komputerze $DISPLAYpowróci na przykład 0:0w emulatorze terminala, ale nic w prawdziwym terminalu. Można to łatwo przetestować za pomocą CtrlAltF1versus CtrlAltF7.

bashWarunek na podstawie $DISPLAYwyglądałby następująco:

if [[ $DISPLAY ]]; then 
  
fi
Serge Stroobandt
źródło