8

I use the following in systemd .conf file to run a graphical zenity dialog every time specific device with SMART capability is inserted to the USB port. This works fine in Xubuntu which uses X display server, but the display of zenity dialog fails in Wayland server.

USER=myName
DISPLAY=:0.0
WAYLAND_DISPLAY=wayland-0
XAUTHORITY=/home/myName/.Xauthority
HOME=/home/myName
SHELL=/bin/bash

I tried adding WAYLAND_DISPLAY=wayland-0 in the .conf file for Wayland server in Ubuntu 23.10 but still zenity dialogue fails to show up. What more do I need to do?


The list of files that my setup-01:

/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

The contents of /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

The contents of /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"'

The contents of /etc/systemd/system/hdd_smart_dump_on_usb_trigger@.service.d/disable_manual_start.conf :

[Unit]
## Allow only to be started/stopped by device events; if manual start is needed
## you should instead call the script which this service calls.
RefuseManualStart=true
RefuseManualStop=true

The contents of /etc/systemd/system/hdd_smart_dump_on_usb_trigger@.target :

[Unit]
Description=HDD SMART Dump on USB Trigger - target unit for %I
Documentation=man:systemd.unit(5) man:systemd.target(5) man:systemd.special(7)
StopWhenUnneeded=yes
Requires=hdd_smart_dump_on_usb_trigger@%i.service
Before=hdd_smart_dump_on_usb_trigger@%i.service
BindsTo=%i.device
RefuseManualStart=true
RefuseManualStop=true

The contents of /etc/udev/rules.d/99-hdd-smart-dump-on-usb-trigger.udev.rules :

SUBSYSTEM!="block", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
KERNEL!="sd*", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
ENV{DEVTYPE}!="disk", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"

Rules to match specific devices; start:

ATTRS{idProduct}=="2312", ATTRS{idVendor}=="0bc2", GOTO="label__enlisted_devices" ATTRS{idProduct}=="5590", ATTRS{idVendor}=="0781", GOTO="label__enlisted_devices" ATTRS{idProduct}!="2312|5590", ATTRS{idVendor}!="0bc2|0781", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"

Rules to match specific devices; end.

