Откройте окно на удаленном дисплее X (почему «Не удается открыть дисплей»)?

81

Давным-давно,

DISPLAY=:0.0 totem /path/to/movie.avi

после того, как ssh вошел в мой рабочий стол с моего ноутбука, тотем играл movie.aviна моем рабочем столе.

Теперь выдает ошибку:

No protocol specified
Cannot open display:

Я переустановил Debian squeeze, когда он стал стабильным на обоих компьютерах, и, думаю, я сломал конфиг.

Я погуглил по этому вопросу и не могу понять, что я должен делать.

(VLC имеет HTTP-интерфейс, который работает, но он не так удобен, как ssh.)

Та же проблема возникает, когда я пытаюсь запустить это из задания cron.

Джастин Кресс
источник
1
Ваш удаленный компьютер показывает файл .Xauthority? Другой очевидный вопрос - настроены ли ваш ssh-сервер и клиент для переадресации X? Какую команду вы использовали для SSH?
Фахим Митха
1
я пытаюсь переслать X? Я хочу, чтобы команда выполнялась на хосте, а не на клиенте. Моя команда ssh просто ssh me @ host locate. Xauthority на хост-компьютере не соответствует ни одному файлу.
Джастин Кресс
Как предполагает Фахим, есть хорошее изменение в том, что ваша проблема связана с тем, что вы totemне нашли свой X cookie, и вам нужно установить XAUTHORITYправильное значение, то есть значение в вашей обычной сессии на рабочем столе. Прочитайте Linux: wmctrl не может открыть дисплей, когда сеанс инициируется через ssh + screen для некоторого фона; см. также соответствующий ответ. Как пользователь root может запустить графическую программу на рабочем столе другого пользователя? ,
Жиль
1
хорошо, физически сидя за компьютером и печатая echo $ XAUTHORITY дает / var / run / gdm3 / auth-for-jcress-bb32gX / database в сеансе ssh, ввод echo $ DISPLAY = (путь выше) не решает проблему
Джастин Кресс
1
Я виню GDM3, почему они не могли бы просто держали $XAUTHORITYна ~/.Xauthorityкак все ожидают , что это будет.
Arrowmaster

Ответы:

78

(Адаптировано из Linux: wmctrl не может открыть дисплей, когда сеанс инициируется через ssh + screen )

ОТОБРАЖЕНИЕ и ВЛАСТЬ

Программе X требуется две части информации для подключения к дисплею X.

  • Требуется адрес дисплея, который обычно отображается :0при локальном входе в систему или :10, :11и т. Д. При удаленном входе в систему (но число может меняться в зависимости от того, сколько активных X-соединений). Адрес дисплея обычно указывается в DISPLAYпеременной окружения.

  • Требуется пароль для отображения. Пароли X-дисплея называются волшебными куки . Магические куки не указываются напрямую: они всегда хранятся в X авторитетных файлах, которые представляют собой набор записей вида «на дисплее :42есть куки 123456». Файл полномочий X обычно указывается в XAUTHORITYпеременной среды. Если $XAUTHORITYне установлено, программы используют ~/.Xauthority.

Вы пытаетесь воздействовать на окна, которые отображаются на вашем рабочем столе. Если вы единственный пользователь, использующий ваш настольный компьютер, вполне вероятно, что отображаемое имя - :0. Найти местоположение авторитетного файла X сложнее, потому что с gdm, настроенным в Debian squeeze или Ubuntu 10.04, он находится в файле со случайно сгенерированным именем. (У вас не было проблем раньше, потому что в более ранних версиях gdm использовались настройки по умолчанию, то есть файлы cookie, хранящиеся в ~/.Xauthority.)

Получение значений переменных

Вот несколько способов получить значения DISPLAYи XAUTHORITY:

  • Вы можете систематически запускать сеанс экрана со своего рабочего стола, возможно, автоматически в сценариях входа в систему (из ~/.profile; но делать это только при входе в систему под X: test if DISPLAYимеет значение, начинающееся с :(которое должно охватывать все вероятные случаи) встретить)). В ~/.profile:

    case $DISPLAY in
      :*) screen -S local -d -m;;
    esac
    

    Затем в сеансе SSH:

    screen -d -r local
    
  • Вы также можете сохранить значения DISPLAYи XAUTHORITYв файле и вызвать их. В ~/.profile:

    case $DISPLAY in
      :*) export | grep -E '(^| )(DISPLAY|XAUTHORITY)=' >~/.local-display-setup.sh;;
    esac
    

    В сеансе SSH:

    . ~/.local-display-setup.sh
    screen
    
  • Вы можете обнаружить значения DISPLAYи XAUTHORITYиз запущенного процесса. Это сложнее автоматизировать. Вы должны выяснить PID процесса, который подключен к дисплею, с которым вы хотите работать, а затем получить переменные среды из /proc/$pid/environ( eval export $(</proc/$pid/environ tr \\0 \\n | grep -E '^(DISPLAY|XAUTHORITY)=')¹).

Копирование куки

Другой подход (следуя предложению Arrowmaster ) состоит в том, чтобы не пытаться получить значение $XAUTHORITYв сеансе ssh, а вместо этого заставить сеанс X копировать свои куки в ~/.Xauthority. Поскольку файлы cookie генерируются каждый раз при входе в систему, это не проблема, если вы сохраняете устаревшие значения ~/.Xauthority.

