繁体   English   中英

CronJob 没有运行

[英]CronJob not running

我已经在 ubuntu 环境中为 root 用户设置了一个 cronjob,如下所示,方法是键入crontab -e

  34 11 * * * sh /srv/www/live/CronJobs/daily.sh
  0 08 * * 2 sh /srv/www/live/CronJobs/weekly.sh
  0 08 1 * * sh /srv/www/live/CronJobs/monthly.sh

但是 cronjob 没有运行。 我尝试使用pgrep cron检查 cronjob 是否正在运行,并给出进程 ID 3033。shell 脚本调用 python 文件并用于发送电子邮件。 运行python文件就可以了。 它没有错误,但 cron 没有运行。 daily.sh 文件中包含以下代码。

python /srv/www/live/CronJobs/daily.py
python /srv/www/live/CronJobs/notification_email.py
python /srv/www/live/CronJobs/log_kpi.py

跆拳道?! 我的 cronjob 没有运行?!

这是调试未运行 cronjobs 的清单指南:

  1. Cron 守护进程是否正在运行?
  • 运行ps ax | grep cron ps ax | grep cron并寻找 cron。
  • Debian: service cron startservice cron restart
  1. cron 工作了吗?
  • * * * * * /bin/echo "cron works" >> /tmp/file
  • 语法正确吗? 见下文。
  • 您显然需要对要将输出重定向到的文件具有写访问权限。 /tmp中当前不存在的唯一文件名应该始终是可写的。
  • 可能还添加2>&1以包含标准错误以及标准输出,或者使用2>>/tmp/errors将标准错误单独输出到另一个文件
  1. 该命令是否独立工作?
  • 通过在 CLI 上进行试运行来检查脚本是否有错误
  • 在测试您的命令时,以您正在编辑其 crontab 的用户身份进行测试,该用户可能不是您的登录名或 root
  1. cron 可以运行你的工作吗?
  • 检查/var/log/cron.log/var/log/messages是否有错误。
  • Ubuntu: grep CRON /var/log/syslog
  • 红帽: /var/log/cron
  1. 检查权限
  • 在命令上设置可执行标志: chmod +x /var/www/app/cron/do-stuff.php
  • 如果您将命令的输出重定向到文件,请验证您是否有权写入该文件/目录
  1. 检查路径
  • 检查she-bangs / hashbangs线
  • 不要依赖诸如 PATH 之类的环境变量,因为它们的值在 cron 下可能与在交互式会话下不同
  1. 调试时不要抑制输出
  • 常用的是这种抑制: 30 1 * * * command > /dev/null 2>&1
  • 通过完全删除>/dev/null 2>&1重新启用标准输出或标准错误消息输出; 或者可能重定向到您具有写访问权限的位置的文件: >>cron.out 2>&1会将标准输出和标准错误附加到调用用户主目录中的cron.out
  • 如果您试图找出失败的原因,错误消息将在此文件中可见。 阅读它并理解它。

还是行不通? 哎呀!

  1. 提高 cron 调试级别
  • Debian
    • /etc/default/cron
    • 设置EXTRA_OPTS="-L 2"
    • service cron restart
    • tail -f /var/log/syslog查看执行的脚本
  • Ubuntu
    • /etc/rsyslog.d/50-default.conf
    • 添加或注释掉cron.* /var/log/cron.log
    • 重新加载记录器sudo /etc/init.d/rsyslog restart
    • 重新运行 cron
    • 打开/var/log/cron.log并查找详细的错误输出
  • 提醒:在完成调试后停用日志级别
  1. 再次运行 cron 并检查日志文件

定时任务语法

# Minute  Hour  Day of Month      Month         Day of Week    User Command    
# (0-59) (0-23)   (1-31)    (1-12 or Jan-Dec) (0-6 or Sun-Sat)  
         
    0       2       *             *                *          root /usr/bin/find

此语法适用于root用户。 常规用户crontab语法没有User字段(不允许常规用户像任何其他用户一样运行代码);

# Minute  Hour  Day of Month      Month         Day of Week    Command    
# (0-59) (0-23)   (1-31)    (1-12 or Jan-Dec) (0-6 or Sun-Sat)  
         
    0       2       *             *                *          /usr/bin/find

