如何通过脚本创建 crontab

Posted

技术标签:

【中文标题】如何通过脚本创建 crontab【英文标题】:How do I create a crontab through a script 【发布时间】:2011-06-20 07:11:27 【问题描述】:

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

可以吗?

【问题讨论】:

***.com/questions/610839/… How can I programmatically create a new cron job?的可能重复 如果您要修改或删除 crontab 条目,请参阅下面的解决方案。 【参考方案1】:

最简单的解决方案是使用 echo 和 >> 然后运行 ​​crontab filename 例如:

 ssh $HOST "echo \"* * * * * echo hello >> /var/spool/cron/crontabs/root\"; sleep 2; crontab /var/spool/cron/crontabs/root" 

【讨论】:

【参考方案2】:

同时向 crontab 添加多个脚本的另一种解决方案:

cat <<EOF | crontab -
* * * * * /bin/foo.sh
* * * * * /bin/gaga.sh
EOF

【讨论】:

【参考方案3】:

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

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

【讨论】:

不赞成直接在 /var/spool/cron 中修改文件。实际上,如果您查看那里的文件,它们通常会在第一行包含诸如“请勿编辑此文件”之类的警告。 @Jared 虽然我非常同意这个想法,但说它“不受欢迎”并没有多大帮助。而是告诉应该编辑哪个 other 文件(如果有的话),或者解释手动编辑文件的风险。我打算通过自动命令行创建一些 cron 作业,如果编辑这个文件是唯一的选择,并且没有明显的副作用,我不明白为什么我不应该使用它。 向下滚动以获得真正的答案。 在我看来,这个答案更好:***.com/a/610860/2681752 我采取了这种方法并后悔了。在 RHEL 上,目录 /var/spool/cron 不是全局可执行的,因此用户无法遍历该目录并手动编辑他们的文件。如果你让 /var/spool/cron world 可执行,你友好的本地系统管理员会生你的气,而且如果 cronie 包被重新安装或更新,权限更改可能会被覆盖。【参考方案4】:

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

  ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"

【讨论】:

【参考方案5】:

作为对那些建议crontab -l | crontab - 的更正:这并不适用于每个系统。例如,我必须在数十台运行旧版本 SUSE 的服务器上的根 crontab 中添加一个作业(不要问为什么)。旧的 SUSE 在 crontab -l 的输出前添加注释行,使 crontab -l | crontab - 非幂等(Debian 在 crontab 手册页中发现了这个问题,并修补了它的 Vixie Cron 版本以更改 crontab -l 的默认行为)。

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

EDITOR=cat crontab -e &gt; old_crontab; cat old_crontab new_job | crontab -

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

【讨论】:

【参考方案6】:

(我没有足够的声誉来发表评论,所以我将其添加为答案:请随时将其作为评论添加到他的答案旁边)

Joe Casadonte's one-liner 是完美的,除非您使用 set -e 运行,即如果您的脚本设置为错误失败,并且还没有 cronjobs。在这种情况下,单行程序不会创建 cronjob,但不会停止脚本。无声的失败可能非常具有误导性。

原因是crontab -l1 返回码返回,导致后续命令(echo)不被执行......因此没有创建cronjob。但由于它们是作为子进程执行的(因为括号),它们不会停止脚本。

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

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

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

【讨论】:

是的,这个更完美。 好一个 - 我希望它能给你带来缺失的声誉! 我为这个问题找到的唯一有用的答案。【参考方案7】:

这里是如何在不直接编辑 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 所要求的,但为什么不将所有解决方案集中在一个地方呢?

【讨论】:

你能给出一个实际替换 cron 表达式的完整工作示例吗?我试过了,但它对我不起作用。特别是当预定脚本的完整路径与正斜杠一起使用时。【参考方案8】:

我用python写了一个crontab部署工具:https://github.com/monklof/deploycron

pip install deploycron

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

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

【讨论】:

【参考方案9】:

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

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

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

【讨论】:

对于像我这样的新手,请注意它是crontab [path to file] .. 这对我来说绝对是最好的选择,因为它允许更清晰的代码。我使用 crontab 来跟踪包裹并使用状态更改我的桌面墙纸。当我不期待包裹时,它不需要每小时检查一次。这就是我希望脚本自动编辑 cron 频率的原因。 @Rasmus 这听起来像是一个很棒的脚本,我很想能够窃取。有机会通过要点或类似方式分享吗? 仅供参考,crontab [path to file] 不一定需要“临时”文件,它可以加载在 crontab 布局中正确格式化的任何文件。这是我们在 SlickStack 中使用的方法,这样 crontab 模板可以随时更新(下载)然后重新安装:github.com/littlebizzy/slickstack/blob/master/00-crontab.txt【参考方案10】:

你的问题更简单的答案是:

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 以在每天凌晨 1 点运行 /root/test.sh

【讨论】:

在 Ubuntu 上应该是 /var/spool/cron/crontabs/root【参考方案11】:

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

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

其中名为“filename”的文件包含要附加的项目。您还可以使用sed 或其他工具代替cat 进行文本操作。您应该使用crontab 命令而不是直接修改文件。

类似的操作是:

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

如果您正在修改或创建系统 crontab,则可能会像处理普通文本文件一样操作这些 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,即带有强制文件名。是否有一些技巧可以让它接受管道数据? @MarkBerry:很抱歉。在管道中,必须使用连字符来表示输入来自stdin。我会更正我的答案。【参考方案12】:

这是一个不使用/不需要新作业在文件中的单行:

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

2&gt;/dev/null 很重要,这样如果当前没有 crontab 条目,您就不会收到某些 *nixes 产生的 no crontab for username 消息。

【讨论】:

这应该是公认的答案。现在只需要一种方法来检查我打算添加的单行是否已经存在...... ...哦,等等,这是在我使用脚本添加之前检查用户的 crontab 中是否有内容的方法:***.com/a/14451184/3686125 如果此脚本旨在作为重复执行和修改现有 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 - 我发现这是删除现有的 crontab 条目,而且我需要使用不同的用户(root),所以我使用以下内容来维护现有条目:echo -e "$(sudo crontab -u root -l)\n* * * * * echo hello &gt; /home/danny/temp.log 2&gt;&amp;1" | sudo crontab -u root - 希望这对某人有所帮助 这里的*/ 是什么意思?【参考方案13】:

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

如果您只需要每天运行一些东西,只需将文件放入/etc/cron.daily。同样,您也可以将文件放入/etc/cron.hourly/etc/cron.monthly/etc/cron.weekly

【讨论】:

但是你必须是root才能做到这一点。 @IvanGoneKrazy - 如果我必须在每次重新启动时运行,是否有这样的文件夹?【参考方案14】:

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

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

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

在 Ubuntu 等平台上,您还可以将文件放在 /etc/cron.* 中,这更容易操作和测试——而且您不会弄乱(系统)配置文件,例如 /etc/crontab

【讨论】:

我认为技术上不需要 crond 来监视对 crontab 的更改,即使实际上大多数实现都这样做,所以我建议之后调用 crontab -e 来刺激它。 crontab -e 如果内存可用,则尊重 EDITOR 变量,因此暂时将其设置为 /bin/true 应该只会强制重新读取 crontab。 在任何最近的 Linux 系统上都是正确的 crond 确实监控,而且它肯定在 OP 声明的平台上。 仅当您是 root 并且希望脚本以 root 身份运行时。在 OP 的情况下,这可能是不可取的。 不是这样,我在 /etc/crontab 中有很多非 root 条目。您“仅”需要 sudo 附加到文件中。无论如何,正如我所说,还有 /etc/cron.*/ 但你也需要是 root 才能在那里写。

以上是关于如何通过脚本创建 crontab的主要内容,如果未能解决你的问题,请参考以下文章

Unity如何通过脚本创建文本?

如何通过 bash 脚本将 ssh 密钥添加到主机

Linux 定时备份oracle库的数据

如何使用带有逗号分隔值的单元格通过apps脚本创建动态下拉列表

linux定时删除N天前的文件(文件夹)

如何创建脚本来自动填充字段?