【问题标题】:What are the differences between running an executable straight from the command line and from a cron job in Linux?直接从命令行运行可执行文件和从 Linux 中的 cron 作业运行有什么区别?
【发布时间】:2024-01-22 18:09:01
【问题描述】:

我有这个可执行文件,它查询远程服务器的命令,在本地机器上执行它并将标准输出(也可能是标准错误)从它返回给服务器。

如果从命令行调用(以 root 身份),这个可执行文件运行得很好,但我发现它在由 cron 作业自动执行时会失败。

在使用 crontab 安排此可执行文件定期运行时,我应该期望在环境(用户、标准输入、标准输出等)方面有哪些差异?

谢谢!

【问题讨论】:

    标签: linux language-agnostic cron


    【解决方案1】:

    最重要的区别是 .bashrc 等文件不会在 cron 作业之前执行,因此您通常在命令行中拥有的许多环境变量将会丢失。因此,如果您的程序无法在 cron 作业中运行,请将其嵌入到设置所有必要环境变量的脚本中。

    关于输入和输出,显然 cron 作业没有用户交互,因此程序不应期望输入(如果有,则从输入文件或直接在脚本中提供),任何输出都应重定向到一个日志文件。

    【讨论】:

    • 一点额外提示:Java 程序有时会使用 AWT 函数,即使它们根本没有 gui。特别是当他们操纵图像时,还有例如计算列宽时的 HSSF。此类程序必须在 cron 作业中以 -Djava.awt.headless=true 启动,否则它们会中断,因为 cron 中没有可用的 X。在 XTerm 的命令行中,您根本不会注意到...
    【解决方案2】:

    如果从命令行调用(以 root 身份),这个可执行文件运行得很好,但我发现它在由 cron 作业自动执行时会失败。

    在 cron 作业中,您可以指定运行脚本的用户,例如:

    0 0 * * * www-data /usr/bin/php /var/www/foo/do_work.php
    

    我指定每天将 'do_work.php' 作为 www-data 运行...该文件将位于 /etc/cron.d/

    【讨论】:

      【解决方案3】:

      此外,您可能应该检查 cron 用于运行任务的 UID,特别是如果它是“全局”/etc/crontab 作业,而不是用户级作业。如果作业从“nobody”或“cron”运行,可能是缺少某些权限。

      【讨论】:

        【解决方案4】:

        主要是

        • 当前工作目录 - 您不能保证这将来自 cron。它可能是 $HOME,但不要指望它
        • 环境变量 - 您为正常登录设置的大多数设置都不会设置,因此需要环境变量具有特定值的事情可能会失败。这尤其包括 $PATH。
        • stdin / stdout / stderr 将不是 tty,因此某些程序的行为会有所不同(stdout 和 err 可能是临时文件;stdin 可能为 null)

        但本质上你不能依赖太多

        • 应按照 cron 作业所有者的正常登录设置用户 ID、组 ID 和补充组

        【讨论】: