Um einige JavaScript-Unit-Tests durchzuführen mitKarmaIn einem Docker-Container (basierend auf Ubuntu 14.04) starte ich Firefox im Container mit einemKarma-Skript-Launchermit xvfb-run
. Das Startskript sieht folgendermaßen aus:
#!/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
Das Starten des Browsers und Ausführen der Unit-Tests funktioniert sehr gut. Nach der Ausführung der Tests beendet Karma die erzeugte Browserinstanz – in meinem Fall das Skript, das Firefox über xvfb-run gestartet hat.
Im obigen Skript können Sie sehen, dass ich ein Skript registriert habe, trap
um den gestarteten Firefox beim Beenden meines Skripts zu beenden. Das funktioniert, aber das Skript ist kein sehr netter Bürger, da es beendet wirdalleInstanzen von Firefox, die derzeit ausgeführt werden, anstatt nur die eine Instanz zu beenden, die vom Skript gestartet wurde. Ich habe zuerst versucht, den xfvb-run
Prozess zu beenden, aber das Beenden dieses Prozesses hat keine Auswirkungen auf den vom Skript gestarteten Unterprozess xvfb-run
...
Wenn ich Firefox xvfb-run
manuell neu starte, werden eine Reihe von Prozessen erzeugt:
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#
Wenn ich nun den xvfb-run
Prozess (PID 348) beende, wird nur dieser Prozess beendet und die anderen Prozesse laufen weiter. Wenn ich stattdessen den Firefox-Prozess (PID 361) beende, wird das xvfb-run
Skript korrekt beendet und beendet auch die anderen Prozesse. Aus meinem Skript kenne ich aber nur die PID des xvfb-run
Prozesses...
Bei meinen Recherchen stieß ich aufdieser ziemlich alte FehlerberichtDies xvfb-run
scheint immer noch gültig zu sein, obwohl der Fehler bereits 2012 behoben wurde.
Gibt es eine höfliche Möglichkeit, den xvfb-run
Prozess zu beenden, damit die anderen Prozesse ordnungsgemäß bereinigt werden können?
Ich habe dies bereits auf Stack Overflow gefragt, aber bisher keine Antwort erhalten. Vielleicht ist es etwas OT für Stack Overflow, aber hier besser aufgehoben?!
Antwort1
Es hört sich an, als würden Sie es nur xvfb-run
wegen der --auto-servernum
Funktionalität verwenden.
Wie @meuh bemerkte: Diese Logik isteigentlich ganz einfach:
# 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
}
Wenn diese Funktion definiert ist, können Sie einen Aufruf wie diesen versuchen.anstattxvfb-run
:
Xvfb :$(find_free_servernum) -screen 0, 1024x768x16 firefox $1 &
THE_PID=$!
# kill Xvfb whenever you feel like it
kill -15 $THE_PID
Mit xvfb-run
„entfernt:“ müssen wir uns keine Gedanken mehr darüber machen, wie wir töten xvfb-run
.
Antwort2
Ich bin heute auf genau dieses Problem gestoßen.
AlleXserverLassen Sie uns das -terminate
Argument stützen.
-beenden
bewirkt, dass der Server beim Zurücksetzen beendet wird, anstatt weiterzulaufen. Dies überschreibt eine vorherige Befehlszeilenoption −noreset.
Daher habe ich es letztendlich mit xvfb-run
's angegeben -s
:
xvfb-run -d -s '-terminate' firefox --no-remote --profile $PROFILE_DIR $URL
In unserem Fall eines Karma-Testläufers beendet sich der Xvfb-Server selbst, sobald die Firefox-Instanz von Karma geschlossen wird, da sein letzter X-Client (Firefox) beendet wurde. xvfb-run hat die Ausführung auch nach dem Beenden von Firefox abgeschlossen.
Bearbeiten
Am Ende habe ich meine eigene „einfachere“ Version des xvfb-run-Skripts zusammengestellt:
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
Antwort3
Meine Lösung bestand darin, xvfb im Docker-Einstiegspunktskript zu starten:
Xvfb :0 -screen 0 1024x768x24 &
Sie können diese gleiche Zeile auch in eine Art Betriebssystem-Startskript (z. B. .bashrc
) einfügen, wenn Sie Docker nicht verwenden.
Dann habe ich in einem anderen Skript die Anzeige exportiert und die eigentliche Funktion aufgerufen, die ich verwenden wollte
export DISPLAY=:0
firefox $1