由于这已成为解决 cron 问题的规范,请允许我添加一个具体但相当复杂的问题:如果您尝试从 cron 运行 GUI 程序,您可能 做错了.
常见的症状是收到有关 DISPLAY 未设置或 cron 作业的进程无法访问显示的错误消息。
简而言之,这意味着您尝试运行的程序正在尝试在 X11(或 Wayland 等)显示器上呈现某些内容,但失败了,因为 cron 未附加到图形环境,或者实际上任何一种输入/输出工具,除了能够读写文件,如果系统配置允许,还可以发送电子邮件。
出于“我无法运行我的图形cron 作业”的目的,让我们大致指出此问题的三种常见情况。
可能确定您尝试实施的案例,并搜索有关该特定场景的相关问题以了解更多信息,并使用实际代码找到实际解决方案。
-
如果您正在尝试开发与用户交流的交互式程序,您需要重新考虑您的方法。一个常见但重要的安排是将程序分成两部分:一个可以从cron 运行的后端服务,但它没有任何用户可见的交互设施,以及一个用户运行的前端客户端当他们想要与后端服务通信时,从他们的 GUI 中获取。
如果需要,或者他们希望在用户登录时自动运行,您的用户客户端可能应该简单地添加到用户的 GUI 启动脚本中。
我想后端服务可以从cron启动,但是如果它需要一个GUI才能使用,也许可以从X11服务器的启动脚本启动它;如果没有,可能从常规启动脚本运行它(systemd 这些天,或者/etc/rc.local 或更传统的类似系统启动目录)。1
-
如果您尝试在不与真实用户交互的情况下运行 GUI 程序 2,您可以设置“无头”X11 服务器 3 并运行cron 作业,它启动该服务器,运行您的作业,然后退出。
您的工作可能应该简单地从cron 运行合适的 X11 服务器(与管理系统可用的实际物理显示器和连接的显卡和键盘的任何交互式 X11 服务器分开) ,并传递给它一个配置,该配置运行您想要运行的客户端,一旦它启动并运行。 (有关一些实际考虑,另请参阅下一点。)
-
您运行计算机的唯一目的是在 GUI 中显示特定应用程序,并且您希望在计算机启动时启动该应用程序。
您的启动脚本可能应该简单地运行 GUI(X11 或其他)并挂钩到其启动脚本,以便在 GUI 启动并运行后也运行客户端程序。换句话说,这里不需要cron;只需配置启动脚本以运行桌面 GUI,并将桌面 GUI 配置为作为(可能是自动的,访客?)登录序列的一部分运行您的应用程序。4
有种方法可以在系统的主显示器 (DISPLAY=:0.0) 上运行 X11 程序,但从 cron 作业执行此操作通常会出现问题,因为该显示器通常保留用于实际交互使用由第一个登录并启动图形桌面的用户。在单用户系统上,如果该用户也是您,您可能能够忍受副作用,但这往往会带来不便的后果并且扩展性非常差。
另一个复杂的问题是决定以哪个用户身份运行cron 作业。像后端服务这样的共享系统资源可以并且可能应该由root 运行(尽管理想情况下有一个专用的系统帐户,一旦它获得了对其所需的任何特权资源的访问权,它就会切换到该帐户),但是任何涉及 GUI 的东西都应该绝对不能在任何时候以root 运行。
一个相关但不同的问题是以任何有意义的方式与用户交互。如果您可以识别用户的活动会话(在某种程度上,这甚至是一开始就明确定义的),那么您如何在不干扰他们中间的任何其他内容的情况下吸引他们的注意力?但更根本的是,你如何找到它们?如果他们根本没有登录,那你会怎么做?如果是,您如何确定它们是活跃的和可用的?如果他们多次登录,他们使用的是哪个终端,中断该会话是否安全?同样,如果他们登录到 GUI,如果他们实际上是通过 VNC 或远程 X11 服务器远程登录,他们可能会错过您在本地控制台上弹出的窗口。
另外:在专用服务器(网络托管服务、超级计算集群等)上,如果您安装可以从外部连接的交互式图形桌面,您甚至可能违反托管公司或机构的服务条款世界,甚至根本没有。
1cron 中的 @reboot 钩子对于在系统启动时没有任何其他工具来运行某些东西的普通用户来说是一种便利,但是如果你是 root 无论如何,在其中隐藏一些东西只是不方便和晦涩的,并且完全控制系统。使用系统工具启动系统服务。
2
一个常见的用例是运行一个 Web 浏览器,它需要运行一个完整的 GUI 客户端,但它是通过编程方式控制的,实际上不需要在任何地方显示任何东西,例如抓取使用 Javascript 的网站,因此需要一个完整的图形浏览器来呈现您要提取的信息。
另一个是设计不佳的科学或办公软件,它不是为批处理使用而编写的,因此即使您只想运行批处理作业然后立即退出而无需在任何地方显示任何内容,也需要 GUI。
(在后一种情况下,可能查看文档以检查是否没有 --batch 或 --noninteractive 或 --headless 或 --script 或 --eval 选项或类似选项以在没有 GUI 的情况下运行该工具,或者可能是用于非交互式使用的单独实用程序。)
3Xvfb 是事实上的标准解决方案;它运行一个“虚拟帧缓冲区”,计算机可以在其中像向显示器一样输出像素,但实际上并未连接到任何显示硬件。
4
这里有几个选项。
最简单的方法是将系统设置为在启动时自动登录特定用户而无需密码提示,并配置该用户的桌面环境(Gnome 或 KDE 或 XFCE 或其他)以从其“启动项”运行脚本或“登录操作”或“自动启动”或任何可能调用的工具。如果您需要对环境进行更多控制,可以在没有桌面环境或窗口管理器的情况下运行裸 X11,而只需运行您的脚本。或者在某些情况下,可以将 X11 登录管理器(“greeter”)替换为自定义构建的东西。
X11 堆栈非常模块化,并且在各个层中有几个挂钩,您可以在其中运行脚本作为标准启动过程的一部分,或者完全替代标准层。这些事情在发行版和实现之间往往会有所不同,并且随着时间的推移,所以这个答案在这些问题上必然是模糊和不完整的。同样,可能会尝试找到一个关于如何为您的特定平台(Ubuntu、Raspbian、Gnome、KDE 等)和场景做事的现有问题。