Para realizar alguns testes de unidade JavaScript comcarmadentro de um contêiner docker (baseado no Ubuntu 14.04) estou iniciando o firefox no contêiner usando umlançador de script de karmacom xvfb-run
. O script inicial é assim:
#!/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
Iniciar o navegador e executar os testes unitários funciona muito bem. Depois de executar os testes, o karma encerra a instância do navegador gerada - no meu caso, o script que iniciou o firefox através do xvfb-run.
No script acima você pode ver que registrei um trap
para matar o firefox iniciado ao sair do meu script. Isso funciona, mas o script não é um cidadão muito legal, pois terminatodosinstâncias do Firefox que estão em execução no momento, em vez de apenas encerrar a instância que foi iniciada pelo script. Primeiro tentei matar o xfvb-run
processo, mas matá-lo não tem efeito no subprocesso iniciado pelo xvfb-run
script...
Se eu iniciar o Firefox xvfb-run
manualmente, haverá vários processos gerados:
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#
Se eu encerrar agora o xvfb-run
processo (PID 348), apenas esse processo será finalizado, deixando os demais processos em execução. Se eu encerrar o processo do Firefox (PID 361), o xvfb-run
script será encerrado corretamente e também encerrará os outros processos. Mas pelo meu script eu só conheço o PID do xvfb-run
processo...
Durante minha pesquisa me depareieste relatório de bug bastante antigopara xvfb-run
o qual ainda parece ser válido, apesar do status do bug ter sido corrigido em 2012.
Existe alguma maneira educada de encerrar o xvfb-run
processo para que os outros processos sejam limpos corretamente?
Já perguntei isso no Stack Overflow, mas não obtive resposta até agora. Talvez seja um pouco OT para Stack Overflow, mas melhor localizado aqui?!
Responder1
Parece que você está usando apenas xvfb-run
por sua --auto-servernum
funcionalidade.
Como @meuh apontou: essa lógica éna verdade bem simples:
# 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
}
Com essa função definida: você poderia tentar uma invocação como estaao invés de usarxvfb-run
:
Xvfb :$(find_free_servernum) -screen 0, 1024x768x16 firefox $1 &
THE_PID=$!
# kill Xvfb whenever you feel like it
kill -15 $THE_PID
Com xvfb-run
removido: não precisamos mais nos preocupar em como matar xvfb-run
.
Responder2
Eu me deparei com esse mesmo problema hoje.
TodosServidor Xs apoiam o -terminate
argumento.
−terminar
faz com que o servidor seja encerrado na reinicialização do servidor, em vez de continuar a execução. Isso substitui uma opção de linha de comando −noreset anterior.
Então acabei especificando isso usando xvfb-run
's -s
:
xvfb-run -d -s '-terminate' firefox --no-remote --profile $PROFILE_DIR $URL
Portanto, em nosso caso de um executor de testes Karma, uma vez que a instância do Firefox é fechada pelo Karma, o servidor Xvfb se encerra quando seu último xclient (firefox) foi encerrado. xvfb-run concluiu a execução após a saída do Firefox também.
Editar
Acabei montando minha própria versão "mais simples" do script 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
Responder3
Minha solução foi iniciar o xvfb no script do ponto de entrada do Docker:
Xvfb :0 -screen 0 1024x768x24 &
Você pode colocar esta mesma linha também em algum tipo de script de inicialização do sistema operacional (por exemplo .bashrc
), se não estiver usando o Docker.
Então, em outro script, exportei a exibição e chamei a função real que queria usar
export DISPLAY=:0
firefox $1