如何为gconf创建一个假“活动会话”?

9 投票
3 回答
5842 浏览
提问于 2025-04-11 09:33

我已经自动化了我的Ubuntu安装过程——我写了一段Python代码,它会在全新安装后、用户第一次登录之前自动运行(这段代码放在一个临时的 /etc/init.d/ 脚本里),可以设置从Apache及其配置到我个人的Gnome偏好设置的一切。不过,后者让我遇到了一些麻烦。

在Ubuntu 8.04(Hardy)上,这一切都运行得很好,但在8.10(Intrepid)上,当我第一次尝试访问gconf时,就出现了这个错误:

无法联系配置服务器;可能的原因包括你需要为ORBit启用TCP/IP网络,或者由于系统崩溃导致NFS锁定过期。有关信息,请查看http://www.gnome.org/projects/gconf/。(详细信息 - 1: 未在活动会话中运行

没错,这段代码运行时没有Gnome会话,因为用户还没有登录——不过,这在之前是可以的;看起来这是Intrepid的Gnome(2.24?)的新问题。

除了直接修改gconf的XML文件,还有没有办法创建一个代理Gnome会话?或者,有其他建议吗?

(更多细节:这段Python代码以root身份运行,但在使用“gconf”模块设置我的偏好设置之前,会切换到我的用户身份。)

3 个回答

1

我觉得我明白你的问题了。看起来你的脚本只需要启动dbus守护进程,或者确保它已经启动。我认为这里的“会话”指的是dbus会话,而不是Gnome会话。(这里有一些证据),其实dbus和gconf在没有Gnome的情况下也能正常运行。

无论如何,假装有一个“活跃的会话”听起来不是个好主意。它只会在需要的时候去查找。

也许我们可以在pastebin上看看这个脚本?在我发表评论之前,应该先看看它。

1

谢谢你们,Ali和Jeremy,你们的回答对我帮助很大。我还在继续这个项目(不过我今晚先停一下)。

首先,我听了Ali的建议,尝试了Jeremy的一部分想法:我用dbus-launch来运行“gconftool-2 --spawn”。结果没成功;现在我明白为什么了(谢谢你,Jeremy)——我试图在同一个启动dbus和gconftool的python程序里使用gconf,但那个环境里没有必要的环境变量——真是傻。

当我发现gconftool-2的--direct选项时,我就把之前的想法放一边了;其实,gconftool-2内部使用的API并没有通过gconf的python绑定暴露出来。所以,我修改了python-gconf,让它可以使用这个额外的方法,一旦这个修改成功编译(我在这方面遇到了一些无关的问题),我们就看看能否解决问题——如果不能解决(也许即使能解决,因为编译这些绑定似乎会编译整个gnome!),我会找到更好的方法来管理第一个策略中的环境变量。

(无论如何,我明天会再来这里补充一个答案)

第二天到了:我在修改后的python-gconf上遇到了一点麻烦,这让我想尝试Jeremy更简单的想法,结果很好用——在进行第一次gconf操作之前,我简单地运行了“dbus-launch”,解析了得到的名称-值对,然后直接把它们添加到python的环境中。这样做之后,我运行了“gconftool-2 --spawn”。问题解决了。

8

我在我的电脑上安装GConf 2.24时可以复现这个问题。GConf 2.22运行得很好,但2.24就出问题了。

GConf无法启动是因为D-Bus没有运行。手动启动D-Bus和GConf守护进程后,它又能正常工作了。

我尝试通过以下方式启动D-Bus会话总线:

import dbus
dummy_bus = dbus.SessionBus()

...但出现了这个错误:

dbus.exceptions.DBusException: org.freedesktop.DBus.Error.Spawn.ExecFailed: dbus-launch failed to autolaunch D-Bus session: Autolaunch error: X11 initialization failed.

真奇怪。看起来如果X没有运行,它就不喜欢启动。为了解决这个问题,可以手动启动dbus-launch(如果我没记错的话,使用os.system()调用):

$ dbus-launch 
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-eAmT3q94u0,guid=c250f62d3c4739dcc9a12d48490fc268
DBUS_SESSION_BUS_PID=15836

你需要以某种方式解析输出,并把它们放入环境变量中(你可能想用os.putenv)。为了测试,我直接在命令行中手动设置了环境变量,比如用export DBUS_SESSION_BUS_ADDRESS=blahblah...等等。

接下来,你需要用从dbus-launch得到的环境变量来启动gconftool-2 --spawn。这会启动GConf守护进程。如果没有设置D-Bus环境变量,守护进程就不会启动。

然后,运行你的GConf代码。只要你为自己的脚本设置了D-Bus会话总线的环境变量,你就可以和GConf守护进程进行通信了。

我知道这很复杂。

gconftool-2提供了一个--direct选项,让你可以在不需要和服务器通信的情况下设置GConf变量,但我还没找到Python绑定的等效选项(除了手动输出XML)。

编辑:为了将来参考,如果有人想在普通的bash脚本中运行dbus-launch(而不是像这个讨论的Python脚本),很容易就能在脚本中获取会话总线地址:

#!/bin/bash

eval `dbus-launch --sh-syntax`

export DBUS_SESSION_BUS_ADDRESS
export DBUS_SESSION_BUS_PID

do_other_stuff_here

撰写回答