如何在退出 Unity 会话时(之前)运行本地命令(运行脚本)?

如何在退出 Unity 会话时(之前)运行本地命令(运行脚本)?

面临发布重复问题的风险:

我如何在注销时运行本地脚本(以当前用户身份)?

我读过(并尝试过)以下内容:

  1. 这个(Marton 的版本)什么都没做,只是用一个简单的脚本创建一个文件、脚本(可执行)和文件的绝对路径。
  2. 这个,它肯定已经过时了;它让我从命令行删除该文件才能再次使用我的系统。
  3. 我也调查过这个,没有成功。

我相信我在这里一定是做错了什么,但却找不到我的盲点是什么。

语境

寻找一个优雅的解决方案(解决方法)这个问题,可能是由于错误,我编写了一个脚本,根据参数,拍摄快照当前桌面图标排列,或排列图标,根据最后一张快照。该脚本运行良好,但实际上不适合作为后台脚本运行。

因此脚本应该在注销时运行得到该安排显然是由当前用户运行的。

答案1

基本理论

你可能知道也可能不知道,很多 Unity 动作都是使用总线. 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 nowgnome-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

它所做的只是监视总线上的信号,如果出现信号,则将其回显到标准输出;当然,echo 可以是任何命令。运行它,并尝试单击会话菜单中应生成信号的每个项目,您应该会看到类似以下内容:

$ ./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 正在运行,则防止关机

相关内容