如何通过脚本创建crontab


153

我需要通过运行设置服务器的脚本来添加cron作业。我目前正在使用Ubuntu。我可以使用,crontab -e但这将打开一个编辑器来编辑当前的crontab。我想以编程方式执行此操作。

有可能这样做吗?




如果您要修改或删除crontab条目,请参见下面的解决方案。
Brian Smith

Answers:


12

Cron作业通常存储在每个用户的文件下 /var/spool/cron

您要做的最简单的事情可能是创建一个配置了作业的文本文件,然后将其复制到cron spool文件夹并确保它具有正确的权限(600)。


19
不建议直接在/ var / spool / cron中修改文件。实际上,如果您查看那里的文件,它们通常会在第一行包含警告,例如“请勿编辑此文件”。
杰瑞德(Jared)

12
@Jared虽然我非常同意这个想法,但是说“皱眉头”并没有多大帮助。而不是告诉应该编辑哪个其他文件(如果有的话),或者说明手动编辑文件的风险。我打算通过自动命令行创建一些cron作业,并且如果编辑此文件既是唯一的选择,又没有明显的副作用,那么我不明白为什么不使用它。
Balmipour

47
向下滚动以获得真实答案。
约翰·雷德

1
在我看来,这个答案要好得多:stackoverflow.com/a/610860/2681752
galaux

2
我采用这种方法感到遗憾。在RHEL上,目录/ var / spool / cron不是世界可执行文件,因此用户无法遍历该目录并手动编辑其文件。如果使/ var / spool / cron world可执行文件,则友好的本地sysadmin会对您发火,如果重新安装或更新cronie软件包,则权限更改可能会被覆盖。
functionvoid

384

这是一种单行代码,它不使用/不需要将新作业存储在文件中:

