Editar

Editar

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 trappara 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-runprocesso, mas matá-lo não tem efeito no subprocesso iniciado pelo xvfb-runscript...

Se eu iniciar o Firefox xvfb-runmanualmente, 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-runprocesso (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-runscript será encerrado corretamente e também encerrará os outros processos. Mas pelo meu script eu só conheço o PID do xvfb-runprocesso...

Durante minha pesquisa me depareieste relatório de bug bastante antigopara xvfb-runo qual ainda parece ser válido, apesar do status do bug ter sido corrigido em 2012.

Existe alguma maneira educada de encerrar o xvfb-runprocesso 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-runpor sua --auto-servernumfuncionalidade.

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-runremovido: não precisamos mais nos preocupar em como matar xvfb-run.

Responder2

Eu me deparei com esse mesmo problema hoje.

TodosServidor Xs apoiam o -terminateargumento.

−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

informação relacionada