【问题标题】:How to wait until environment is non-headless?如何等到环境非无头?
【发布时间】:2015-06-25 02:16:07
【问题描述】:

我创建了一个在 Ubuntu 12.04 上启动的 Java 服务器,但我遇到了一个问题:我的代码需要一个非无头(或有头)环境才能工作,否则会引发 HeadlessException :

java.awt.AWTException: headless environment
at java.awt.Robot.<init>(Robot.java:91)
at remote_control.RobotThread.run(RobotThread.java:35)
at java.lang.Thread.run(Thread.java:745)

但似乎我的 .jar 是在启动时在 X 服务器之前启动的,所以我总是收到“HeadlessException”。为了让我的 JAR 从我的系统开始,我做了类似的事情:

sudo update-rc.d my_script_to_initiate_my_jar defaults 99 01

我还没有找到一种方法来启动 X 服务器之后的 JAR,所以我认为解决这个问题的最佳方法是在我的代码中使用忙等待。我已经检查了很多问题(在 StackOverflow 和 Google),并找到了一些常见的解决方案:

// First solution
while (GraphicsEnvironment.isHeadless()) {
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// Second solution
GraphicsEnvironment ge;
do {
    ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
} while (ge.isHeadless());

很遗憾,这些解决方案不起作用:isHeadless() 总是返回 true,因此它永远不会退出循环。是的,此时我已经在使用 Unity(Ubuntu 图形界面),所以我已经有了一个“充满活力的环境”。对不起,如果我犯了一些错误,但我是 UNIX / Linux 的新手。

如果您需要任何进一步的信息,请询问我,我会提供。解决方案还必须是非 GUI 特定的(例如:仅适用于 GNOME 或 Unity,必须适用于所有这些)。

编辑

接下来你可以检查我的 .sh 脚本,它位于/etc/init.d/ 中,负责用系统启动 JAR。包含 @that-other-guy 提供的脚本。

#!/bin/sh
SERVICE_NAME=labspy_client
PATH_TO_JAR=/var/lib/LabSpy/Student.jar
PID_PATH_NAME=/tmp/labspy_client_pid
case $1 in
    start)
        echo "Starting $SERVICE_NAME ..."
        if [ ! -f $PID_PATH_NAME ]; then
                export DISPLAY=:0
                until xwininfo -root > /dev/null
                do
                    sleep 5
                done
                nohup /opt/java/bin/java -jar $PATH_TO_JAR /tmp 2>> /var/log/labspy_stdout >> /var/log/labspy_stderr &
                        echo $! > $PID_PATH_NAME
                echo "$SERVICE_NAME started ..."
        else
                echo "$SERVICE_NAME is already running ..."
        fi
    ;;
    stop)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stoping ..."
            kill $PID;
            echo "$SERVICE_NAME stopped ..."
            rm $PID_PATH_NAME
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
    restart)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stopping ...";
            kill $PID;
            echo "$SERVICE_NAME stopped ...";
            rm $PID_PATH_NAME
            echo "$SERVICE_NAME starting ..."
            nohup java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
                        echo $! > $PID_PATH_NAME
            echo "$SERVICE_NAME started ..."
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
esac 

【问题讨论】:

  • 为什么不捕获异常并在短暂延迟后重试,直到您的代码成功?
  • 我还没有想过 O.o 我会尝试,但我仍然接受更好的方法来解决这个问题(而不是忙着等待)。无论如何,谢谢你的评论!
  • 我很确定环境永远不会变成非无头。相反,你需要弄清楚它为什么需要 X 并修复它(因为它是一个服务器,它不应该需要它)。
  • 你是如何启动你的应用程序的?有可能让它在 X 和其他依赖项之后加载。
  • 您是否尝试将您的应用程序添加为 Xsession.d(x 服务器启动)中的启动脚本而不是 rc 脚本? (就像这样debian-administration.org/article/50/…

标签: java linux headless


【解决方案1】:

图形程序使用的显示由DISPLAY 环境变量决定。这通常由 X 会话设置并继承自 X 会话。

如果您认为合适的显示服务器将在不久的将来启动并运行,您可以猜测它的显示编号——可能是:0——然后等待它做出响应。

我真的不相信 Java 会在第一次初始化后重新检查显示器是否正常工作,所以这里有一个 shell 脚本循环:

export DISPLAY=:0
export XAUTHORITY="/home/youruser/.Xauthority"
until xwininfo -root > /dev/null
do
  sleep 5
done
echo "X server is now running"

这是一种高度反 Unix 的解决方案,因为您的 Windows 风格要求假设只有一个屏幕并且您需要控制它。

表现良好的 Unix 程序不会像这样对系统起作用,而是让用户在他们选择的显示器上启动服务器。

【讨论】:

  • 我真的很喜欢你的解决方案,我正在尝试实现它,但是当我重新启动我的虚拟机时(使用更新的 JAR [没有任何忙等待] 并且 Ubuntu 配置为使用系统启动 JAR)什么都没发生。我将更新我的问题,发布我的脚本的当前版本。
  • 请包括以下所有四 (4) 项: 1. 当您在显示屏上打开 xterm 时,echo $DISPLAY 会说什么? 2. 您的脚本以哪个用户身份运行,echo $USER 在 xterm 中说哪个用户? 3. 你的日志文件是否被创建,表明 jar 试图运行,如果是,他们说什么? 4、在xterm中运行脚本会得到什么输出?
  • (1) :0.0 (2) 我认为应该是root 用户,因为它在系统启动时运行。请求的命令返回batman [它是我的用户] (3) 不,文件没有创建[这就是我说什么都没有发生的原因]。 (4) 普通终端的相同输出(我总是用“sudo”运行):Starting labspy_client ... labspy_client started ...谢谢你的帮助!
  • 那你能不能把 until xwininfo -root &gt; /dev/null 改成 until xwininfo -root &gt;&gt; /tmp/xwininfo 2&gt;&amp;1 ,重新启动,然后在 xterm 恢复时 cat /tmp/xwininfo ?它说什么?
  • 抱歉耽搁了(这是所有日志):gist.github.com/paladini/25477f460ad4f4e2600e
猜你喜欢
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 2014-06-22
  • 2013-07-30
  • 1970-01-01
相关资源
最近更新 更多