下一页 上一页 目录

7. 以其他用户 ID 运行 X 应用程序

假设您想要运行一个需要 root 权限的图形配置工具。然而,您的 X 会话正在您常用的账户下运行。起初这可能看起来很奇怪,但是 X 服务器将 允许该工具访问您的显示。当 root 通常可以做任何事情时,这怎么可能呢?您又该如何解决这个问题呢?

让我们将其推广到您想要以用户 ID clientuser 运行 X 应用程序,但 X 会话是由 serveruser 启动的情况。如果您已经阅读了关于 cookies 的章节,那么很明显为什么 clientuser 无法访问您的显示:~clientuser/.Xauthority 不包含访问显示所需的正确 magic cookie。正确的 cookie 可以在 ~serveruser/.Xauthority 中找到。

7.1 同一台主机上的不同用户

当然,任何适用于远程 X 的方法也适用于来自不同用户 ID 的 X(特别是 slogin localhost -l clientuser)。只是客户端主机和服务器主机恰好是同一台。然而,当两台主机相同时,有一些传输 magic cookie 的快捷方式。

我们假设您使用 su 来切换用户 ID。基本上,您必须编写一个脚本来调用 su,但将 su 执行的命令用一些代码包装起来,这些代码执行远程 X 所需的操作。这些必要的操作是设置 DISPLAY 变量和传输 magic cookie。

设置 DISPLAY 相对容易;它只是意味着在运行 su 命令参数之前定义 DISPLAY="$DISPLAY"。所以您可以直接这样做

su - clientuser -c "env DISPLAY=$DISPLAY clientprogram &"

这还不行,因为我们仍然需要传输 cookie。我们可以使用 xauth list "$DISPLAY" 来检索 cookie。这个命令恰好以适合反馈给 xauth add 命令的格式列出 cookie;这正是我们所需要的!

我们需要通过管道传递 cookie。不幸的是,通过管道向 su 命令传递东西并不容易,因为 su 想要从其标准输入读取密码。幸运的是,在 shell 脚本中,我们可以调整一些文件描述符,并完成它。

因此,我们围绕此编写一个脚本,通过 clientuserclientprogram 进行参数化。让我们在编写脚本的同时稍微改进一下它,使其可读性降低但更健壮。它看起来像这样

#!/bin/sh

if [ $# -lt 2 ]
then echo "usage: `basename $0` clientuser command" >&2
     exit 2
fi

CLIENTUSER="$1"
shift

# FD 4 becomes stdin too
exec 4>&0

xauth list "$DISPLAY" | sed -e 's/^/add /' | {

    # FD 3 becomes xauth output
    # FD 0 becomes stdin again
    # FD 4 is closed
    exec 3>&0 0>&4 4>&-

    exec su - "$CLIENTUSER" -c \
         "xauth -q <&3
          exec env DISPLAY='$DISPLAY' "'"$SHELL"'" -c '$*' 3>&-"

}

我认为这是可移植的,并且在大多数情况下都能很好地工作。我现在能想到的唯一缺点是,由于使用了 '$*'command 中的单引号会搞乱 su 命令参数 (`'$*'`) 中的引用。如果还有其他严重的错误,请给我发邮件。

将脚本命名为 /usr/local/bin/xsu,您可以这样做

xsu clientuser 'command &'

不可能更简单了,除非您去掉密码。是的,也有其他方法可以做到这一点 (`sudo`),但这里不是讨论这个的地方。

刚刚提到的微小的 xsu 脚本已成为一个更扩展的脚本 sux 的基础,该脚本显然已作为软件包进入了 Debian 发行版。

7.2 客户端用户是 Root

显然,任何适用于非 root 客户端用户的方法也适用于 root 用户。然而,对于 root 用户,您可以使其更加容易,因为 root 可以读取任何人的 ~/.Xauthority 文件。无需传输 cookie。您所要做的就是设置 DISPLAY,并将 XAUTHORITY 指向 ~serveruser/.Xauthority。所以您可以这样做

su - -c "exec env DISPLAY='$DISPLAY' \
                  XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
                  command"

将其放入脚本中会得到类似这样的内容

#!/bin/sh
if [ $# -lt 1 ]
then echo "usage: `basename $0` command" >&2
     exit 2
fi
su - -c "exec env DISPLAY='$DISPLAY' \
                  XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
                  "'"$SHELL"'" -c '$*'"

将脚本命名为 /usr/local/bin/xroot,您可以这样做

xroot 'control-panel &'

虽然,如果您已经设置了 xsu,那么就没有真正的理由再这样做了。


下一页 上一页 目录