您尚未登录。

#1 2014-11-11 00:21:21

danielhugo
偶爸刚弄死他
注册时间: 2012-07-31
帖子: 269
个人网站

关于使用BCloud遇到的“勾选记住密码会卡住”问题的研究和理解

问题描述

我用的是 Arch Linux 发行版, 窗口管理器是 Awesome WM,登录管理器是 SLiM ,安装的 GNOME 软件包只有这几个:

gnome-icon-theme
gnome-icon-theme-symbolic
gnome-keyring
libgnome-keyring
libsoup
seahorse

登录以后马上打开 htop ,可以清楚地看到一个 gnome-keyring-daemon 进程,然后打开 seahorseGNOME Keyring 的图形界面管理器),一个叫 Login 的密钥环(已经是默认的密钥环)是解锁了的。

这时候在终端运行 bcloud-gui ,在登录界面输入用户名及密码后,勾选“记住密码”,点登录按钮后会卡住,在终端上会显示:

Please set a password for your new keyring:
Please confirm the password:

这个问题的另一种表述见:

* https://github.com/LiuLang/bcloud/issues/63
* https://bbs.archlinuxcn.org/viewtopic.php?id=2920

相似的问题还有:

* https://github.com/LiuLang/bcloud/issues/26
* https://github.com/LiuLang/bcloud/issues/49
* https://github.com/LiuLang/bcloud/issues/61
* https://github.com/LiuLang/bcloud-packages/issues/72
* http://tieba.baidu.com/p/3287420983
* https://bbs.archlinuxcn.org/viewtopic.php?id=2849

最近编辑记录 danielhugo (2014-11-11 01:00:07)


本人的 Arch Linux 软件仓库:http://git.io/-1
本人的广告过滤及代·理规则订阅页面:http://git.io/f0x

离线

#2 2014-11-11 00:57:30

danielhugo
偶爸刚弄死他
注册时间: 2012-07-31
帖子: 269
个人网站

Re: 关于使用BCloud遇到的“勾选记住密码会卡住”问题的研究和理解

初步研究

我谷歌了不少文章和帖子,在几个论坛上发问,找到了一些有用的东西:

* Why couldn't Python3 handle GNOME Keyring?

首先我在总坛发问, @mauritiusdadd 告诉我可以通过创建 ~/.local/share/python_keyring/keyringrc.cfg 强行设置 Python Keyringbackend

[backend]
default-keyring=keyring.backends.Gnome.Keyring

通过这个方法找到了 Python Keyring 抛出的错误:

keyring.errors.PasswordSetError: GNOME_KEYRING_RESULT_IO_ERROR

===============================================

* 百度网盘的Gtk/Linux客户端 (已发布)
* 求问只要选择记住密码就卡住怎么破?

在这里找到了两个类似的错误,但是并未看到相应的解决办法。

于是,决定从 Python Keyring 的源代码开始研究,找出抛出该错误的源代码。

===============================================

* Python Keyring 中的源代码文件 Gnome.py

i1820682

图 1 - Gnome.py 摘录

在第34~35行找到了抛出错误的语句:

        if not cls.has_requisite_vars():
            raise RuntimeError("Requisite environment vars are not present")

如果在系统环境中找不到两个需要定义的环境变量,则抛出上述错误。这两个需要定义的环境变量是:

DISPLAY
DBUS_SESSION_BUS_ADDRESS

关键就在于这个 DBUS_SESSION_BUS_ADDRESS

=========================================

* FS#5695 - dbus: variable DBUS_SESSION_BUS_ADDRESS not set
* FS#18930 - Unable to access secrets service

首先是搜索 Arch Linux 网站,找到两个 Arch Linux 相关的 Bug 报告。

第一个报告指出只有从 .xinitrc 运行 dbus-launch --auto-syntax --exit-with-session 才能设定此环境变量。
第二个报告的信息量大得多,指出了很多使 GNOME Keyring 运行正常要做的设置。

然后是搜索 Arch 维基的相关页面。研究的方向转向了 D-Bus

最近编辑记录 danielhugo (2014-11-14 21:32:38)


本人的 Arch Linux 软件仓库:http://git.io/-1
本人的广告过滤及代·理规则订阅页面:http://git.io/f0x

