我一直在脚本当您连接或断开 HDMI 屏幕/电视时更改音频输出。基本上,它使用 UDEV 检查连接中的任何变化并采取相应措施。
一切都很好,除了一件事:我不能用它notify-send
来警告变化。我使用以下代码(output
只是一个包装器subprocess.check_output
):
output("sudo -u {0} notify-send \"{1}\" \"{2}\"".format(user, title, message))
但我根本没有收到任何通知。
真正奇怪的是,如果我运行hdmi_sound_toggle
(作为普通用户或使用sudo
),一切都正常!
那么这里可能存在什么问题?有没有比 更好的方法来呈现通知notify-send
?
答案1
当从 root 或其他用户运行的脚本调用时,无法notify-send
将通知放在用户的屏幕上。
你应该使用:
output("export DISPLAY=:0; sudo -u {0} notify-send \"{1}\" \"{2}\"".format(user, title, message))
因此,使用:
export DISPLAY=:0
通常情况下,用户在显示器上,但是为了确保万无一失,您可以使用以下命令:0
查找用户在哪个显示器上:who
who | grep -m1 ^username.*\( | awk '{print $5}' | sed 's/[(|)]//g'
这对我有用这个脚本。
答案2
我正在研究一种一致的方式来通知所有 X 用户(以 root 身份),我的研究(查看了网络上的很多地方)表明,尽管可以以这种方式使用通知发送,但它需要编写脚本来查找 DBUS 会话信息和/或正在使用的 DISPLAY 和/或 Xauthority 文件名和位置,即使这样,有时人们仍然无法使其工作。总之,试图让通知发送服从您的意愿以启用对 X 用户的广播将被证明是不可靠的(特别是如果您将来某个时候升级或更改发行版)。
但是... 在我的系统上,该wall
命令运行良好,使用起来非常简单。唯一的缺点是它还会将消息广播到所有文本终端/控制台。如果您不介意,那么这wall
可能是一个更好、更可靠的选择。注意:调用的用户wall
必须是root
。
答案3
Radu 的答案似乎对我在 16.04 上不起作用。我没有尝试解决 DISPLAY 问题(该问题似乎会随着不同版本的发布而改变),而是以稍微不同的方式来解决这个问题。我创建了一个以两种方式调用的脚本。udev 规则调用该脚本,将某种输出发送到命名管道。登录后,脚本也会以服务模式启动。在这里,它会监听管道并运行所需的 GUI 命令。
例如,我喜欢在连接 USB 存储设备时接收通知,特别是,我喜欢知道设备的路径和序列号(这可能看起来很奇怪,但我有充分的理由)。这是我用来实现这一点的脚本。
#!/bin/bash
# script name: usb-notify.sh
# This script needs to be called at logon with "service" parameter
# This script needs to be called by udev on USB insertion with no parameter
pipe="/tmp/usb-notifications"
if [ "$1" == "service" ]; then
# create the named pipe that will help us trigger events from udev
rm "$pipe"
mkfifo "$pipe"
# This outer while loop ensures that we can process multiple triggers
while true
do
# This inner while loop reads individual trigger events
while read info
do
# run some GUI command. Here, I'm running notify-send
notify-send "USB Inserted" "$(echo -e $info)"
done < "$pipe"
done
else
# Here's where udev triggers our event. If you don't need to pass any arguments
# you could just as easily pass an empty line as a trigger for the service.
[ -e "$pipe" ] && echo "Device: $DEVNAME\\\nSN: $ID_SERIAL_SHORT" > "$pipe"
fi
然后需要以两种方式调用此脚本。首先,需要创建一个 udev 规则来调用此脚本。这可以通过以下命令完成(显然您应该更改它以监视应该触发脚本的任何设备):
echo 'ACTION=="add",KERNEL=="sd?",RUN+="[path-to-script]/usb-notify.sh"' | sudo tee -a /etc/udev/rules.d/80-USB.rules
其次,您需要在登录时使用“service”参数调用此脚本。因此,打开“启动应用程序”程序并添加运行“[path-to-your-script]/usb-notify.sh service”的条目
此脚本可以修改为在 udev 事件上运行几乎任何 GUI 应用程序。如果您不希望其他用户能够查看您的管道,您可能应该对其设置限制性权限。
答案4
您可以使用 pynotify 代替 shell 命令。它非常简单,在 Ubuntu 中默认安装。快速示例:
import pynotify
pynotify.init("Name")
n = pynotify.Notification("Name", "This is a notification")
n.show()