Как я могу выполнить локальную команду (для запуска скрипта) при (непосредственно перед) выходе из сеанса Unity?
На риск размещения дублирующего вопроса:
Как я могу запустить локальный скрипт (как текущий пользователь) при выходе?
Я прочитал (и попробовал) среди других:
- Этот (версия Мартона), который совершенно ничего не делал, использовался в простом сценарии, создающем файл, абсолютные пути к сценарию (будучи исполняемым) и к файлу.
- Этот, который должен быть устаревшим; это заставило меня удалить файл из командной строки, чтобы иметь возможность снова использовать мою систему.
- Я также посмотрел на это, без успеха.
Я полагаю, что я, должно быть, делаю что-то не так, но не могу понять, в чем моя слепая зона
контекст
В поисках элегантного решения (обходного пути) для этого вопроса, предположительно в результате ошибки, я создал сценарий, который, в зависимости от аргумента, либо делает снимок текущего расположения значков на рабочем столе, либо упорядочивает значки в соответствии с последним снимок. Скрипт работает нормально, но на самом деле не подходит для запуска в качестве фонового скрипта.
Поэтому скрипт должен запускаться при выходе из системы, чтобы получить расположение, очевидно, запускаемое текущим пользователем.
1 ответ
Основная теория
Как вы можете знать или не знать, многие действия Unity реализованы с использованием dbus. Большим преимуществом dbus является то, что вы можете выполнять множество необходимых действий с правами root, вызывая соответствующие методы в командной строке без необходимости иметь учетную запись администратора, например, закрывая вашу систему.
Именно в нашем случае нас интересует com.canonical.Unity
оказание услуг, /com/canonical/Unity/Session
дорожка. Вы можете перечислить информацию об этом с qdbus
команда. Особенно нас интересуют сигналы, которые имеют Requested
в них.
$ qdbus com.canonical.Unity /com/canonical/Unity/Session | grep 'signal.*Requested.*'
signal void com.canonical.Unity.Session.LockRequested()
signal void com.canonical.Unity.Session.LogoutRequested(bool have_inhibitors)
signal void com.canonical.Unity.Session.RebootRequested(bool have_inhibitors)
signal void com.canonical.Unity.Session.ShutdownRequested(bool have_inhibitors)
signal void com.canonical.Unity.Session.UnlockRequested()
Эти сигналы появляются в шине, когда пользователь щелкает по любому из пунктов выключения, блокировки, выхода из системы или перезагрузки в раскрывающемся меню сеанса в правой части верхней панели Unity. Итак, что нам нужно сделать, это:
- контролировать шину для появления этих сигналов.
- как только они появятся - выполните определенное действие.
Конечно, большой недостаток заключается в том, что если пользователь использует sudo shutdown -P now
или же gnome-session-quit
это не будет сказано dbus
так что, какие бы действия ни требовались, они не будут выполнены.
Мониторинг dbus
Удобно, есть команда для этого, dbus-monitor
и мы можем отфильтровать его вывод, используя набор параметров, и выполнить действие над ним, используя while read do … done
состав
Ниже приведен пример простого сценария мониторинга.
dbus-monitor --profile "interface='com.canonical.Unity.Session',type=signal" | \
while read -r line;
do
echo "$line"
sleep 0.25
done
Он просто контролирует шину на наличие сигналов и возвращает их обратно на стандартный вывод, если они появляются; Конечно, эхо может быть любой командой. Запустите его и попробуйте нажать на каждый пункт в меню сеанса, который должен генерировать сигналы, и вы должны увидеть что-то вроде этого:
$ ./logout_monitor.sh
sig 1458319246 172587 2 /org/freedesktop/DBus org.freedesktop.DBus NameAcquired
sig 1458319251 213766 5496 /com/canonical/Unity/Session com.canonical.Unity.Session RebootRequested
sig 1458319265 62555 5525 /com/canonical/Unity/Session com.canonical.Unity.Session LogoutRequested
sig 1458319271 856770 5555 /com/canonical/Unity/Session com.canonical.Unity.Session LockRequested
sig 1458319273 223940 5564 /com/canonical/Unity/Session com.canonical.Unity.Session Locked
sig 1458319276 991413 5604 /com/canonical/Unity/Session com.canonical.Unity.Session UnlockRequested
sig 1458319278 3443 5606 /com/canonical/Unity/Session com.canonical.Unity.Session Unlocked
Итак, теперь у нас есть функция мониторинга, которая может выполнять действие, когда происходит прерывание. Теперь, чтобы ответить на конкретный вопрос, который вы пытались решить, ваш сценарий делает снимки значков на рабочем столе. Нет никакого вреда, если мы делаем снимок каждый раз, когда появляется сигнал - его не нужно специально перезагружать или выключать. Поэтому, если мы будем отслеживать этот конкретный интерфейс Unity на наличие сигналов и делать снимки при поступлении каждого сигнала, мы можем упростить сценарии.
Сценарий, управляемый прерываниями
Ниже вы можете увидеть скрипт, управляемый прерываниями, который будет отслеживать шину на наличие сигналов (игнорируя первый), и если у нас будет поступающий сигнал, то вызовите функцию прерывания (которая в вашем случае будет сценарием снимка значка, который вы ' мы написали).
#!/bin/bash
main()
{
ARG="cow"
dbus-monitor --profile "interface='com.canonical.Unity.Session',type=signal" |
while read -r line;
do
grep -q '.*NameAcquired.*' <<< "$line" && continue # Ignore that first line
if [ -n "$line" ];then
interrupt $ARG # call your python snapshot script here
fi
done
}
interrupt()
{
echo 'Old McDonald had a ' $ARG ' e-i-e-i-o '
}
main
ПРИМЕЧАНИЕ: Dbus полагается на сеанс GUI, поскольку (насколько я знаю) он начинается с входа в Unity/Gnome. В более старых средах, таких как blackbox и openbox, а также в средах TTY, сеанс dbus не запускается, поэтому этот сценарий будет прерван, если вы попытаетесь запустить его в ~/.profile
(У меня был один пользователь, который пытался сделать что-то подобное, и он попал в беду). Запустите такой скрипт, используя программу запуска приложений Unity или Gnome.
Выходя за рамки этого сценария
- У Dbus много API, включая Python
- Я предпочитаю использовать
qdbus
потому что это просто, но всегда можно использоватьdbus-send
, Примеры - Функция прерывания может быть любой, даже другой
dbus
методы. Там есть что посмотреть.
Общая информация: я использовал этот же метод для предотвращения выключения, если работает apt