【问题标题】:Find a free X11 display number查找免费的 X11 显示编号
【发布时间】:2021-07-13 13:22:49
【问题描述】:

我有一些需要 X11 显示的单元测试,所以我计划在运行它们之前启动 Xvfb,但是要启动 Xvfb,我需要一个空闲的显示编号来连接它。我最好的猜测是查看/tmp/.X11-unix 中的免费内容,但如果许多测试尝试同时开始,我不确定如何处理比赛。

sshd 必须这样做,有人知道怎么做吗?

【问题讨论】:

    标签: x11


    【解决方案1】:

    感谢this answer 相关问题How high do X11 display numbers go?

    最近的 X 服务器 1.13 版(Xvfb,也是)支持-displayfd <fd> 命令行选项:它将使 X 服务器自己选择显示器并将显示器编号写回文件描述符 <fd>。这有点令人费解,但这是要求Xvfb 使用任何免费显示的安全且无竞争条件的方式。一个bash 的例子:

    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>&-
    

    【讨论】:

    • 请注意:在 Debian 中 Xvfb v1.14 在 jessie 中可用,这意味着平均发行版应该是相当新的(2013 年下半年或之后)。
    【解决方案2】:

    为什么不利用每个 X11 服务器都将“锁定”文件放入 /tmp 的事实?

    这称为/tmp/.Xn-lock,其中“n”是显示ID。 (还要注意文件名中的前导 .)。

    这是 Xserver 本身用来检查重复的机制,它似乎在我尝试过的所有 *nix 平台(HP-UX、Linux、...)上都是一致的

    所以你可以调整你的脚本(请原谅我的语法错误,我不习惯 C shell 而不是 Bourne/Korn shell 脚本)

    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
    

    【讨论】:

    • 部分问题是如何避免比赛。如果同时运行,您的代码最终也会失败。
    • 您可以通过额外的自定义锁来帮助避免比赛 - 例如将所有这些放在另一个羊群中。这对我有用(比实际接受的答案更好)。
    • 我在下面添加了一个对我有用的新答案stackoverflow.com/a/68128883/101152
    【解决方案3】:

    试图找到一个免费的显示号码是没有意义的。正如您已经猜到的,在您找到一个空闲端口和 Xvfb 启动之间,另一台 X 服务器可能占用了您认为空闲的端口。因此,最好尝试启动 Xvfb,如果端口被占用,则处理失败,然后在下一个端口重试,直到成功或用完端口尝试。

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

    【讨论】:

    • 如果xterm 启动成功,在用户手动退出之前它不会阻塞你的脚本吗?否则看起来TEST_HAS_RUN 永远不会被设置,并且循环永远不会退出。事实上,如果xterm 启动失败,您的测试似乎通过。我错过了什么吗?
    • 从技术上讲,如果 Xvfb 失败,然后在您的 2 秒睡眠内另一台 X 服务器占用该端口,您的测试将在错误的服务器上通过(特别是如果您的脚本在后台有另一个 Xvfb 以满足 @ 987654325@)。最好使用 unique fbdir(例如 -fbdir /var/tmp/$0.$$.$RANDOM)启动 Xvfb,然后在该目录中检查文件 Xvfb_screen0
    • @jrodatus 此答案假定“xterm”是测试,因此在此之后关闭显示是正确的。另一个与之竞争的实例不会找到错误的服务器,因为“jobs”只报告这个shell的孩子。不过,krlmlr 的答案现在更好了。
    【解决方案4】:

    可能有点跑题了,但是如果您使用 xvfb-run 来启动需要 Xserver 的命令,那么只需运行

    # xvfb-run -a your command
    

    成功了。

    【讨论】:

      【解决方案5】:

      基于@karunski 的回答。

      在Xvfb进程中使用Xvfb探测显示器,使用lsof检查是否是unix套接字,更有效,注意sleep 0.5,可以根据机器变化。

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

      【讨论】:

        【解决方案6】:

        这对我有用(注意 - 使用 bash)

        exec {lock_fd}>/var/lock/xlockfile || exit 1
        flock "$lock_fd" || { echo "ERROR: flock() failed." >&2; exit 1; }
        
        DISPLAY_NUM=1
        until [[ $xvfb ]]; do
          if [[ -e /tmp/.X$DISPLAY_NUM-lock ]]; then
            let DISPLAY_NUM=$DISPLAY_NUM+1
          else
            Xvfb :$DISPLAY_NUM -ac -screen 0 $XVFB_WHD -nolisten tcp &
            xvfb=$!
          fi
        done
        
        flock -u "$lock_fd"
        

        请注意,外向锁只有在所有运行 xvfb 命令的脚本都使用它时才有效,否则你会再次遇到竞争条件

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-05
          • 1970-01-01
          • 1970-01-01
          • 2016-11-01
          • 2010-10-04
          • 1970-01-01
          • 2021-11-19
          • 1970-01-01
          相关资源
          最近更新 更多