为什么 crontab 脚本不起作用?

为什么 crontab 脚本不起作用?

脚本经常crontab无法按计划或按预期执行。造成这种情况的原因有很多:

  1. 错误的 crontab 符号
  2. 权限问题
  3. 环境变量

crontab此社区 wiki 旨在汇总脚本未按预期执行的主要原因。将每个原因写在单独的答案中。

请在每个答案中说明一个原因 - 有关未执行的原因的详细信息 - 以及针对该原因的修复。

请仅写特定于 cron 的问题,例如从 shell 按预期执行但由 cron 错误执行的命令。

答案1

不同的环境

Cron 将一组最小的环境变量传递给您的作业。要查看差异,请添加如下虚拟作业:

* * * * * 环境 > /tmp/env.output

等待/tmp/env.output创建,然后再次删除该作业。现在将的内容与常规终端中运行/tmp/env.output的输出进行比较。env

这里常见的“陷阱”是环境变量不同。也许您的 cron 脚本使用了中的PATH命令,而您在 中添加了? cron 会忽略该文件,因此使用 cron 运行时,从脚本运行会失败,但在终端中运行时可以运行。值得注意的是, 中的变量将传递给 cron 作业,但不是 cron 专门设置的变量,例如。somecommand/opt/someApp/binPATH/etc/environmentPATHsomecommand/etc/environmentPATH

为了解决这个问题,只需PATH在脚本顶部设置你自己的变量。例如

#!/bin/bash
PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# rest of script follows

有些人更喜欢使用绝对路径来执行所有命令。我不建议这样做。考虑一下,如果您想在另一个系统上运行脚本,而该系统上的命令是 ,会发生什么情况/opt/someAppv2.2/bin。您必须遍历整个脚本,用 替换 ,/opt/someApp/bin/opt/someAppv2.2/bin不是只在脚本的第一行进行小幅编辑。

您还可以在 crontab 文件中设置 PATH 变量,该变量将应用于所有 cron 作业。例如

PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

15 1 * * * backupscript --incremental /home /root

答案2

我最大的问题:如果你忘记在文件末尾添加换行符crontab。换句话说,crontab 文件应该以空行结尾。

以下是手册页中与此问题相关的部分(man crontab然后跳到最后):

   Although cron requires that each entry in a crontab end  in  a  newline
   character,  neither the crontab command nor the cron daemon will detect
   this error. Instead, the crontab will appear to load normally. However,
   the  command  will  never  run.  The best choice is to ensure that your
   crontab has a blank line at the end.

   4th Berkeley Distribution      29 December 1993               CRONTAB(1)

答案3

Cron 守护进程未运行。几个月前我真的把这件事搞砸了。

类型:

pgrep cron 

如果您看不到数字(即 cron 的主 PID),那么 cron 没有运行。sudo /etc/init.d/cron start可以用来启动 cron。

编辑:不要通过 /etc/init.d 调用初始化脚本,而是使用服务实用程序,例如

sudo service cron start

编辑:您也可以在现代 Linux 中使用 systemctl,例如

sudo systemctl start cron

答案4

在许多环境中,cron 使用 执行命令sh,但许多人认为它会使用bash

对于失败的命令,测试或修复的建议:

  • 尝试运行命令sh以查看其是否有效:

    sh -c "mycommand"
    
  • 将命令包装在 bash 子 shell 中以确保它在 bash 中运行:

    bash -c "mybashcommand"
    
  • 通过在 crontab 顶部设置 shell 来告诉 cron 在 bash 中运行所有命令:

    SHELL=/bin/bash
    
  • 如果命令是脚本,请确保脚本包含 shebang:

    #!/bin/bash
    

相关内容