LABEL="label__enlisted_devices" ACTION=="remove", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_for_action_remove" ACTION!="add", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end" ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd", ENV{DEVTYPE}=="disk", ATTRS{idProduct}=="2312", ATTRS{idVendor}=="0bc2", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hdd_smart_dump_on_usb_trigger@dev-%k.target", RUN+="/etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh ==01== UDEV_ACTION==ADD #### ENVIRONMENT::::[[ DEVNAME=$env{DEVNAME} | DEVPATH=$env{DEVPATH} | ID_MODEL=$env{ID_MODEL} | ID_SERIAL=$env{ID_SERIAL} | ID_SERIAL_SHORT=$env{ID_SERIAL_SHORT} | ID_VENDOR=$env{ID_VENDOR} | TAGS=$env{TAGS} | ID_ATA=$env{ID_ATA} | ID_ATA_FEATURE_SET_SMART=$env{ID_ATA_FEATURE_SET_SMART} | ID_ATA_FEATURE_SET_SMART_ENABLED=$env{ID_ATA_FEATURE_SET_SMART_ENABLED} | ID_ATA_SATA=$env{ID_ATA_SATA} | ID_ATA_WRITE_CACHE=$env{ID_ATA_WRITE_CACHE} | ID_ATA_WRITE_CACHE_ENABLED=$env{ID_ATA_WRITE_CACHE_ENABLED} | ID_VENDOR_ID=$env{ID_VENDOR_ID} | ID_MODEL_ID=$env{ID_MODEL_ID} | ]] #### ATTRIBUTE::::[[ size=$attr{size} | KERNEL=%k | idProduct=$attr{idProduct} | idVendor=$attr{idVendor} | manufacturer=$attr{manufacturer} | product=$attr{product} | removable=$attr{removable} | bMaxPower=$attr{bMaxPower} | ]]", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end" ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd", ENV{DEVTYPE}=="disk", ATTRS{idProduct}=="5590", ATTRS{idVendor}=="0781", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hdd_smart_dump_on_usb_trigger@dev-%k.target", RUN+="/etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh ==01== UDEV_ACTION==ADD #### ENVIRONMENT::::[[ DEVNAME=$env{DEVNAME} | DEVPATH=$env{DEVPATH} | ID_MODEL=$env{ID_MODEL} | ID_SERIAL=$env{ID_SERIAL} | ID_SERIAL_SHORT=$env{ID_SERIAL_SHORT} | ID_VENDOR=$env{ID_VENDOR} | TAGS=$env{TAGS} | ID_ATA=$env{ID_ATA} | ID_ATA_FEATURE_SET_SMART=$env{ID_ATA_FEATURE_SET_SMART} | ID_ATA_FEATURE_SET_SMART_ENABLED=$env{ID_ATA_FEATURE_SET_SMART_ENABLED} | ID_ATA_SATA=$env{ID_ATA_SATA} | ID_ATA_WRITE_CACHE=$env{ID_ATA_WRITE_CACHE} | ID_ATA_WRITE_CACHE_ENABLED=$env{ID_ATA_WRITE_CACHE_ENABLED} | ID_VENDOR_ID=$env{ID_VENDOR_ID} | ID_MODEL_ID=$env{ID_MODEL_ID} | ]] #### ATTRIBUTE::::[[ size=$attr{size} | KERNEL=%k | idProduct=$attr{idProduct} | idVendor=$attr{idVendor} | manufacturer=$attr{manufacturer} | product=$attr{product} | removable=$attr{removable} | bMaxPower=$attr{bMaxPower} | ]]", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end" LABEL="label__hdd_smart_dump_on_usb_trigger_rules_for_action_remove" ACTION=="remove", SUBSYSTEM=="block", KERNEL=="sd*", ENV{DEVTYPE}=="disk", RUN+="/etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh ==02== UDEV_ACTION==REMOVE #### ENVIRONMENT::::[[ DEVNAME=$env{DEVNAME} | ID_MODEL=$env{ID_MODEL} | ID_SERIAL=$env{ID_SERIAL} | ID_SERIAL_SHORT=$env{ID_SERIAL_SHORT} | ID_VENDOR=$env{ID_VENDOR} | TAGS=$env{TAGS} | ID_ATA=$env{ID_ATA} | ID_ATA_FEATURE_SET_SMART=$env{ID_ATA_FEATURE_SET_SMART} | ID_ATA_FEATURE_SET_SMART_ENABLED=$env{ID_ATA_FEATURE_SET_SMART_ENABLED} | ID_ATA_SATA=$env{ID_ATA_SATA} | ID_ATA_WRITE_CACHE=$env{ID_ATA_WRITE_CACHE} | ID_ATA_WRITE_CACHE_ENABLED=$env{ID_ATA_WRITE_CACHE_ENABLED} | ID_VENDOR_ID=$env{ID_VENDOR_ID} | ID_MODEL_ID=$env{ID_MODEL_ID} ]] #### ATTRIBUTE::::[[ size=$attr{size} | KERNEL=$kernel | idProduct=$attr{idProduct} | idVendor=$attr{idVendor} | manufacturer=$attr{manufacturer} | product=$attr{product} | model=$attr{model} | removable=$attr{removable} ]]" LABEL="label__hdd_smart_dump_on_usb_trigger_rules_end"

The /etc/udev/rules.d/99-hdd-smart-dump-on-usb-trigger.udev.rules contains rules to match specific set of devices, on which it executes /etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh which in turn writes some attributes to a file in /var/run/ directory. The rules file also triggers systemd unit files, which then executes /bin/hdd_smart_dump_on_usb_trigger.sh . This script uses zenity to allow users to save the output of smartmontools to selected location.

UPDATE:

Setup-02:

List of files:

