I've got an eeepc with an intel graphics. I'd like to hook a script to the event of a monitor plugged via VGA. How to do that?
-
1For people looking for a Windows solution: http://stackoverflow.com/questions/1440285/how-to-detect-hot-plugging-of-monitor-in-a-win32-application http://stackoverflow.com/questions/3267722/getting-an-event-on-monitor-hotplug-for-windows http://stackoverflow.com/questions/5981520/detect-external-display-being-connected-or-removed-under-windows-7 – hippietrail May 13 '11 at 08:12
5 Answers
As a crude solution, you may be able to poll on sysfs. On my laptop I have:
$ cat /sys/class/drm/card0-LVDS-1/status
connected
$ cat /sys/class/drm/card0-VGA-1/status
disconnected
I'm guessing this requires kernel DRM and possibly KMS.
To see if you can trigger something automatically, you could run udevadm monitor --property
, and watch while you are (dis-)connecting the monitor to see if events are reported.
With my radeon, I get an event the first time I connect a VGA monitor, but no events on subsequent disconnects and reconnects. The event should look something like (using yours as an example):
KERNEL[1303765357.560848] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV_LOG=0
ACTION=change
DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0
SUBSYSTEM=drm
HOTPLUG=1
DEVNAME=dri/card0
DEVTYPE=drm_minor
SEQNUM=2943
MAJOR=226
MINOR=0
Unfortunately there's not a lot to match against, but as long as there's only one video card in the picture that's not too important. Find where udev gets rules from on your system (probably /etc/udev/rules.d/
), and create a 99-monitor-hotplug.rules
file with:
ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/root/hotplug.sh"
udev
will then run hotplug.sh
when a display is connected. As a test, I put the following in /root/hotplug.sh
(don't forget to make this script executable):
#!/bin/sh
for output in DVI-I-1 LVDS-1 VGA-1; do
echo $output >> /root/hotplug.log
cat /sys/class/drm/card0-$output/status >> /root/hotplug.log
done
With that, I got an entry in hotplug.log
after I connected an external display. Even filtering for ACTION=="change"
, I still got some events on boot, so you may want to take that into account somehow in your script.

- 399
- 2
- 9

- 4,789
- 23
- 20
-
1
-
@Tass if you are getting events, ping me, and I can probably come up with a udev rule to run a script – Andy Apr 21 '11 at 04:48
-
4Thanks Andy for this! I've created a script that is inspired by this post. You can fetch it at https://github.com/codingtony/udev-monitor-hotplug .It uses xrandr to toggle the monitor on and off when they are plugged in/plugged out. I hope it will help. – Tony Dec 03 '12 at 01:16
-
"I get an event the first time I connect a VGA monitor, but no events on subsequent disconnects and reconnects" Same for me, but it seems to only execute my script that first time. Is your hotplug.sh custom script getting called on each time you disconnect and reconnect your monitor? – user779159 Mar 21 '13 at 12:50
-
I'm trying to set this up to account for the possibility of the system being started with no monitor attached. For me, udev shows both connect and disconnect events, but only if the monitor was attached at system boot. Any idea how to get it to pay attention if nothing's hooked up when udev starts? Resorting to polling would require a much messier script... – Perkins Oct 29 '14 at 22:06
-
This other answer is on the right path: you want to listen to DRM events from udev
.
I've implemented a Python script that runs some code when either USB devices or external displays are (un)plugged. I'm including below a minimal version of that script (untested):
#!/usr/bin/env python3
import pyudev
def udev_event_received(device):
... # Your code here!
context = pyudev.Context()
monitor_drm = pyudev.Monitor.from_netlink(context)
monitor_drm.filter_by(subsystem='drm')
observer_drm = pyudev.MonitorObserver(monitor_drm, callback=udev_event_received, daemon=False)
observer_drm.start()
# This will prevent the program from finishing:
observer_drm.join()
See also:

- 47,466
- 33
- 109
- 111
You have three options:
- Poll on a specific entry in sysfs.
- Use inotify to detect changes in sysfs.
- Use a netlink socket with NETLINK_KOBJECT_UEVENT and listen for a
change
uevent for the device you want.
In any of the ways mentioned, you're still going to have to poll in one way or another, so I'd just go with the first option.

- 3,751
- 17
- 20
-
2Both `inotify` and `netlink` sockets enable you to use `select()` and friends. Do you really consider that "polling"? – Brian Cain Nov 30 '12 at 03:03
-
The beauty of using select() or poll() for "polling for updates" is that you get to sleep until either a timeout or the kernel wakes you up to tell you that one of the things you're "polling" for has happened (Kind of misleading. It is and isn't the same thing as what most people call "polling". It's even the interface for GPIO interrupts... ;) )- so it's less wasteful of the CPU resources, etc. You're better off "polling" using the select() or poll() interfaces. – Svartalf Feb 23 '15 at 16:52
-
4inotify does not work on sysfs changes since it is not a real file system per se. Try it if you don't believe me. `sudo inotifywait -e modify -m --format '%:e %f' /sys/class/drm/something` so your 2nd option is not valid. – nicholas.alipaz Mar 11 '15 at 20:49
-
*“No, inotify doesn't work on sysfs, or if it does, that's by "accident", and any data you are getting for this is probably totally wrong.”* [Greg KH on 2014-03-29](http://comments.gmane.org/gmane.linux.file-systems/83641) – Denilson Sá Maia Feb 13 '16 at 10:50
-
@DenilsonSáMaia Your link is broken today, or I don't have access to it... – WinEunuuchs2Unix Sep 30 '18 at 15:29
-
@WinEunuuchs2Unix: New link: https://www.spinics.net/lists/linux-fsdevel/msg73924.html – Denilson Sá Maia Oct 01 '18 at 16:22
-
@DenilsonSáMaia Thanks for the link. I'm going to abandon `inotifywait` for now and attempt `dbus-monitor` instead. – WinEunuuchs2Unix Oct 01 '18 at 22:39
-
@WinEunuuchs2Unix, in case you missed; yesterday I also posted an answer: https://stackoverflow.com/a/52595370 – Denilson Sá Maia Oct 03 '18 at 05:45
Thanks sebastianwagner!
With this information, I've been able to successfully boot my Kodi media center with the TV turned off.
Indeed, when the TV is off, the Intel driver doesn't want to set up a mode and I got a blank screen when I later powered on the TV.
The Kodi log showed the following line:
WARNING: CXRandR::Query - output HDMI1 has no current mode, assuming disconnected
So I created the following line in /etc/udev/rules.d/99-monitor-hotplug.rules :
ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/usr/sbin/hotplugtv.sh"
Content of /usr/sbin/hotplugtv.sh (my X server is running as root) :
#!/bin/bash
export DISPLAY=:0
export XAUTHORITY=/root/.Xauthority
/bin/date 2>&1 >> /var/log/hotplugtv.log;
if [[ $(cat /sys/class/drm/card0-HDMI-A-1/status | grep -Ec "^connected") -eq 1 ]]; then
echo "TV connected!" >> /var/log/hotplugtv.log;
/bin/sleep 2s;
/usr/bin/xrandr --verbose --output HDMI1 --auto 2>&1 >> /var/log/hotplugtv.log;
else
echo "TV disconnected!" >> /var/log/hotplugtv.log;
fi
Don't forget to reload udev rules when you make any change to your script (this was driving me crazy!):
udevadm control --reload-rules
Be careful to disable any screen saver in Kodi because they stay activated forever when you finally power up the TV. On the other hand energy saving / DPMS seems to work fine.

- 31
- 2
Assuming you're running X, a script can parse the output of xrandr to see what monitors are connected. This should work with any graphics card. This is the same tool you'll probably use to make use of the change in your script.
It doesn't solve the issue with notifications to automatically run a script. While I don't have a great generic solution, a common case is detecting when an external monitor is present because a laptop is connected to a docking station. In this case, you can have your script trigger off of something else that triggers when connecting to the docking station such as the addition or removal of a USB keyboard or ethernet.

- 21
- 1