如何在没有 root 的情况下运行 Xvfb?

Dra*_*kes 6 xorg centos xvfb xkb

在没有 root 的服务器上的期望结果:

1) 在Xvfb没有输入设备的情况下运行,或

2) 开始Xvfb运行

背景:

我有两台机器都具有几乎相同的 CentOS 构建。一台机器有 root 访问权限和互联网,另一台是沙盒(没有 root 访问权限),没有包管理器(没有 yum),也没有 Xserver。我试图让XvfbX 虚拟帧缓冲区)在目标机器上运行以试验无头 firefox。当Xvfb工作时,我可以使用xvfb-run

我试过的:

我已Xvfb使用此方法成功传输了二进制文件和用户共享库(请参阅答案下方的注释)。我能够运行Xvfb,像这样

Xvfb :1 -nolisten tcp -screen 0 1680x1050x16
Run Code Online (Sandbox Code Playgroud)

但后来我收到一个键盘映射错误(旁白:我还想处理我设置的临时目录问题export TMPDIR=~/tmp):

_XSERVTransmkdir: Owner of /tmp/.X11-unix should be set to root
XKB: Failed to compile keymap
Keyboard initialization failed. This could be a missing or incorrect setup of xkeyboard-config.
(EE)
Fatal server error:
(EE) Failed to activate core devices.(EE)
Run Code Online (Sandbox Code Playgroud)

我根本不需要物理键盘或鼠标支持。如果有人可以解释如何在Xvfb没有输入设备的情况下运行,那么我们可以到此为止。我已经搜索了几个小时但没有成功。


我如何尝试让 xkb 工作:

我的下一个操作是xkbcomp从源计算机和共享库中带过来。接下来,我从源计算机导出了键盘映射文件,如下所示:

xkbcomp -xkb $DISPLAY xkbmap
Run Code Online (Sandbox Code Playgroud)

我试图通过xkbdirxkbmap运行以下但没有成功

Xvfb :1 -xkbdir ~/X11/xkb -xkbmap xkbmap -nolisten tcp -screen 0 1680x1050x16
Run Code Online (Sandbox Code Playgroud)

因为-xkbdir是一个有效的参数,而-xkbmap尽管Xvfb的手册页说明:

除了 Xserver(1) 手册页中描述的普通服务器选项之外,Xvfb 还接受以下命令行开关:

和Xserver的手册页说明:

?xkbdir directory
    base directory for keyboard layout files. This option is not available for setuid X servers (i.e., when the X server’s real and effective uids are different).
    ...
?xkbmap filename
    loads keyboard description in filename on server startup.
Run Code Online (Sandbox Code Playgroud)

如果我只是传入 -xkbdir

$ export PATH=~/bin:$PATH; # all copied binaries are here, including xkbcomp
$ Xvfb :1 -xkbdir ~/X11/xkb -nolisten tcp -screen 0 1680x1050x16
Run Code Online (Sandbox Code Playgroud)

然后我得到

_XSERVTransmkdir: Owner of /tmp/.X11-unix should be set to root
    sh: /usr/bin/xkbcomp: No such file or directory <-- WHY THIS PATH?
    sh: /usr/bin/xkbcomp: No such file or directory
    XKB: Failed to compile keymap
    Keyboard initialization failed. This could be a missing or incorrect setup of xkeyboard-config.
    (EE)
    Fatal server error:
    (EE) Failed to activate core devices.(EE)
Run Code Online (Sandbox Code Playgroud)

这是我被困了几个小时的地方。在没有 root 的机器上,要么

1) 如何在Xvfb没有输入设备的情况下运行?或者

2)我怎样才能Xvfb开始跑步?

dir*_*rkt 5

部分答案:如何在没有xkeycomp.

根据您的描述,您的主要问题似乎不是Xvfb以非root身份运行(在我的系统上运行得很好),而是作为非root您无法xkeycomp在该位置安装辅助程序及其关联的数据文件哪里Xvfb期待他们。