Crontab 命令

  1. crontab -l
    • 列出所有用户的 cron 任务。
  2. crontab -e ,针对特定用户: crontab -e -u agentsmith
    • 启动 crontab 文件的编辑会话。
    • 当您退出编辑器时,会自动安装修改后的 crontab。
  3. crontab -r
    • 从 cron 假脱机程序中删除您的 crontab 条目,但不从 crontab 文件中删除。

crontab 失败的另一个原因:对%字符的特殊处理。

手册文件

The entire command portion of the line, up to a newline or a
"%" character, will be executed by /bin/sh or by the shell specified
in the SHELL variable of the cronfile.  A "%" character in the
command, unless escaped with a backslash (\), will be changed into
newline characters, and all data after the first % will be sent to
the command as standard input.

在我的特殊情况下,我使用date --date="7 days ago" "+%Y-%m-%d"为我的脚本生成参数,但它默默地失败了。 当我检查syslog并看到我的命令在%符号处被截断时,我终于发现了发生了什么。 你需要像这样逃避它:

date --date="7 days ago" "+\%Y-\%m-\%d"

请参阅此处了解更多详情:

http://www.ducea.com/2008/11/12/using-the-character-in-crontab-entries/

最后我找到了解决方案。 以下是解决方案:-

  1. 切勿在要通过 crontab 执行的 python 脚本中使用相对路径。 我做了这样的事情: -

     import os import sys import time, datetime CLASS_PATH = '/srv/www/live/mainapp/classes' SETTINGS_PATH = '/srv/www/live/foodtrade' sys.path.insert(0, CLASS_PATH) sys.path.insert(1,SETTINGS_PATH) import other_py_files
  2. 永远不要压制 crontab 代码,而是使用邮件服务器并检查用户的邮件。 这样可以更清楚地了解正在发生的事情。

我想补充两点我学到的:

  1. 放在 /etc/cron.d/ 中的 Cron 配置文件不应包含点 (.)。 否则,它不会被 cron 读取。
  2. 如果运行您的命令的用户不在 /etc/shadow 中。 不允许调度 cron。

参考:

  1. http://manpages.ubuntu.com/manpages/xenial/en/man8/cron.8.html
  2. https://help.ubuntu.com/community/CronHowto

要添加另一个点,/etc/cron.d 中的文件必须在末尾包含一个空的新行。 这可能与 Luciano 的回应有关,其中指出:

The entire command portion of the line, up to a newline or a "%"
character, will be executed

我发现用户的 crontab 未运行的另一个原因:主机名不存在于主机文件中:

user@ubuntu:~$ cat /etc/hostname
ubuntu

现在主机文件:

user@ubuntu:~$ cat /etc/hosts
127.0.0.1 localhost

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

这是在 Ubuntu 14.04.3 LTS 上,修复它的方法是将主机名添加到主机文件中,使其类似于以下内容:

user@ubuntu:~$ cat /etc/hosts
127.0.0.1 ubuntu localhost

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

对我来说,解决方案是 cron 试图运行的文件位于加密目录中,更具体地说是 /home/ 上的用户目录。 虽然crontab被配置为root,但是因为运行的脚本存在于/home/的加密用户目录中,cron只能在用户实际登录时读取该目录。要查看该目录是否加密,请检查该目录是否存在:

/home/.ecryptfs/<yourusername>

如果是这样,那么您有一个加密的主目录。

我的解决方法是将脚本移到非加密目录中,并且一切正常。

我通过运行在 Ubuntu 16.04 服务器上找到了有用的调试信息:

systemctl status cron.service

就我而言,我被告知我在备注行中留下了评论“#”:

Aug 18 19:12:01 is-feb19 cron[14307]: Error: bad minute; while reading /etc/crontab
Aug 18 19:12:01 is-feb19 cron[14307]: (*system*) ERROR (Syntax error, this crontab file will be ignored)

也可能是时区问题。

Cron 使用本地时间。

运行命令timedatectl以查看机器时间并确保您的 crontab 处于同一时区。

我遇到了与以下链接类似的问题。

类似于我的问题
我原来的帖子

我的问题

我的问题是 cron / crontab 不会执行我的 bash 脚本。 该 bash 脚本执行了一个 python 脚本。

原始 bash 文件

#!/bin/bash

python /home/frosty/code/test_scripts/test.py

python文件(test.py)

