為了執行一些 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