如果不确切知道沙盒 CentOS 环境中安装了什么和未安装什么,就很难进行模拟。但摆脱xkeycomp依赖性的方法如下:

正如使用stringsonXvfb所示, 的调用xkeycomp如下所示"%s%sxkbcomp" -w %d %s -xkm "%s" -em1 %s -emp %s -eml %s "%s%s.xkm",对应的源文件为xkbInit.cddxLoad.c。从粗略的观察来看,通往的路径似乎xkbcomp是硬连线的。但该字符串足够长,可以将其替换为对脚本的调用,这表明Xvfb要编译以下描述

xkb_keymap "default" {
    xkb_keycodes             { include "evdev+aliases(qwerty)" };
    xkb_types                { include "complete" };
    xkb_compatibility        { include "complete" };
    xkb_symbols              { include "pc+us+inet(evdev)" };
    xkb_geometry             { include "pc(pc105)" };
};
Run Code Online (Sandbox Code Playgroud)

提供自stdin、 到文件中/tmp/server-1.xkm。因此,在具有 X 和工具的机器上,将此描述复制到文件中,例如default.xkb,然后编译它

xkbcomp -xkm default.xkb 
Run Code Online (Sandbox Code Playgroud)

default.xkmXvfb现在通过搜索调用来修补 CentOS 沙盒上的副本:

$ grep -FobUa '"%s%sxkbcomp' Xvfb
1648800:"%s%sxkbcomp
Run Code Online (Sandbox Code Playgroud)

并通过调用来修补它cp

echo -n '/bin/cp /home/dirk/tmp/xvfb/default.xkm /tmp/server-1.xkm          ' | dd bs=1 of=Xvfb seek=1648800 conv=notrunc
Run Code Online (Sandbox Code Playgroud)

(当然还有你的位置和你的路径default.xkm)。

这在我的机器上运行良好,但在您的沙盒 CentOS 机器上,它现在可能会触发下一个问题。:-)

X API 将检查键盘映射的函数与实际输入设备解耦,因此即使没有输入设备,键盘映射也必须存在。


Dra*_*kes 4

我成功地在没有 root 的情况下运行 Xvfb。

最后,我从https://www.x.org/wiki/Releases/Download/下载了源代码,注入了环境变量,安装了依赖项(yum),并编译了Xvfb二进制和共享库并将其传输到我的沙箱中。

重要的是,[sources]/xkb/xkbInit.c我在第 815 行周围添加了这些行:

        if (++i >= argc)
            UseMsg();
        else
            XkbDfltRepeatInterval = (long) atoi(argv[i]);
        return 2;
    }
    /* End original code */


    // Change xkbcomp bin directory with an environment variable
    char *xkbBinDir = getenv("XKB_BINDIR");
    if (xkbBinDir) {
        XkbBinDirectory = Xstrdup(xkbBinDir);
    }

    // Change base xkb directory with an environment variable
    char *xkbBaseDir = getenv("XKBDIR");
    if (xkbBaseDir) {
        XkbBaseDirectory = Xstrdup(xkbBaseDir);
    }


    /* Original code */
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我可以将环境变量设置XKB_BINDIR为我的xkbcomp二进制路径(复制到沙箱)以及XKBDIR我的文件所在的位置default.xkm

同样,我的成功策略是Xvfb从源代码进行修改进行编译。对于令人难以忍受的细节和分步说明,我在我的网站上写了这篇文章 - https://ericdraken.com/running-xvfb-on-a-shared-host-without-x/


@dirkt 有一个有趣的方法,那就是破解 Xvfb 二进制文件并进行字符串操作。这很吸引人,因为它速度快而且有点顽皮,但它有缺点:1)我无法提前知道服务器编号是多少[1 .. 99],2)我的路径太长并且需要符号链接。我实际上尝试使用 NOP 命令 (:) 作为字符串替换以及手动复制server-N.xkm,除了源代码中有两个逻辑路径需要处理,一个是当 xkm 文件被缓存时。