Сценарии, запущенные с udev, больше не имеют доступа к DISPLAY?

У меня есть script, который работает от udev, когда я подключаю внешний диск. Это всегда сработало. Но после обновления от Linux 3.8/Xorg 1.12/Mint 14 (Ubuntu 12.10) до Linux 3.11/Xorg 1.14/Mint 16 ( Ubuntu 13.10), он больше не работает.

script по-прежнему выполняется, но ни одна из команд, требующих отображения, не работает. Я решил, что выйдем из демона udev и запустим вручную udevd --debug для подробного вывода (подробнее см. Ниже).

Этот script используется для работы в Mint 14/12.10:

export DISPLAY=:0
UUID=$1
DEV=$2

notify-send -t 700 "mounting $DEV ($UUID)"
gnome-terminal -t "Backing up home..." -x rsync long line of data
zenity --warning --text="Done."

Но не больше в Монетный двор 16/13.10. Если вы задаетесь вопросом о возможных решениях, я постепенно добавлял материал, и теперь он выглядит так:

export DISPLAY=:0.0

xhost +local:
xhost +si:localuser:root
xhost +

DISPLAY=:0.0
export DISPLAY=:0.0
UUID=$1
DEV=$2

notify-send -t 700 "mounting $DEV ($UUID)"
gnome-terminal -t "Backing up home..." -x rsync long line of data
zenity --warning --text="Done." --display=:0.0

Но это все еще не работает. udevd --debug все еще показывает это:

'(err) 'No protocol specified'
'(err) ''
'(err) '** (gnome-terminal:24171): WARNING **: Could not open X display'
'(err) 'No protocol specified'
'(err) 'Failed to parse arguments: Cannot open display: '
'(err) 'No protocol specified'
'(err) ''
'(err) '** (zenity:24173): WARNING **: Could not open X display'
'(err) 'No protocol specified'
'(err) ''
'(err) '(zenity:24173): Gtk-WARNING **: cannot open display: :0.0'
'(err) 'No protocol specified'

Обратите внимание, что работает любая логика bash. Повторяются тестовые vars до >>/tmp/test.log. Это просто доступ к дисплею, который больше не работает.

Это сводит меня с ума. Каков правильный способ достичь этого сейчас?

Обновление 2013-12-20

Таким образом, в предыдущем Ubuntu команды X автоматически найдут путь к текущему X, используя пользователя.

Теперь мне кажутся эти две вещи каждый раз:

  • На X с использованием пользователя:
    • xhost +si:localuser:root
  • На стороне root/udev:
    • Скопируйте X с помощью файла пользователя ~/.Xauthority в /root

Это "чувствует", как шаг назад во времени. Это работает только при первом входе в систему как один и тот же пользователь, поэтому я могу скопировать файл .Xauthority из этого дома пользователя, когда выполняется script.

Какой "трюк" использовал старый Ubuntu, чтобы сделать это автоматически?

Ответ 1

Хорошо, я пишу этот ответ, чтобы попытаться прояснить модель безопасности X-сервера, насколько я понимаю. Я не специалист по этому вопросу, поэтому у меня могут быть некоторые (многие?) Вещи не так. Кроме того, многие вещи различны в разных дистрибутивах или даже в разных версиях одного и того же дистрибутива, как отметил OP.

Существует два основных способа авторизации для подключения к X-серверу:

  • Способ xhost (хост-доступ): сервер поддерживает список хостов, локальных пользователей, групп и т.д., которым разрешено подключаться к серверу.
  • Способ xauth (основанный на файлах cookie): на сервере есть список случайно сгенерированных файлов cookie, и любому, кто показывает один из этих файлов cookie, будет предоставлен доступ.

Теперь материал, специфичный для распространения...

Когда X-сервер запускается системой запуска, обычно передается командная строка формы -auth <filename>. Этот файл содержит список исходных файлов cookie, которые будут использоваться для авторизации. Он создается до запуска X-сервера с помощью инструмента xauth. Затем сразу после X-сервера запускается диспетчер регистрации, и ему дается указание прочитать куки файл из этого же файла, чтобы он мог подключиться.

