Wayland环境下udev触发systemd用户单元无法正确显示Zenity对话框的问题排查求助
我现在遇到一个棘手的问题:原本在Xubuntu(X11显示服务器)下正常运行的脚本,切换到Ubuntu 23.10的Wayland环境后彻底失效了。这个脚本的功能是:当特定带SMART功能的USB设备插入时,通过udev触发systemd单元,调用zenity弹出图形对话框,让用户选择SMART检测报告的保存位置。
最初我尝试在systemd的.conf文件中添加Wayland相关环境变量,但zenity依旧无法弹出。下面是我尝试过的几个配置版本,以及遇到的问题:
Setup-01:初始X11兼容配置(Wayland下失效)
这套配置在X11下正常,但Wayland环境中zenity对话框无法显示。
涉及文件列表:
/bin/hdd_smart_dump_on_usb_trigger.sh/etc/00_hdd_smart_dump_on_usb_trigger.conf/etc/systemd/system/hdd_smart_dump_on_usb_trigger@.service/etc/systemd/system/hdd_smart_dump_on_usb_trigger@.service.d/disable_manual_start.conf/etc/systemd/system/hdd_smart_dump_on_usb_trigger@.target/etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh/etc/udev/rules.d/99-hdd-smart-dump-on-usb-trigger.udev.rules
核心配置内容:
/etc/00_hdd_smart_dump_on_usb_trigger.conf
USER=myName DISPLAY=:0.0 WAYLAND_DISPLAY=wayland-0 XAUTHORITY=/home/ajthapa/.Xauthority HOME=/home/myName SHELL=/bin/bash
/etc/systemd/system/hdd_smart_dump_on_usb_trigger@.service
[Unit] Description=HDD SMART Dump on USB Trigger - service unit for %I Documentation=man:systemd.unit(5) man:systemd.exec(5) man:systemd.special(7) man:systemd.target(5) ConditionPathExistsGlob=/sys/class/block/sd* # RefuseManualStart=true # RefuseManualStop=true [Service] EnvironmentFile=/etc/00_hdd_smart_dump_on_usb_trigger.conf ExecStart=-/bin/bash -c '/bin/hdd_smart_dump_on_usb_trigger.sh -d %i -t "start_of_session"'
问题:添加WAYLAND_DISPLAY=wayland-0后,Wayland环境下zenity仍无法弹出。
Setup-02:拆分系统单元与用户单元
我尝试把zenity相关的逻辑移到systemd用户单元中,让系统单元负责采集SMART数据,用户单元负责弹出对话框,但用户单元始终无法启动。
新增/调整文件:
/opt/hdd_smart_dump_on_usb_trigger/bin/hdd_smart_dump_display_with_zenity.sh/opt/hdd_smart_dump_on_usb_trigger/bin/hdd_smart_dump_on_usb_trigger.sh/home/myName/.config/systemd/user/hdd_smart_dump_display_using_zenity@.service
核心配置:
/home/myName/.config/systemd/user/hdd_smart_dump_display_using_zenity@.service
[Unit] Description=HDD SMART Dump Display Using Zenity Dialogue Documentation=man:systemd.unit(5) man:systemd.exec(5) man:systemd.special(7) man:systemd.target(5) Requires=hdd_smart_dump_on_usb_trigger@%i.service After=hdd_smart_dump_on_usb_trigger@%i.service ConditionPathExistsGlob=/sys/class/block/sd* # RefuseManualStart=true # RefuseManualStop=true [Service] Type=oneshot ExecStart=-/bin/bash -c '/opt/hdd_smart_dump_on_usb_trigger/bin/hdd_smart_dump_display_with_zenity.sh --display-dialogue'
udev规则调整(添加用户单元触发)
在udev规则中加入:
ENV{SYSTEMD_USER_WANTS}+="hdd_smart_dump_display_using_zenity@dev-%k.system"
问题:系统单元正常启动,但用户单元无任何运行记录(执行systemctl --user --no-pager -l status 'hdd_*'无输出)。
Setup-03:尝试通过依赖关联用户单元与系统单元
我尝试将用户单元设为系统单元的依赖,但遇到了单元不存在的错误。
用户单元配置调整:
/home/ajthapa/.config/systemd/user/hdd_smart_dump_display_using_zenity.service
[Unit] Description=HDD SMART Dump Display Using Zenity Dialogue Documentation=man:systemd.unit(5) man:systemd.exec(5) man:systemd.special(7) man:systemd.target(5) StopWhenUnneeded=yes After=hdd_smart_dump_on_usb_trigger@%i.service #BindsTo=%i.device RefuseManualStart=true RefuseManualStop=true [Service] Type=oneshot ExecStart=-/bin/bash -c '/opt/hdd_smart_dump_on_usb_trigger/bin/hdd_smart_dump_display_with_zenity.sh --display-dialogue' [Install] WantedBy=hdd_smart_dump_on_usb_trigger@%i.service
错误输出:
执行systemctl --user enable hdd_smart_dump_display_using_zenity.service时提示:
Created symlink /home/ajthapa/.config/systemd/user/hdd_smart_dump_on_usb_trigger@.service.wants/hdd_smart_dump_display_using_zenity.service → /home/ajthapa/.config/systemd/user/hdd_smart_dump_display_using_zenity.service. Unit /home/ajthapa/.config/systemd/user/hdd_smart_dump_display_using_zenity.service is added as a dependency to a non-existent unit hdd_smart_dump_on_usb_trigger@.service.
这个错误导致用户单元无法被正确触发。
Setup-04:添加用户单元Target控制执行顺序
我为用户单元也创建了对应的target,试图通过target来控制执行顺序,但出现了用户单元先于系统单元执行的问题。
新增文件:
/home/ajthapa/.config/systemd/user/hdd_smart_dump_display_using_zenity@.target
核心配置:
/home/ajthapa/.config/systemd/user/hdd_smart_dump_display_using_zenity@.target
[Unit] Description=HDD SMART Dump Display Using Zenity Dialogue - target unit for %I Documentation=man:systemd.unit(5) man:systemd.exec(5) man:systemd.special(7) man:systemd.target(5) StopWhenUnneeded=yes Requires=hdd_smart_dump_display_using_zenity@%i.service Before=hdd_smart_dump_display_using_zenity@%i.service RefuseManualStart=true RefuseManualStop=true
问题:用户单元会先于系统单元执行,导致第一次插入设备时zenity显示空白,再次插入时显示上一次设备的 stale 数据。临时在用户单元中添加sleep 3s可以解决,但这是临时 workaround,我希望通过systemd的依赖配置来正确控制顺序。
核心疑问:
- Wayland环境下,udev触发的systemd用户单元需要哪些额外配置才能正常显示zenity对话框?
- 如何正确配置systemd单元依赖,确保系统单元完成SMART数据采集后,再触发用户单元弹出对话框?
备注:内容来源于stack exchange,提问作者rusty