-rw-r--r-- 1 root root 3018 Feb 19 12:25 /etc/00_hdd_smart_dump_on_usb_trigger.conf
-rw-r--r-- 1 root root 2013 Feb 19 12:15 /etc/systemd/system/hdd_smart_dump_on_usb_trigger@.service
-rw-r--r-- 1 root root 196 Aug  8  2020 /etc/systemd/system/hdd_smart_dump_on_usb_trigger@.service.d/disable_manual_start.conf
-rw-r--r-- 1 root root 573 Feb 19 07:42 /etc/systemd/system/hdd_smart_dump_on_usb_trigger@.target
-rwxr-xr-x 1 root root 7562 Sep  5  2020 /etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh
-rw-r--r-- 1 root root 7710 Feb 19 13:29 /etc/udev/rules.d/99-hdd-smart-dump-on-usb-trigger.udev.rules
-rwxr-xr-x 1 root root 5032 Feb 19 13:18 /opt/hdd_smart_dump_on_usb_trigger/bin/hdd_smart_dump_display_with_zenity.sh
-rwxr-xr-x 1 root root 34594 Feb 19 11:58 /opt/hdd_smart_dump_on_usb_trigger/bin/hdd_smart_dump_on_usb_trigger.sh
-rw-r--r-- 1 myName myName 502 Feb 19 13:30 /home/myName/.config/systemd/user/hdd_smart_dump_display_using_zenity@.service

With this setup, udev writes attributes which is then read by my systemd system-units, but my systemd user-units fail to launch and show the dump in zenity dialogue. I can use the same command in my /home/myName/.config/systemd/user/hdd_smart_dump_display_using_zenity@.service to launch zenity with the SMART dump. So, the problem could be in my udev .rules file and/or my systemd user-unit file and/or it's naming.

The contents of /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'

The contents of /etc/udev/rules.d/99-hdd-smart-dump-on-usb-trigger.udev.rules :

