如何在恢复后和解锁屏幕后运行脚本

如何在恢复后和解锁屏幕后运行脚本

在 Ubuntu 12.04 LTS 中,我想在从挂起状态恢复后以及解锁桌面后运行脚本。这些脚本需要以我的用户身份运行,并有权访问我的$DISPLAY

我尤其希望

  • 重新启动nm-applet以解决问题错误 985028
  • 使用显示自定义通知notify-send
  • 当我让这些工作时可能会有其他的东西

当我恢复时,脚本/etc/pm/sleep.d/会运行,但它们以 root 身份运行,不知道我的屏幕和用户名。如果我在这些脚本中硬编码我的用户名和export默认值,它可能会起作用DISPLAY :0,但这感觉像是一个非常丑陋的黑客行为。

脚本在~/.config/autostart/xyz.desktop登录后运行,但它们不会在恢复后仅仅解锁屏幕后运行。

有没有办法在恢复后解锁屏幕后运行脚本?

答案1

无论如何,看起来您都必须在上一个答案中对用户名进行硬编码,因此如果有人正在寻找快速修复,这里有一个 /etc/pm/sleep.d 中的简单脚本:

#!/bin/bash 
case "$1" in
    hibernate|suspend)
        sudo -u USERNAME env DISPLAY=:0 zenity --info --text "do stuff on suspend"
        ;;
    thaw|resume)
        sudo -u USERNAME env DISPLAY=:0 zenity --info --text "do stuff on resume"
        ;;
esac

答案2

Unix & Linux 网站上的这个问题记录了使用 dbus 消息的替代方法:

dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" | \
( while true; do
    read X;
    if echo $X | grep "boolean true" &> /dev/null; then
        SCREEN_LOCKED;
    elif echo $X | grep "boolean false" &> /dev/null; then
        SCREEN_UNLOCKED;
        fi
done )

(将 SCREEN_LOCKED 和 SCREEN_UNLOCKED 替换为您想要执行的操作。)

用作xrandr 1>/dev/null 2>1解锁操作解决了我的问题,即屏幕解锁时显示器分辨率/位置无法正确恢复(xrandr 似乎会导致重新读取屏幕设置)。我在 .bash_profile 中将此行作为后台任务添加(严格来说,将其作为 ~/.config/autostart 中的桌面文件可能会更好,因为它仅在启动 gnome 时运行):

dbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" | \
( while true; do
    read X;
    if echo $X | grep "boolean false" &> /dev/null; then
        xrandr 1>/dev/null 2>1;
        fi
done ) &

有关 gnome-screensaver API 的更多背景信息,请参阅本网站以及 dbus 监视器这里

答案3

一个解决方案是登录桌面时运行一个脚本,该脚本会捕获 dbus 消息。从挂起状态恢复后,屏幕被锁定,输入密码后,dbus 上会出现解锁事件。

(感谢 Kim SJ 引导我走上正确的道路。我没有屏幕保护程序信号,但找到了另一个可以使用的界面)。

在 中~/.config/autostart/,我有一个 .desktop 文件,它启动一个 bash 脚本:

$ cat ~/.config/autostart/mymonitor.desktop
[Desktop Entry]
Categories=System;Monitor;
Comment=Monitor dbus for unlock signals
Exec=/usr/local/bin/unlock_monitor
Name=unlock_monitor
Type=Application

监视unlock_monitor脚本从信号读取 dbus 消息com.canonical.Unity.Session并执行操作Unlocked

#!/bin/bash

dbus-monitor --session "type=signal,interface=com.canonical.Unity.Session" --profile \
| while read dbusmsg; do
    if [[ "$dbusmsg" =~ Unlocked$ || "$dbusmsg" =~ NameAcquired$ ]] ; then
        sleep 5
        notify-send "$(basename $0)" "Unlocked or freshly logged in..."
        # ...
    fi
done

登录时没有“Unlocked”信号,但dbus-monitor启动时有“NameAcquired”信号。

答案4

您可以使用 start-stop-daemon 运行脚本。start-stop-daemon 可以分叉以不同 uid 和 gid 运行的线程,从而解决您的问题。

您需要做的是编写一个放置在系统 PATH 中的作业脚本,如/usr/bin,并在 中创建一个额外的守护程序脚本/etc/pm/sleep.d。匹配pm-suspend操作,如resumethaw守护程序脚本通过以下方式提交作业脚本

start-stop-daemon --start $ARGs --name nm-rtvt--exec /usr/bin/job_script

哪里ARGs可以--chuid 1001:1001或者只是--user your_username

为了完整性,您可能还希望守护进程脚本nm-rtvt通过以下方式停止在 suspend 之前命名的守护进程:

start-stop-daemon --stop <...>

匹配pm-suspend动作如suspendhibernate

有关详细信息,请参阅man start-stop-daemon。守护进程脚本中还有许多其他示例/etc/init.d

相关内容