I'd like to run a screen if the Gnome session is locked and unlocked. Is there a way that I can intercept this and perform certain actions when the desktop is locked or unlocked?

up vote 40 down vote accepted

Gnome-screensaver emits some signals on dbus when something happens.

Here the documentation (with some examples).

You could write a scripts that runs:

dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'"

and that does what you need anytime dbus-monitor prints a line about the screen being locked/unlocked.


Here a bash command to do what you need:

dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" |
  while read x; do
    case "$x" in 
      *"boolean true"*) echo SCREEN_LOCKED;;
      *"boolean false"*) echo SCREEN_UNLOCKED;;  
    esac
  done

Just replace echo SCREEN_LOCKED and echo SCREEN_UNLOCKED with what you need.

  • Hi @peoro, That makes me think you can unlock or lock gnome screen/session from a scripted program, worth doing some ssh tricks about it ;-) – Nikhil Mulley Jan 3 '12 at 5:13
  • 1
    @Nikhil: to do that you don't need to play around with dbus: gnome-screensaver-command is already there. Passing -a to gnome-screensaver-command you'll lock the screen, while you'll unlock it with -d. Anyway most gnome apps use dbus extensively, so you'll be able to do many amazing things with it. – peoro Jan 3 '12 at 5:18
  • 1
    @peoro Thanks great, very helpful! Can I also run this as some sort of daemon? When I enter this in the terminal now, it has to stay open to monitor the dbus for that case. I would like to execute this command at login and then it can be active during the entire session. – Sander Jan 4 '12 at 16:13
  • 1
    I think things may have changed now in 2014? as the output doesnt change if the screen was only locked, it only shows something when it gets blanked and is very different from here :(, I created this question askubuntu.com/questions/505681/…, do you believe there is still some way to do that? thx! – Aquarius Power Aug 2 '14 at 2:18
  • How to run that script that it catches the lock event? Kinda like a watcher. – Starx Nov 1 '16 at 13:03

In ubuntu 14.04 the DBus event for screen lock unlock has changed and the new script for binding to screen lock and unlock events looks like the following

dbus-monitor --session "type='signal',interface='com.ubuntu.Upstart0_6'" | \
(
  while true; do
    read X
    if echo $X | grep "desktop-lock" &> /dev/null; then
      SCREEN_LOCKED;
    elif echo $X | grep "desktop-unlock" &> /dev/null; then
      SCREEN_UNLOCKED;
    fi
  done
)
  • ideas on how to make this work on fedora 23? – Ray Foss Apr 30 '16 at 21:49
  • 2
    Works fine on 16.04 as well – Jacob Vlijm Nov 29 '16 at 6:43
  • @JacobVlijm Thanks for testing this and green-lighting it for me to use tonight :) – WinEunuuchs2Unix Dec 8 '16 at 0:44

Ubuntu 16.04: ozma’s solution did not work for me, however this one did:

dbus-monitor --session "type=signal,interface=com.canonical.Unity.Session,member=Unlocked" | 
  while read MSG; do
    LOCK_STAT=`echo $MSG | awk '{print $NF}'`
    if [[ "$LOCK_STAT" == "member=Unlocked" ]]; then
        echo "was unlocked"
    fi
  done
  • It might work on Unity but question was in regards to Gnome. – cprn Jun 1 '17 at 10:03

If you're on Kubuntu or using KDE / Plasma as your Desktop Environment, you have to listen for the interface org.freedesktop.ScreenSaver, so the script for listening to that event would look like this:

dbus-monitor --session "type='signal',interface='org.freedesktop.ScreenSaver'" |
  while read x; do
    case "$x" in 
      *"boolean true"*) echo SCREEN_LOCKED;;
      *"boolean false"*) echo SCREEN_UNLOCKED;;  
    esac
  done

Expanding on already given answer.

If you try to run a script from inside a screen or tmux session, you'll need to find the correct $DBUS_SESSION_BUS_ADDRESS first and pass it as an argument for dbus-monitor instead of --session. Also if you're running it as a daemon you should make sure only one instance is running at a time (e.g. with a lock file) and that the script cleans up after itself with trap. The following example will work as a daemon in most current Gnome environments (tested on Ubuntu GNOME 16.04):

#!/bin/bash
set -o nounset                # good practice, exit if unset variable used

pidfile=/tmp/lastauth.pid     # lock file path
logfile=/tmp/lastauth.log     # log file path

cleanup() {                   # when cleaning up:
    rm -f $pidfile            # * remove the lock file
    trap - INT TERM EXIT      # * reset kernel signal catching
    exit                      # * stop the daemon
}

log() {                       # simple logging format example
    echo $(date +%Y-%m-%d\ %X) -- $USER -- "$@" >> $logfile
}

if [ -e "$pidfile" ]; then    # if lock file exists, exit
    log $0 already running...
    exit
fi

trap cleanup INT TERM EXIT    # call cleanup() if e.g. killed

log daemon started...

echo $$ > $pidfile            # create lock file with own PID inside

# usually `dbus-daemon` address can be guessed (`-s` returns 1st PID found)
export $(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pidof -s dbus-daemon)/environ)

expr='type=signal,interface=org.gnome.ScreenSaver' # DBus watch expression here

dbus-monitor --address $DBUS_SESSION_BUS_ADDRESS "$expr" | \ 
    while read line; do
        case "$line" in
            *"boolean true"*) log session locked;;
            *"boolean false"*) log session unlocked;;
        esac
    done

cleanup # let's not leave orphaned lock file when the loop ends (e.g. dbus dies)

If this doesn't work for you, it's probably because:

  1. you don't use Gnome - check other answers for better DBus watch expression
  2. you run multiple DBus lines - check details on how to make PID finding deterministic
  • 1
    This actually answers a different question I had for dynamically discovering the DBus session information given a user account, which I have solved here. Thanks for your contribution here! – Naftuli Kay Jun 2 '17 at 5:10
  • Thanks. I'll link your solution in the answer for further reading. – cprn Jun 2 '17 at 9:53

Nowadays I think it's better to listen to the LockedHint rather than screensaver messages. That way you're not tied to a screensaver implementation.

Here's a simple script to do that:

gdbus monitor -y -d org.freedesktop.login1 | grep LockedHint

Gives this:

/org/freedesktop/login1/session/_32: org.freedesktop.DBus.Properties.PropertiesChanged ('org.freedesktop.login1.Session', {'LockedHint': <true>}, @as [])
/org/freedesktop/login1/session/_32: org.freedesktop.DBus.Properties.PropertiesChanged ('org.freedesktop.login1.Session', {'LockedHint': <false>}, @as [])

Where to write this code and how it will run:

dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" |
  while read x; do
    case "$x" in 
      *"boolean true"*) echo SCREEN_LOCKED;;
      *"boolean false"*) echo SCREEN_UNLOCKED;;  
    esac
  done

this is what worked for me in ubuntu 16.04

dbus-monitor --session "type=signal,interface=org.gnome.ScreenSaver" | 
  while read MSG; do
    LOCK_STAT=`echo $MSG | grep boolean | awk '{print $2}'`
    if [[ "$LOCK_STAT" == "true" ]]; then
        echo "was locked"
    else
        echo "was un-locked"
    fi
  done
  • This didn't work for me. As it finished executing and does not listen to the state changed. – Starx Nov 1 '16 at 13:12
  • which screen saver are you using? gnome or xscreensaver? which flavor ubuntu, xubuntu, kubuntu etc. which version (it was tested on 16.04) – ozma Nov 1 '16 at 14:06
  • ubuntu gnome 16.04 – Starx Nov 2 '16 at 9:25

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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