为什么这个 cron 记录会被执行两次?

28
*/5 * * * * my command

这个条目有效,但每5分钟会执行两次,为什么?

/var/log/cron中显示:

Jun 16 22:20:01 Test CROND[12512]: (root) CMD (my command)
Jun 16 22:20:01 Test CROND[12516]: (root) CMD (my command)

所以它不是来自两个用户。

它只被输入了一次,使用了crontab -e -u root命令。该命令是一个php命令。


可能是重复问题:为什么我的定时任务会执行多次? - Ken Sharp
14个回答

47

这段描述没有充分的理由来解释它为什么会执行两次,需要在其他地方寻找原因。

  • 有没有两个用户同时调用它?
  • 有没有被输入两次?
  • 它是否自我调用?
  • 它是否引发了重复执行的条件?

如果您正在执行shell脚本,请让它附加将whoamidate添加到日志文件中。你应该能够找到原因。

更新

键入ps -A | grep crond,确保crond没有运行两次。


1
你没有回答:它会自己调用吗?它会启动重复条件吗? - John Weldon
7
这是我问题的解决办法,cron运行了多次。在我的系统中,我必须查找cron而不是crond。一旦我停止并重新启动cron服务,它就只有一个运行实例。感谢@StefanMai。 - jeremib
是的,我同意Stefan Mai的观点。谢谢。 - Rameshwar Vyevhare
5
“ps -A”可能会令人困惑,因为cron将创建子进程,它们会在单独的行中列出。使用“ps axjf”将列出一棵以“cron”作为主要cron进程根的树形结构;如果存在多个根,则更容易识别。 - Rondo
1
点赞支持 'ps axjf' - 谢谢。每一天都是学校。 - Martin Greenaway
显示剩余2条评论

11

在crontab中使用wget通常有15分钟的限制。在我们的情况下,正是如此,在这15分钟后,任务将超时,然后立即重新运行。因此,解决方案是在crontab中设置cronjob,类似于以下内容:

1 2 * * * root wget --read-timeout=3600 -O - 'http://cron-job-url' >/dev/null 2>&1
 1 2 * * * root wget -O - 'http://cron-job-url' >/dev/null 2>&1

所以,wget就是那个东西。意思是3600 = 1小时。或者更多,如果您需要!


如果我每分钟运行cron(* * * * *),会发生什么?我应该为--read-timeout设置什么值? - tarako
--read-timeout=60,然后呢? :) 我这样想的是,每分钟运行一次的作业可能不应该太大。 - anoraq
这让我免去了无数小时的搜索幽灵。 - Diego

3

我确认 - 我的cron也运行了两次...

Jul 24 14:40:01 localhost cron[2713]: (root) CMD (/etc/apache2/generator/reloader.do)
Jul 24 14:41:01 localhost cron[9481]: (root) CMD (/etc/apache2/generator/reloader.do)
Jul 24 14:41:01 localhost cron[10724]: (root) CMD (/etc/apache2/generator/reloader.do)
Jul 24 14:42:01 localhost cron[20380]: (root) CMD (/etc/apache2/generator/reloader.do)
Jul 24 14:42:01 localhost cron[20832]: (root) CMD (/etc/apache2/generator/reloader.do)

我的定时任务表

在/var/spool/目录下使用grep命令查找reloader关键字:

/var/spool/cron/crontabs/root:* * * * * /etc/apache2/generator/reloader.do

输出结果为:

whoami
date
------

输出:

root
root
Tue Jul 24 14:46:02 CEST 2012
---------
Tue Jul 24 14:46:03 CEST 2012
---------

我的当前解决方案是:

if [ -f /etc/apache2/generator/reloader.lock ]
then
exit
fi
touch /etc/apache2/generator/reloader.lock
/etc/apache2/generator/reloader
rm /etc/apache2/generator/reloader.lock

但这并不是为什么会发生这种情况的答案...

系统 - gentoo 计划任务 - vixie-cron

ps aux wwf 输出的一部分(在计划任务中启动)

root     10843  0.0  0.0  16480   560 ?        Ss   Jun06   0:01 /usr/sbin/cron
root     29797  0.0  0.0  25020   964 ?        S    15:08   0:00  \_ /usr/sbin/cron
root     29799  0.0  0.0   9188  1228 ?        Ss   15:08   0:00      \_ /bin/bash /etc/apache2/generator/reloader
root     29822  0.0  0.0  14800   988 ?        R    15:08   0:00          \_ ps aux wwf
------
root      8215  0.0  0.0  16480   836 ?        Ss   14:23   0:00 /usr/sbin/cron
root     31419  0.0  0.0  25020   968 ?        S    15:08   0:00  \_ /usr/sbin/cron
root     31423  0.0  0.0   9188  1228 ?        Ss   15:08   0:00      \_ /bin/bash /etc/apache2/generator/reloader
root     31431  0.0  0.0  14804  1004 ?        R    15:08   0:00          \_ ps aux wwf

编辑:

我注意到其中一个cron进程报告的开始日期是Jun06(今天是Jun24)

root     10843  0.0  0.0  16480   560 ?        Ss   Jun06   0:01 /usr/sbin/cron
root      8215  0.0  0.0  16480   836 ?        Ss   14:23   0:00 /usr/sbin/cron

第二个进程报告正确(服务器uprime大约40分钟 - 我最近重新启动了它)

一个重要的信息 - 它是在主机上运行的V服务器。

无论我做什么(/etc/init.d/vixie-cron restart),它都会以相同的PID启动。

已解决:

我找到了原因。一个V服务器以不同的上下文运行了两次。可能的解释是 - 当机器正在运行时,有人改变了上下文,结果,并没有杀死所有进程,而且更重要的是 - 它们影响了新实例的vserver(上下文303和3031):

root     10843  3031 developer      0.0  0.0  16480   560 ?        Ss   Jun06   0:01 /usr/sbin/cron
root     16509   303 developer      0.0  0.0  16480   836 ?        Ss   15:18   0:00 /usr/sbin/cron

我有一个 TERM 老的进程,问题已经解决了。

3

肯定不是crontab条目导致它运行两次。要找出问题,最快的方法是在cron作业脚本中添加一些调试代码。如果你什么都不做,默认情况下cron输出将被发送到root@localhost(除非你已经配置为不同的地址),所以假设你有root访问权限,请在脚本中添加一些调试信息,例如:

echo "Script starting"
date
whoami

看一下输出。这将使你开始理解为什么会调用两次。


这帮助我检测到其他的crontab用户。谢谢。 - JRichardsz

3
如果这是你安装的应用程序的命令,那么它可能已经添加了相同的条目到 /etc/crontab 或者 /etc/cron.d/<something> 中。

这是我的问题 - 我手动输入了它到根crontab中,但是在/etc/cron.d中也有一个文件调用了非常相似但不完全相同版本的同一调用。现在尾巴追踪已经完成,回到手头的工作。 :) - Martin Greenaway

2
我原以为cron会启动我的bash脚本两次,但我错了。我想分享一下自己的经验,希望对其他人有所帮助。这让我困惑了一段时间...
当cron启动时,'ps aux'输出从显示0个实例运行到两个实例,或者乍一看是这样的:
kdeen    1797750  0.0  0.0   2608   600 ?        Ss   15:52   0:00 /bin/sh -c /home/kdeen/bin/once-a-day-local.sh
kdeen    1797751  0.0  0.0  19520  3488 ?        S    15:52   0:00 /bin/bash /home/kdeen/bin/once-a-day-local.sh

但仔细看一下,我发现一个实例是/bin/sh -c,而另一个实例是/bin/bash。这是正确的行为。我的脚本以“#!/bin/bash”开头,但cron总是以/bin/sh运行程序。因此会出现一个'sh'启动器进程和我的bash脚本。一切都好。

1
我曾经遇到过同样的问题,我的情况是错误地两次初始化了cron服务。在我停止cron # /etc/init.d/crond stop 并重新启动它 # /etc/init.d/crond start 后,它就完美地工作了。
我希望这能帮助任何人。

1

对于其他没有解决方案的人,请不要犯新手错误(就像我一样!)以* 05 * * 0开始你的crontab,并期望它在星期天运行一次。

实际上,它会在早上5点后每分钟尝试运行一次(直到在我的情况下它崩溃了Postgres备份)。如果你只想让它运行一次,你需要指定一个分钟:

0 05 * * 0


0

我使用OpenWrt。

我有同样的问题,但我只有一个cron: ps | grep crond:

31447 root      1508 S    /usr/sbin/crond -c /etc/crontabs -l 8 
31454 root      1500 S    sh -c ps | grep crond 
31456 root      1496 S    grep crond

logread | grep cron

May 27 13:15:01 decibox cron.info crond[31447]: crond: USER root pid 1594 cmd /root/check_connect.php.sh 
May 27 13:20:01 decibox cron.info crond[31447]: crond: USER root pid 2103 cmd /root/check_connect.php.sh 
May 27 13:20:01 decibox cron.info crond[31447]: crond: USER root pid 2325 cmd /root/check_connect.php.sh 
May 27 13:25:01 decibox cron.info crond[31447]: crond: USER root pid 2880 cmd /root/check_connect.php.sh

这并没有回答问题。要么在原问题下发表评论,要么如果您的情况不同,请自己提出一个新问题。 - Kostas Rousis

0

运行 ps -A | grep cron,杀死所有作业在我的情况下没有帮助。

问题是在杀死所有 cron 作业并仅使用一个 cron 守护程序重新启动后,我会从相同的父 cron PPID 启动两个 cron 作业 - 一个是 /bin/bash,另一个是 /bin/sh。

解决方案是重新启动服务器。

这种情况发生在几个不同的操作系统上 - centos 6 和 redhat 7。通常是在线操作系统升级后没有重启。

正如有人所说 - 可能是一些不同的上下文。

我在网上看到了一篇文章,其中有相同的进程,一个是 /bin/bash,另一个是 /bin/sh,在完全相同的时间内 - 我想,哎呀 - 这就是我的情况 - 但是,那个人甚至没有考虑过这种奇怪行为的根本原因,只是开始编写一些脚本逻辑来使第二个进程退出,这并不是真正的解决方案。

顺便说一句,ps -A | grep cron 也会列出所有 cron 子进程 - 正常的 cron 作业,更多的 cron 进程并不意味着它有更多的 cron 守护程序,可能只有一个守护程序和其他子进程。

另一方面,ps -ef | grep cron 只列出一个 - 为什么?因为 ps -ef 将子进程列为 CROND - 要获取它们所有,请执行 ps -ef | grep -i cron。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接