如何在屏幕锁定/解锁时运行脚本?

Naf*_*Kay 72 linux gnome x11

如果 Gnome 会话被锁定和解锁,我想运行一个脚本。
有没有办法在桌面锁定或解锁时拦截它并执行某些操作?

peo*_*oro 66

当发生某些事情时,Gnome-screensaver 会在 dbus 上发出一些信号。

这里的文档(带有一些示例)。

您可以编写一个运行的脚本:

dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'"
Run Code Online (Sandbox Code Playgroud)

并且可以随时dbus-monitor打印有关屏幕被锁定/解锁的行。


这里有一个 bash 命令来做你需要的:

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
Run Code Online (Sandbox Code Playgroud)

只需更换echo SCREEN_LOCKEDecho SCREEN_UNLOCKED使用您需要的东西。

  • @Nikhil:要做到这一点,您无需使用 dbus:`gnome-screensaver-command` 已经存在。将 `-a` 传递给 `gnome-screensaver-command` 你会锁定屏幕,而你会用 `-d` 解锁它。无论如何,大多数 gnome 应用程序都广泛使用 dbus,因此您将能够用它做许多令人惊奇的事情。 (2认同)

Luv*_*wal 23

在 ubuntu 14.04 中,用于屏幕锁定解锁的 DBus 事件已更改,用于绑定到屏幕锁定和解锁事件的新脚本如下所示

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
)
Run Code Online (Sandbox Code Playgroud)

  • 在 16.04 上也能正常工作 (2认同)

小智 17

现在我觉得最好听听 LockedHint而不是屏幕保护程序消息。这样你就不会被屏幕保护程序的实现所束缚。

这是一个简单的脚本来做到这一点:

gdbus monitor -y -d org.freedesktop.login1 | grep LockedHint
Run Code Online (Sandbox Code Playgroud)

给出了这个:

/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 [])
Run Code Online (Sandbox Code Playgroud)


Bob*_*Bob 7

如果您使用 Kubuntu 或使用 KDE/Plasma 作为桌面环境,则必须监听 interface org.freedesktop.ScreenSaver,因此监听该事件的脚本如下所示:

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
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用 KDE/Plasma,您可以使用 Plasma 桌面设置在通知上执行脚本...`Personalization&gt;Notifications&gt;Notifications&gt;Screensaver`。 (3认同)

cpr*_*prn 7

扩展已经给出的答案。

如果您尝试从screentmux会话中运行脚本,则需要首先找到正确的$DBUS_SESSION_BUS_ADDRESS并将其作为参数传递给dbus-monitor而不是--session。此外,如果您将它作为守护程序运行,则应确保一次仅运行一个实例(例如,使用锁定文件),并且脚本在使用trap. 以下示例将在大多数当前 Gnome 环境(在 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)
Run Code Online (Sandbox Code Playgroud)

如果这对您不起作用,可能是因为:

  1. 你不使用 Gnome - 检查其他答案以获得更好的 DBus 手表表达。
  2. 您运行多条 DBus 线路 - 检查有关如何使 PID 查找具有确定性的详细信息


小智 5

Ubuntu 16.04:ozma 的解决方案对我不起作用,但是这个解决方案做到了:

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
Run Code Online (Sandbox Code Playgroud)