离线

#3 2014-11-11 01:30:41

danielhugo
偶爸刚弄死他
注册时间: 2012-07-31
帖子: 269
个人网站

Re: 关于使用BCloud遇到的“勾选记住密码会卡住”问题的研究和理解

D-Bus 研究

diagram.png

图 2 - D-Bus 的体系结构图

* Arch 维基的 D-Bus 条目

D-Bus 是一个提供简便进程间通信的消息总线系统。包含一个能以全系统或者针对一个用户会话运行的守护进程,和一系列提供与 D-Bus 通信的库。

* dbus-daemon使用技巧

通常情况下,会有数个dbus-daemon进程,其中一个是属于系统的,还有一个是属于会话的,这两个进程,都是在用户登录的时候由dbus-launch启动的。

i1820697

图 3 - 登录后的部分 D-Bus 守护进程(上面一个是系统的,下面一个是会话的)

大多数普通程序,都是使用会话的dbus-daemon,默认情况下,就是将消息发给了这个属于会话的dbus-daemon。

其实dbus-daemon是有地址的,而且有一个环境变量来表示它——DBUS_SESSION_BUS_ADDRESS,可以用命令 env 查看到。我们的程序,也就是依靠这个环境变量来确认使用哪一个dbus-daemon的。

当我们登录进桌面环境的时候,系统启动脚本会调用到 dbus-launch 来启动一个dbus-daemon,同时会把这个dbus-daemon的地址赋予环境变量 DBUS_SESSION_BUS_ADDRESS

因为 Systemd 依赖 D-Bus,在使用 Systemd 时,D-Bus 会被自动启动。

桌面环境 和 xinitrc 会自动启动 D-Bus 会话。 xorg-xinit 提供的框架文件 ~/.xinitrc (/etc/skel/.xinitrc) 也会执行同样的操作。请确保自己的 ~/.xinitrc 是基于框架文件 /etc/skel/.xinitrc.

===========================================

* Arch 维基的 Xinitrc 条目

~/.xinitrc 文件是 xinit 和 startx 第一次启动时会读取的脚本。通常用在启动 X 时执行窗口管理器和其他程序,例如启动守护进程和设置环境变量。

/etc/skel/ 为新创建用户提供了合理的默认配置文件和目录(skel 是 skeleton 的简写,包含了用户主目录的基本结构)。 xorg-xinit 软件包会在 /etc/skel 中加入 .xinitrc 文件。

框架文件 /etc/skel/.xinitrc 的内容:

#!/bin/sh
#
# ~/.xinitrc
#
# Executed by startx (run your window manager from here)

if [ -d /etc/X11/xinit/xinitrc.d ]; then
  for f in /etc/X11/xinit/xinitrc.d/*; do
    [ -x "$f" ] && . "$f"
  done
  unset f
fi

# exec gnome-session
# exec startkde
# exec startxfce4
# ...or the Window Manager of your choice

D-Bus 文件 /etc/X11/xinit/xinitrc.d/30-dbus 的内容:

#!/bin/bash

# launches a session dbus instance
if [ -z "$DBUS_SESSION_BUS_ADDRESS" ] && type dbus-launch >/dev/null; then
  eval $(dbus-launch --sh-syntax --exit-with-session)
fi

SLiM 配置文件 /etc/slim.conf 与登录相关的内容:

# This command is executed after a succesful login.
# you can place the %session and %theme variables
# to handle launching of specific commands in .xinitrc
# depending of chosen session and slim theme
#
# NOTE: if your system does not have bash you need
# to adjust the command according to your preferred shell,
# i.e. for freebsd use:
# login_cmd           exec /bin/sh - ~/.xinitrc %session
login_cmd           exec /bin/bash -login ~/.xinitrc %session

===================================

根据我的理解,D-Bus 的会话进程的启动过程是这样的:(此处描述的是我的系统环境)

SLiM 执行登录命令,即 login_cmd 的内容:

exec /bin/bash -login ~/.xinitrc %session

替换当前进程为 bash ,并且执行 ~/.xinitrc awesome 命令。

~/.xinitrc 随即遍历 /etc/X11/xinit/xinitrc.d/ 的文件,从而执行 /etc/X11/xinit/xinitrc.d/30-dbus

/etc/X11/xinit/xinitrc.d/30-dbus 执行 dbus-launch --sh-syntax --exit-with-session 命令,从而启动 D-Bus 的会话进程。

然后会把这个 D-Bus 的会话进程的地址赋予到环境变量 DBUS_SESSION_BUS_ADDRESS

最近编辑记录 danielhugo (2014-11-14 21:33:52)


本人的 Arch Linux 软件仓库:http://git.io/-1
本人的广告过滤及代·理规则订阅页面:http://git.io/f0x

离线

#4 2014-11-11 02:33:55

danielhugo
偶爸刚弄死他
注册时间: 2012-07-31
帖子: 269
个人网站

Re: 关于使用BCloud遇到的“勾选记住密码会卡住”问题的研究和理解

解决方案

所以解决方案就比较明确了,确保在 ~/.xinitrc 文件最顶端有以下内容:

if [ -d /etc/X11/xinit/xinitrc.d ]; then
  for f in /etc/X11/xinit/xinitrc.d/*; do
    [ -x "$f" ] && . "$f"
  done
  unset f
fi

所以最后我作出了以下修改:Make python-keyring running properly

==========================================

总结

关于使用BCloud遇到的“勾选记住密码会卡住”问题,应该分成以下几个情况入手研究:

首先,是否安装了密码管理软件。

由于 BCloud 使用了 Python Keyring ,而 Python Keyring 可以使用 GNOME Keyring 、KWallet 作为后端,甚至可以不依靠这些软件,只使用加密的文本文件来存放密码。当 Python Keyring 调用 GNOME Keyring 和 KWallet 失败时,就会转向使用加密的文本文件来存放密码。而使用加密的文本文件来存放密码需要一个主密码作为加密的密钥。这也就是为什么点登录按钮后会卡住,在终端上会显示:

Please set a password for your new keyring:
Please confirm the password:

由于 Arch Linux 的包管理机制的缺陷,无法实现像 Debian 那样的选择性依赖

BCloud 的 Debian 包构建文件

Depends: ... , gnome-keyring|kwalletmanager

而只能将 GNOME Keyring 和 KWallet 均作为可选依赖,这也导致在安装 BCloud 后并未同时安装相应的密码管理软件,必须手动安装任意一个密码管理软件。

BCloud 的 PKGBUILD 文件

optdepends=('gnome-keyring: To store password in GNOME Keyring'
            'libgnome-keyring: To store password in GNOME Keyring'
            'kdebindings-python: To store password in KWallet'
            'kwallet: To store password in KWallet')
其次,若使用 GNOME Keyring,是否作了相应配置使 GNOME Keyring 自动启动并正常运行。

Arch 维基的 GNOME Keyring 条目 清楚地写明了在不同的登录管理器及桌面环境下如何配置 GNOME Keyring 自动启动并正常运行。用户可能需要手动配置,至少应该确保登录后在当前进程列表中有 gnome-keyring-daemon 进程,并且在 seahorse 中一个叫 Login 的密钥环(确保是默认的密钥环)是解锁了的。(看文字前面的锁头标志)

vRM9f.jpg

图 8 - Seahorse 界面

再次,是否作了相应配置使 D-Bus 会话进程自动启动

确保在 ~/.xinitrc 文件最顶端有以下内容:

if [ -d /etc/X11/xinit/xinitrc.d ]; then
  for f in /etc/X11/xinit/xinitrc.d/*; do
    [ -x "$f" ] && . "$f"
  done
  unset f
fi

并且环境变量 DBUS_SESSION_BUS_ADDRESS 已被赋值。(通过在终端执行 env 查看)

最后,如果以上三项均已做到,就应该从 Python Keyring 中找原因。

首先通过创建 ~/.local/share/python_keyring/keyringrc.cfg 强行设置 Python Keyringbackend

[backend]
default-keyring=keyring.backends.Gnome.Keyring

然后打开终端,执行以下命令:

$ python

>>> import keyring
>>> print(keyring.get_keyring())

记录下 Python Keyring 抛出的错误,并从这个错误入手研究。

classkeyring_1_1backend_1_1_basic_file_keyring__inherit__graph.png

图 4 - Python Keyring 类图摘录 - BasicFileKeyring

classkeyring_1_1backend_1_1_gnome_keyring__inherit__graph.png

图 5 - Python Keyring 类图摘录 - GnomeKeyring

classkeyring_1_1backend_1_1_k_d_e_k_wallet__inherit__graph.png

图 6 - Python Keyring 类图摘录 - KDEKWallet

classkeyring_1_1backend_1_1_crypted_file_keyring__inherit__graph.png

图 7 - Python Keyring 类图摘录 - CryptedFileKeyring

最最后,向作者报告错误或提出问题。

BCloud 的作者 @LiuLang 大神也讲中文,而且非常活跃,非常热心。大家完全可以到他的项目主页上报告错误或者提出问题,而不必担心语言障碍或者是否回应。

拥有GitHub帐号的(注册一个也很方便),请到此处提问:https://github.com/LiuLang/bcloud/issues。点击页面右上方"New Issue"按钮即可提出一个新的问题。

不想注册GitHub帐号的,可以发电子邮件到:gsushzhsosgsu@gmail.com 向作者提问。

最近编辑记录 danielhugo (2014-11-11 21:41:50)


本人的 Arch Linux 软件仓库:http://git.io/-1
本人的广告过滤及代·理规则订阅页面:http://git.io/f0x

离线

#5 2014-11-11 03:28:53

danielhugo
偶爸刚弄死他
注册时间: 2012-07-31
帖子: 269
个人网站

Re: 关于使用BCloud遇到的“勾选记住密码会卡住”问题的研究和理解

本来是想为 BCloud 建立一个 Arch 维基条目的,但是不知道我的研究和理解有没有问题。还是先发一篇帖子,求各位大神指点一下! big_smile  @百合仙子 @尹良灿 @众大神


本人的 Arch Linux 软件仓库:http://git.io/-1
本人的广告过滤及代·理规则订阅页面:http://git.io/f0x

离线

#6 2014-11-11 09:17:13

qi437103
会员
所在地: XJTU
注册时间: 2012-03-02
帖子: 1

Re: 关于使用BCloud遇到的“勾选记住密码会卡住”问题的研究和理解

的确,pacman没法处理多个可选依赖中必须选择某几个安装的情况……

我昨天遇到了类似的问题,绕了一圈最后看了keyring的代码,发现其实是kde的python binding没装 -_-||,所以即使开了kwallet,在kde环境下给我fallback到了gnome keyring……

我向作者提交了pull request在keyring不能用的情况下禁用保存密码的功能,总好过卡住… 已经通过了,不过我没考虑到最终会用加密文本存储的情况,你能用最新的git版本试试看会这种情况下会出什么问题么(°ー°〃)

离线

#7 2014-11-11 09:37:40

依云
会员
所在地: a.k.a. 百合仙子
注册时间: 2011-08-21
帖子: 8,953
个人网站

Re: 关于使用BCloud遇到的“勾选记住密码会卡住”问题的研究和理解

D-Bus 部分没有什么问题。不过 dbus-daemon 数量没有那么少。我这里有五个:

>>> zargs -- $(pgrep dbus-daemon) -- pid
392: /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation 
875: /usr/bin/dbus-daemon --fork --print-pid 6 --print-address 8 --session 
992: /usr/bin/dbus-daemon --config-file=/etc/at-spi2/accessibility.conf --nofork --print-address 3 
10156: /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation 
19053: /usr/bin/dbus-daemon --fork --print-pid 5 --print-address 7 --config-file /usr/share/fcitx/dbus/daemon.conf 

其中,10156 是一个 LXC container 的。992 是 at-spi2 的,不知道它为什么会自己启一个。19053 是 fcitx 的。875 是我这个用户的会话的。剩下的一个是系统的。

另外,我这里没有 /run/user/%I/dbus/user_bus_socket 这个文件。在 ~/.dbus/session-bus 下有一个文件名格式为 <machine-id>-<display-name> 的文件,里边有会话的 D-Bus 地址和 PID、Window ID 信息。fcitx 的在 ~/.config/fcitx/dbus 下,里边只有一个 D-Bus 地址。

离线

#8 2014-11-11 19:30:20

danielhugo
偶爸刚弄死他
注册时间: 2012-07-31
帖子: 269
个人网站

Re: 关于使用BCloud遇到的“勾选记住密码会卡住”问题的研究和理解

百合仙子 说:

D-Bus 部分没有什么问题。不过 dbus-daemon 数量没有那么少。我这里有五个:

>>> zargs -- $(pgrep dbus-daemon) -- pid
392: /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation 
875: /usr/bin/dbus-daemon --fork --print-pid 6 --print-address 8 --session 
992: /usr/bin/dbus-daemon --config-file=/etc/at-spi2/accessibility.conf --nofork --print-address 3 
10156: /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation 
19053: /usr/bin/dbus-daemon --fork --print-pid 5 --print-address 7 --config-file /usr/share/fcitx/dbus/daemon.conf 

其中,10156 是一个 LXC container 的。992 是 at-spi2 的,不知道它为什么会自己启一个。19053 是 fcitx 的。875 是我这个用户的会话的。剩下的一个是系统的。

另外,我这里没有 /run/user/%I/dbus/user_bus_socket 这个文件。在 ~/.dbus/session-bus 下有一个文件名格式为 <machine-id>-<display-name> 的文件,里边有会话的 D-Bus 地址和 PID、Window ID 信息。fcitx 的在 ~/.config/fcitx/dbus 下,里边只有一个 D-Bus 地址。

OK,已经补充了几幅图!被你这么一说,我看了看,果然我也有这些dbus-daemon进程,看来我对D-Bus的理解还不够深。

可是在 ~/.dbus/session-bus 文件的最顶端有这么一段注释:

# This file allows processes on the machine with id bc42151bef3404e1847700880000039d using 
# display :0.0 to find the D-Bus session bus with the below address.
# If the DBUS_SESSION_BUS_ADDRESS environment variable is set, it will
# be used rather than this file.
# See "man dbus-launch" for more details.

/usr/share/man/man1/dbus-launch.1.gz 里面有这么一段話:

AUTOMATIC LAUNCHING

       If DBUS_SESSION_BUS_ADDRESS is not set for a process that tries to use D-Bus, by default the process will attempt to invoke
       dbus-launch with the --autolaunch option to start up a new session bus or find the existing bus address on the X display or in a
       file in ~/.dbus/session-bus/

       Whenever an autolaunch occurs, the application that had to start a new bus will be in its own little world; it can effectively
       end up starting a whole new session if it tries to use a lot of bus services. This can be suboptimal or even totally broken,
       depending on the app and what it tries to do.

       There are two common reasons for autolaunch. One is ssh to a remote machine. The ideal fix for that would be forwarding of
       DBUS_SESSION_BUS_ADDRESS in the same way that DISPLAY is forwarded. In the meantime, you can edit the session.conf config file to
       have your session bus listen on TCP, and manually set DBUS_SESSION_BUS_ADDRESS, if you like.

       The second common reason for autolaunch is an su to another user, and display of X applications running as the second user on the
       display belonging to the first user. Perhaps the ideal fix in this case would be to allow the second user to connect to the
       session bus of the first user, just as they can connect to the first user's display. However, a mechanism for that has not been
       coded.

       You can always avoid autolaunch by manually setting DBUS_SESSION_BUS_ADDRESS. Autolaunch happens because the default address if
       none is set is "autolaunch:", so if any other address is set there will be no autolaunch. You can however include autolaunch in
       an explicit session bus address as a fallback, for example DBUS_SESSION_BUS_ADDRESS="something:,autolaunch:" - in that case if
       the first address doesn't work, processes will autolaunch. (The bus address variable contains a comma-separated list of addresses
       to try.)

       The --autolaunch option is considered an internal implementation detail of libdbus, and in fact there are plans to change it.
       There's no real reason to use it outside of the libdbus implementation anyhow.

看来我要再细看一下,修改一下文章了。 mad


本人的 Arch Linux 软件仓库:http://git.io/-1
本人的广告过滤及代·理规则订阅页面:http://git.io/f0x

离线

页脚