如何等到环境是非无头的?
How to wait until environment is non-headless?
我创建了一个 Java 服务器,它使用 Ubuntu 12.04 启动,我有一个问题:我的代码需要一个非无头的(或 headfull) 环境工作,否则它会抛出 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 server 之后启动 JAR 的方法,所以我认为解决这个问题的最好方法是在我的代码中使用忙等待。我已经检查了很多问题(在 Whosebug 和 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() 始终 returns true,因此它永远不会退出循环。是的,此时我已经在使用 Unity(Ubuntu 图形界面),所以我已经有了 "headfull environment"。对不起,如果我犯了一些错误,但我是 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 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
用于图形程序的显示是使用 DISPLAY
环境变量确定的。这通常由 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 程序不会像这样针对系统工作,而是让用户在他们选择的显示器上启动服务器。
我创建了一个 Java 服务器,它使用 Ubuntu 12.04 启动,我有一个问题:我的代码需要一个非无头的(或 headfull) 环境工作,否则它会抛出 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 server 之后启动 JAR 的方法,所以我认为解决这个问题的最好方法是在我的代码中使用忙等待。我已经检查了很多问题(在 Whosebug 和 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() 始终 returns true,因此它永远不会退出循环。是的,此时我已经在使用 Unity(Ubuntu 图形界面),所以我已经有了 "headfull environment"。对不起,如果我犯了一些错误,但我是 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 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
用于图形程序的显示是使用 DISPLAY
环境变量确定的。这通常由 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 程序不会像这样针对系统工作,而是让用户在他们选择的显示器上启动服务器。