Запустить скрипт на экране блокировки / разблокировки

54

Я хотел бы запустить экран, если сеанс Gnome заблокирован и разблокирован. Есть ли способ, которым я могу перехватить это и выполнить определенные действия, когда рабочий стол заблокирован или разблокирован?

Нафтули Кей
источник

Ответы:

49

Gnome-заставка генерирует некоторые сигналы на dbus, когда что-то происходит.

Здесь документация (с некоторыми примерами).

Вы могли бы написать сценарии, которые выполняются:

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

и это делает то, что вам нужно, в любое время 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

Просто замените echo SCREEN_LOCKEDи echo SCREEN_UNLOCKEDтем, что вам нужно.

peoro
источник
Привет @peoro, Это заставляет меня думать, что ты можешь разблокировать или заблокировать экран / сессию gnome с помощью скриптовой программы, стоит сделать некоторые трюки с ssh ;-)
Nikhil Mulley
1
@Nikhil: для этого вам не нужно играть с dbus: gnome-screensaver-commandуже есть. Переходя -aк gnome-screensaver-commandблокировке экрана, вы разблокируете его с помощью -d. В любом случае, большинство приложений для гномов широко используют dbus, поэтому вы сможете делать с ним много удивительных вещей.
peoro
1
@peoro Спасибо большое, очень полезно! Могу ли я запустить это как своего рода демон? Когда я сейчас ввожу это в терминал, он должен оставаться открытым, чтобы контролировать шину для этого случая. Я хотел бы выполнить эту команду при входе в систему, а затем она может быть активной в течение всего сеанса.
Сандер
1
Я думаю, что все могло измениться в 2014 году? так как вывод не меняется, если экран был заблокирован, он только показывает что-то, когда он отключается и сильно отличается от этого :(, я создал этот вопрос askubuntu.com/questions/505681/… , вы верите, что еще есть способ сделать это? THX!
Водолей Power
Как запустить тот скрипт, чтобы он ловил событие блокировки? Вроде как наблюдатель.
Starx
20

В 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
)
Лув Агарвал
источник
идеи о том, как сделать эту работу на Fedora 23?
Рэй Фосс
2
Хорошо работает и 16.04
Якоб Влийм
@JacobVlijm Спасибо за тестирование этого и зеленое освещение для меня, чтобы использовать сегодня вечером :)
WinEunuuchs2Unix
6

В настоящее время я думаю, что лучше слушать сообщения LockedHint, чем заставки. Таким образом, вы не привязаны к реализации заставки.

Вот простой скрипт для этого:

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

Дает это:

/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 [])
Мэтью
источник
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
Артемий Трегубенко
источник
Это может работать на Unity, но вопрос был в отношении Gnome.
cprn
5

Расширение на уже предоставленный ответ.

Если вы попытаетесь запустить сценарий из сеанса screenили tmux, вам нужно $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)

Если это не работает для вас, это, вероятно, потому что:

  1. Вы не используете Gnome - проверьте другие ответы для лучшего выражения часов DBus.
  2. Вы запускаете несколько строк DBus - проверьте детали того, как сделать PID-детерминированным.
CpRn
источник
1
Это фактически отвечает на другой вопрос, который у меня был для динамического поиска информации о сеансе DBus с учетом учетной записи пользователя, который я решил здесь . Спасибо за ваш вклад здесь!
Нафтули Кей
Благодарю. Я свяжу ваше решение в ответе для дальнейшего чтения.
cprn
4

Если вы используете Kubuntu или используете KDE / Plasma в качестве среды рабочего стола, вы должны прослушивать интерфейс 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
боб
источник
1
Если вы используете KDE / Plasma вы можете использовать настройки Plasma Desktop для выполнения скриптов на уведомлениях ... Personalization>Notifications>Notifications>Screensaver.
ксеноид
спасибо @xenoid! KDE настолько персонализированный, что вам никогда не придется возиться с этими вещами. как будто они ожидают, что мне нужно
Ankur S
0

upstart сессионный Иов Поддержит desktop-lockи desktop-unlockсобытие в start onстрофе. Просто создать работу .conf для вашего пользователя с соответствующими триггерами и командами вызова в соответствии $XDG_CONFIG_HOME/upstart/или $HOME/.config/upstartкак пример ниже:

description "some job description"
start on desktop-lock
script
        /path/to/your/executable
end script
Олег В. Волков
источник
0

это может быть не самое чистое решение, но оно работает для меня, когда dbus-monitor ...нет:

gdbus monitor -y -d org.freedesktop.login1 |\
 grep --line-buffered -i "LockedHint" |\
 sed -uE 's/.*LockedHint.*<(.*)>.*/\1/g'

Должен возвращать поток строк со строками 'true' или 'false'

Использование: Fedora релиз 30 (тридцать)

user2777461
источник
кажется, продолжение этого ответа
Джефф Шаллер
-1

это то, что у меня сработало в 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
Озма
источник
Это не сработало для меня. Как он закончил выполнение и не слушал, состояние изменилось.
Starx
какую заставку вы используете? гном или экранная заставка? какой вкус ubuntu, xubuntu, kubuntu и т. д. какая версия (была протестирована 16.04)
ozma
Убунту гном 16.04
Starx