編輯

編輯

為了執行一些 JavaScript 單元測試業力在 docker 容器內(基於 ubuntu 14.04),我在容器中使用業力腳本啟動器xvfb-run。啟動腳本如下所示:

#!/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 $1

啟動瀏覽器並執行單元測試效果很好。執行測試後,karma 會終止產生的瀏覽器實例 - 在我的例子中,是透過 xvfb-run 啟動 Firefox 的腳本。

在上面的腳本中,您可以看到我註冊了一個trap在退出腳本時殺死啟動的 Firefox 的程式。這是可行的,但腳本不是一個很好的公民,因為它終止了全部目前正在執行的 Firefox 實例,而不是僅僅終止由腳本啟動的實例。我首先嘗試殺死該xfvb-run進程,但殺死該進程對腳本啟動的子進程沒有影響xvfb-run...

如果我手動啟動 Firefox,xvfb-run則會產生一堆進程:

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),則只有該進程將被終止,而其他進程仍在運行。如果我終止 firefox 進程(PID 361),xvfb-run腳本會正確終止並終止其他進程。但從我的腳本我只知道進程的PID xvfb-run......

在我的研究過程中我偶然發現這個相當舊的錯誤報告xvfb-run儘管 bug 的狀態早在 2012 年就被修復了,但它似乎仍然有效。

是否有任何禮貌的方式來終止該xvfb-run進程,以便正確清理其他進程?


我已經在 Stack Overflow 上問過這個問題,但到目前為止還沒有得到答案。也許對於 Stack Overflow 來說有點 OT,但這裡位置更好?

答案1

聽起來您只是xvfb-run為了它的--auto-servernum功能而使用。

正如@meuh 指出的:邏輯是其實很簡單:

# Copyright (C) 2005 The T2 SDE Project
# Copyright (C) XXXX - 2005 Debian
# GNU GPLv2
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
}

定義該函數後:您可以嘗試這樣的調用而不是使用xvfb-run:

Xvfb :$(find_free_servernum) -screen 0, 1024x768x16 firefox $1 &
THE_PID=$!
# kill Xvfb whenever you feel like it
kill -15 $THE_PID

刪除後xvfb-run:我們不再需要擔心如何殺死xvfb-run

答案2

我今天就遇到這個問題了。

全部X伺服器支持該-terminate論點。

−終止

導致伺服器在伺服器重置時終止,而不是繼續運作。這會覆蓋先前的 -noreset 命令列選項。

所以我最終使用xvfb-run's指定了這一點-s

xvfb-run -d -s '-terminate' firefox --no-remote --profile $PROFILE_DIR $URL

因此,在我們的 Karma 測試執行程式的範例中,一旦 Karma 關閉了 firefox 實例,Xvfb 伺服器就會在其最後一個 xclient (firefox) 終止時自行終止。 xvfb-run在firefox退出後也完成執行。

編輯

我最終將我自己的“更簡單”版本的 xvfb-run 腳本放在一起:


PROFILE=$(mktemp -d)
trap "rm -rf $PROFILE" EXIT

# Start Xvfb and let it find a display number itself.
# Some versions of Xvfb (apparently 1.17.x) refuse to write to stdout
Xvfb -displayfd 4 -terminate -nolisten tcp 4>$PROFILE/.Xdisplay &

# Wait a few seconds for Xvfb to start
sleep ${START_WAIT-2}

${FIREFOX_HOME}/firefox --profile $PROFILE --no-remote --display :$(<$PROFILE/.Xdisplay) "${@?}" &
# Karma appears to send a SIGTERM to the browser when it's done, forward that signal to the Firefox process.
trap "kill -SIGTERM $!" SIGTERM

# Wait for all children to terminate
wait

答案3

我的解決方案是在 Docker 入口點腳本中啟動 xvfb:

Xvfb :0 -screen 0 1024x768x24 &

.bashrc如果您不使用 Docker,您也可以將同一行放入某種作業系統啟動腳本(例如)腳本中。

然後在另一個腳本中,我導出顯示並調用我想要使用的實際函數

export DISPLAY=:0
firefox $1

相關內容