How to run script after resume and after unlocking screen

In Ubuntu 12.04 LTS, I would like to run scripts after resuming from suspend, and after unlocking my desktop. These need to run as my user, and with access to my $DISPLAY.

In particular, I would like to

  • restart nm-applet to work around bug 985028
  • show a custom notification using notify-send
  • possibly other stuff when I get these working

When I resume, scripts in /etc/pm/sleep.d/ are run, but they run as root, without knowledge of my screen and username. It might work if I hard-code my username and export the default DISPLAY :0 in these scripts, but that feels like a very ugly hack.

Scripts in ~/.config/autostart/xyz.desktop run after login, but they don't run after merely unlocking the screen after resume.

Is there a way to run scripts after unlocking the screen after a resume?


It looks like you have to hard code the username in the previous answer anyways, so here's a simple script for in /etc/pm/sleep.d if anyone is looking for a quick fix:

#!/bin/bash 
case "$1" in
    hibernate|suspend)
        sudo -u USERNAME env DISPLAY=:0 zenity --info --text "do stuff on suspend"
        ;;
    thaw|resume)
        sudo -u USERNAME env DISPLAY=:0 zenity --info --text "do stuff on resume"
        ;;
esac

This question at the Unix & Linux site documents an alternative approach using dbus messages:

dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" | \
( while true; do
    read X;
    if echo $X | grep "boolean true" &> /dev/null; then
        SCREEN_LOCKED;
    elif echo $X | grep "boolean false" &> /dev/null; then
        SCREEN_UNLOCKED;
        fi
done )

(Replace SCREEN_LOCKED and SCREEN_UNLOCKED with the actions you want to perform.)

Using xrandr 1>/dev/null 2>1 as the action on unlocking fixed my problem that monitor resolutions/positions were not being correctly restored on screen unlocking (xrandr seems to cause a re-reading of screen settings). I added this line as a background task in my .bash_profile (strictly it might be better as a desktop file in ~/.config/autostart, since that only runs when you start gnome):

dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" | \
( while true; do
    read X;
    if echo $X | grep "boolean false" &> /dev/null; then
        xrandr 1>/dev/null 2>1;
        fi
done ) &

Further background on the gnome-screensaver API can be found at this site, and on the dbus monitor here.


One solution is a script which runs when logging into the desktop, and which catches dbus messages. After resume from suspend the screen is locked, and after entering the password, there is an Unlock event on dbus.

(Thanks to Kim SJ for putting me on the right track. I have no ScreenSaver signals, but found another interface to use).

In ~/.config/autostart/, I have a .desktop file which starts a bash script:

$ cat ~/.config/autostart/mymonitor.desktop
[Desktop Entry]
Categories=System;Monitor;
Comment=Monitor dbus for unlock signals
Exec=/usr/local/bin/unlock_monitor
Name=unlock_monitor
Type=Application

The unlock_monitor monitor script reads dbus messages from com.canonical.Unity.Session and does stuff on Unlocked signals:

#!/bin/bash

dbus-monitor --session "type=signal,interface=com.canonical.Unity.Session" --profile \
| while read dbusmsg; do
    if [[ "$dbusmsg" =~ Unlocked$ || "$dbusmsg" =~ NameAcquired$ ]] ; then
        sleep 5
        notify-send "$(basename $0)" "Unlocked or freshly logged in..."
        # ...
    fi
done

When logging in, there is no "Unlocked" signal, but there is a "NameAcquired" signal when dbus-monitor starts.