Теперь, когда пользователь rodrigo входит в систему, ему необходимо авторизоваться для подключения к серверу. Это делается диспетчером входа, и у него есть два варианта:

  • Он выполняет эквивалент: xhost +si:localuser:rodrigo.
  • Он генерирует другой файл cookie, добавляет его на сервер и передает его пользователю. Это может быть сделано двумя способами:
    • Он записывается в файл $HOME/.Xauthority (дом нового пользователя).
    • Он написан где-то еще (/var/run/gdm/auth-for-rodrigo-xxxx), а переменная окружения XAUTHORITY установлена ​​на имя этого файла.

Кроме того, он может делать обе вещи. Некоторые администраторы входа даже добавили пользователя root в список авторизованных пользователей по умолчанию (как будто xhost +si:localuser:root).

Но учтите, что если вы не авторизованы для подключения к X-серверу, вы не можете добавить себя в список (например, xhost +). Причина та же, что и то, почему вы не можете открыть дом doof снаружи без ключа... Это правда, даже если вы root!

Означает ли это, что пользователь root не может подключиться к серверу? Точно нет! Но для этого вам нужно знать, как зарегистрированный пользователь настроен для подключения к серверу. Для этого выполните как зарегистрированный пользователь:

$ xhost

Он покажет сообщение и список авторизованных пользователей, хостов или групп, если таковые имеются:

access control enabled, only authorized clients can connect
SI:localuser:rodrigo

Затем запустите:

$ echo $XAUTHORITY

Чтобы узнать, где сохранен файл авторизации. Если он пуст, то он будет ~/.Xauthority. Тогда:

$ xauth list :0

Чтобы просмотреть список одобренных файлов cookie.

Теперь, если на сервере есть куки файл, пользователь root должен иметь возможность подключить, чтобы переменная окружения XAUTHORITY указывала на правый файл cookie. Обратите внимание, что во многих настройках cookie менеджера входа также поддерживается. Просто ищите его!

Другая возможность для доступа root - это изменить файлы Xsession, чтобы добавить команду xhost +si:localuser:root и получить постоянный доступ. Детали зависят от конкретной используемой программы, но для gdm вы просто добавляете исполняемый файл script в /etc/gdm/Init/ с помощью команды xhost, и он будет запущен автоматически при следующей загрузке.

PS: вы можете проверить свой корневой доступ к X-серверу с помощью sudo -i, но обратите внимание, что некоторые конфигурации sudo могут содержать переменные DISPLAY, XAUTHORITY или HOME и изменять результаты тестов.

ПРИМЕР. Этот script должен быть способен подключить вас к X-серверу с правами root

export DISPLAY=:0
export XAUTHORITY=`ls /var/run/gdm/auth-for-gdm-*/database`
xrandr #just for show

Естественно, что путь для переменной XAUTHORITY будет зависеть от того, какой менеджер входа вы используете (greeter). Вы можете использовать файл пользователя (вы говорите, что он находится в /home/redsandro/.Xauthority, но я не уверен). Или вы можете использовать greeting cookie. Чтобы получить greeting cookie, вы можете использовать следующую команду:

$ pgrep -a Xorg

Что в моей системе дает:

408 /usr/bin/Xorg :0 -background none -verbose -auth /var/run/gdm/auth-for-gdm-gDg3Ij/database -seat seat0 -nolisten tcp vt1

Итак, мой файл /var/run/gdm/auth-for-gdm-gDg3Ij/database. gDg3Ij является случайным и изменяется при каждом перезапуске сервера, поэтому трюк ls ....

Хорошая вещь использования cookie GDM вместо пользователя заключается в том, что он не зависит от пользователя, входившего в систему. Он даже будет работать без какого-либо пользователя!

UPDATE. Из вашего последнего комментария я вижу, что ваша команда X-сервера:

