I'd like to run a script 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?

- 14,406

- 39,676
12 Answers
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.
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 [])

- 401
-
1This approach with
gdbus monitor
is the one that worked for me on Ubuntu 20.04 with Gnome 3. Packaged it as a script if you want to use it as a building block for automation: https://github.com/gogama/lockheed. – 0xbe5077ed Nov 04 '22 at 17:52 -
Nice. A little more information would be appreciated (without having to go through all the docs). – Luis A. Florit Sep 04 '23 at 20:37
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
)

- 341
-
-
2
-
@JacobVlijm Thanks for testing this and green-lighting it for me to use tonight :) – WinEunuuchs2Unix Dec 08 '16 at 00:44
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:
- you don't use Gnome - check other answers for better DBus watch expression.
- you run multiple DBus lines - check details on how to make PID finding deterministic.
-
1This 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 02 '17 at 05:10
-
-
1Nice solution with great techniques within. To suppress
bash: warning: command substitution: ignored null byte in input
, I suggest:export $(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pidof -s dbus-daemon)/environ|xargs -0)
. – fbicknel Jan 31 '22 at 21:45
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

- 350
-
5If you use KDE/Plasma you can use the Plasma Desktop settings to execute scripts on notifications...
Personalization>Notifications>Notifications>Screensaver
. – xenoid Apr 03 '19 at 12:40 -
1thanks @xenoid ! KDE is such a personalizable de that you never have to fiddle with these things. its as if they anticipate what I need – Ankur S Sep 19 '19 at 13:32
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

- 181
this may not be the cleanest solution but it works for me when dbus-monitor ...
does not:
gdbus monitor -y -d org.freedesktop.login1 |\
grep --line-buffered -i "LockedHint" |\
sed -uE 's/.*LockedHint.*<(.*)>.*/\1/g'
Should return stream of lines with strings 'true' or 'false'
Using: Fedora release 30 (Thirty)

- 21
Thanks for HaterTot comment another version. Tested on ubuntu 18.04
echo "start at `date`" >> ~/Documents/time-trecking.log
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 "locked `date +%s` `date`" >> ~/Documents/time-trecking.log
elif [[ "$LOCK_STAT" == "false" ]]; then
echo "unlock `date +%s` `date`" >> ~/Documents/time-trecking.log
fi
done
[Before Edit] 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

- 119
-
This didn't work for me. As it finished executing and does not listen to the state changed. – Starx Nov 01 '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 01 '16 at 14:06
-
-
1this worked for me on Ubuntu 19.10, but for me the "else" condition kept triggering when other messages unrelated messages popped up on invocation. So I just changed the logic to explicitly check for "false" – HaterTot Mar 10 '20 at 17:02
-
1Might be easier to use a
case
rather than (non-portable)[[
. Instead ofgrep|awk
, consider using a singleawk
invocation (awk '$1 == "boolean" {print $2}'
). – Toby Speight Oct 13 '22 at 15:55
Version for Cinnamon Desktop (Ubuntu 18.04):
dbus-monitor --session "type='signal',interface='org.cinnamon.ScreenSaver'" | \
(
while true; do
read X
if echo $X | grep "boolean true" &> /dev/null; then
echo `date` - SCREEN_LOCKED;
elif echo $X | grep "boolean false" &> /dev/null; then
echo `date` - SCREEN_UNLOCKED;
fi
done
)

- 11
upstart
session jobs support desktop-lock
and desktop-unlock
events in start on
stanza. Just create a job .conf for your user with relevant triggers and commands to call under $XDG_CONFIG_HOME/upstart/
or $HOME/.config/upstart
like example below:
description "some job description"
start on desktop-lock
script
/path/to/your/executable
end script

- 328
For KDE Plasma, we can listen to org.freedesktop.ScreenSaver
with:
dbus-monitor --session "type='signal',interface='org.freedesktop.ScreenSaver'"
But note that lock/unlock action are reported twice, the following script limit the action within 5 seconds (to avoid executing required command twice)
#!/bin/bash
screen_locked () {
if [[ $firstrun == '' ]] || [[ $(expr $(date +%s) - $firstrun) -ge 5 ]]
then
screen_locked_core;
firstrun=$(date +%s);
fi
}
screen_locked_core () {
echo locked
}
dbus-monitor --session "type='signal',interface='org.freedesktop.ScreenSaver'" |
while read x; do
case "$x" in
*"boolean true"*) screen_locked;;
# *"boolean false"*) screen_unlocked;;
esac
done

- 14,406
I used the same answer as peoro, but first I run only dbus-monitor --session "type='signal'"
in a terminal, and locked an unlocked my screen. Then, I could figure out the correct name for my operating system:
signal time=1680812432.954794 sender=:1.27 -> destination=(null destination) serial=3080 path=/org/xfce/ScreenSaver; interface=org.xfce.ScreenSaver; member=ActiveChanged
boolean true
signal time=1680812435.757417 sender=:1.27 -> destination=(null destination) serial=3082 path=/org/xfce/ScreenSaver; interface=org.xfce.ScreenSaver; member=ActiveChanged
boolean false
So, my command starts with dbus-monitor --session "type='signal',interface='org.xfce.ScreenSaver'"'
instead of dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'"
.

- 781
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 03 '12 at 05:13gnome-screensaver-command
is already there. Passing-a
tognome-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 03 '12 at 05:18I would like to execute this command at login and then it can be active during the entire session.
– Sander Jan 04 '12 at 16:13