SUBSYSTEM!="block", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
KERNEL!="sd*", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
ENV{DEVTYPE}!="disk", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
ATTRS{idProduct}=="2312", ATTRS{idVendor}=="0bc2", GOTO="label__enlisted_devices"
ATTRS{idProduct}=="5590", ATTRS{idVendor}=="0781", GOTO="label__enlisted_devices"
ATTRS{idProduct}!="2312|5590", ATTRS{idVendor}!="0bc2|0781", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
LABEL="label__enlisted_devices"
ACTION=="remove", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_for_action_remove"
ACTION!="add", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd*", ENV{DEVTYPE}=="disk", ATTRS{idProduct}=="2312", ATTRS{idVendor}=="0bc2", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hdd_smart_dump_on_usb_trigger@dev-%k.target", ENV{SYSTEMD_USER_WANTS}+="hdd_smart_dump_display_using_zenity@dev-%k.system", RUN+="/etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh ==01== UDEV_ACTION==ADD ####  ENVIRONMENT::::[[ DEVNAME=$env{DEVNAME} | DEVPATH=$env{DEVPATH} | ID_MODEL=$env{ID_MODEL} | ID_SERIAL=$env{ID_SERIAL} | ID_SERIAL_SHORT=$env{ID_SERIAL_SHORT} | ID_VENDOR=$env{ID_VENDOR} | TAGS=$env{TAGS} | ID_ATA=$env{ID_ATA} | ID_ATA_FEATURE_SET_SMART=$env{ID_ATA_FEATURE_SET_SMART} | ID_ATA_FEATURE_SET_SMART_ENABLED=$env{ID_ATA_FEATURE_SET_SMART_ENABLED} | ID_ATA_SATA=$env{ID_ATA_SATA} | ID_ATA_WRITE_CACHE=$env{ID_ATA_WRITE_CACHE} | ID_ATA_WRITE_CACHE_ENABLED=$env{ID_ATA_WRITE_CACHE_ENABLED} | ID_VENDOR_ID=$env{ID_VENDOR_ID} | ID_MODEL_ID=$env{ID_MODEL_ID} | ]]  ####  ATTRIBUTE::::[[ size=$attr{size} | KERNEL=%k | idProduct=$attr{idProduct} | idVendor=$attr{idVendor} | manufacturer=$attr{manufacturer} | product=$attr{product} | removable=$attr{removable} | bMaxPower=$attr{bMaxPower} | ]]", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd*", ENV{DEVTYPE}=="disk", ATTRS{idProduct}=="5590", ATTRS{idVendor}=="0781", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hdd_smart_dump_on_usb_trigger@dev-%k.target", ENV{SYSTEMD_USER_WANTS}+="hdd_smart_dump_display_using_zenity@dev-%k.system", RUN+="/etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh ==01== UDEV_ACTION==ADD ####  ENVIRONMENT::::[[ DEVNAME=$env{DEVNAME} | DEVPATH=$env{DEVPATH} | ID_MODEL=$env{ID_MODEL} | ID_SERIAL=$env{ID_SERIAL} | ID_SERIAL_SHORT=$env{ID_SERIAL_SHORT} | ID_VENDOR=$env{ID_VENDOR} | TAGS=$env{TAGS} | ID_ATA=$env{ID_ATA} | ID_ATA_FEATURE_SET_SMART=$env{ID_ATA_FEATURE_SET_SMART} | ID_ATA_FEATURE_SET_SMART_ENABLED=$env{ID_ATA_FEATURE_SET_SMART_ENABLED} | ID_ATA_SATA=$env{ID_ATA_SATA} | ID_ATA_WRITE_CACHE=$env{ID_ATA_WRITE_CACHE} | ID_ATA_WRITE_CACHE_ENABLED=$env{ID_ATA_WRITE_CACHE_ENABLED} | ID_VENDOR_ID=$env{ID_VENDOR_ID} | ID_MODEL_ID=$env{ID_MODEL_ID} | ]]  ####  ATTRIBUTE::::[[ size=$attr{size} | KERNEL=%k | idProduct=$attr{idProduct} | idVendor=$attr{idVendor} | manufacturer=$attr{manufacturer} | product=$attr{product} | removable=$attr{removable} | bMaxPower=$attr{bMaxPower} | ]]", GOTO="label__hdd_smart_dump_on_usb_trigger_rules_end"
LABEL="label__hdd_smart_dump_on_usb_trigger_rules_for_action_remove"
ACTION=="remove", SUBSYSTEM=="block", KERNEL=="sd*", ENV{DEVTYPE}=="disk", RUN+="/etc/udev/00_hdd_smart_dump_on_usb_trigger.udev.sh ==02== UDEV_ACTION==REMOVE ####  ENVIRONMENT::::[[ DEVNAME=$env{DEVNAME} | ID_MODEL=$env{ID_MODEL} | ID_SERIAL=$env{ID_SERIAL} | ID_SERIAL_SHORT=$env{ID_SERIAL_SHORT} | ID_VENDOR=$env{ID_VENDOR} | TAGS=$env{TAGS} | ID_ATA=$env{ID_ATA} | ID_ATA_FEATURE_SET_SMART=$env{ID_ATA_FEATURE_SET_SMART} | ID_ATA_FEATURE_SET_SMART_ENABLED=$env{ID_ATA_FEATURE_SET_SMART_ENABLED} | ID_ATA_SATA=$env{ID_ATA_SATA} | ID_ATA_WRITE_CACHE=$env{ID_ATA_WRITE_CACHE} | ID_ATA_WRITE_CACHE_ENABLED=$env{ID_ATA_WRITE_CACHE_ENABLED} | ID_VENDOR_ID=$env{ID_VENDOR_ID} | ID_MODEL_ID=$env{ID_MODEL_ID} ]]  ####  ATTRIBUTE::::[[ size=$attr{size} | KERNEL=$kernel | idProduct=$attr{idProduct} | idVendor=$attr{idVendor} | manufacturer=$attr{manufacturer} | product=$attr{product} | model=$attr{model} | removable=$attr{removable} ]]"
LABEL="label__hdd_smart_dump_on_usb_trigger_rules_end"

Output of sudo systemctl --no-pager -l status 'hdd_smart_dump_on_usb_trigger*' with USB device inserted:

● hdd_smart_dump_on_usb_trigger@dev-sdb.target - HDD SMART Dump on USB Trigger - target unit for dev/sdb
     Loaded: loaded (/etc/systemd/system/hdd_smart_dump_on_usb_trigger@.target; static)
     Active: active since Mon 2024-02-19 14:17:50 +0545; 2min 24s ago
       Docs: man:systemd.unit(5)
             man:systemd.target(5)
             man:systemd.special(7)

Feb 19 14:17:50 ajthapa-vcomputer systemd[1]: Reached target hdd_smart_dump_on_usb_trigger@dev-sdb.target - HDD SMART Dump on USB Trigger - target unit for dev/sdb.

