如何正确终止 xvfb-运行

Howto terminate xvfb-run properly

为了用 karma inside a docker container (based on ubuntu 14.04) I'm starting firefox in the container using a karma-script-launcherxvfb-run 执行一些 JavaScript 单元测试。启动脚本如下所示:

#!/bin/bash
set -o errexit 

# nasty workaround as xvfb-run doesn't cleanup properly...
trap "pkill -f /usr/lib/firefox/firefox" EXIT

xvfb-run --auto-servernum --server-args='-screen 0, 1024x768x16' firefox 

启动浏览器并执行单元测试效果很好。执行测试后,karma 终止生成的浏览器实例 - 在我的例子中是通过 xvfb-运行.

启动 firefox 的脚本

在上面的脚本中你可以看到我注册了一个 trap 来在我的脚本退出时终止启动的 firefox。这行得通,但是脚本不是一个很好的公民,因为它终止了当前 运行ning 的 all 个 firefox 实例,而不是仅仅终止由脚本。我首先尝试终止 xfvb-run 进程,但终止此进程对 xvfb-run 脚本启动的子进程没有影响...

如果我在 xvfb-run 上手动启动 firefox,则会出现一堆生成的进程:

root@1d7a5988e521:/data# xvfb-run --auto-servernum --server-args='-screen 0, 1024x768x16' firefox &
[1] 348
root@1d7a5988e521:/data# ps ax
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 bash
  348 ?        S      0:00 /bin/sh /usr/bin/xvfb-run --auto-servernum --server-args=-screen 0, 1024x768x16 firefox
  360 ?        S      0:00 Xvfb :99 -screen 0, 1024x768x16 -nolisten tcp -auth /tmp/xvfb-run.bgMEuq/Xauthority
  361 ?        Sl     0:00 /usr/lib/firefox/firefox
  378 ?        S      0:00 dbus-launch --autolaunch bcf665e095759bae9fc1929b57455cad --binary-syntax --close-stderr
  379 ?        Ss     0:00 //bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
  388 ?        S      0:00 /usr/lib/x86_64-linux-gnu/gconf/gconfd-2
  414 ?        R+     0:00 ps ax
root@1d7a5988e521:/data#

如果我现在终止 xvfb-run 进程(PID 348),只有这个进程会被终止,而其他进程 运行ning。如果我改为终止 firefox 进程 (PID 361),xvfb-run 脚本会正确终止并终止其他进程。但是从我的脚本中我只知道 xvfb-run 进程的 PID...

在我的研究过程中,我偶然发现了 this rather old bug reportxvfb-run,尽管该错误的状态已在 2012 年修复,但它似乎仍然有效。

是否有礼貌的方式终止 xvfb-run 进程以便正确清理其他进程?

我前段时间在 unix.stackexchange.com 上发布了这个问题,因为它与 Unix/Linux 的关系比与一般编程的关系更大,因此在这里没有引起太多关注:

Howto terminate xvfb-run properly @ Unix & Linux

然而,正确终止 X 程序的唯一选择似乎是不使用 xvfb-运行 并编写您自己的脚本以使用 Xvfb 启动进程。

虽然年纪大了,但我最终还是遇到了这个。 dpr 的 post 中的 link 基本上是说要重新创建 xvfb-run 以便它可以更好地进行清理。因为我有一些空闲时间,所以我最后想看看是否可以避免这种情况。

我最终得到的是使用进程组。 xvfb-run 不会分离 Xvfb 或它在其下生成的命令,它仍然是同一 PGID 的一部分。对于 bash,这意味着 运行 处于监控模式,然后执行类似的操作(注意 PID 前的“-”):

xvfb-run -a blah &
xvfb_pid=$!
kill -- "-$xvfb_pid"

这将杀死 xvfb-run 领导的整个进程组。这仅适用于监控模式,因为只有监控模式才会为每个后台进程提供自己的组。

我不建议将作业控制功能与 bash 和脚本一起使用。我建议改为调用 setsid:

setsid xvfb-run -a blah &
xvfb_pid=$!
kill -- "-$xvfb_pid"

但是,请注意它调用 setsid 这也使子进程成为会话领导者。这比一个团体更强大,可能比我们想要的更多(虽然我想不出任何它会立即引起问题的东西)。

我最终使用了一个 C 解决方案,该解决方案在执行到 xvfb-run 之前在子进程中调用 setpgid(0,0) 而不是 setsid(),并使用 killpg 终止进程。