为什么这个脚本从 cron 运行时会失败,但手动运行时却可以运行?

为什么这个脚本从 cron 运行时会失败,但手动运行时却可以运行?

我有一个相对简单的 bash 脚本,直接调用时运行良好,但通过 cron 运行时失败。为什么会失败?我如何通过 cron 使其运行?

#!/bin/bash
apt-get update -y
apt-get upgrade -y
apt-get install boinc-client -y

一旦 cron 尝试运行它,手动调用将导致此错误:

dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.

但只要第一次手动执行,它就可以正常工作。

答案1

对此类问题的通常回答是,cron 作业在非交互式、非登录 shell 中运行,因此大多数 shell 启动文件(包括系统范围的文件/etc和主目录中的个人点文件)都不是源文件(读入和执行的),因为大多数 shell 启动文件适用于登录 shell(登录计算机时看到的第一个 shell)或交互式 shell(连接到终端、ssh 会话或终端仿真器的 shell,因为用户通过所述终端与它们交互)。

因此,如果您将命令放入 cron 作业中,而该作业实际上依赖于某些环境设置(包括PATH更改),而这些环境设置通常发生在/etc/profile/etc/bashrc~/.profile或等位置~/.bashrc,则该设置不会发生在 cron 作业中。 cron 文件格式允许您为作业指定环境变量,因此您可能需要指定BASH_ENVENV将其指向要源的 shell 启动脚本。请参阅手册页的“调用”部分bash(1)

答案2

这不算是一个答案,但我无法评论。建议:

  1. 将以下内容添加到您的 bash 脚本中。记录到邮件输出的最后一行将是失败的命令。

    set -x
    set -e
    
    • 确保您有 sendmail(安装提供包,例如postfixesmtp
    • 安装邮件阅读器(推荐mutt
    • 确保邮件送达
      • 通过 postfix(可能由安装程序自动完成):添加root: my-user-name/etc/aliases/etc/postfix/aliases
      • 通过 cron:添加MAILTO="my-user-name"到适当的crontab文件
  2. 验证脚本是否能在不同环境中运行。指定 apt-get 的完整路径(可能不是罪魁祸首,因为已知已找到 apt-get)并在 X 之外的控制台(而非终端)中运行它。(某些 dpkg configure 脚本需要 X 会话)。

    • 修改脚本以使用绝对路径,即/usr/bin/apt-get update -y(替换为正确的路径)
    • 通过按切换到控制台ctrl-alt-f1
    • 切换到root用户:sudo -i
    • 启动没有环境的非登录 shell:(env -i /bin/bash --noprofile --norc替换为正确的路径)
    • 运行脚本:/my/full/path/to/cronscript。它起作用了吗?
  3. 脚本是否有权限?您是否使用系统 crontab?(再次说明,可能不是罪魁祸首)

    • 您已声明正在使用系统 crontab,因此跳过此步骤。
  4. apt-get 是否需要会话支持(consolekit 或 systemd)。不过,这只是一个猜测。

    • 了解的还不够多,无法提供帮助。

答案3

在几乎不了解发生了什么的情况下设法解决了这个问题。结果发现,即使我从 root crontab 运行,apt-get 命令仍然需要在前面添加 sudo。从逻辑上讲,我原本以为不需要这个,因为脚本已经“以 root 身份”执行,但是一旦我添加了 sudo... 一切都按预期工作。

相关内容