Обнаружение X-сессии в bash-скрипте (.bashrc и т. Д.)

16

Недавно я поставил xset b offна свой .bashrc. Теперь меня раздражает ошибка, возникающая при входе в систему через tty или через ssh, то есть вне сеанса X.

Первое, что мне пришло в голову, было [[ -z "$SOME_VAR" ]] && xset b off(ну, получается, что проверяемая переменная устанавливается против пустого - это другой вопрос). Но какой SOME_VAR является правильным?

Поэтому я просмотрел вывод tty и setвывод urxvt, setчтобы увидеть, какие переменные установлены в X и отсутствуют в tty. Как и ожидалось, было довольно много различий (перечисляя только те, которые мне показались актуальными):

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

Какой из них наиболее правильный и универсальный для тестирования, чтобы определить, нахожусь ли я в сеансе Х или нет? Что-то, что будет работать на максимально возможном количестве дистрибутивов, платформ и сред рабочего стола?

Или есть даже лучший способ, чем тестирование переменных среды?

Алоис Махдал
источник

Ответы:

8

Простой и эффективный способ проверить, что ваш сервер дисплея доступен и действителен, это проверить его xhost. Вы не всегда можете полагаться на проверку значения в DISPLAYпеременной, поскольку оно может быть установлено с недопустимым значением.

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

Причина, по которой я это делаю, заключается в том, что я запускаю несколько сценариев в моем пользователе, crontabкоторые работают на дисплее, когда он существует, но работают по-другому, когда нет. В верхней части моей crontabя установил DISPLAYпеременную, :0хотя она еще не существует. Сценарии, crontabкоторые начинаются с, @rebootбудут запускаться независимо от того, есть ли у вас дисплей или нет. Это позволит вам динамически определять, когда ваш дисплей приходит и уходит в пределах одного и того же сценария.

ПРИМЕЧАНИЕ: >&работает только в bash> = 4. В противном случае используйте> /dev/null 2>&1

cmevoli
источник
Хороший, проверенный также с ssh -X; работает отлично!
Алоис
13

Я думаю, что проверка DISPLAYбудет лучшим подходом.

  • Он обрабатывает удаленные логины (например, ssh -X).
  • Он доступен на большинстве - если не на всех - платформах.
  • Он не зависит от оконного менеджера / DE.
Ренан
источник
2
Я бы тоже пошел DISPLAYили просто подавил сообщение об ошибке вообще. Дарите /dev/nullвремя от времени немного любви.
frostschutz
3
@frostschutz Нет, я пытаюсь запустить только соответствующую часть скрипта. Подавление сообщений об ошибках не делает никаких шагов в этом направлении. На самом деле, это может привести к серьезной путанице в поиске и устранении других проблем, которые потенциально могут сломаться
Алоис Махдал
1
Я начал использовать этот подход вскоре после ответа, и он прекрасно работал с простыми sshs до тех пор, пока я не начал делать это ssh -X- чтобы иметь возможность использовать Vim поверх ssh, чтобы контент, выбранный в визуальном режиме, попадал в локальный буфер обмена X, для чего вам не нужен xserver на стороне сервера. Таким образом, DISPLAY устанавливается как эффект простого включения пересылки, даже если xserver и xset отсутствуют.
Алоис Махдал
Это было бы тогда:if [[ $DISPLAY ]]; then … fi
Серж
1
Ваша DISPLAYпеременная может указывать на экран, на котором на самом деле не запущен X-сервер (например, когда он жестко задан в скрипте или X-сервер был выключен после того, как была установлена ​​переменная).
n.st
6

Я обычно использую TERMпеременную для проверки X в моих скриптах.

TERMобычно устанавливается linuxна TTY и xtermна X. Здесь
я использую слово «обычно», поскольку такие приложения, как GNU Screen и TMux, похоже, путаются с TERMпеременной.

darnir
источник
Попробуй echo $TERMвыяснить настройку richt на своем компьютере в разных консолях. Я использую [ $TERM == "linux" ] && echo do some stuffна Ubuntu
rubo77
3

Это должно работать на отлично:

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

Итак, когда это оценивается как false ( [ ! -t 0 ]), мы находимся в среде графического интерфейса.

Тердон
источник
При этом я получаю одинаковый результат как в X, так и в консоли, а именно [ -t 0 ]и [ -t 1 ]оба являются истинными.
Эмануэль Берг
Странно, у меня это работает при подключении к удаленному хосту.
Terdon
[ -t 0 ]отлично работает на консоли в Ubuntu (с помощью CTRL ALT F1)
rubo77
0

Есть много способов сделать это.

В bash попробуй

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

Или в зш попробуйте

#!/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
Эмануэль Берг
источник
Точка занята, но проверяете ли вы свой код перед публикацией? Первый из них имеет синтаксическую ошибку и фактически не определяет, находимся ли мы в сеансе X, так будет, echo 1если X работает, и вы входите через tty1-6 или ssh. Другой всегда делает "не-X материал" - я думаю, что ${CURRENT_VT[6]}это скорее 6-я строка, чем 6-й символ
Алоис Махдал
@AloisMahdal: Ага, мои вещи не работают в bash (я использую zsh). Не думал об этом. Ну, вы можете попробовать это в zsh (type zsh) и, возможно, сделать некоторые изменения, если хотите, чтобы это работало в bash.
Эмануэль Берг
@AloisMahdal: Хорошо, я изменил это. Что касается «входа в систему через tty1-6», то, как это происходит, это то, что я делаю, а затем я использую второе решение (выше) и устанавливаю переменную. Проверьте это .zshrc и ищите export VT. Я использую переменную для хранения того, что у меня Linux VT / console / tty (для приглашения zsh), но в X я просто устанавливаю его в «X» (хотя и не в VT). Но это детали, вы можете решить это любым способом в bash, используя тот же принцип.
Эмануэль Берг
Я добавил версию условия bash для второго примера. Тем не менее, я думаю, что первый все еще не так. Может быть, поможет распечатать ps только предков . Я не уверен, если это возможно, хотя.
Алоис Махдал
@AloisMahdal: Проверьте редактирование. Это делает это для меня, включая tty.
Эмануэль Берг
0

if [[ $DISPLAY ]]

На том же компьютере $DISPLAYвернется, например, 0:0в эмуляторе терминала, но ничего в реальном терминале. Это можно легко проверить с CtrlAltF1против CtrlAltF7.

bashСостояние на основе $DISPLAYбудет выглядеть следующим образом :

if [[ $DISPLAY ]]; then 
  
fi
Серж Строобандт
источник