編集

編集

JavaScriptユニットテストを実行するにはカルマdockerコンテナ内(ubuntu 14.04ベース)で、コンテナ内でFirefoxを起動しています。カルマ スクリプト ランチャーとします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 を起動したスクリプト) を終了します。

上記のスクリプトでは、スクリプトの終了時に起動したFirefoxを終了するように登録していることがわかりますtrap。これは機能しますが、スクリプトは終了するのであまり良い市民ではありません。全てスクリプトによって起動された 1 つのインスタンスを終了するのではなく、現在実行中の 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このバグの状態は 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、 を kill する方法について心配する必要がなくなりますxvfb-run

答え2

今日、まさにこの問題に遭遇しました。

全てXサーバーsはその-terminate議論を支持します。

−終了する

サーバーのリセット時にサーバーが実行を継続せずに終了します。これは、以前の −noreset コマンドライン オプションを上書きします。

xvfb-runそこで、 's を使用してこれを指定しました-s

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

したがって、Karma テスト ランナーの場合、Firefox インスタンスが Karma によって閉じられると、最後の xclient (Firefox) が終了したため、Xvfb サーバーも終了します。Firefox が終了した後も、xvfb-run の実行が完了します。

編集

最終的に、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 &

.bashrcDocker を使用していない場合は、この同じ行を何らかの OS 起動スクリプト (例 ) スクリプトにも配置できます。

次に別のスクリプトで表示をエクスポートし、実際に使用したい関数を呼び出しました

export DISPLAY=:0
firefox $1

関連情報