(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -

2>/dev/null让你没有得到的是很重要的no crontab for username,如果目前没有crontab项,一些* nixes产生的消息。


14
这应该是公认的答案。现在只需要一种方法来检查我打算添加的
单线

7
...哦,等等,这是在添加脚本之前检查用户crontab中是否存在内容的方法:stackoverflow.com/a/14451184/3686125
ChrisPrime 2014年

1
如果此脚本旨在作为重复执行的命令并修改现有的cron任务,则最好替换crontab中的现有行。几个标记可用于控制不同的cron任务(control-marker-1,control-marker-2等):(crontab -l 2> / dev / null | grep -v control-marker-1; echo '* / 5 * * * * / path / to / job -with args#control-marker-1')| crontab中-
厨师

7
我发现这将删除现有的crontab条目,并且我还需要使用其他用户(root),因此我使用以下方法来维护现有的条目:echo -e "$(sudo crontab -u root -l)\n* * * * * echo hello > /home/danny/temp.log 2>&1" | sudo crontab -u root -希望这对某人有所帮助
Danny

60

对于用户crontabs(包括root),您可以执行以下操作:

crontab -l -u user | cat - filename | crontab -u user -

其中名为“文件名”的文件包含要追加的项目。您也可以使用sed或其他工具代替进行文字处理cat。您应该使用crontab命令而不是直接修改文件。

类似的操作将是:

{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -

如果要修改或创建系统crontab,可以像处理普通文本文件一样对它们进行操作。它们存储在/etc/cron.d/etc/cron.hourly/etc/cron.daily/etc/cron.weekly/etc/cron.monthly目录和文件/etc/crontab/etc/anacrontab


看起来很有希望,但是尝试第二种方法(使用echo),我得到了“ crontab:用法错误:必须指定文件名来替换。” Cron手册页的语法显示为crontab [ -u user ] file,即带有必需的文件名。是否有一些技巧可以使其接受管道数据呢?
Mark Berry 2014年

1
@MarkBerry:对不起。在管道中,必须使用连字符来表示输入来自stdin。我会改正答案。
暂停,直到另行通知。

29

在Ubuntu和许多其他发行版中,您可以将文件放入/etc/cron.d包含有效crontab条目的单行目录中。无需在现有文件中添加一行。

如果您只需要日常运行,只需将文件放入即可/etc/cron.daily。同样的,你也可以文件拖放到/etc/cron.hourly/etc/cron.monthly/etc/cron.weekly


5
但是您必须是root用户才能这样做。
基思

17

对于您的问题,更简单的答案是:

echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root

您可以在远程服务器上设置cronjobs,如下所示:

#!/bin/bash
servers="srv1 srv2 srv3 srv4 srv5"
for i in $servers
  do
  echo "0 1 * * * /root/test.sh" | ssh $i " tee -a /var/spool/cron/root"
done

在Linux中,crontab文件的默认位置是/var/spool/cron/。在这里您可以找到crontab所有用户的文件。您只需要将cronjob条目附加到相应用户的文件即可。在上面的示例中,root用户的crontab文件被追加了cronjob,以/root/test.sh每天凌晨1点运行。


那将/var/spool/cron/crontabs/root在Ubuntu上。
的IhorMé

17

Crontab文件只是文本文件,因此可以像其他任何文本文件一样对待。该crontab命令的目的是使编辑crontab文件更安全。通过此命令编辑时,将检查文件是否有错误,并且仅在没有文件的情况下保存文件。

crontab [path to file]可用于指定存储在文件中的crontab。像一样crontab -e,这只会在没有错误的情况下安装文件。

因此,脚本可以直接写入cron选项卡文件,也可以将它们写入临时文件并使用crontab [path to temp file]命令加载它们。直接写可以省去写临时文件的麻烦,但同时也避免了安全检查。


2
对于像我这样的菜鸟,请注意,它crontab [path to file]绝对是我的最佳选择,因为它允许使用更清晰的代码。我使用crontab来跟踪包裹并使用状态更改我的桌面墙纸。当我不希望收到包裹时,不需要每小时检查一次。这就是为什么我想要脚本自动编辑cron频率的原因。
拉斯姆斯

1
@Rasmus听起来像是我希望能够偷的很棒的脚本。有机会通过要旨或类似方式分享吗?
cledoux '16

8

(我没有足够的声誉来发表评论,所以我在这里添加一个答案:随时在他的答案旁边添加它作为评论)

Joe Casadonte的单行代码是完美的,除非您使用运行set -e,即,如果脚本设置为因错误而失败,并且还没有cronjobs。在这种情况下,单行将不会创建cronjob,但不会停止脚本。无声的失败可能会引起很大的误导。

原因是crontab -l返回时返回了一个1返回代码,导致后续命令(echo)不被执行……因此不会创建cronjob。但是由于它们作为子过程执行(由于括号),因此它们不会停止脚本。

(有趣的是,如果再次运行相同的命令,它将起作用:一旦执行crontab -一次,crontab -l仍然不输出任何内容,但不再返回错误(不再收到该no crontab for <user>消息)。因此echo执行后续命令并创建crontab)

无论如何,如果使用进行运行set -e,则该行必须为:

(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -

是的,这个更加完美。
Yngve Sneen Lindal

7

作为对这些建议的更正crontab -l | crontab -:并非在所有系统上都有效。例如,我不得不在数十台运行旧版本SUSE的服务器上的根crontab中添加作业(不要问为什么)。旧的SUSE会将注释行添加到的输出之前crontab -l,从而使其成为crontab -l | crontab -非幂等的(Debian在crontab联机帮助页中识别了此问题,并对其Vixie Cron版本进行了修补以更改的默认行为crontab -l)。

要在crontab -l添加注释的系统上以编程方式编辑crontabs ,可以尝试以下操作:

EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -

EDITOR=cat告诉crontab cat用作编辑器(不是通常的默认vi),该编辑器不会更改文件,而是将其复制到stdout。如果crontab -期望输入的格式与crontab -e输出的格式不同,这可能仍然会失败。不要尝试更换最后crontab -crontab -e-这是行不通的。


4

好吧,/etc/crontab只是一个ascii文件,所以最简单的就是

 echo "*/15 * * * *   root     date" >> /etc/crontab

每15分钟就会发送一封电子邮件给您。调整口味,并通过grep或其他方式测试该行是否已添加以使脚本具有幂等性。

在Ubuntu等上,您还可以删除/etc/cron.*更易于执行和测试的文件-而且您不会弄乱诸如的(系统)配置文件/etc/crontab


1
我认为从技术上讲,crond不需要监视crontab的更改,即使实际上大多数实现都需要,因此我建议事后调用crontab -e进行生产。如果有内存,crontab -e会保留EDITOR变量,因此暂时将其设置为/ bin / true应该只是强制重新读取crontab。
Ulrich Schwarz

1
没错,但是在任何最新的Linux系统上crond 都可以进行监视,并且可以在OP所述平台上进行监视。
Dirk Eddelbuettel'2

仅当您是root用户并希望脚本以root用户身份运行时。在OP的情况下,这可能不是理想的。
基思

并非如此,我在/ etc / crontab中有很多非root用户条目。您仅需要sudo即可附加到文件。无论如何,正如我所说,这里也有/etc/cron.*/,但是您也需要成为root用户才能在那写。
Dirk Eddelbuettel

2

以下是在不直接编辑cron文件(皱眉)的情况下修改cron条目的方法。

crontab -l -u <user> | sed 's/find/replace/g' | crontab -u <user> -

如果要删除cron条目,请使用以下命令:

crontab -l -u <user> | sed '/find/d' | crontab -u <user> -

我意识到这不是gaurav要求的,但是为什么不将所有解决方案都放在一个地方呢?


1

我已经在python中编写了一个crontab部署工具:https : //github.com/monklof/deploycron

pip install deploycron

安装您的crontab非常简单,这会将crontab合并到系统现有的crontab中。

from deploycron import deploycron
deploycron(content="* * * * * echo hello > /tmp/hello")

1

这是一种增量添加cron作业的方法:

  ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.