从udev启动的脚本不再有DISPLAY访问?

当我插入外部驱动器时,我有一个从udev运行的脚本。 它一直工作。 但从Linux 3.8 / Xorg 1.12 / Mint 14Ubuntu 12.10兼容)升级到Linux 3.11 / Xorg 1.14 / Mint 16Ubuntu 13.10兼容)后,它不再工作。

该脚本仍然运行,但没有任何需要显示的命令工作。 我想通过退出udev守护进程并手动运行udevd --debug进行详细输出(更多下面)。

这个脚本用于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 。 如果你想知道可能的解决scheme,我逐渐添加了东西,现在看起来像这样:

 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逻辑的作品。 回应testingvariables>>/tmp/test.log工程。 只是访问不再工作的显示器。

这真让我抓狂。 现在实现这个的正确方法是什么?

更新2013-12-20

所以,在以前的Ubuntu中, X命令会自动find当前使用X用户。

现在,我似乎每次都需要这两样东西:

  • X使用用户:
    • xhost +si:localuser:root
  • root/udev方面:
    • 将用户的~/.Xauthority文件复制到/root

这“感觉”就像退后一步。 当我每次以同一个用户login时,这只能用脚本编写,因此我可以在脚本执行时从该用户的家中复制.Xauthority文件。

旧的Ubuntu使用“欺骗”来实现自动化吗?

好吧,我正在写这个答案,试图澄清X服务器的安全模型,据我所知。 我不是这方面的专家,所以我可能有一些(很多?)的东西是错的。 此外,许多事情在不同的发行版中是不同的,甚至不同的发行版,就像OP所说的那样。

有两种主要方法可以获得授权连接到X服务器:

  • xhost方式( 主机访问 ):服务器维护允许连接到服务器的主机,本地用户,组等的列表。
  • xauth方式( 基于Cookie ):服务器有一个随机生成的cookie列表,任何显示这些cookie的人都将被授予访问权限。

现在,分配特定的东西…

当X服务器由启动系统启动时,通常会通过形式为-auth <filename>的命令行。 该文件包含用于授权的初始cookie列表。 它是在使用xauth工具运行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用户无法连接到服务器? 绝对不! 但是为了达到这个目的,首先你必须知道如何配置记录的用户连接到服务器。 对于以登录的用户身份运行:

 $ xhost 

它将显示一条消息和授权用户,主机或组的列表(如果有):

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

然后运行:

 $ echo $XAUTHORITY 

查看授权文件的保存位置 如果它是空的,那么它将是~/.Xauthority 。 然后:

 $ xauth list :0 

查看您的授权cookie的列表。

现在,如果服务器中有任何cookie,根用户应该能够连接使XAUTHORITY环境变量指向正确的cookie文件。 请注意,在许多设置中,登录管理器的cookie也被保留。 只要找它!

根访问的另一种可能性是修改Xsession文件以添加命令xhost +si:localuser:root并获得永久访问权限。 细节因使用的特定程序而异,但对于gdm您只需在/etc/gdm/Init/使用xhost命令添加可执行脚本,并在下次启动时自动运行。

PS:你可以使用sudo -i检查你对X服务器的root权限,但是请注意,一些sudo配置可能会保留DISPLAYXAUTHORITYHOME变量,并修改测试结果。

示例 :该脚本应该能够以root身份连接到X服务器

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

当然, XAUTHORITY变量的路径将取决于您使用的登录管理器(greeter)。 你可以使用用户文件(你说它在/home/redsandro/.Xauthority但我不太确定)。 或者您可以使用迎宾cookie。 要获得迎宾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/databasegDg3Ij是随机的,每当服务器重新启动时都会更改,这就是为什么ls ...技巧。

使用GDM cookie而不是用户的好处是,它不依赖于登录的用户,它甚至可以在没有用户的情况下工作!

更新 :从您的最新评论我看到你的X服务器命令是:

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

所以有用于启动登录管理器的cookie的名称。 如果我是正确的,那么应该可以随时使用,如果你能够读取文件。 你是根,所以,下面的行应该足以让你以root身份访问显示器:

 export DISPLAY=:0 export XAUTHORITY=/var/lib/mdm/:0.Xauth zenity --info --text 'Happy New Year' 

快速搜索出现以下内容:

X身份验证是基于cookies – 秘密的一小段随机数据,只有你和X服务器知道…所以,你需要让其他用户在你的cookie是什么。 一种方法如下:在你发出su或者sudo之前(但是如果你使用的是ssh,在ssh进入远程系统之后),请求连接到你的X服务器的当前DISPLAY的cookie:

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

这不是很好,但我还没有看到任何解决方案。 所以这是迄今为止最好的一个。

  • X使用用户:
    • xhost +si:localuser:root
  • 在根/ udev方面:
    • 将用户的~/.Xauthority文件复制到/root (* 参见下面的注释

现在起作用了。 试试zenity --warning --text=Hooray

这只有当你知道哪个用户将被登录到X时才起作用。因此,只有当单个用户使用具有单个用户帐户的计算机时才可以接受。

*) 注意
这是值得注意的,因为我尝试了xauth merge /home/redsandro/.Xauthority$XAUTHORITY=/home/redsandro/.Xauthority 。 即使root拥有读取权限的权限,这些文档化的方法也不能做任何事情。 你需要从字面上整个.Xauthority文件而不是指向它。

较新版本的Ubuntu使用不同的显示管理器,所以你必须知道你正在使用哪一个。 在Rodrigo的文章中,有一个提示如何使用这个命令来发现它:

 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!"'