Categories

Gracefully Shutdown in openbox

Openbox懒散了很长一段时间,一直持续本本 Windows XP 实验室 Ubuntu 的状态,最近终于借“毕业了要喜庆一下”的理由又给本本装了一个 Linux 。虽然仍旧很懒散,但是毕竟是自己的本本,还是喜欢清爽一点,因此用了 openbox 作为窗口管理器,tint2 作为任务栏,用了一周左右挺舒服的。

不过有一个小问题,就是我希望从 openbox 中 shutdown 、restart 的时候能像在 Gnome 或者 KDE 的 session 中那样“优雅”地退出,然后 login manager 也退出,然后屏幕上显示正在关闭的服务,而不是要暴力地直接运行 sudo shutdown -r now 然后屏幕直接黑掉,需要看指示灯才能知道什么时候机器真正关掉了。另外,在 Gnome 或者 KDE 中从对应的 GDM/KDM 中登录进来的话,关机是不需要 sudo 权限的。

一开始我想到了 xfce4 的解决方案,在 xfce4 里有一个 xfsm-shutdown-helper ,只是我不想装 xfce4 (新装的系统总是有些洁癖的 ^_^ ),于是去它的源代码仓库里把对应的源码下载下来,只有一个文件,也比较简单,只是似乎依赖于 gtk 的库,我在折腾的时候还一时头脑发热,弄混了 glib 和 glibc ,结果不小心把 glibc 给卸载掉了,系统立即全面瘫痪了,几乎所有的命令都不能用了,最后还好用 LiveCD 比较暴力地修复了。-.-bb

无奈直接下载了 xfce4 的二进制包解压开用它里面的那个编译好的 xfsm-shutdown-helper ,才发现被骗了,仔细看一看源码,虽然是额外发送了一些信号之类的,但是似乎就跟 sudo shutdown -r now 一样的效果。于是继续寻求解决方案。

应为我是用 gdm 进行登录的,所以也顺便查阅了一下 gdm 相关的信息,竟然一下子就找到了,就是 gdm-control 。比如,运行

gdm-control --shutdown

就是告诉 gdm ,在当前的 session 退出之后关闭电脑。而 --reboot 选项就是重启,正合我意,立即写了一个小脚本,然后在 openbox 的菜单项里调用,关机和重启都变得很“正常”了。 😀

Virtualbox我给这个脚本取名叫做 graceful-shutdown ,然而有时候还是不那么 graceful 的,比如另外一个虚拟桌面上还开着 VirtualBox 没有关呢,结果被强行关闭了。这个问题也算是一直存在的吧,我之前在 Windows 下的时候也曾写过一个小程序来阻止这样的悲剧发生。其实如果在 Windows 下的话,虚拟机可以内置这样的功能,但是 Linux 下的桌面环境实在是太多样化了,要求 VirtualBox 本身做这个似乎还真是很麻烦,不过通过外部脚本来检查倒是挺方便的。

这里要用到一个小工具叫做 xdotool ,可以模拟鼠标、键盘动作等,另外,还可以对窗口做一些其他操作,例如查找窗口、激活窗口等,我想用它来实现 Jump-or-Exec 应该也很方便,不过这里主要是要用它来查看是否有 VirtualBox 窗口存在。用 xprop 查到 VirtualBox 的窗口 class 为 VirtualBox ,于是整个脚本如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh
 
vboxwin=$(xdotool search --class VirtualBox | head -1)
if ! [ -z $vboxwin ];
then
    xdotool windowactivate $vboxwin
    exit 1
fi
 
if [[ "$1" = "SHUTDOWN" ]];
then
    gdm-control --shutdown && openbox --exit
elif [[ "$1" = "REBOOT" ]];
then
    gdm-control --reboot   && openbox --exit
else
    echo "Unknown command: $1, do nothing"
fi

如果有 VirtualBox 窗口在运行的话,就激活它,(我本来还想用 libnotify 弹出一个提示让关闭 VirtualBox 的,但是不知为什么 libnotify 在我这里运行之后没有任何反应也没有任何错误,难道不能在 openbox 的环境下用?Update: 原来是没有安装 notification-daemon 的缘故啊。)否则就执行关机/重启操作。在 openbox 的 ~/.config/openbox/menu.rc 里加上如下的菜单项:

<separator label="Actions" />
<item label="Logout">
    <action name="Exit">
        <prompt>no</prompt>
    </action>
</item>
<item label="Shutdown">
    <action name="Execute">
        <prompt>Shutdown the computer?</prompt>
        <command>graceful-shutdown SHUTDOWN</command>
    </action>
</item>
<item label="Restart">
    <action name="Execute">
        <prompt>Restart the computer?</prompt>
        <command>graceful-shutdown REBOOT</command>
    </action>
</item>

这下子终于可以舒服地关机了。 🙂

8 comments to Gracefully Shutdown in openbox