[英]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
这是调试未运行 cronjobs 的清单指南:
ps ax | grep cron
ps ax | grep cron
并寻找 cron。service cron start
或service cron restart
* * * * * /bin/echo "cron works" >> /tmp/file
/tmp
中当前不存在的唯一文件名应该始终是可写的。2>&1
以包含标准错误以及标准输出,或者使用2>>/tmp/errors
将标准错误单独输出到另一个文件/var/log/cron.log
或/var/log/messages
是否有错误。grep CRON /var/log/syslog
/var/log/cron
chmod +x /var/www/app/cron/do-stuff.php
30 1 * * * command > /dev/null 2>&1
>/dev/null 2>&1
重新启用标准输出或标准错误消息输出; 或者可能重定向到您具有写访问权限的位置的文件: >>cron.out 2>&1
会将标准输出和标准错误附加到调用用户主目录中的cron.out
。/etc/default/cron
EXTRA_OPTS="-L 2"
service cron restart
tail -f /var/log/syslog
查看执行的脚本/etc/rsyslog.d/50-default.conf
cron.* /var/log/cron.log
sudo /etc/init.d/rsyslog restart
/var/log/cron.log
并查找详细的错误输出# 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 -l
crontab -e
,针对特定用户: crontab -e -u agentsmith
crontab -r
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/
最后我找到了解决方案。 以下是解决方案:-
切勿在要通过 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
永远不要压制 crontab 代码,而是使用邮件服务器并检查用户的邮件。 这样可以更清楚地了解正在发生的事情。
我想补充两点我学到的:
参考:
要添加另一个点,/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 脚本。
#!/bin/bash
python /home/frosty/code/test_scripts/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 没有运行的同样问题。 正如我们在 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
作业”的目的,让我们粗略地指出此问题的三种常见情况。 可能确定您尝试实施的案例,并搜索有关该特定场景的相关问题以了解更多信息,并使用实际代码找到实际解决方案。
如果您正在尝试运行与用户通信的交互式程序,您需要重新考虑您的方法。 一个常见但重要的安排是将程序分成两部分:一个可以从cron
运行但没有任何用户可见的交互设施的后端服务,以及一个用户从其运行的前端客户端当他们想要与后端服务通信时的 GUI。
如果需要或他们希望在登录时自动运行,您的用户客户端可能应该简单地添加到用户的 GUI 启动脚本中。
我想后端服务可以从cron
启动,但如果它需要一个有用的 GUI,也许可以从 X11 服务器的启动脚本启动它; 如果没有,可能会从常规启动脚本(现在是systemd
,或/etc/rc.local
或更传统的类似系统启动目录)运行它。 1
如果您尝试在不与真实用户2交互的情况下运行 GUI 程序,您可以设置“无头”X11 服务器3并运行启动该服务器的cron
作业,运行您的作业,然后退出。
可能你的工作应该简单地从cron
运行一个合适的 X11 服务器(与管理系统可用的显示器和连接的图形卡和键盘的任何交互式 X11 服务器分开),并向它传递一个配置一旦启动并运行,就运行您想要运行的客户端。 (有关一些实际考虑,另请参阅下一点。)
您运行计算机的唯一目的是在 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种解决方案:
如果 Python 位于/usr/bin/python
,您可以更改 cron 作业以使用绝对路径: /usr/bin/python /srv/www/live/CronJobs/daily.py
或者,您也可以使用PATH=/usr/bin
向 crontab 添加 PATH 值。
另一种解决方案是在脚本文件中指定一个解释器,使其可执行,并在您的 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.