如何在(仅在之前)注销Unity会话时运行本地命令(运行脚本)?

冒着发布重复问题的风险:

当我退出时,如何运行本地脚本(作为当前用户)?

我读过(并尝试过)其他人:

  1. 这个 (Marton的版本),完全没有做任何事情,用于创建文件的简单脚本,脚本的绝对路径(可执行)和文件。
  2. 这一个 ,必须过时; 它让我从命令行中删除文件,以便能够再次使用我的系统。
  3. 我也看了这个 ,没有成功。

我相信我一定是在做错事,但是找不到我的盲点。

上下文

寻找这个问题的优雅解决方案(解决方法),可能是一个错误的结果,我制作了一个脚本,根据参数,可以获取当前桌面图标排列的快照 ,或根据最后一个排列图标快照。 该脚本工作正常,但实际上不能作为后台脚本运行。

因此,脚本应该在注销时运行以获得安排,显然由当前用户运行。

基础理论

您可能知道也可能不知道,使用dbus实现了很多Unity操作。 dbus的一大优点是,您可以通过在命令行中调用适当的方法来执行许多根需要的操作,而无需使用管理员帐户,例如关闭系统 。

特别是在我们的案例中,我们对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结构对其执行操作

Bellow是一个简单监控脚本的示例。

 dbus-monitor --profile "interface='com.canonical.Unity.Session',type=signal" | \ while read -r line; do echo "$line" sleep 0.25 done 

它的作用仅仅是监视总线上的信号,如果出现则将它们回显到stdout; 当然,回声可以是任何命令。 运行它,并尝试单击会话菜单中应生成信号的每个项目,您应该看到如下内容:

 $ ./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 

所以现在我们有一个监控function,可以在中断发生后执行操作。 现在,为了解决您尝试解决的具体问题,您的脚本正在拍摄桌面上图标的快照。 如果我们每次发出信号时拍摄快照都没有坏处 – 它不必专门重启或关机。 因此,如果我们监视特定的Unity接口以获取信号并在每个信号到达时拍摄快照,我们就可以简化脚本编写。

中断驱动的脚本

Bellow你可以看到一个中断驱动的脚本,它将监视总线上的信号(忽略第一个),如果我们有信号进入,那么调用一个中断函数(在你的情况下将是你的图标快照脚本)写的)。

 #!/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 ' eieio ' } main 

注意 :Dbus依赖于GUI会话,因为(据我所知)它从Unity / Gnome登录开始。 较旧的环境,如blackbox和openbox,以及TTY环境都无法启动dbus会话,因此如果您尝试在~/.profile启动它,该脚本会发呕(我有一个用户试图做类似的事情而且他得到了陷入麻烦)。 使用Unity或Gnome的启动应用程序启动此类脚本

超越这个脚本

  • Dbus有很多API,包括python
  • 我更喜欢使用qdbus因为它很简单,但总是可以使用dbus-send 。 例子
  • 中断function可以是任何东西,甚至是其他dbus方法。 有很多值得关注的问题。

琐事 : 如果apt正在运行,我已经使用了同样的方法来防止关机