85

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?

0

12 Answers 12

79

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.

6
  • 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 ;-) Commented Jan 3, 2012 at 5:13
  • 2
    @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
    Commented Jan 3, 2012 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
    Commented Jan 4, 2012 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! Commented Aug 2, 2014 at 2:18
  • 1
    Does anybody know how or where to hook this script to start listening on first login?
    – hanzo2001
    Commented Nov 29, 2017 at 11:30
28

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 [])
2
  • 1
    This 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: github.com/gogama/lockheed.
    – 0xbe5077ed
    Commented Nov 4, 2022 at 17:52
  • Nice. A little more information would be appreciated (without having to go through all the docs). Commented Sep 4, 2023 at 20:37
23

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
)
3
  • ideas on how to make this work on fedora 23?
    – Ray Foss
    Commented Apr 30, 2016 at 21:49
  • 2
    Works fine on 16.04 as well Commented Nov 29, 2016 at 6:43
  • @JacobVlijm Thanks for testing this and green-lighting it for me to use tonight :) Commented Dec 8, 2016 at 0:44
9

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.
3
  • 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! Commented Jun 2, 2017 at 5:10
  • Thanks. I'll link your solution in the answer for further reading.
    – cprn
    Commented Jun 2, 2017 at 9:53
  • 1
    Nice 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
    Commented Jan 31, 2022 at 21:45
8

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
2
  • 5
    If you use KDE/Plasma you can use the Plasma Desktop settings to execute scripts on notifications... Personalization>Notifications>Notifications>Screensaver.
    – xenoid
    Commented Apr 3, 2019 at 12:40
  • 1
    thanks @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
    Commented Sep 19, 2019 at 13:32
5

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
1
  • It might work on Unity but question was in regards to Gnome.
    – cprn
    Commented Jun 1, 2017 at 10:03
2

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)

1
1

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
)
1

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
5
  • This didn't work for me. As it finished executing and does not listen to the state changed.
    – Starx
    Commented Nov 1, 2016 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
    Commented Nov 1, 2016 at 14:06
  • ubuntu gnome 16.04
    – Starx
    Commented Nov 2, 2016 at 9:25
  • 1
    this 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
    Commented Mar 10, 2020 at 17:02
  • 1
    Might be easier to use a case rather than (non-portable) [[. Instead of grep|awk, consider using a single awk invocation (awk '$1 == "boolean" {print $2}'). Commented Oct 13, 2022 at 15:55
0

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
0

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
0

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'".

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .