2010-03-26 10 views
9

Tengo algunas pruebas de unidad que necesitan una pantalla X11, así que planeo iniciar Xvfb antes de ejecutarlas, pero para iniciar Xvfb necesitaré un número de pantalla gratuito para conectarlo. Mi mejor opción es ver lo que es gratis en /tmp/.X11-unix pero no estoy seguro de cómo manejar la carrera si muchas pruebas intentan comenzar simultáneamente.Encuentre un número de pantalla gratis de X11

sshd debe hacer esto, ¿alguien sabe cómo?

Respuesta

8

con el crédito a this answer a la pregunta relacionada How high do X11 display numbers go?:

servidores X recientes a partir de versio n 1.13 (Xvfb, también) admite la opción de línea de comando -displayfd <fd>: hará que el servidor X elija la pantalla y escriba el número de pantalla nuevamente en el descriptor de archivo <fd>. Es un poco intrincado, pero esta sería una forma segura y libre de condiciones de carrera para pedirle al Xvfb que use cualquier pantalla gratis. A bash ejemplo:

exec 6>display.log 
Xvfb -displayfd 6 
# The display number of the new Xvfb instance has been written to display.log 
# Kill Xvfb 
exec 6>&- 
+0

Solo una nota: en Debian 'Xvfb' v1.14 está disponible en [' jessie'] (http://packages.debian.org/search?suite=jessie&searchon=names&keywords=xvfb), eso significa que en una distribución promedio debería ser bastante reciente (segunda mitad de 2013 o posterior). –

5

No tiene sentido tratar de encontrar un número de pantalla gratis. Como habrás adivinado, entre el momento en que encuentras uno gratis y el momento en que se inicia Xvfb, otro servidor X podría haber tomado el puerto que creías que era libre. Por lo tanto, es mejor tratar de ejecutar Xvfb, manejar el error si se toma el puerto, y luego volver a intentar en el siguiente puerto hasta que tenga éxito o se quede sin puertos para probar.

#!/bin/bash 
DISPLAY_NUM=0 
unset TEST_HAS_RUN 
until [ $TEST_HAS_RUN ] || (($DISPLAY_NUM > 10)) 
do 
Xvfb :$DISPLAY_NUM & 
jobs 
sleep 2 # assumption here is that Xvfb will exit quickly if it can't launch 
if jobs | grep Xvfb 
then 
    echo launching test on :$DISPLAY_NUM 
    xterm -display :$DISPLAY_NUM 
    TEST_HAS_RUN=1 
    kill %- 
else 
    let DISPLAY_NUM=$DISPLAY_NUM+1 
fi 
done 
+0

Si 'xterm' se inicia correctamente, ¿no bloqueará su script hasta que el usuario lo salga manualmente? De lo contrario, parece que 'TEST_HAS_RUN' nunca se establece y el bucle nunca se cierra. De hecho, parece que tu prueba _pases_ si 'xterm' falla al iniciarse. ¿Me estoy perdiendo de algo? – jrodatus

+1

Técnicamente, si Xvfb falla y luego, en su suspensión de 2 segundos, otro servidor X toma el puerto, su prueba pasará al servidor incorrecto (particularmente si su script tiene otro Xvfb en segundo plano para satisfacer 'jobs | grep Xvfb'). Sería mejor lanzar Xvfb con ** ** ** fbdir (por ejemplo, '-fbdir/var/tmp/$ 0. $$. $ RANDOM'), y luego verificar el archivo' Xvfb_screen0' dentro de ese directorio. – jrodatus

+0

@jrodatus Esta respuesta asume que "xterm" es la prueba, por lo que es correcto que la pantalla se cierre después de eso. Y otra instancia que compite contra esto no encontraría el servidor equivocado porque "jobs" informa solo hijos de este shell. La respuesta de krlmlr ahora es mejor, sin embargo. – James

10

¿Por qué no explotar el hecho de que cada servidor X11 pone un archivo "Lock" en/tmp?

Esto se llama /tmp/.Xn-lock donde "n" es la ID de pantalla. (También tenga en cuenta el encabezado. En el nombre del archivo).

Este es el mecanismo que el propio servidor X utiliza para comprobar si hay duplicación, y parece ser consistente en todas las plataformas * nix que he probado (HP-UX, Linux, ...)

Por lo que podría adaptarse por tanto, la secuencia de comandos (perdón por los errores de sintaxis, estoy acostumbrado a Nore C shell de Bourne/Korn shell scripting)

DISPLAY_NUM=0 

do 

    if (-e /tmp/.X$DISPLAY_NUM-lock) then 

    let DISPLAY_NUM=$DISPLAY_NUM+1 

    else 

    Xvfb :$DISPLAY_NUM -screen 0 1280x1024x24 -ac (or whatever args take your fancy) 

    fi 

done 
0

Basado en la respuesta de @karunski.

El uso de Xvfb para sondear las pantallas, y lsof para comprobar si son sockets unix en el proceso Xvfb, es más efectivo, observe que el sleep 0.5, puede ser variable depende de la máquina.

#!/bin/bash 
DISPLAY=0 

until [ $DISPLAY_NUM > 10 ]; do 
     echo -n "Looking for display on $DISPLAY..." 
     Xvfb :$DISPLAY > /dev/null 2>&1 & 
     pid=$! 
     sleep 0.5 
     lsof -a -U -p $pid > /dev/null 2>&1  

     notfound="$?" 
     kill $pid > /dev/null 2>&1 

     wait $pid 

     [ "$notfound" == "0" ] && echo "found" && break 

     echo "fail" 
     let DISPLAY=DISPLAY+1 
done 
Cuestiones relacionadas