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

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

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

этот скрипт используется для работы в монетный двор 14/12.10:

export DISPLAY=:0
UUID=
DEV=

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=
DEV=

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 работает. Эхо тест ВАР >>/tmp/test.log завод. Это просто доступ к дисплею, который больше не работает.

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

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

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

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

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

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

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

5 ответов


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

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

  • на xhost путь (Доступ К Узлу): в сервер поддерживает список хостов, Локальные пользователи, группы и т. д. которые могут подключаться к серверу.
  • на xauth путь (Cookie на основе): на сервере есть список случайно сгенерированных куки, и любой, кто показывает один из этих куки будет предоставлен доступ.

теперь, распределение конкретных вещей...

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

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

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

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

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

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

$ xhost

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

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

запустите:

$ echo $XAUTHORITY

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

$ xauth list :0

чтобы увидеть список ваших авторизованных cookies.

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

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

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

пример: этот скрипт должен иметь возможность подключить вас к X-серверу как root

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

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

$ 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. The gDg3Ij является случайным и изменяется каждый раз при перезапуске сервера, поэтому ls ... трюк.

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

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

/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'

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

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

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

некий_хост.somedomain: 10 mit-magic-cookie-1 4d22408a71a55b41ccd1657d377923ae

затем, сделав su, скажите новому пользователю, что такое cookie:

$ xauth добавить somehost.somedomain: 10 MIT-MAGIC-COOKIE-1 4d22408a71a55b41ccd1657d377923ae

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

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


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

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

теперь все работает. Попробуй!--5-->

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

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


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

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

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

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

сценарий бы это:

#!/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

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

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