Cron job:如何运行需要打开显示器的脚本?

9
我希望设置一个cron任务来运行一个python脚本,但是它给我返回了这个错误:
RuntimeError: could not open display

这是因为我导入了一个需要打开显示器的模块(例如pylab)。即使我的脚本不会生成任何要在监视器上显示的图片。
有没有办法让crontab在打开显示器的情况下运行我的任务(就像我通过ssh -X进入一台机器一样)?实际上,我并不需要向监视器生成任何图形。我只需要正确地导入我的模块即可。

3
请访问https://dev59.com/Ym445IYBdhLWcg3wTIjm,此链接介绍了如何在没有运行X服务器的情况下生成Matplotlib图表。 - NPE
@aix 我必须直接使用 matplotlib API 吗?我更喜欢使用 pylab.. 而且一般来说,在 crontab 中有没有办法解决这个问题? - CuriousMind
如果您在脚本顶部(在导入“pylab”之前)添加“import matplotlib as mpl; mpl.use('Agg')”,那可能会解决问题。 - NPE
@aix 谢谢aix。你知道通常如何在crontab中打开显示器吗? - CuriousMind
更根本地说,这要求您的计算机配置为在启动时自动运行显示管理器并自动登录,否则它将无法工作。虽然还有其他可能的机制,但通常不会默认启用任何一种机制。请参见 https://dev59.com/uWEh5IYBdhLWcg3wKQnY ,这是一个有关 cron 故障排除的问题,我在其中发布了一个带有(略微)更多细节的答案。 - tripleee
2个回答

6

如果想在Cron中使用X-程序,你需要一个有效的DISPLAY和XAUTHORITY。

设置DISPLAY非常简单,在Bash中输入:

export DISPLAY=":0.0"

为了获取有效的XAUTHORITY,您需要寻找它。 在Debian/Gnome/gdm3下,它们保存在var/run/gdm3/*/database中。 我使用了以下脚本:
export DISPLAY=":0.0"
[ -z $USER ] && USER=$( who | awk '{ print $1 }' | sort | uniq >/tmp/test )
for I in /var/run/gdm3/*; do
    AUTHUSER="`echo $I | awk -F '-' '{ print $3 }'`"
    for J in $USER; do
        [ "${AUTHUSER}" = "${J}" ] || continue
        USER="$J"
        export XAUTHORITY="${I}/database" && break
    done
done
sudo -u ${USER} /Path/to/xProgramm

变量 $USER 可能为空,此时脚本会寻找一个有效的用户,否则你可以告诉脚本这个变量!

感谢您提供这个出色的答案。我进行了一些小修改,使其在Ubuntu 20.04上运行成功。 - Abrar Hossain
那些小修改是什么? - Chris Stenkamp

2

您还可以使用xvfb或类似工具在帧缓冲中运行应用程序:

Downloadsudo apt-get install xvfb

用法:

xvfb :1 -screen 0 800x600x8 & # WIDTHxHEIGHTxCOLORDEPTH
export DISPLAY=":1"
java application_name.jar 

或者更简短:

xvfb-run -a -e /tmp/some/log/file.log /home/user/application.run

-a 选项会自动选择一个显示号码,-e file 选项用于指定错误消息的日志文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接