from datetime import datetime

def main():
    dt_now = datetime.now()
    string_now = dt_now.strftime('%Y-%m-%d %H:%M:%S.%f')
    with open('./text_file.txt', 'a') as f:
        f.write(f'wrote at {string_now}\n')

    return None

if __name__ == '__main__':
    main()

我得到的错误

  File "/home/frosty/code/test_scripts/test.py", line 7
    string_to_write = f'wrote at {string_now}\n'
                                               ^
SyntaxError: invalid syntax

这个错误没有意义,因为从 bash 文件和 python 文件中执行的代码没有错误。

** 注意 -> 确保在crontab -e文件中不要抑制输出。 我通过在命令后添加>>/path/to/cron/output/file.log 2>&1将输出发送到文件。 下面是我的 crontab -e 条目

*/5 * * * * /home/frosty/code/test_scripts/echo_message_sh >>/home/frosty/code/test_scripts/cron_out.log 2>&1

问题

cron 使用了错误的 python 解释器,可能是语法错误中的 python 2。

我是如何解决问题的

我将我的 bash 文件更改为以下内容

#!/bin/bash

conda_shell=/home/frosty/anaconda3/etc/profile.d/conda.sh
conda_env=base

source ${conda_shell}
conda activate ${conda_env}

python /home/frosty/code/test_scripts/test.py

我将我的 python 文件更改为以下内容

from datetime import datetime

def main():
    dt_now = datetime.now()
    string_now = dt_now.strftime('%Y-%m-%d %H:%M:%S.%f')
    string_file = '/home/frosty/code/test_scripts/text_file.txt'
    string_to_write = 'wrote at {}\n'.format(string_now)
    with open(string_file, 'a') as f:
        f.write(string_to_write)

    return None

if __name__ == '__main__':
    main()

未安装 MTA,丢弃 output

对于作为 CRON 作业执行的 PHP 文件,我遇到了类似的问题。 当我手动执行文件时,它可以工作,但不能使用 CRON 选项卡。

我收到 output 消息: “未安装 MTA,正在丢弃输出”

Postfix 是 Ubuntu 中的默认邮件传输代理 (MTA),可以使用

sudo apt-get install postfix

但同样的消息也可能是 output 当您添加如下日志文件并且它对 /path/to/logfile.log 没有适当的写入权限时

/path/to/php -f /path/to/script.php >> /path/to/logfile.log

如果您在以其他用户身份登录时使用touch等命令手动创建 cron-log 文件,并且您在另一个用户(组)的选项卡中添加 CRON,例如www-data ,则可能会出现权限问题: sudo crontab -u www-data -e 然后 CRON 守护程序尝试写入日志文件并失败,然后尝试使用 Ubuntu 的 MTA 将 output 作为 email 发送,当找不到时,输出“未安装 MTA,丢弃输出”。

为了防止这种情况:

  • 创建具有适当权限的文件。
  • 避免手动创建相关的 CRON 日志文件,在 CRON 选项卡中添加日志,并在运行 cron 时自动创建日志文件。

我遇到了 cron 没有运行的同样问题。 正如我们在 crontab 和 Cronjobs 644 权限中提到的那样,我们通过更改权限和 Crons 的所有者使 root 所有者进行了修复

已经有很多答案了,但没有一个对我有帮助,所以我会在这里添加我的答案,以防对其他人有用。

在我的情况下,我的 cronjobs 一直在工作,直到电力短缺导致我的 Raspberry Pi 断电。 Cron 损坏了。 我认为正是在短缺发生时它正在运行一个很长的 python 脚本。 上面的主要答案中没有任何内容对我有用。 然而,解决方案非常简单。 我只需要强制重新安装 cron:

sudo apt-get --reinstall install cron 

在此之后它立即起作用。

由于这正在成为解决cron问题的规范,请允许我添加一个特定但相当复杂的问题:如果您尝试从cron运行 GUI 程序,您可能做错了。

一个常见的症状是收到有关DISPLAY未设置或cron作业的进程无法访问显示的错误消息。

简而言之,这意味着您尝试运行的程序正在尝试在 X11(或 Wayland 等)显示器上渲染某些内容,但失败了,因为cron未连接到图形环境,或者实际上任何类型的输入/输出除了能够读取和写入文件以及在系统配置为允许的情况下发送电子邮件之外,根本就没有设施。

