当并行调用多个实例时,xvfb运行不可靠



你能帮帮我吗,为什么我有时会(50:50):

webkit_server.NoX11Error: Cannot connect to X. You can try running with xvfb-run.

当我并行启动脚本时:

xvfb-run -a python script.py 

你可以自己复制如下:

for ((i=0; i<10; i++)); do
  xvfb-run -a xterm &
done

在启动的10个xterm实例中,其中9个通常会失败,并以消息Xvfb failed to start退出。

看看xvfb-run 1.0,它的操作如下:

# Find a free server number by looking at .X*-lock files in /tmp.
find_free_servernum() {
    # Sadly, the "local" keyword is not POSIX.  Leave the next line commented in
    # the hope Debian Policy eventually changes to allow it in /bin/sh scripts
    # anyway.
    #local i
    i=$SERVERNUM
    while [ -f /tmp/.X$i-lock ]; do
        i=$(($i + 1))
    done
    echo $i
}

这是一个非常糟糕的做法:如果两个find_free_servernum副本同时运行,它们都不会知道另一个副本,因此它们都可以确定相同的数字是可用的,即使只有其中一个能够使用它。

所以,为了解决这个问题,让我们自己编写代码来找到一个空闲的显示数字,而不是假设xvfb-run -a将可靠地工作:
#!/bin/bash
# allow settings to be updated via environment
: "${xvfb_lockdir:=$HOME/.xvfb-locks}"
: "${xvfb_display_min:=99}"
: "${xvfb_display_max:=599}"
# assuming only one user will use this, let's put the locks in our own home directory
# avoids vulnerability to symlink attacks.
mkdir -p -- "$xvfb_lockdir" || exit
i=$xvfb_display_min     # minimum display number
while (( i < xvfb_display_max )); do
  if [ -f "/tmp/.X$i-lock" ]; then                # still avoid an obvious open display
    (( ++i )); continue
  fi
  exec 5>"$xvfb_lockdir/$i" || continue           # open a lockfile
  if flock -x -n 5; then                          # try to lock it
    exec xvfb-run --server-num="$i" "$@" || exit  # if locked, run xvfb-run
  fi
  (( i++ ))
done

如果将此脚本保存为xvfb-run-safe,则可以调用:

xvfb-run-safe python script.py 

…只要系统上没有其他用户也在运行xvfb,就不用担心竞争条件。


可以这样测试:

for ((i=0; i<10; i++)); do xvfb-wrap-safe xchat & done

…在这种情况下,所有10个实例都正确启动并在后台运行,而不是:

for ((i=0; i<10; i++)); do xvfb-run -a xchat & done

…其中,根据系统的时间,十分之九(通常)会失败。

这个问题在2015年就被问过了。

在我的xvfb (2:1.20.13-1ubuntu1~20.04.2)版本中,这个问题已经修复。

它查看/tmp/.X*-lock以找到可用的端口,然后运行Xvfb。如果Xvfb启动失败,它会找到一个新端口并重试,最多重试10次。

最新更新