2010-03-26 18 views
9

Mam kilka testów jednostkowych, które wymagają wyświetlacza X11, więc planuję uruchomić Xvfb przed ich uruchomieniem, ale aby uruchomić Xvfb, potrzebuję darmowego numeru wyświetlacza, aby go podłączyć. Domyślam się, że to, co jest darmowe w /tmp/.X11-unix, ale nie jestem pewien, jak sobie z tym poradzić, jeśli wiele prób spróbuje uruchomić jednocześnie.Znajdź bezpłatny numer wyświetlacza X11

sshd musi to zrobić, czy ktoś wie jak?

Odpowiedz

8

z pełnym kredytu this answer do powiązanego pytanie How high do X11 display numbers go?:

Najnowsze Xserwer od wersji versio n 1,13 (Xvfb) obsługuje także opcję wiersza poleceń -displayfd <fd>: spowoduje to, że serwer X wybierze sam ekran i zapisze numer wyświetlacza z powrotem do deskryptora pliku <fd>. Jest nieco zawikłany, ale byłby to bezpieczny i wolny od warunków wyścigowych sposób, aby poprosić użytkownika Xvfb o użycie dowolnego wolnego ekranu. Przykład: bash przykład:

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

Po prostu uwaga: w Debianie 'Xvfb' v1.14 jest dostępny w [' jessie'] (http://packages.debian.org/search?suite=jessie&searchon=names&keywords=xvfb), co oznacza, że ​​w przeciętnej dystrybucji powinno być być całkiem nowym (druga połowa 2013 r. lub później). –

5

Nie ma sensu szukanie wolnego numeru wyświetlacza. Jak już się domyślacie, od czasu, kiedy znajdziecie wolny i czas rozpoczęcia Xvfb, inny X serwer mógłby wziąć port, który uważaliście za wolny. Lepiej więc po prostu spróbować uruchomić Xvfb, poradzić sobie z awarią, jeśli port jest zajęty, a następnie ponowić próbę na następnym porcie, aż się uda lub zabraknie portów, aby spróbować.

#!/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

Jeśli 'xterm' uruchamia się pomyślnie, czy nie zablokuje twojego skryptu, dopóki użytkownik nie wyjdzie z niego ręcznie? W przeciwnym razie wygląda na to, że 'TEST_HAS_RUN' nigdy nie zostanie ustawione, a pętla nigdy nie zostanie zamknięta. W rzeczywistości wygląda na to, że Twój test _passes_, jeśli 'xterm' nie uruchomi się. Czy czegoś brakuje? – jrodatus

+1

Technicznie, jeśli Xvfb ulegnie awarii, a następnie w ciągu 2-sekundowego snu inny serwer X pobierze port, test przełoży się na zły serwer (szczególnie, jeśli twój skrypt ma inny Xvfb w tle, aby spełnić 'jobs | grep Xvfb'). Lepiej byłoby uruchomić Xvfb z ** unikalnym ** fbdir (np. '-fbdir/var/tmp/$ 0. $$. $ RANDOM'), a następnie sprawdzić plik' Xvfb_screen0' w tym katalogu. – jrodatus

+0

@jrodatus W tej odpowiedzi zakłada się, że "xterm" jest testem, więc po zamknięciu ekranu może się on zamknąć. Inna instancja ścigająca się z tym nie znajdzie niewłaściwego serwera, ponieważ "zadania" zgłasza tylko dzieci z tej powłoki. Odpowiedź krlmlr jest teraz lepsza. – James

10

Dlaczego nie wykorzystać faktu, że każdy serwer X11 umieszcza plik "Lock" w/tmp?

Nazywa się to /tmp/.Xn-lock gdzie "n" jest identyfikatorem wyświetlania. (Zwróć także uwagę na wiodące. W nazwie pliku).

Jest to mechanizm, który sam Xserver używa do sprawdzania duplikacji, a to wydaje się być spójne na wszystkich platformach * nix próbowałem (HP-UX, Linux, ...)

Więc można dostosować więc skrypt (wybacz mi błędy składni, jestem nore przyzwyczajeni do powłoki C niż 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

Na podstawie odpowiedzi @karunski.

Używanie Xvfb do sondowania wyświetlaczy i lsof do sprawdzenia, czy są gniazdami uniksowymi w procesie Xvfb, jest bardziej efektywne, zauważ, że sleep 0.5, może być zmienna, w zależności od maszyny.

#!/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