出于“我无法运行我的cron作业”的目的,让我们粗略地指出此问题的三种常见情况。 可能确定您尝试实施的案例,并搜索有关该特定场景的相关问题以了解更多信息,并使用实际代码找到实际解决方案。

  1. 如果您正在尝试运行与用户通信的交互式程序,您需要重新考虑您的方法。 一个常见但重要的安排是将程序分成两部分:一个可以从cron运行但没有任何用户可见的交互设施的后端服务,以及一个用户从其运行的前端客户端当他们想要与后端服务通信时的 GUI。

    如果需要或他们希望在登录时自动运行,您的用户客户端可能应该简单地添加到用户的 GUI 启动脚本中。

    我想后端服务可以从cron启动,但如果它需要一个有用的 GUI,也许可以从 X11 服务器的启动脚本启动它; 如果没有,可能会从常规启动脚本(现在是systemd ,或/etc/rc.local或更传统的类似系统启动目录)运行它。 1

  2. 如果您尝试在不与真实用户2交互的情况下运行 GUI 程序,您可以设置“无头”X11 服务器3并运行启动该服务器的cron作业,运行您的作业,然后退出。

    可能你的工作应该简单地从cron运行一个合适的 X11 服务器(与管理系统可用的显示器和连接的图形卡和键盘的任何交互式 X11 服务器分开),并向它传递一个配置一旦启动并运行,就运行您想要运行的客户端。 (有关一些实际考虑,另请参阅下一点。)

  3. 您运行计算机的唯一目的是在 GUI 中显示特定应用程序,并且希望在计算机启动时启动该应用程序。

    可能您的启动脚本应该简单地运行 GUI(X11 或其他)并连接到它的启动脚本,以便在 GUI 启动并运行后运行客户端程序。 换句话说,这里不需要cron 只需配置启动脚本以运行桌面 GUI,并将桌面 GUI 配置为作为(大概是自动的,来宾?)登录序列的一部分运行您的应用程序。 4

很多方法来运行系统的主显示屏上的X11程序( DISPLAY=:0.0 ),但这样做,从一个cron工作往往是有问题的,因为这显示通常保留给实际交互使用由谁在登录和启动一个图形化的第一个用户桌面。 在单用户系统上,如果该用户也是您,您可能能够忍受副作用,但这往往会产生不便的后果并且扩展性非常差。

另一个复杂因素是决定以哪个用户身份运行cron作业。 像后端服务这样的共享系统资源可以而且可能应该由root运行(尽管理想情况下有一个专用的系统帐户,一旦它获得了对它需要的任何特权资源的访问权限,它就会切换到该帐户)但是任何涉及 GUI 的东西绝对不应该在任何时候都以root身份运行。

一个相关但明显的问题是以任何有意义的方式与用户交互。 如果您可以识别用户的活动会话(在某种程度上,这甚至是明确定义的),您如何在不干扰他们中间的任何其他内容的情况下吸引他们的注意力? 但更根本的是,您如何找到它们? 如果他们根本没有登录,你会怎么做? 如果是,您如何确定它们是活动的和可用的? 如果他们多次登录,他们使用的是哪个终端,中断该会话是否安全? 同样,如果他们登录到 GUI,如果他们实际上是通过 VNC 或远程 X11 服务器远程登录的,他们可能会错过您在本地控制台上弹出的窗口。

另外:在专用服务器(网络托管服务、超级计算集群等)上,如果您安装可以从外部世界连接的交互式图形桌面,您甚至可能违反托管公司或机构的服务条款。


1 cron@reboot钩子对于在系统启动时没有任何其他工具来运行某些东西的普通用户来说是一种便利,但是如果您是root并且可以完全控制,那么在那里隐藏某些东西是不方便和晦涩的系统。

2一个常见的情况是运行需要运行完整 GUI 客户端的 Web 浏览器,但该浏览器以编程方式控制并且不需要在任何地方显示任何内容。

另一个是设计糟糕的科学或办公软件,它不是为批处理而编写的,因此即使您只想运行批处理作业然后立即退出而无需在任何地方显示任何内容,也需要 GUI。

(在后一种情况下,可能会查看文档以检查是否没有--batch--noninteractive--headless--script--eval选项或类似选项来在没有 GUI 的情况下运行该工具,或者也许用于非交互式使用的单独实用程序。)