There is no output for systemctl --user --no-pager -l status 'hdd_*' .

Setup-03:

The files:

/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
/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/ajthapa/.config/systemd/user/hdd_smart_dump_display_using_zenity.service

The contents of /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

The output of command 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.

The '... dependency added to non-existent unit ...' prevents the starting of the encoded script in the user-unit.

In setup-03, the udev .rules file triggers only the system-unit of systemd files.

SETUP-04:

The list of files:

/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
/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/ajthapa/.config/systemd/user/hdd_smart_dump_display_using_zenity@.service
/home/ajthapa/.config/systemd/user/hdd_smart_dump_display_using_zenity@.target

The contents of /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)
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'

The contents of /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

The system-unit .target and user-unit .target are triggered by udev rules. With this configuration of systemd system, and user units, and udev rule, these user-units seem to be executing before the system-units. E.g. when a USB device connected for the first time, the zenity displays blank. When the device is ejected, and connected again the user-unit executes first and reads the previous values written by scripts run by system-unit and hence displays stale value (of previously inserted device).

Update: In setup-04, in user-unit .service file I added a delay of about 3-5 seconds, and the setup work as expected, but this is not how I want it to be, I want this to be done via Systemd settings in the unit files.

I used ExecStart=-/bin/bash -c 'sleep 3s; /opt/hdd_smart_dump_on_usb_trigger/bin/hdd_smart_dump_display_with_zenity.sh --display-dialogue' in the .service user-unit file.


Any idea what I'm doing wrong in these setup?

rusty
  • 16,327
  • Are you using a system service for that? ... I'm sure you know it but doesn't harm to remind that in such use cases a user service will inherit those needed environment settings/variables like USER, DISPLAY ... etc. by default so might be worth considering using a user service in that case. – Raffa Feb 16 '24 at 13:07
  • @Raffa Yes, and I think system service is the option I have, because I tried user service and the systemd part failed to work, not just GUI part but also there are no logs to say the script executed. Please see my updated post. – rusty Feb 16 '24 at 15:30
  • Apologies for late response ... I've been busy the whole day but, kept this in my head until I finally found time to write an answer that I hope will help ... It's a demonstration not a full solution but, it will be more than enough a pointer (I hope) for an experienced user like you ... There is a bit of a reminder though that user services run as the logged-in user vs. system services run as the user root by default so keep that in mind especially when a user's system permissions can make a difference. – Raffa Feb 17 '24 at 16:28
  • 1
    Oh, my my :-) the Systemd rabbit hole … We’ve all been there … Here is what might clear that or complicate it, but user units can not reference or depend on system units and vice versa is true … They run in completely isolated processes and they are managed by two different Systemd managers (a system units manager and a user units manager) … A sleep call is the simplest solution and if it must be in the Systemd units syntax (not in the script), then let it be ExecStartPre=/bin/sleep 3 … The outcome, however, is the same … I wish I had better news, but let’s hope someone else does. – Raffa Feb 19 '24 at 16:44
  • Thanks for clearing that up - no reference case. I think I'll have to go with ExecStartPre=/bin/sleep 3s if there is no more answer. – rusty Feb 19 '24 at 16:54
  • AFAIK smartctl processing time varies from disk to another (maybe it will exceed the set sleep time in some cases) … Therefore, including a timestamp in the generated output file or even in its name and having the script triggered by the user service process that timestamp comparing it to current time so it avoids old output file and wait for the new one (or something similar) might be a more sustainable solution I think. – Raffa Feb 19 '24 at 17:17
  • You could use a systemd.path unit to wait for the results file – Daniel T Feb 19 '24 at 17:23
  • Your question has an accepted answer but the bounty hasn't been awarded. I've quickly browsed comments but am unclear as to if the problem has been solved? – WinEunuuchs2Unix Feb 24 '24 at 00:58
  • @WinEunuuchs2Unix, Yes, the initial question has been solved - bringing up zenity in Wayland part. But the systemd user unit as suggested, in the solution existing, can not guarantee the order of execution which I need is after the system unit has run/finished. To this as Raffa has suggested I've implemented a test timestamp and wait for a margin of time before quitting user unit. This was needed because he also stated that we may not control startup orders between system and user units in systemd. – rusty Feb 24 '24 at 02:55

1 Answers1

4

This is a demonstration for triggering a zenity dialog from within a Systemd user service that is triggered by a UDEV rule that is triggered bu inserting (adding) a USB disk ... The purpose of this answer is to serve as a template or boilerplate and it's not meant as an actual solution to your use case.

Create the user service unit file:

cat <<'EOF'>  ~/.config/systemd/user/my-test-zenity.service 
[Unit]
Description=Test zenity dialog from a user sevice
After=graphical-session.target

[Service] Type=oneshot ExecStart=/bin/sh -c 'zenity --info --text="USB Disk Added"'

[Install] WantedBy=graphical-session.target EOF

Inform the Systemd daemon about it:

systemctl --user daemon-reload

Enable it and start it:

systemctl --user enable --now my-test-zenity.service

... that should have triggered the zenity dialog window and you should have seen it.

Create the UDEV rule:

cat <<'EOF' | sudo tee /etc/udev/rules.d/70-user-service.rules
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd*", ENV{DEVTYPE}=="disk", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}+="my-test-zenity.service"
EOF

... Notice SYSTEMD_USER_WANTS for user services vs. SYSTEMD_WANTS for system services.

Restart the UDEV service to catch the new rules file:

sudo systemctl restart udev

Test it:

Insert a USB disk and you should see the zenity dialog window triggered ... This should trigger equally on any display server as long as a graphical user session is running ... More related discussion here.

Notes:

An excerpt from the comments above: ... user units can not reference or depend on system units and vice versa is true … They run in completely isolated processes and they are managed by two different Systemd managers (a system units manager and a user units manager) ...

rusty
  • 16,327
Raffa
  • 32,237
  • I tried user service, and indeed my systemd units ran and could also launch zenity, but my goal is to display result of scan performed by smartctl which requires root, where the user service came short, and my script failed. When I use system service smartctl succeeds and does write a log at my temporary directory, but zenity fails to launch and show this file in Wayland. Can you help me with that? – rusty Feb 18 '24 at 13:50
  • 1
    @rusty One possible solution is to use both ENV{SYSTEMD_WANTS}+="your-systm.service" , ENV{SYSTEMD_USER_WANTS}+="my-test-zenity.service" where the system service will do things that require elevated user privileges as the root user and the user service will check for, processes output and show the zenity dialogue as the logged in user. – Raffa Feb 18 '24 at 15:05
  • I have the option to perform smartctl scan in either udev run .sh script, or from systemd system service. Which one would you recommend? – rusty Feb 18 '24 at 15:31
  • 2
    @rusty UDEV processes are sandboxed in some aspects e.g network access and a device that triggers a UDEV rule might not be made available until all rules it triggers finish processing so utilities might not see the device if they are run meanwhile see for example https://askubuntu.com/a/1417803 … Therefore a systemd service is preferable as it will allow the UDEV rule to finish processing and make the device available for utilities used in your script including smartctl. – Raffa Feb 18 '24 at 15:46
  • I remember I needed quite a bit of research, and reading to clobber my setup which worked for me at the time of Xubuntu 16.04, still works in Xubuntu 23.10. Now, I seem to be not remembering much of those, so I ask for more help, not that I could have managed to get this user unit setup then. – rusty Feb 19 '24 at 08:30
  • Using similar constructs of system unit templates ...@.service and ...@.target, for user unit I managed to bring up zenity command run by user unit ...@.system, but as I did not specify any precedence in my user unit, the zenity came up with blank. After that I added Requires=system-unit@%i.??? and After=system-unit@%i.??? in user unit ...@.target, then the user unit failed to launch. – rusty Feb 19 '24 at 11:09
  • Awarding bounty +50 for your answer in comments. – rusty Feb 25 '24 at 14:09
  • @rusty Thanks ... Please, feel free to add whichever of those comments you might feel will benefit future readers as notes in my answer if you like ... You don't have to but, if you do, it would be a great honor for me ... I am happy I could help :-) – Raffa Feb 25 '24 at 14:18