Для того чтобы выполнить некоторые модульные тесты 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 завершает порожденный экземпляр браузера - в моем случае скрипт, который запускал firefox через xvfb-run.
В приведенном выше скрипте вы можете видеть, что я зарегистрировал a 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
, похоже, все еще актуально, несмотря на то, что ошибка была исправлена еще в 2012 году.
Есть ли какой-либо вежливый способ завершить xvfb-run
процесс, чтобы другие процессы были правильно очищены?
Я уже спрашивал об этом на Stack Overflow, но до сих пор не получил ответа. Возможно, это немного OT для Stack Overflow, но лучше разместить здесь?!
решение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, как только экземпляр Firefox закрывается программой Karma, сервер 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
Моим решением было запустить xvfb в скрипте точки входа Docker:
Xvfb :0 -screen 0 1024x768x24 &
Эту же строку можно поместить в какой-либо скрипт запуска ОС (например .bashrc
, ), если вы не используете Docker.
Затем в другом скрипте я экспортировал отображение и вызвал нужную мне функцию.
export DISPLAY=:0
firefox $1