3 Xvfb事实上的标准解决方案; 它运行一个“虚拟帧缓冲区”,计算机可以在其中像向显示器一样吐出像素,但实际上并未连接到任何显示硬件。

4这里有几个选项。 最简单的方法是将系统设置为在启动时自动登录特定用户而无需密码提示,并配置该用户的桌面环境(Gnome 或 KDE 或 XFCE 或其他)以从其“启动项”运行您的脚本或“登录操作”或“自动启动”或任何可能调用的工具。 如果您需要对环境进行更多控制,可以在没有桌面环境或窗口管理器的情况下运行裸 X11,而只需运行您的脚本即可。 或者在某些情况下,可以用自定义构建的东西替换 X11 登录管理器(“greeter”)。

在此处复制我对重复问题的回答。

cron 可能不知道在哪里可以找到 Python 解释器,因为它不共享您的用户帐户的环境变量。

有3种解决方案:

  1. 如果 Python 位于/usr/bin/python ,您可以更改 cron 作业以使用绝对路径: /usr/bin/python /srv/www/live/CronJobs/daily.py

  2. 或者,您也可以使用PATH=/usr/bin向 crontab 添加 PATH 值。

  3. 另一种解决方案是在脚本文件中指定一个解释器,使其可执行,并在您的 crontab 中调用脚本本身:

    一个。 将 shebang 放在 python 文件的顶部: #!/usr/bin/python

    将其设置为可执行文件: $ chmod +x /srv/www/live/CronJobs/daily.py

    C。 将其放入 crontab: /srv/www/live/CronJobs/daily.py

如果您的系统上的路径不同,请调整 Python 解释器的路径。

参考

CRON 使用不同的 TIMEZONE

一个非常常见的问题是:cron 时间设置可能与您的不同。 特别是,时区可能不同:

# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.

你可以运行:

* * * * * echo $(date) >> /tmp/test.txt

这应该生成一个文件,如:

# cat test.txt 
Sun 03 Apr 2022 09:02:01 AM UTC
Sun 03 Apr 2022 09:03:01 AM UTC
Sun 03 Apr 2022 09:04:01 AM UTC
Sun 03 Apr 2022 09:05:01 AM UTC
Sun 03 Apr 2022 09:06:01 AM UTC

如果您使用的是 UTC 以外的 TZ,您可以尝试:

timedatectl set-timezone America/Sao_Paulo

根据您的设置替换America/Sao_Paulo

我不确定它是否真的有必要,但你可以运行:

sudo systemctl restart cron.service

之后,cron 按我的预期工作:

# cat test.txt 
Sun 03 Apr 2022 09:02:01 AM UTC
Sun 03 Apr 2022 09:03:01 AM UTC
Sun 03 Apr 2022 09:04:01 AM UTC
Sun 03 Apr 2022 09:05:01 AM UTC
Sun 03 Apr 2022 09:06:01 AM UTC
Sun 03 Apr 2022 09:07:01 AM UTC
Sun 03 Apr 2022 09:08:01 AM UTC
Sun 03 Apr 2022 09:09:01 AM UTC
Sun 03 Apr 2022 09:10:01 AM UTC
Sun 03 Apr 2022 06:11:01 AM -03
Sun 03 Apr 2022 06:12:01 AM -03
Sun 03 Apr 2022 06:13:01 AM -03
Sun 03 Apr 2022 06:14:01 AM -03

尝试

service cron start

要么

systemctl start cron

就我而言,我试图在本地运行 cron。 我检查了状态:

service cron status

它告诉我:

* cron is not running

然后我简单地启动了服务:

service cron start

有时,cron 需要运行的命令位于 cron 无权访问的目录中,通常在用户主目录权限为 700 且命令位于该目录中的系统上。

尽管已接受此问题的答案,但我想添加对我有用的内容。 引用 URL 是个好主意,如果它包含查询,如果没有引用所有内容,它可能无法工作。

不要忘记将包含“?、=、#、%”的 URL 放在引号中。

例子。 https://paystack.com/indexphp?docs/api/#transaction-charge-authorization&date=today应该像这样引用“https://paystack.com/indexphp?docs/api/#transaction-charge-authorization&date =今天”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM