4

I am trying to get a script to run every time my HDMI monitor is plugged in and after doing some reading I found this and in it asks me to create 99-monitor-hotplug.rules and put it /etc/udev/rules.d and specify which script I want to run. The rule looks like this:

ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/root/hotplug.sh"

Well I did that but the script does not run. I know this because in the script all I have is:

#!/bin/bash
opera

I made the script deliberately that simple so I can see something is happening. When I invoke the script from the command line, Opera does run.

Here is what what happens when I plug and unplug my HDMI monitor when "udevadm monitor --property" is running:

monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[730.834194] change   /devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1 (drm)
ACTION=change
DEVNAME=/dev/dri/card1
DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1
DEVTYPE=drm_minor
HOTPLUG=1
MAJOR=226
MINOR=1
SEQNUM=3245
SUBSYSTEM=drm

UDEV  [730.835499] change   /devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1 (drm)
ACTION=change
DEVNAME=/dev/dri/card1
DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1
DEVTYPE=drm_minor
HOTPLUG=1
ID_FOR_SEAT=drm-pci-0000_01_00_0
ID_PATH=pci-0000:01:00.0
ID_PATH_TAG=pci-0000_01_00_0
MAJOR=226
MINOR=1
SEQNUM=3245
SUBSYSTEM=drm
TAGS=:seat:uaccess:master-of-seat:
USEC_INITIALIZED=3217504

KERNEL[738.204082] change   /devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1 (drm)
ACTION=change
DEVNAME=/dev/dri/card1
DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1
DEVTYPE=drm_minor
HOTPLUG=1
MAJOR=226
MINOR=1
SEQNUM=3246
SUBSYSTEM=drm

UDEV  [738.206107] change   /devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1 (drm)
ACTION=change
DEVNAME=/dev/dri/card1
DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1
DEVTYPE=drm_minor
HOTPLUG=1
ID_FOR_SEAT=drm-pci-0000_01_00_0
ID_PATH=pci-0000:01:00.0
ID_PATH_TAG=pci-0000_01_00_0
MAJOR=226
MINOR=1
SEQNUM=3246
SUBSYSTEM=drm
TAGS=:seat:uaccess:master-of-seat:
USEC_INITIALIZED=3217504

Once the rule was added, I did run: sudo udevadm control --reload-rules

Can someone assist please? I have a feeling the rule might be incorrect and I am new to creating udev rules. I am running Ubuntu 16.04.

rwx
  • 163

2 Answers2

2

opera? Oh no! RUN is only for short running tasks, udev run the command in a confined environment.

No GUI supported, daemon will be killed just after finishing the event processing.

If you want just to test if the rule is triggered, try this:

#!/bin/bash
date >> /root/myrule.log

Reference: man udev

RUN{type}

This can only be used for very short-running foreground tasks. Running an event process for a long period of time may block all further events for this or a dependent device.

Starting daemons or other long-running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished.

user.dz
  • 48,105
  • 1
    It worked! Thank you! I had no idea we are not meant to invoke GUIs, thank you. As I said I am new to this area but now I know! :) I've marked the post as solved. – rwx Jun 24 '16 at 08:52
  • 1
    @rwx: It is not exactly as you wrote/understood it; you CAN invoke GUI-running programs from udev rules, but you must specify the DISPLAY environment variables within yr script. What is even more pertinent in Sneetscher's answer is the fact that you should NOT invoke LONG-RUNNING programs using ANY udev rule. – Cbhihe Jun 24 '16 at 11:45
  • @Cbhihe right , even there is workaround for LONG-RUNNING programs . By creating dual script, 1st calls 2nd and disown it. – user.dz Jun 24 '16 at 14:52
  • @Sneetsher: yes, Sir ! ... or simply run it in the background, but it must be made non interactive if a script. (somewhat out of OP's question's scope anyway). – Cbhihe Jun 24 '16 at 18:44
  • @Cbhihe, background?! have you tried it. I thought it will be killed after some timeout. I have to try this later :) – user.dz Jun 24 '16 at 18:47
  • 1
    @Sneetsher: It definitely works, if you're a little careful not to run into race situations between yr calling one or several background jobs and the rest of the script where it may apply. I actually run non-interactive "background gui jobs" to launch gui backup apps from udev rules checking for external backup volume being added/hot-plugged in. At the end of the job the gui window automatically dies. Most importantly it does not hang-up other udev rules while the background job runs. I would not write this down as a recommendation though. It's a bit on the odd/sloppy side. – Cbhihe Jun 24 '16 at 18:55
1

user.dz' answer works for me only the first time. This approach works for me every time:

KERNEL=="card0", SUBSYSTEM=="drm", ACTION=="change", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/marco/.Xauthority", RUN+="/bin/bash /root/hdmi_hotplug.sh"
Marco Sulla
  • 662
  • 3
  • 11
  • 30