Ask Ubuntu is a question and answer site for Ubuntu users and developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have the following rule call my script when I dock or un-dock my ThinkPad:

# /lib/udev/rules.d/81-thinkpad-dock.rules
KERNEL=="dock.0", ATTR{docked}=="0", RUN+="/usr/bin/think-dock-hook off"
KERNEL=="dock.0", ATTR{docked}=="1", RUN+="/usr/bin/think-dock-hook on"

That is the script that will be called:

# /usr/bin/think-dock-hook
# Find the user who is currently logged in on the primary screen.
user="$(who -u | grep -F '(:0)' | head -n 1 | awk '{print $1}')"
su -c "bash -x /usr/bin/think-dock $setto" "$user" >> /root/think-dock.log 2>&1 &

And the script that is then called does something with xrandr.

The thing is that I can run think-dock on as my user (mu) and it works. I can sudo -i and run think-dock-hook on and it works too. But when I let udev run it, it just get the following error from xrandr:

# output of bash -x think-dock on
+ xrandr --output LVDS1 --auto
Can't open display

Now if I call xrandr from my sudo -i shell, I get:

No protocol specified
No protocol specified
Can't open display :0

However, if I do su -c xrandr mu from my sudo -i shell, I get the expected output.

So I do not really understand, the script called from udev fails.

share|improve this question
grep -F '(:0)' should be grep -F '(:0.0)'; also try sticking a DISPLAY=:0.0 in front of /usr/bin/think-dock – izx Aug 28 '12 at 20:38
That DISPLAY seems good. My who displays (:0) although. So I do not think that grep would be better that way. – Martin Ueding Aug 29 '12 at 19:38
Okay, with the DISPLAY in front of bash, it seems to work now. Thanks! – Martin Ueding Aug 29 '12 at 19:50
Great! My who had 0.0, but anyway. Since it worked, I'll add the DISPLAY part as an answer; please accept it. Thanks! – izx Aug 29 '12 at 23:38
up vote 6 down vote accepted
  • xrandr needs to know which display you're talking about, typically via the DISPLAY environment variable
  • root (which udev runs as) has no default DISPLAY set; even if he/she did, su -c does not preserve the environment by default
  • So pass it along explicitly to bash, and that should solve your problem, e.g.:

    su -c "DISPLAY=:0.0 bash -x /usr/bin/think-dock $setto" "$user"
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.