UDEV 是否可以以某种方式为会话中登录的用户触发 zenity ?

UDEV 是否可以以某种方式为会话中登录的用户触发 zenity ?

当我连接特定的外部驱动器时,我希望zenity弹出一个对话框询问我是否要运行备份。

不幸的是,我对 UDEV 规则语法有疑问。我有以下规则/etc/udev/rules.d/test.rules

ACTION=="add", ATTRS{manufacturer}=="Western Digital", ATTRS{idVendor}=="1058", ATTRS{idProduct}=="1140", RUN+="/usr/local/bin/test.sh"

这是非常基础的,但是:

  1. 它会触发十几次,而不是一次。
  2. zenity它无法使用when test.shgoes 来“说话”,sudo -Hu <username> zenity --warning --text="Just some random text for now."因为 udev 隐藏在系统中并且找不到窗口管理器:Gtk-警告**:无法打开显示:
  3. 它不太适合编辑,我希望有某种规则,我只需输入我想要触发某些脚本的某些分区的标签即可。

我希望看到 UDEV 规则的全面改进,因为除了关于它的许多问题和答案之外,这里和其他地方,它们似乎都有点不同,并且大多数都会触发多次。

但最重要的是,我怎样才能从这里连接到我家里的脚本,该脚本可以访问我的会话和屏幕等内容,以便zenity可以工作?

答案1

您已经找到答案了。脚本 (zenity) 需要 X Window Server 来显示消息。脚本从中运行udev,但没有附加显示。您可以通过DISPLAY在脚本中硬连线变量来解决这个问题,即

DISPLAY=:0; export DISPLAY

缺点是,只有当您是唯一的用户和/或提前知道显示内容时,它才有效。如果您的系统上有多个用户,则显示内容可能是其他内容,例如:1:2等等。或者其他用户会在其屏幕上看到 zenity 消息。

更好的方法是将事件的检测与与用户的交互或消息的显示分开。

为此,您可以创建一个脚本或程序,它在您的 GUI 会话中运行并监听来自守护进程或 udev 触发脚本的触发器。

第三种可能性是udisks-daemon当外部设备插入时,连接到并询问信息。您可以尝试udisks --monitor或者udisks --monitor-detail每当事件发生时,解析输出。

似乎有一个udisksctl命令,它的功能相同,只是语法略有不同。也许它只是udisks命令的较新版本。

你也可以看看一些 Gui 工具,比如GNOME 磁盘,它们也依赖于 udev/udisks 系统。

更新

多次调用通常来自各个子系统的报告。您可以看到,当您将环境记录到脚本中的某个日志文件/usr/local/bin/test.sh

umask 077
mkdir -p /tmp/udevtest.d
env >>/tmp/udevtest.d/udevtest.log

当我插入 USB 时,我收到以下报告

$ grep -e ACTION -e SUBSYSTEM /tmp/udevtest.d/udevtest.log
ACTION=add
SUBSYSTEM=usb
ACTION=add
SUBSYSTEM=usb
ACTION=add
SUBSYSTEM=scsi
ACTION=add
SUBSYSTEM=scsi_host
ACTION=add
SUBSYSTEM=scsi
ACTION=add
SUBSYSTEM=scsi
ACTION=add
SUBSYSTEM=scsi_disk
ACTION=add
SUBSYSTEM=scsi_generic
ACTION=add
SUBSYSTEM=scsi_device
ACTION=add
SUBSYSTEM=bsg
ACTION=add
SUBSYSTEM=block
ACTION=add
SUBSYSTEM=block

您还可以添加DEVTYPE以区分两个usbdisk报告。因此,为了将报告减少到只有几个甚至只有一个调用,您必须更加具体并在 udev 规则文件中添加其他条件,例如选择SUBSYSTEM=scsi_disk或任何适合您的设备的内容。

答案2

对于其他读到这篇文章的人来说,我能够让脚本在 Kali Linux 2016 中运行的唯一方法是这样的:

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

相关内容