Может быть проблема безопасности, если ваш домашний каталог доступен через NFS или другую сетевую файловую систему, что позволяет удаленным администраторам просматривать его содержимое. Им все равно нужно каким-то образом подключаться к вашей машине, если вы не включили X TCP-соединения (по умолчанию в Debian они отключены). Таким образом, для большинства людей это либо не применяется (без NFS), либо не является проблемой (без подключений X TCP).

Чтобы скопировать файлы cookie при входе в сеанс X рабочего стола, добавьте следующие строки в ~/.xprofileили ~/.profile(или другой сценарий, который читается при входе в систему):

case $DISPLAY:$XAUTHORITY in
  :*:?*)
    # DISPLAY is set and points to a local display, and XAUTHORITY is
    # set, so merge the contents of `$XAUTHORITY` into ~/.Xauthority.
    XAUTHORITY=~/.Xauthority xauth merge "$XAUTHORITY";;
esac

¹ В принципе это не хватает собственно цитирования, но в данном конкретном случае , $DISPLAYи $XAUTHORITYне будет содержать какой - либо оболочку метасимвола.

жилль
источник
2
Один из способов автоматизировать это - создать файл, ~/.xprofileкоторый должен запускаться только во время входа в систему X, и создать / обновить его ~/.Xauthorityс правильной информацией. Будет ли достаточно символической ссылки?
Arrowmaster
@Arrowmaster: Это хорошее предложение. Я не думал об этом. Это не будет работать во всех случаях, например, если вы входите в более чем один сеанс X (на разных терминалах, с помощью vnc,…), но это просто и достаточно для обычного использования. Символическая ссылка - лучший способ. Хм, на самом деле есть лучший, более простой способ: вы можете скопировать информацию в ~/.Xauthority.
Жиль
1
Поместит ли что-нибудь подобное xauth extract - $DISPLAY | xauth -f "$HOME/.Xauthority" merge -в ~/.xprofileслучае с несколькими $ DISPLAY?
Arrowmaster
@Arrowmaster: Какую проблему вы видите с несколькими дисплеями? Хотя ваш код может быть немного чище в принципе, поскольку вы извлекаете информацию только о том, что вас интересует, я не вижу ничего плохого в простом слиянии в случае спрашивающего или даже в очень необычных обстоятельствах.
Жиль
1
Чтение окружения из существующего процесса, подключенного к дисплею, неожиданно, потому что это восхитительно зло. Я одобряю от всего сердца. Для этого Unix.SE нужен значок Evil Genius ™.
Дероберт
19

Я решил эту проблему, добавив

xhost +si:localuser:$USER

к ~/.xprofile. Я не знаю, является ли это полностью безопасным (мне было бы очень интересно услышать, что думают более знающие люди), но я предполагаю, что это намного лучше, чем отключение контроля доступа (с xhost +), как обычно предлагается, когда вы Google для этой проблемы.

эдам
источник
1
localuserинтерпретируемые сервером адреса полностью защищены. Debian даже делает это по умолчанию как часть процесса входа в систему (in /etc/X11/Xsession.d/35x11-common_xhost-local). См. Справочную страницу Xsecurity для более подробной информации.
Сэм Моррис
Если вы находитесь в локальной сети, xhost +вероятно, достаточно в большинстве случаев ...
Алексис Уилк
Не могли бы вы объяснить, что означает эта команда?
alpha_989
@ alpha_989: Это означает «Предоставить доступ [+] любому локально работающему приложению [localuser], работающему от имени меня [$ USER]». «Си» это просто клей (см. xhost(1)И Xsecurity(7)для документов). Сама по себе эта команда не разрешает какой-либо удаленный доступ или пересылку X11 (для которой обычно предпочтительнее механизм «магических cookie» xhost).
Кевин
7

Тебе следует export DISPLAY=:0.0

asoundmove
источник
Нет. Unix не требует экспорта, когда переменная записана в той же строке. Эта переменная действует до конца строки.
Алексис Уилке
Действительно, ты прав.
Asoundmove
Этот ответ явно неправильный и должен быть удален.
Петр Доброгост
Не знал, что просто набрав DISPLAY =: 0.0 установит имя переменной. Спасибо @asoundmove. Однако я думаю: 0.0 - это значение переменной DISPLAY на дисплее сервера. Если вы входите из Putty, значение переменной DISPLAY должно быть 10 или выше. так что это должно быть DISPLAY =: 10
alpha_989
3

У меня работает, debian wheezy -> Ubuntu Trusty.

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

bob@laptop:~$ grep -iB 1 tcp /etc/gdm3/daemon.conf
[security]
DisallowTCP = false
bob@laptop:~$ ssh -C -R 6000:127.0.0.1:6000 alice@server
X11 forwarding request failed on channel 0
alice@server:~$ export DISPLAY=:0.0
alice@server:~$ xterm

X дисплей на ноутбуке показывает вывод xterm на сервере.

Отладка с использованием:

bob@laptop:~/tmp$ nc -v 127.0.0.1 6001
localhost [127.0.0.1] 6001 (x11-1) : Connection refused
bob@laptop:~/tmp$ nc -v 127.0.0.1 6000
localhost [127.0.0.1] 6000 (x11) open
alice@server:~$ nc -v 127.0.0.1 6000
Connection to 127.0.0.1 6000 port [tcp/x11] succeeded!*
alice@server:~$ strace xterm

strace будет проливать кучу кровавых подробностей о том, что он делает, вы должны быть в состоянии угадать, где он застрял - ожидание соединения или что-то еще.

В одну строчку ..

ssh -C -R 6000:127.0.0.1:6000 alice@server "DISPLAY=:0.0 xterm"
jmullee
источник