/usr/bin/X :0 -audit 0 -auth /var/lib/mdm/:0.Xauth -nolisten tcp vt8

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

export DISPLAY=:0
export XAUTHORITY=/var/lib/mdm/:0.Xauth

zenity --info --text 'Happy New Year'

Ответ 2

Быстрый поиск показал следующее:

X аутентификация основана на файлах cookie - секретных маленьких фрагментов случайных данные, которые только вы и сервер X знаете... Итак, вы должны другой пользователь в том, что ваш cookie. Один из способов сделать это - следует: Прежде чем вы выполните su или sudo (но после того, как ssh'ed в удаленная система, если вы используете ssh), запросите файл cookie для текущий DISPLAY, который подключается к вашему X-серверу:

$xauth list $DISPLAY Вы получите что-то вроде

somehost.somedomain: 10 mit-magic-cookie-1 4d22408a71a55b41ccd1657d377923ae

Затем, выполнив su, сообщите новому пользователю, что такое cookie:

$xauth add somehost.somedomain: 10 MIT-MAGIC-COOKIE-1 4d22408a71a55b41ccd1657d377923ae

(просто скопируйте и вставьте вывод вышеперечисленного "xauth list" на "xauth" add ') Это. Теперь вы можете запустить любое X-приложение.

Для справки, вот начало http://www.linuxquestions.org/questions/linux-newbie-8/xlib-connection-to-0-0-refused-by-server-xlib-no-protocol-specified-152556/

Ответ 3

Это не очень, но я пока не видел никаких решений. Так что это лучший пока.

  • На X с использованием пользователя:
    • xhost +si:localuser:root
  • На стороне root/udev:
    • Скопировать X с помощью файла пользователя ~/.Xauthority на /root (* см. примечание ниже)

Теперь он работает. Попробуйте zenity --warning --text=Hooray

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

*) Примечание
Это примечательно, потому что я пробовал документированные способы xauth merge /home/redsandro/.Xauthority и $XAUTHORITY=/home/redsandro/.Xauthority. Эти документированные методы просто ничего не делают в наши дни, даже если root имеет разрешение на его чтение. Вам нужно буквально весь файл .Xauthority вместо того, чтобы просто указывать на него.

Ответ 4

В новых версиях Ubuntu используются разные диспетчеры дисплеев, поэтому вам нужно знать, какой из них вы используете. В сообщении Rodrigo есть подсказка, показывающая, как ее обнаружить, используя следующую команду:

ls /var/run/gdm/auth-for-gdm-*/database

Чтобы проверить это, перечислите каталог /var/run и используйте команду "pgrep -a Xorg". В Ubuntu 16 * он использует sddm, поэтому вы можете использовать

ls/var/run/sddm * для экспорта переменной XAUTHORITY.

script будет выглядеть следующим образом:

#!/bin/bash
export DISPLAY=:0
export XAUTHORITY=`ls /var/run/sddm*`
HDMI_STATUS="$(cat /sys/class/drm/card0-HDMI-A-1/status)"
USER="your username"
export XAUTHORITY=/home/$USER/.Xauthority
export DISPLAY=:0

if [ "$HDMI_STATUS" = connected ];
then
sudo -u $USER pactl set-card-profile 0 output:hdmi-stereo+input:analog-stereo
else
sudo -u $USER pactl set-card-profile 0 output:analog-stereo+input:analog-stereo
fi
exit 0

затем выполните:

sudo chmod 755 /usr/local/bin/toggle-sound

echo 'ACTION=="change", SUBSYSTEM=="drm", RUN+="/usr/local/bin/toggle-sound"' | sudo tee /etc/udev/rules.d/99-hdmi-sound.rules

sudo udevadm control --reload-rules

Ответ 5

Мне пришлось использовать это в Kali Linux 2016, чтобы заставить его работать:

#!/bin/bash
set -x
xhost local:root
export DISPLAY=:0.0
su root -c 'zenity --notification --text="I am a notification!"'